ac: replace ac_build_kill with ac_build_kill_if_false
authorMarek Olšák <marek.olsak@amd.com>
Wed, 4 Oct 2017 02:51:39 +0000 (04:51 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Tue, 24 Oct 2017 12:56:34 +0000 (14:56 +0200)
This will be a new LLVM intrinsic and will also work nicely with
llvm.amdgcn.wqm.vote.

Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/amd/common/ac_llvm_build.c
src/amd/common/ac_llvm_build.h
src/amd/common/ac_nir_to_llvm.c
src/gallium/drivers/radeonsi/si_shader.c
src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c

index 4d8f42d572c27ff488f969519ae78aa9a816e522..5bd0466321687860f4e388d52113c21926aaa0dd 100644 (file)
@@ -1405,20 +1405,13 @@ LLVMValueRef ac_build_cvt_pkrtz_f16(struct ac_llvm_context *ctx,
                                  AC_FUNC_ATTR_LEGACY);
 }
 
-/**
- * KILL, AKA discard in GLSL.
- *
- * \param value  kill if value < 0.0 or value == NULL.
- */
-void ac_build_kill(struct ac_llvm_context *ctx, LLVMValueRef value)
+void ac_build_kill_if_false(struct ac_llvm_context *ctx, LLVMValueRef i1)
 {
-       if (value) {
-               ac_build_intrinsic(ctx, "llvm.AMDGPU.kill", ctx->voidt,
-                                  &value, 1, AC_FUNC_ATTR_LEGACY);
-       } else {
-               ac_build_intrinsic(ctx, "llvm.AMDGPU.kilp", ctx->voidt,
-                                  NULL, 0, AC_FUNC_ATTR_LEGACY);
-       }
+       LLVMValueRef value = LLVMBuildSelect(ctx->builder, i1,
+                                            LLVMConstReal(ctx->f32, 1),
+                                            LLVMConstReal(ctx->f32, -1), "");
+       ac_build_intrinsic(ctx, "llvm.AMDGPU.kill", ctx->voidt,
+                          &value, 1, AC_FUNC_ATTR_LEGACY);
 }
 
 LLVMValueRef ac_build_bfe(struct ac_llvm_context *ctx, LLVMValueRef input,
index aa2a2899ab424b53b8a01dfd2c6b3b355f15bb42..8f7a9abb76cd1bee530a90f485b37e9865ac4500 100644 (file)
@@ -265,7 +265,7 @@ LLVMValueRef ac_build_image_opcode(struct ac_llvm_context *ctx,
                                   struct ac_image_args *a);
 LLVMValueRef ac_build_cvt_pkrtz_f16(struct ac_llvm_context *ctx,
                                    LLVMValueRef args[2]);
-void ac_build_kill(struct ac_llvm_context *ctx, LLVMValueRef value);
+void ac_build_kill_if_false(struct ac_llvm_context *ctx, LLVMValueRef i1);
 LLVMValueRef ac_build_bfe(struct ac_llvm_context *ctx, LLVMValueRef input,
                          LLVMValueRef offset, LLVMValueRef width,
                          bool is_signed);
index 2e50e50b129301a99d478d03aca0b89e59cd4201..4f7e84497253d4e04e37c2d937c1f72c54315620 100644 (file)
@@ -3779,14 +3779,10 @@ static void emit_discard_if(struct ac_nir_context *ctx,
 {
        LLVMValueRef cond;
 
-       cond = LLVMBuildICmp(ctx->ac.builder, LLVMIntNE,
+       cond = LLVMBuildICmp(ctx->ac.builder, LLVMIntEQ,
                             get_src(ctx, instr->src[0]),
                             ctx->ac.i32_0, "");
-
-       cond = LLVMBuildSelect(ctx->ac.builder, cond,
-                              LLVMConstReal(ctx->ac.f32, -1.0f),
-                              ctx->ac.f32_0, "");
-       ac_build_kill(&ctx->ac, cond);
+       ac_build_kill_if_false(&ctx->ac, cond);
 }
 
 static LLVMValueRef
@@ -4021,7 +4017,7 @@ visit_emit_vertex(struct nir_to_llvm_context *ctx,
                  const nir_intrinsic_instr *instr)
 {
        LLVMValueRef gs_next_vertex;
-       LLVMValueRef can_emit, kill;
+       LLVMValueRef can_emit;
        int idx;
 
        assert(instr->const_index[0] == 0);
@@ -4037,11 +4033,7 @@ visit_emit_vertex(struct nir_to_llvm_context *ctx,
         */
        can_emit = LLVMBuildICmp(ctx->builder, LLVMIntULT, gs_next_vertex,
                                 LLVMConstInt(ctx->i32, ctx->gs_max_out_vertices, false), "");
-
-       kill = LLVMBuildSelect(ctx->builder, can_emit,
-                              LLVMConstReal(ctx->f32, 1.0f),
-                              LLVMConstReal(ctx->f32, -1.0f), "");
-       ac_build_kill(&ctx->ac, kill);
+       ac_build_kill_if_false(&ctx->ac, can_emit);
 
        /* loop num outputs */
        idx = 0;
index c3fe13deeaac94cacf3920db0146575cefbdd5c3..8abacac8c8d3e1f6edaeb5a0b3144a38a914f823 100644 (file)
@@ -2272,22 +2272,24 @@ static void si_alpha_test(struct lp_build_tgsi_context *bld_base,
        struct si_shader_context *ctx = si_shader_context(bld_base);
 
        if (ctx->shader->key.part.ps.epilog.alpha_func != PIPE_FUNC_NEVER) {
+               static LLVMRealPredicate cond_map[PIPE_FUNC_ALWAYS + 1] = {
+                       [PIPE_FUNC_LESS] = LLVMRealOLT,
+                       [PIPE_FUNC_EQUAL] = LLVMRealOEQ,
+                       [PIPE_FUNC_LEQUAL] = LLVMRealOLE,
+                       [PIPE_FUNC_GREATER] = LLVMRealOGT,
+                       [PIPE_FUNC_NOTEQUAL] = LLVMRealONE,
+                       [PIPE_FUNC_GEQUAL] = LLVMRealOGE,
+               };
+               LLVMRealPredicate cond = cond_map[ctx->shader->key.part.ps.epilog.alpha_func];
+               assert(cond);
+
                LLVMValueRef alpha_ref = LLVMGetParam(ctx->main_fn,
                                SI_PARAM_ALPHA_REF);
-
                LLVMValueRef alpha_pass =
-                       lp_build_cmp(&bld_base->base,
-                                    ctx->shader->key.part.ps.epilog.alpha_func,
-                                    alpha, alpha_ref);
-               LLVMValueRef arg =
-                       lp_build_select(&bld_base->base,
-                                       alpha_pass,
-                                       LLVMConstReal(ctx->f32, 1.0f),
-                                       LLVMConstReal(ctx->f32, -1.0f));
-
-               ac_build_kill(&ctx->ac, arg);
+                       LLVMBuildFCmp(ctx->ac.builder, cond, alpha, alpha_ref, "");
+               ac_build_kill_if_false(&ctx->ac, alpha_pass);
        } else {
-               ac_build_kill(&ctx->ac, NULL);
+               ac_build_kill_if_false(&ctx->ac, LLVMConstInt(ctx->i1, 0, 0));
        }
 }
 
@@ -3573,7 +3575,7 @@ static void si_llvm_return_fs_outputs(struct ac_shader_abi *abi,
        LLVMValueRef ret;
 
        if (ctx->postponed_kill)
-               ac_build_kill(&ctx->ac, LLVMBuildLoad(builder, ctx->postponed_kill, ""));
+               ac_build_kill_if_false(&ctx->ac, LLVMBuildLoad(builder, ctx->postponed_kill, ""));
 
        /* Read the output values. */
        for (i = 0; i < info->num_outputs; i++) {
@@ -4056,7 +4058,7 @@ static void si_llvm_emit_vertex(
        LLVMValueRef soffset = LLVMGetParam(ctx->main_fn,
                                            ctx->param_gs2vs_offset);
        LLVMValueRef gs_next_vertex;
-       LLVMValueRef can_emit, kill;
+       LLVMValueRef can_emit;
        unsigned chan, offset;
        int i;
        unsigned stream;
@@ -4082,11 +4084,7 @@ static void si_llvm_emit_vertex(
 
        bool use_kill = !info->writes_memory;
        if (use_kill) {
-               kill = lp_build_select(&bld_base->base, can_emit,
-                                      LLVMConstReal(ctx->f32, 1.0f),
-                                      LLVMConstReal(ctx->f32, -1.0f));
-
-               ac_build_kill(&ctx->ac, kill);
+               ac_build_kill_if_false(&ctx->ac, can_emit);
        } else {
                lp_build_if(&if_state, &ctx->gallivm, can_emit);
        }
@@ -4881,11 +4879,7 @@ static void si_llvm_emit_polygon_stipple(struct si_shader_context *ctx,
        row = ac_to_integer(&ctx->ac, row);
        bit = LLVMBuildLShr(builder, row, address[0], "");
        bit = LLVMBuildTrunc(builder, bit, ctx->i1, "");
-
-       /* The intrinsic kills the thread if arg < 0. */
-       bit = LLVMBuildSelect(builder, bit, LLVMConstReal(ctx->f32, 0),
-                             LLVMConstReal(ctx->f32, -1), "");
-       ac_build_kill(&ctx->ac, bit);
+       ac_build_kill_if_false(&ctx->ac, bit);
 }
 
 void si_shader_binary_read_config(struct ac_shader_binary *binary,
@@ -5854,8 +5848,10 @@ static bool si_compile_tgsi_main(struct si_shader_context *ctx,
 
        if (ctx->type == PIPE_SHADER_FRAGMENT && sel->info.uses_kill &&
            ctx->screen->b.debug_flags & DBG(FS_CORRECT_DERIVS_AFTER_KILL)) {
-               /* This is initialized to 0.0 = not kill. */
-               ctx->postponed_kill = lp_build_alloca(&ctx->gallivm, ctx->f32, "");
+               ctx->postponed_kill = lp_build_alloca_undef(&ctx->gallivm, ctx->i1, "");
+               /* true = don't kill. */
+               LLVMBuildStore(ctx->ac.builder, LLVMConstInt(ctx->i1, 1, 0),
+                              ctx->postponed_kill);
        }
 
        if (sel->tokens) {
index fc705c376e52295fdc48123e3c4f9045a0bf0f79..ad7a42f7b84bb2641adba831db5952b10ffa33d0 100644 (file)
@@ -39,20 +39,18 @@ static void kill_if_fetch_args(struct lp_build_tgsi_context *bld_base,
 
        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,
+               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],
-                                       LLVMConstReal(ctx->f32, -1.0f),
-                                       ctx->ac.f32_0, "");
+       emit_data->args[0] = conds[0];
 }
 
 static void kil_emit(const struct lp_build_tgsi_action *action,
@@ -61,31 +59,23 @@ 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 (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->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 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,