ac: replace ac_build_kill with ac_build_kill_if_false

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>
This commit is contained in:
Marek Olšák
2017-10-04 04:51:39 +02:00
parent f0a2bbd1a4
commit 1ff9e27cbd
5 changed files with 49 additions and 78 deletions

View 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,

View 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);

View 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;

View 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) {

View 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,