{
const struct tgsi_full_instruction *inst = emit_data->inst;
struct si_shader_context *ctx = si_shader_context(bld_base);
- struct gallivm_state *gallivm = bld_base->base.gallivm;
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);
- conds[i] = LLVMBuildFCmp(builder, LLVMRealOLT, value,
- bld_base->base.zero, "");
+ conds[i] = LLVMBuildFCmp(builder, LLVMRealOGE, value,
+ ctx->ac.f32_0, "");
}
- /* Or the conditions together */
+ /* And the conditions together */
for (i = TGSI_NUM_CHANNELS - 1; i > 0; i--) {
- conds[i - 1] = LLVMBuildOr(builder, conds[i], conds[i - 1], "");
+ conds[i - 1] = LLVMBuildAnd(builder, conds[i], conds[i - 1], "");
}
emit_data->dst_type = ctx->voidt;
emit_data->arg_count = 1;
- emit_data->args[0] = LLVMBuildSelect(builder, conds[0],
- lp_build_const_float(gallivm, -1.0f),
- bld_base->base.zero, "");
+ emit_data->args[0] = conds[0];
}
static void kil_emit(const struct lp_build_tgsi_action *action,
{
struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMBuilderRef builder = ctx->ac.builder;
+ LLVMValueRef visible;
- 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);
+ if (emit_data->inst->Instruction.Opcode == TGSI_OPCODE_KILL_IF) {
+ visible = emit_data->args[0];
+ } else {
+ assert(emit_data->inst->Instruction.Opcode == TGSI_OPCODE_KILL);
+ visible = LLVMConstInt(ctx->i1, false, 0);
+ }
+
+ if (ctx->shader->selector->force_correct_derivs_after_kill) {
+ /* LLVM 6.0 can kill immediately while maintaining WQM. */
+ if (HAVE_LLVM >= 0x0600) {
+ 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;
}
- 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);
+ ac_build_kill_if_false(&ctx->ac, visible);
}
static void emit_icmp(const struct lp_build_tgsi_action *action,
LLVMValueRef cond, *args = emit_data->args;
cond = LLVMBuildFCmp(ctx->ac.builder, LLVMRealOLT, args[0],
- bld_base->base.zero, "");
+ ctx->ac.f32_0, "");
emit_data->output[emit_data->chan] =
LLVMBuildSelect(ctx->ac.builder, cond, args[1], args[2], "");
pred, emit_data->args[0], emit_data->args[1], "");
emit_data->output[emit_data->chan] = LLVMBuildSelect(ctx->ac.builder,
- cond, bld_base->base.one, bld_base->base.zero, "");
+ cond, ctx->ac.f32_1, ctx->ac.f32_0, "");
}
static void emit_fcmp(const struct lp_build_tgsi_action *action,
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, "");
+ cmp = LLVMBuildFCmp(builder, LLVMRealOGT, emit_data->args[0], ctx->ac.f32_0, "");
+ val = LLVMBuildSelect(builder, cmp, ctx->ac.f32_1, emit_data->args[0], "");
+ cmp = LLVMBuildFCmp(builder, LLVMRealOGE, val, ctx->ac.f32_0, "");
val = LLVMBuildSelect(builder, cmp, val, LLVMConstReal(ctx->f32, -1), "");
}
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildFPToSI(ctx->ac.builder,
- emit_data->args[0], bld_base->int_bld.elem_type, "");
+ emit_data->args[0], ctx->i32, "");
}
static void emit_f2u(const struct lp_build_tgsi_action *action,
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildFPToUI(ctx->ac.builder,
- emit_data->args[0], bld_base->uint_bld.elem_type, "");
+ emit_data->args[0], ctx->i32, "");
}
static void emit_i2f(const struct lp_build_tgsi_action *action,
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildSIToFP(ctx->ac.builder,
- emit_data->args[0], bld_base->base.elem_type, "");
+ emit_data->args[0], ctx->f32, "");
}
static void emit_u2f(const struct lp_build_tgsi_action *action,
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildUIToFP(ctx->ac.builder,
- emit_data->args[0], bld_base->base.elem_type, "");
+ emit_data->args[0], ctx->f32, "");
}
static void
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
- struct gallivm_state *gallivm = bld_base->base.gallivm;
LLVMBuilderRef builder = ctx->ac.builder;
LLVMValueRef bfi_args[3];
LLVMValueRef bfi_sm5;
* 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 = bld_base->base.gallivm;
- 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(ctx->i1, 1, 0)
- };
-
- LLVMValueRef lsb =
- lp_build_intrinsic(ctx->ac.builder, "llvm.cttz.i32",
- emit_data->dst_type, args, ARRAY_SIZE(args),
- LP_FUNC_ATTR_READNONE);
- /* TODO: We need an intrinsic to skip this conditional. */
- /* Check for zero: */
- emit_data->output[emit_data->chan] =
- LLVMBuildSelect(ctx->ac.builder,
- LLVMBuildICmp(ctx->ac.builder, LLVMIntEQ, args[0],
- ctx->i32_0, ""),
- 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_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
- struct lp_build_context *uint_bld = &bld_base->uint_bld;
LLVMTypeRef i16;
LLVMValueRef const16, input, val;
unsigned i;
i16 = LLVMInt16TypeInContext(ctx->ac.context);
- const16 = lp_build_const_int32(uint_bld->gallivm, 16);
+ const16 = LLVMConstInt(ctx->i32, 16, 0);
input = emit_data->args[0];
for (i = 0; i < 2; i++) {
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] =
- LLVMBuildFDiv(ctx->ac.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]);
emit_data->output[emit_data->chan] =
lp_build_emit_llvm_binary(bld_base, TGSI_OPCODE_DIV,
- bld_base->base.one, sqrt);
+ ctx->ac.f32_1, sqrt);
}
static void dfracexp_fetch_args(struct lp_build_tgsi_context *bld_base,