ac/llvm: consolidate find lsb function.
This was the same between si and ac. Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
@@ -1774,3 +1774,34 @@ void ac_lds_store(struct ac_llvm_context *ctx,
|
|||||||
ac_build_indexed_store(ctx, ctx->lds,
|
ac_build_indexed_store(ctx, ctx->lds,
|
||||||
dw_addr, value);
|
dw_addr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LLVMValueRef ac_find_lsb(struct ac_llvm_context *ctx,
|
||||||
|
LLVMTypeRef dst_type,
|
||||||
|
LLVMValueRef src0)
|
||||||
|
{
|
||||||
|
LLVMValueRef params[2] = {
|
||||||
|
src0,
|
||||||
|
|
||||||
|
/* 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.
|
||||||
|
*
|
||||||
|
* The hardware already implements the correct behavior.
|
||||||
|
*/
|
||||||
|
LLVMConstInt(ctx->i1, 1, false),
|
||||||
|
};
|
||||||
|
|
||||||
|
LLVMValueRef lsb = ac_build_intrinsic(ctx, "llvm.cttz.i32", ctx->i32,
|
||||||
|
params, 2,
|
||||||
|
AC_FUNC_ATTR_READNONE);
|
||||||
|
|
||||||
|
/* TODO: We need an intrinsic to skip this conditional. */
|
||||||
|
/* Check for zero: */
|
||||||
|
return LLVMBuildSelect(ctx->builder, LLVMBuildICmp(ctx->builder,
|
||||||
|
LLVMIntEQ, src0,
|
||||||
|
ctx->i32_0, ""),
|
||||||
|
LLVMConstInt(ctx->i32, -1, 0), lsb, "");
|
||||||
|
}
|
||||||
|
@@ -297,6 +297,10 @@ LLVMValueRef ac_lds_load(struct ac_llvm_context *ctx,
|
|||||||
LLVMValueRef dw_addr);
|
LLVMValueRef dw_addr);
|
||||||
void ac_lds_store(struct ac_llvm_context *ctx,
|
void ac_lds_store(struct ac_llvm_context *ctx,
|
||||||
LLVMValueRef dw_addr, LLVMValueRef value);
|
LLVMValueRef dw_addr, LLVMValueRef value);
|
||||||
|
|
||||||
|
LLVMValueRef ac_find_lsb(struct ac_llvm_context *ctx,
|
||||||
|
LLVMTypeRef dst_type,
|
||||||
|
LLVMValueRef src0);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1227,34 +1227,6 @@ static LLVMValueRef emit_bcsel(struct ac_llvm_context *ctx,
|
|||||||
return LLVMBuildSelect(ctx->builder, v, src1, src2, "");
|
return LLVMBuildSelect(ctx->builder, v, src1, src2, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
static LLVMValueRef emit_find_lsb(struct ac_llvm_context *ctx,
|
|
||||||
LLVMValueRef src0)
|
|
||||||
{
|
|
||||||
LLVMValueRef params[2] = {
|
|
||||||
src0,
|
|
||||||
|
|
||||||
/* 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.
|
|
||||||
*
|
|
||||||
* The hardware already implements the correct behavior.
|
|
||||||
*/
|
|
||||||
LLVMConstInt(ctx->i1, 1, false),
|
|
||||||
};
|
|
||||||
|
|
||||||
LLVMValueRef lsb = ac_build_intrinsic(ctx, "llvm.cttz.i32", ctx->i32,
|
|
||||||
params, 2,
|
|
||||||
AC_FUNC_ATTR_READNONE);
|
|
||||||
|
|
||||||
/* TODO: We need an intrinsic to skip this conditional. */
|
|
||||||
/* Check for zero: */
|
|
||||||
return LLVMBuildSelect(ctx->builder, LLVMBuildICmp(ctx->builder,
|
|
||||||
LLVMIntEQ, src0,
|
|
||||||
ctx->i32_0, ""),
|
|
||||||
LLVMConstInt(ctx->i32, -1, 0), lsb, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
static LLVMValueRef emit_ifind_msb(struct ac_llvm_context *ctx,
|
static LLVMValueRef emit_ifind_msb(struct ac_llvm_context *ctx,
|
||||||
LLVMValueRef src0)
|
LLVMValueRef src0)
|
||||||
{
|
{
|
||||||
@@ -1895,7 +1867,7 @@ static void visit_alu(struct ac_nir_context *ctx, const nir_alu_instr *instr)
|
|||||||
break;
|
break;
|
||||||
case nir_op_find_lsb:
|
case nir_op_find_lsb:
|
||||||
src[0] = ac_to_integer(&ctx->ac, src[0]);
|
src[0] = ac_to_integer(&ctx->ac, src[0]);
|
||||||
result = emit_find_lsb(&ctx->ac, src[0]);
|
result = ac_find_lsb(&ctx->ac, ctx->ac.i32, src[0]);
|
||||||
break;
|
break;
|
||||||
case nir_op_ufind_msb:
|
case nir_op_ufind_msb:
|
||||||
src[0] = ac_to_integer(&ctx->ac, src[0]);
|
src[0] = ac_to_integer(&ctx->ac, src[0]);
|
||||||
|
@@ -535,31 +535,8 @@ static void emit_lsb(const struct lp_build_tgsi_action *action,
|
|||||||
struct lp_build_emit_data *emit_data)
|
struct lp_build_emit_data *emit_data)
|
||||||
{
|
{
|
||||||
struct si_shader_context *ctx = si_shader_context(bld_base);
|
struct si_shader_context *ctx = si_shader_context(bld_base);
|
||||||
LLVMValueRef args[2] = {
|
|
||||||
emit_data->args[0],
|
|
||||||
|
|
||||||
/* The value of 1 means that ffs(x=0) = undef, so LLVM won't
|
emit_data->output[emit_data->chan] = ac_find_lsb(&ctx->ac, emit_data->dst_type, emit_data->args[0]);
|
||||||
* 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, ""),
|
|
||||||
LLVMConstInt(ctx->i32, -1, 0), lsb, "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the last bit set. */
|
/* Find the last bit set. */
|
||||||
|
Reference in New Issue
Block a user