/*
* Copyright 2016 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
*/
#include "si_shader_internal.h"
-#include "gallivm/lp_bld_const.h"
-#include "gallivm/lp_bld_intr.h"
-#include "gallivm/lp_bld_gather.h"
-#include "tgsi/tgsi_parse.h"
-#include "amd/common/ac_llvm_build.h"
-
-static void kill_if_fetch_args(struct lp_build_tgsi_context *bld_base,
- struct lp_build_emit_data *emit_data)
-{
- const struct tgsi_full_instruction *inst = emit_data->inst;
- struct gallivm_state *gallivm = bld_base->base.gallivm;
- LLVMBuilderRef builder = gallivm->builder;
- unsigned i;
- LLVMValueRef conds[TGSI_NUM_CHANNELS];
+#include "ac_llvm_util.h"
- for (i = 0; i < TGSI_NUM_CHANNELS; i++) {
- LLVMValueRef value = lp_build_emit_fetch(bld_base, inst, 0, i);
- conds[i] = LLVMBuildFCmp(builder, LLVMRealOLT, value,
- bld_base->base.zero, "");
- }
+void si_llvm_emit_kill(struct ac_shader_abi *abi, LLVMValueRef visible)
+{
+ struct si_shader_context *ctx = si_shader_context_from_abi(abi);
+ LLVMBuilderRef builder = ctx->ac.builder;
- /* Or the conditions together */
- for (i = TGSI_NUM_CHANNELS - 1; i > 0; i--) {
- conds[i - 1] = LLVMBuildOr(builder, conds[i], conds[i - 1], "");
+ if (ctx->shader->selector->force_correct_derivs_after_kill) {
+ /* Kill immediately while maintaining WQM. */
+ ac_build_kill_if_false(&ctx->ac,
+ ac_build_wqm_vote(&ctx->ac, visible));
+
+ LLVMValueRef mask = LLVMBuildLoad(builder, ctx->postponed_kill, "");
+ mask = LLVMBuildAnd(builder, mask, visible, "");
+ LLVMBuildStore(builder, mask, ctx->postponed_kill);
+ return;
}
- emit_data->dst_type = LLVMVoidTypeInContext(gallivm->context);
- emit_data->arg_count = 1;
- emit_data->args[0] = LLVMBuildSelect(builder, conds[0],
- lp_build_const_float(gallivm, -1.0f),
- bld_base->base.zero, "");
+ ac_build_kill_if_false(&ctx->ac, visible);
}
static void kil_emit(const struct lp_build_tgsi_action *action,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
- LLVMBuilderRef builder = ctx->gallivm.builder;
-
- if (ctx->postponed_kill) {
- if (emit_data->inst->Instruction.Opcode == TGSI_OPCODE_KILL_IF) {
- LLVMValueRef val;
-
- /* Take the minimum kill value. This is the same as OR
- * between 2 kill values. If the value is negative,
- * the pixel will be killed.
- */
- val = LLVMBuildLoad(builder, ctx->postponed_kill, "");
- val = lp_build_emit_llvm_binary(bld_base, TGSI_OPCODE_MIN,
- val, emit_data->args[0]);
- LLVMBuildStore(builder, val, ctx->postponed_kill);
- } else {
- LLVMBuildStore(builder,
- LLVMConstReal(ctx->f32, -1),
- ctx->postponed_kill);
+ LLVMValueRef visible;
+
+ if (emit_data->inst->Instruction.Opcode == TGSI_OPCODE_KILL_IF) {
+ const struct tgsi_full_instruction *inst = emit_data->inst;
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ LLVMBuilderRef builder = ctx->ac.builder;
+ unsigned i;
+ LLVMValueRef conds[TGSI_NUM_CHANNELS];
+
+ for (i = 0; i < TGSI_NUM_CHANNELS; i++) {
+ LLVMValueRef value = lp_build_emit_fetch(bld_base, inst, 0, i);
+ /* UGE because NaN shouldn't get killed */
+ conds[i] = LLVMBuildFCmp(builder, LLVMRealUGE, value,
+ ctx->ac.f32_0, "");
}
- return;
+
+ /* And the conditions together */
+ for (i = TGSI_NUM_CHANNELS - 1; i > 0; i--) {
+ conds[i - 1] = LLVMBuildAnd(builder, conds[i], conds[i - 1], "");
+ }
+ visible = conds[0];
+ } else {
+ assert(emit_data->inst->Instruction.Opcode == TGSI_OPCODE_KILL);
+ visible = ctx->i1false;
}
- if (emit_data->inst->Instruction.Opcode == TGSI_OPCODE_KILL_IF)
- ac_build_kill(&ctx->ac, emit_data->args[0]);
- else
- ac_build_kill(&ctx->ac, NULL);
+ si_llvm_emit_kill(&ctx->abi, visible);
}
static void emit_icmp(const struct lp_build_tgsi_action *action,
struct lp_build_emit_data *emit_data)
{
unsigned pred;
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- LLVMContextRef context = bld_base->base.gallivm->context;
+ struct si_shader_context *ctx = si_shader_context(bld_base);
switch (emit_data->inst->Instruction.Opcode) {
case TGSI_OPCODE_USEQ:
break;
}
- LLVMValueRef v = LLVMBuildICmp(builder, pred,
+ LLVMValueRef v = LLVMBuildICmp(ctx->ac.builder, pred,
emit_data->args[0], emit_data->args[1],"");
- v = LLVMBuildSExtOrBitCast(builder, v,
- LLVMInt32TypeInContext(context), "");
+ v = LLVMBuildSExtOrBitCast(ctx->ac.builder, v, ctx->i32, "");
emit_data->output[emit_data->chan] = v;
}
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
-
LLVMValueRef arg0 = ac_to_integer(&ctx->ac, emit_data->args[0]);
- LLVMValueRef v = LLVMBuildICmp(builder, LLVMIntNE, arg0,
- bld_base->uint_bld.zero, "");
+ LLVMValueRef v = LLVMBuildICmp(ctx->ac.builder, LLVMIntNE, arg0,
+ ctx->i32_0, "");
emit_data->output[emit_data->chan] =
- LLVMBuildSelect(builder, v, emit_data->args[1], emit_data->args[2], "");
+ LLVMBuildSelect(ctx->ac.builder, v, emit_data->args[1], emit_data->args[2], "");
}
static void emit_cmp(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
+ struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMValueRef cond, *args = emit_data->args;
- cond = LLVMBuildFCmp(builder, LLVMRealOLT, args[0],
- bld_base->base.zero, "");
+ cond = LLVMBuildFCmp(ctx->ac.builder, LLVMRealOLT, args[0],
+ ctx->ac.f32_0, "");
emit_data->output[emit_data->chan] =
- LLVMBuildSelect(builder, cond, args[1], args[2], "");
+ LLVMBuildSelect(ctx->ac.builder, cond, args[1], args[2], "");
}
static void emit_set_cond(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
+ struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMRealPredicate pred;
LLVMValueRef cond;
default: assert(!"unknown instruction"); pred = 0; break;
}
- cond = LLVMBuildFCmp(builder,
+ cond = LLVMBuildFCmp(ctx->ac.builder,
pred, emit_data->args[0], emit_data->args[1], "");
- emit_data->output[emit_data->chan] = LLVMBuildSelect(builder,
- cond, bld_base->base.one, bld_base->base.zero, "");
+ emit_data->output[emit_data->chan] = LLVMBuildSelect(ctx->ac.builder,
+ cond, ctx->ac.f32_1, ctx->ac.f32_0, "");
}
static void emit_fcmp(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- LLVMContextRef context = bld_base->base.gallivm->context;
+ struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMRealPredicate pred;
/* Use ordered for everything but NE (which is usual for
default: assert(!"unknown instruction"); pred = 0; break;
}
- LLVMValueRef v = LLVMBuildFCmp(builder, pred,
+ LLVMValueRef v = LLVMBuildFCmp(ctx->ac.builder, pred,
emit_data->args[0], emit_data->args[1],"");
- v = LLVMBuildSExtOrBitCast(builder, v,
- LLVMInt32TypeInContext(context), "");
+ v = LLVMBuildSExtOrBitCast(ctx->ac.builder, v, ctx->i32, "");
emit_data->output[emit_data->chan] = v;
}
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- LLVMContextRef context = bld_base->base.gallivm->context;
+ struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMRealPredicate pred;
/* Use ordered for everything but NE (which is usual for
default: assert(!"unknown instruction"); pred = 0; break;
}
- LLVMValueRef v = LLVMBuildFCmp(builder, pred,
+ LLVMValueRef v = LLVMBuildFCmp(ctx->ac.builder, pred,
emit_data->args[0], emit_data->args[1],"");
- v = LLVMBuildSExtOrBitCast(builder, v,
- LLVMInt32TypeInContext(context), "");
+ v = LLVMBuildSExtOrBitCast(ctx->ac.builder, v, ctx->i32, "");
emit_data->output[emit_data->chan] = v;
}
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
LLVMValueRef v = ac_to_integer(&ctx->ac, emit_data->args[0]);
- emit_data->output[emit_data->chan] = LLVMBuildNot(builder, v, "");
+ emit_data->output[emit_data->chan] = LLVMBuildNot(ctx->ac.builder, v, "");
}
static void emit_arl(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- LLVMValueRef floor_index = lp_build_emit_llvm_unary(bld_base, TGSI_OPCODE_FLR, emit_data->args[0]);
- emit_data->output[emit_data->chan] = LLVMBuildFPToSI(builder,
- floor_index, bld_base->base.int_elem_type , "");
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ LLVMValueRef floor_index =
+ ac_build_intrinsic(&ctx->ac, "llvm.floor.f32", ctx->f32,
+ &emit_data->args[0], 1, AC_FUNC_ATTR_READNONE);
+ emit_data->output[emit_data->chan] = LLVMBuildFPToSI(ctx->ac.builder,
+ floor_index, ctx->i32, "");
}
static void emit_and(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- emit_data->output[emit_data->chan] = LLVMBuildAnd(builder,
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ emit_data->output[emit_data->chan] = LLVMBuildAnd(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- emit_data->output[emit_data->chan] = LLVMBuildOr(builder,
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ emit_data->output[emit_data->chan] = LLVMBuildOr(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- emit_data->output[emit_data->chan] = LLVMBuildAdd(builder,
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ emit_data->output[emit_data->chan] = LLVMBuildAdd(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- emit_data->output[emit_data->chan] = LLVMBuildUDiv(builder,
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ emit_data->output[emit_data->chan] = LLVMBuildUDiv(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- emit_data->output[emit_data->chan] = LLVMBuildSDiv(builder,
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ emit_data->output[emit_data->chan] = LLVMBuildSDiv(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- emit_data->output[emit_data->chan] = LLVMBuildSRem(builder,
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ emit_data->output[emit_data->chan] = LLVMBuildSRem(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- emit_data->output[emit_data->chan] = LLVMBuildURem(builder,
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ emit_data->output[emit_data->chan] = LLVMBuildURem(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- emit_data->output[emit_data->chan] = LLVMBuildShl(builder,
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ emit_data->output[emit_data->chan] = LLVMBuildShl(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- emit_data->output[emit_data->chan] = LLVMBuildLShr(builder,
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ emit_data->output[emit_data->chan] = LLVMBuildLShr(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
static void emit_ishr(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- emit_data->output[emit_data->chan] = LLVMBuildAShr(builder,
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ emit_data->output[emit_data->chan] = LLVMBuildAShr(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- emit_data->output[emit_data->chan] = LLVMBuildXor(builder,
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ emit_data->output[emit_data->chan] = LLVMBuildXor(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
+ struct si_shader_context *ctx = si_shader_context(bld_base);
- LLVMValueRef cmp, val;
+ LLVMValueRef val;
if (emit_data->inst->Instruction.Opcode == TGSI_OPCODE_I64SSG) {
- cmp = LLVMBuildICmp(builder, LLVMIntSGT, emit_data->args[0], bld_base->int64_bld.zero, "");
- val = LLVMBuildSelect(builder, cmp, bld_base->int64_bld.one, emit_data->args[0], "");
- cmp = LLVMBuildICmp(builder, LLVMIntSGE, val, bld_base->int64_bld.zero, "");
- val = LLVMBuildSelect(builder, cmp, val, LLVMConstInt(bld_base->int64_bld.elem_type, -1, true), "");
+ val = ac_build_isign(&ctx->ac, emit_data->args[0], 64);
} else if (emit_data->inst->Instruction.Opcode == TGSI_OPCODE_ISSG) {
- cmp = LLVMBuildICmp(builder, LLVMIntSGT, emit_data->args[0], bld_base->int_bld.zero, "");
- val = LLVMBuildSelect(builder, cmp, bld_base->int_bld.one, emit_data->args[0], "");
- cmp = LLVMBuildICmp(builder, LLVMIntSGE, val, bld_base->int_bld.zero, "");
- val = LLVMBuildSelect(builder, cmp, val, LLVMConstInt(bld_base->int_bld.elem_type, -1, true), "");
+ val = ac_build_isign(&ctx->ac, emit_data->args[0], 32);
} else if (emit_data->inst->Instruction.Opcode == TGSI_OPCODE_DSSG) {
- cmp = LLVMBuildFCmp(builder, LLVMRealOGT, emit_data->args[0], bld_base->dbl_bld.zero, "");
- val = LLVMBuildSelect(builder, cmp, bld_base->dbl_bld.one, emit_data->args[0], "");
- cmp = LLVMBuildFCmp(builder, LLVMRealOGE, val, bld_base->dbl_bld.zero, "");
- val = LLVMBuildSelect(builder, cmp, val, LLVMConstReal(bld_base->dbl_bld.elem_type, -1), "");
- } else { // float SSG
- cmp = LLVMBuildFCmp(builder, LLVMRealOGT, emit_data->args[0], bld_base->base.zero, "");
- val = LLVMBuildSelect(builder, cmp, bld_base->base.one, emit_data->args[0], "");
- cmp = LLVMBuildFCmp(builder, LLVMRealOGE, val, bld_base->base.zero, "");
- val = LLVMBuildSelect(builder, cmp, val, LLVMConstReal(bld_base->base.elem_type, -1), "");
+ val = ac_build_fsign(&ctx->ac, emit_data->args[0], 64);
+ } else {
+ val = ac_build_fsign(&ctx->ac, emit_data->args[0], 32);
}
emit_data->output[emit_data->chan] = val;
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- emit_data->output[emit_data->chan] = LLVMBuildNeg(builder,
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ emit_data->output[emit_data->chan] = LLVMBuildNeg(ctx->ac.builder,
emit_data->args[0], "");
}
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- emit_data->output[emit_data->chan] = LLVMBuildFNeg(builder,
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ emit_data->output[emit_data->chan] = LLVMBuildFNeg(ctx->ac.builder,
emit_data->args[0], "");
}
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- char *intr;
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ unsigned bitsize;
if (emit_data->info->opcode == TGSI_OPCODE_FRC)
- intr = "llvm.floor.f32";
+ bitsize = 32;
else if (emit_data->info->opcode == TGSI_OPCODE_DFRAC)
- intr = "llvm.floor.f64";
+ bitsize = 64;
else {
assert(0);
return;
}
- LLVMValueRef floor = lp_build_intrinsic(builder, intr, emit_data->dst_type,
- &emit_data->args[0], 1,
- LP_FUNC_ATTR_READNONE);
- emit_data->output[emit_data->chan] = LLVMBuildFSub(builder,
- emit_data->args[0], floor, "");
+ emit_data->output[emit_data->chan] =
+ ac_build_fract(&ctx->ac, emit_data->args[0], bitsize);
}
static void emit_f2i(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- emit_data->output[emit_data->chan] = LLVMBuildFPToSI(builder,
- emit_data->args[0], bld_base->int_bld.elem_type, "");
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ emit_data->output[emit_data->chan] = LLVMBuildFPToSI(ctx->ac.builder,
+ emit_data->args[0], ctx->i32, "");
}
static void emit_f2u(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- emit_data->output[emit_data->chan] = LLVMBuildFPToUI(builder,
- emit_data->args[0], bld_base->uint_bld.elem_type, "");
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ emit_data->output[emit_data->chan] = LLVMBuildFPToUI(ctx->ac.builder,
+ emit_data->args[0], ctx->i32, "");
}
static void emit_i2f(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- emit_data->output[emit_data->chan] = LLVMBuildSIToFP(builder,
- emit_data->args[0], bld_base->base.elem_type, "");
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ emit_data->output[emit_data->chan] = LLVMBuildSIToFP(ctx->ac.builder,
+ emit_data->args[0], ctx->f32, "");
}
static void emit_u2f(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- emit_data->output[emit_data->chan] = LLVMBuildUIToFP(builder,
- emit_data->args[0], bld_base->base.elem_type, "");
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ emit_data->output[emit_data->chan] = LLVMBuildUIToFP(ctx->ac.builder,
+ emit_data->args[0], ctx->f32, "");
}
static void
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- struct lp_build_context *base = &bld_base->base;
+ struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] =
- lp_build_intrinsic(base->gallivm->builder, action->intr_name,
+ ac_build_intrinsic(&ctx->ac, action->intr_name,
emit_data->dst_type, emit_data->args,
- emit_data->arg_count, LP_FUNC_ATTR_READNONE);
+ emit_data->arg_count, AC_FUNC_ATTR_READNONE);
}
static void emit_bfi(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- struct gallivm_state *gallivm = bld_base->base.gallivm;
- LLVMBuilderRef builder = gallivm->builder;
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ LLVMBuilderRef builder = ctx->ac.builder;
LLVMValueRef bfi_args[3];
LLVMValueRef bfi_sm5;
LLVMValueRef cond;
bfi_args[0] = LLVMBuildShl(builder,
LLVMBuildSub(builder,
LLVMBuildShl(builder,
- bld_base->int_bld.one,
+ ctx->i32_1,
emit_data->args[3], ""),
- bld_base->int_bld.one, ""),
+ ctx->i32_1, ""),
emit_data->args[2], "");
bfi_args[1] = LLVMBuildShl(builder, emit_data->args[1],
* and disagrees with GLSL semantics when bits (src3) is 32.
*/
cond = LLVMBuildICmp(builder, LLVMIntUGE, emit_data->args[3],
- lp_build_const_int32(gallivm, 32), "");
+ LLVMConstInt(ctx->i32, 32, 0), "");
emit_data->output[emit_data->chan] =
LLVMBuildSelect(builder, cond, emit_data->args[1], bfi_sm5, "");
}
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
- struct gallivm_state *gallivm = &ctx->gallivm;
- LLVMBuilderRef builder = gallivm->builder;
- LLVMValueRef bfe_sm5;
- LLVMValueRef cond;
- bfe_sm5 = ac_build_bfe(&ctx->ac, emit_data->args[0],
- emit_data->args[1], emit_data->args[2],
- emit_data->info->opcode == TGSI_OPCODE_IBFE);
+ /* FIXME: LLVM 7 returns incorrect result when count is 0.
+ * https://bugs.freedesktop.org/show_bug.cgi?id=107276
+ */
+ LLVMValueRef zero = ctx->i32_0;
+ LLVMValueRef bfe_sm5 =
+ ac_build_bfe(&ctx->ac, emit_data->args[0],
+ emit_data->args[1], emit_data->args[2],
+ emit_data->info->opcode == TGSI_OPCODE_IBFE);
/* Correct for GLSL semantics. */
- cond = LLVMBuildICmp(builder, LLVMIntUGE, emit_data->args[2],
- LLVMConstInt(ctx->i32, 32, 0), "");
+ LLVMValueRef cond = LLVMBuildICmp(ctx->ac.builder, LLVMIntUGE, emit_data->args[2],
+ LLVMConstInt(ctx->i32, 32, 0), "");
+ LLVMValueRef cond2 = LLVMBuildICmp(ctx->ac.builder, LLVMIntEQ, emit_data->args[2],
+ zero, "");
+ bfe_sm5 = LLVMBuildSelect(ctx->ac.builder, cond, emit_data->args[0], bfe_sm5, "");
emit_data->output[emit_data->chan] =
- LLVMBuildSelect(builder, cond, emit_data->args[0], bfe_sm5, "");
+ LLVMBuildSelect(ctx->ac.builder, cond2, zero, bfe_sm5, "");
}
/* this is ffs in C */
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- struct gallivm_state *gallivm = bld_base->base.gallivm;
- LLVMBuilderRef builder = gallivm->builder;
- LLVMValueRef args[2] = {
- emit_data->args[0],
-
- /* The value of 1 means that ffs(x=0) = undef, so LLVM won't
- * add special code to check for x=0. The reason is that
- * the LLVM behavior for x=0 is different from what we
- * need here. However, LLVM also assumes that ffs(x) is
- * in [0, 31], but GLSL expects that ffs(0) = -1, so
- * a conditional assignment to handle 0 is still required.
- */
- LLVMConstInt(LLVMInt1TypeInContext(gallivm->context), 1, 0)
- };
-
- LLVMValueRef lsb =
- lp_build_intrinsic(gallivm->builder, "llvm.cttz.i32",
- emit_data->dst_type, args, ARRAY_SIZE(args),
- LP_FUNC_ATTR_READNONE);
+ struct si_shader_context *ctx = si_shader_context(bld_base);
- /* TODO: We need an intrinsic to skip this conditional. */
- /* Check for zero: */
- emit_data->output[emit_data->chan] =
- LLVMBuildSelect(builder,
- LLVMBuildICmp(builder, LLVMIntEQ, args[0],
- bld_base->uint_bld.zero, ""),
- lp_build_const_int32(gallivm, -1), lsb, "");
+ emit_data->output[emit_data->chan] = ac_find_lsb(&ctx->ac, emit_data->dst_type, emit_data->args[0]);
}
/* Find the last bit set. */
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
+ struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] =
- lp_build_emit_llvm_binary(bld_base, TGSI_OPCODE_IMAX,
- emit_data->args[0],
- LLVMBuildNeg(builder,
- emit_data->args[0], ""));
+ ac_build_imax(&ctx->ac, emit_data->args[0],
+ LLVMBuildNeg(ctx->ac.builder, emit_data->args[0], ""));
}
static void emit_minmax_int(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
+ struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMIntPredicate op;
switch (emit_data->info->opcode) {
}
emit_data->output[emit_data->chan] =
- LLVMBuildSelect(builder,
- LLVMBuildICmp(builder, op, emit_data->args[0],
+ LLVMBuildSelect(ctx->ac.builder,
+ LLVMBuildICmp(ctx->ac.builder, op, emit_data->args[0],
emit_data->args[1], ""),
emit_data->args[0],
emit_data->args[1], "");
}
-static void pk2h_fetch_args(struct lp_build_tgsi_context *bld_base,
- struct lp_build_emit_data *emit_data)
-{
- emit_data->args[0] = lp_build_emit_fetch(bld_base, emit_data->inst,
- 0, TGSI_CHAN_X);
- emit_data->args[1] = lp_build_emit_fetch(bld_base, emit_data->inst,
- 0, TGSI_CHAN_Y);
-}
-
static void emit_pk2h(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ LLVMValueRef v[] = {
+ lp_build_emit_fetch(bld_base, emit_data->inst, 0, TGSI_CHAN_X),
+ lp_build_emit_fetch(bld_base, emit_data->inst, 0, TGSI_CHAN_Y),
+ };
+
+
/* From the GLSL 4.50 spec:
* "The rounding mode cannot be set and is undefined."
*
* v_cvt_pkrtz_f16 rounds to zero, but it's fastest.
*/
emit_data->output[emit_data->chan] =
- ac_build_cvt_pkrtz_f16(&si_shader_context(bld_base)->ac,
- emit_data->args);
-}
-
-static void up2h_fetch_args(struct lp_build_tgsi_context *bld_base,
- struct lp_build_emit_data *emit_data)
-{
- emit_data->args[0] = lp_build_emit_fetch(bld_base, emit_data->inst,
- 0, TGSI_CHAN_X);
+ LLVMBuildBitCast(ctx->ac.builder, ac_build_cvt_pkrtz_f16(&ctx->ac, v),
+ ctx->i32, "");
}
static void emit_up2h(const struct lp_build_tgsi_action *action,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- LLVMContextRef context = bld_base->base.gallivm->context;
- struct lp_build_context *uint_bld = &bld_base->uint_bld;
LLVMTypeRef i16;
LLVMValueRef const16, input, val;
unsigned i;
- i16 = LLVMInt16TypeInContext(context);
- const16 = lp_build_const_int32(uint_bld->gallivm, 16);
- input = emit_data->args[0];
+ i16 = LLVMInt16TypeInContext(ctx->ac.context);
+ const16 = LLVMConstInt(ctx->i32, 16, 0);
+ input = lp_build_emit_fetch(bld_base, emit_data->inst, 0, TGSI_CHAN_X);
for (i = 0; i < 2; i++) {
- val = i == 1 ? LLVMBuildLShr(builder, input, const16, "") : input;
- val = LLVMBuildTrunc(builder, val, i16, "");
+ val = i == 1 ? LLVMBuildLShr(ctx->ac.builder, input, const16, "") : input;
+ val = LLVMBuildTrunc(ctx->ac.builder, val, i16, "");
val = ac_to_float(&ctx->ac, val);
- emit_data->output[i] =
- LLVMBuildFPExt(builder, val, bld_base->base.elem_type, "");
+ emit_data->output[i] = LLVMBuildFPExt(ctx->ac.builder, val, ctx->f32, "");
}
}
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] =
- LLVMBuildFDiv(ctx->gallivm.builder,
- emit_data->args[0], emit_data->args[1], "");
-
- /* Use v_rcp_f32 instead of precise division. */
- if (!LLVMIsConstant(emit_data->output[emit_data->chan]))
- LLVMSetMetadata(emit_data->output[emit_data->chan],
- ctx->fpmath_md_kind, ctx->fpmath_md_2p5_ulp);
+ ac_build_fdiv(&ctx->ac, emit_data->args[0], emit_data->args[1]);
}
/* 1/sqrt is translated to rsq for f32 if fp32 denormals are not enabled in
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+
LLVMValueRef sqrt =
- lp_build_emit_llvm_unary(bld_base, TGSI_OPCODE_SQRT,
- emit_data->args[0]);
+ ac_build_intrinsic(&ctx->ac, "llvm.sqrt.f32", ctx->f32,
+ &emit_data->args[0], 1, AC_FUNC_ATTR_READNONE);
emit_data->output[emit_data->chan] =
- lp_build_emit_llvm_binary(bld_base, TGSI_OPCODE_DIV,
- bld_base->base.one, sqrt);
-}
-
-static void dfracexp_fetch_args(struct lp_build_tgsi_context *bld_base,
- struct lp_build_emit_data *emit_data)
-{
- emit_data->args[0] = lp_build_emit_fetch(bld_base, emit_data->inst, 0, TGSI_CHAN_X);
- emit_data->arg_count = 1;
+ ac_build_fdiv(&ctx->ac, ctx->ac.f32_1, sqrt);
}
static void dfracexp_emit(const struct lp_build_tgsi_action *action,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
+ LLVMValueRef in = lp_build_emit_fetch(bld_base, emit_data->inst, 0, TGSI_CHAN_X);
emit_data->output[emit_data->chan] =
- lp_build_intrinsic(ctx->ac.builder, "llvm.amdgcn.frexp.mant.f64",
- ctx->ac.f64, &emit_data->args[0], 1, 0);
+ ac_build_intrinsic(&ctx->ac, "llvm.amdgcn.frexp.mant.f64",
+ ctx->ac.f64, &in, 1, 0);
emit_data->output1[emit_data->chan] =
- lp_build_intrinsic(ctx->ac.builder, "llvm.amdgcn.frexp.exp.i32.f64",
- ctx->ac.i32, &emit_data->args[0], 1, 0);
+ ac_build_intrinsic(&ctx->ac, "llvm.amdgcn.frexp.exp.i32.f64",
+ ctx->ac.i32, &in, 1, 0);
}
void si_shader_context_init_alu(struct lp_build_tgsi_context *bld_base)
bld_base->op_actions[TGSI_OPCODE_DSQRT].intr_name = "llvm.sqrt.f64";
bld_base->op_actions[TGSI_OPCODE_DTRUNC].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_DTRUNC].intr_name = "llvm.trunc.f64";
- bld_base->op_actions[TGSI_OPCODE_DFRACEXP].fetch_args = dfracexp_fetch_args;
bld_base->op_actions[TGSI_OPCODE_DFRACEXP].emit = dfracexp_emit;
bld_base->op_actions[TGSI_OPCODE_DLDEXP].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_DLDEXP].intr_name = "llvm.amdgcn.ldexp.f64";
bld_base->op_actions[TGSI_OPCODE_ISLT].emit = emit_icmp;
bld_base->op_actions[TGSI_OPCODE_ISSG].emit = emit_ssg;
bld_base->op_actions[TGSI_OPCODE_I2F].emit = emit_i2f;
- bld_base->op_actions[TGSI_OPCODE_KILL_IF].fetch_args = kill_if_fetch_args;
bld_base->op_actions[TGSI_OPCODE_KILL_IF].emit = kil_emit;
bld_base->op_actions[TGSI_OPCODE_KILL].emit = kil_emit;
bld_base->op_actions[TGSI_OPCODE_LDEXP].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_UMSB].emit = emit_umsb;
bld_base->op_actions[TGSI_OPCODE_NOT].emit = emit_not;
bld_base->op_actions[TGSI_OPCODE_OR].emit = emit_or;
- bld_base->op_actions[TGSI_OPCODE_PK2H].fetch_args = pk2h_fetch_args;
bld_base->op_actions[TGSI_OPCODE_PK2H].emit = emit_pk2h;
bld_base->op_actions[TGSI_OPCODE_POPC].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_POPC].intr_name = "llvm.ctpop.i32";
bld_base->op_actions[TGSI_OPCODE_U2F].emit = emit_u2f;
bld_base->op_actions[TGSI_OPCODE_XOR].emit = emit_xor;
bld_base->op_actions[TGSI_OPCODE_UCMP].emit = emit_ucmp;
- bld_base->op_actions[TGSI_OPCODE_UP2H].fetch_args = up2h_fetch_args;
bld_base->op_actions[TGSI_OPCODE_UP2H].emit = emit_up2h;
bld_base->op_actions[TGSI_OPCODE_I64MAX].emit = emit_minmax_int;