From 1ff9e27cbdd1fe770f18e5316c6f32a867e39095 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Wed, 4 Oct 2017 04:51:39 +0200 Subject: [PATCH] ac: replace ac_build_kill with ac_build_kill_if_false MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This will be a new LLVM intrinsic and will also work nicely with llvm.amdgcn.wqm.vote. Reviewed-by: Nicolai Hähnle --- src/amd/common/ac_llvm_build.c | 19 +++----- src/amd/common/ac_llvm_build.h | 2 +- src/amd/common/ac_nir_to_llvm.c | 16 ++----- src/gallium/drivers/radeonsi/si_shader.c | 48 +++++++++---------- .../drivers/radeonsi/si_shader_tgsi_alu.c | 42 +++++++--------- 5 files changed, 49 insertions(+), 78 deletions(-) diff --git a/src/amd/common/ac_llvm_build.c b/src/amd/common/ac_llvm_build.c index 4d8f42d572c..5bd04663216 100644 --- a/src/amd/common/ac_llvm_build.c +++ b/src/amd/common/ac_llvm_build.c @@ -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, diff --git a/src/amd/common/ac_llvm_build.h b/src/amd/common/ac_llvm_build.h index aa2a2899ab4..8f7a9abb76c 100644 --- a/src/amd/common/ac_llvm_build.h +++ b/src/amd/common/ac_llvm_build.h @@ -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); diff --git a/src/amd/common/ac_nir_to_llvm.c b/src/amd/common/ac_nir_to_llvm.c index 2e50e50b129..4f7e8449725 100644 --- a/src/amd/common/ac_nir_to_llvm.c +++ b/src/amd/common/ac_nir_to_llvm.c @@ -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; diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index c3fe13deeaa..8abacac8c8d 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -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) { diff --git a/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c b/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c index fc705c376e5..ad7a42f7b84 100644 --- a/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c +++ b/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c @@ -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, -- 2.30.2