From 049b60cf4bd2b16667a9d85ebe8a110a24236bc3 Mon Sep 17 00:00:00 2001 From: Georg Lehmann Date: Tue, 4 Oct 2022 15:24:59 +0200 Subject: [PATCH] ac/llvm: Implement [ui]find_msb_rev. Signed-off-by: Georg Lehmann Reviewed-by: Rhys Perry Part-of: --- src/amd/llvm/ac_llvm_build.c | 11 +++++++---- src/amd/llvm/ac_llvm_build.h | 3 ++- src/amd/llvm/ac_nir_to_llvm.c | 13 ++++++++++--- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/amd/llvm/ac_llvm_build.c b/src/amd/llvm/ac_llvm_build.c index 3f7159bb56e..0758fee8b01 100644 --- a/src/amd/llvm/ac_llvm_build.c +++ b/src/amd/llvm/ac_llvm_build.c @@ -1877,7 +1877,8 @@ LLVMValueRef ac_build_imsb(struct ac_llvm_context *ctx, LLVMValueRef arg, LLVMTy return LLVMBuildSelect(ctx->builder, cond, all_ones, msb, ""); } -LLVMValueRef ac_build_umsb(struct ac_llvm_context *ctx, LLVMValueRef arg, LLVMTypeRef dst_type) +LLVMValueRef ac_build_umsb(struct ac_llvm_context *ctx, LLVMValueRef arg, LLVMTypeRef dst_type, + bool rev) { const char *intrin_name; LLVMTypeRef type; @@ -1923,9 +1924,11 @@ LLVMValueRef ac_build_umsb(struct ac_llvm_context *ctx, LLVMValueRef arg, LLVMTy LLVMValueRef msb = ac_build_intrinsic(ctx, intrin_name, type, params, 2, AC_FUNC_ATTR_READNONE); - /* The HW returns the last bit index from MSB, but TGSI/NIR wants - * the index from LSB. Invert it by doing "31 - msb". */ - msb = LLVMBuildSub(ctx->builder, highest_bit, msb, ""); + if (!rev) { + /* The HW returns the last bit index from MSB, but TGSI/NIR wants + * the index from LSB. Invert it by doing "31 - msb". */ + msb = LLVMBuildSub(ctx->builder, highest_bit, msb, ""); + } if (bitsize == 64) { msb = LLVMBuildTrunc(ctx->builder, msb, ctx->i32, ""); diff --git a/src/amd/llvm/ac_llvm_build.h b/src/amd/llvm/ac_llvm_build.h index d3f2ea99a2c..cf06fba1a4f 100644 --- a/src/amd/llvm/ac_llvm_build.h +++ b/src/amd/llvm/ac_llvm_build.h @@ -340,7 +340,8 @@ void ac_build_sendmsg(struct ac_llvm_context *ctx, uint32_t msg, LLVMValueRef wa LLVMValueRef ac_build_imsb(struct ac_llvm_context *ctx, LLVMValueRef arg, LLVMTypeRef dst_type); -LLVMValueRef ac_build_umsb(struct ac_llvm_context *ctx, LLVMValueRef arg, LLVMTypeRef dst_type); +LLVMValueRef ac_build_umsb(struct ac_llvm_context *ctx, LLVMValueRef arg, LLVMTypeRef dst_type, + bool rev); LLVMValueRef ac_build_fmin(struct ac_llvm_context *ctx, LLVMValueRef a, LLVMValueRef b); LLVMValueRef ac_build_fmax(struct ac_llvm_context *ctx, LLVMValueRef a, LLVMValueRef b); LLVMValueRef ac_build_imin(struct ac_llvm_context *ctx, LLVMValueRef a, LLVMValueRef b); diff --git a/src/amd/llvm/ac_nir_to_llvm.c b/src/amd/llvm/ac_nir_to_llvm.c index 17cbeeaa082..9ab8d0d58a4 100644 --- a/src/amd/llvm/ac_nir_to_llvm.c +++ b/src/amd/llvm/ac_nir_to_llvm.c @@ -1072,19 +1072,26 @@ static bool visit_alu(struct ac_nir_context *ctx, const nir_alu_instr *instr) result = ac_find_lsb(&ctx->ac, ctx->ac.i32, src[0]); break; case nir_op_ufind_msb: - result = ac_build_umsb(&ctx->ac, src[0], ctx->ac.i32); + result = ac_build_umsb(&ctx->ac, src[0], ctx->ac.i32, false); break; case nir_op_ifind_msb: result = ac_build_imsb(&ctx->ac, src[0], ctx->ac.i32); break; - case nir_op_uclz: { + case nir_op_ufind_msb_rev: + result = ac_build_umsb(&ctx->ac, src[0], ctx->ac.i32, true); + break; + case nir_op_ifind_msb_rev: + result = ac_build_intrinsic(&ctx->ac, "llvm.amdgcn.sffbh.i32", ctx->ac.i32, &src[0], 1, + AC_FUNC_ATTR_READNONE); + break; + case nir_op_uclz: { LLVMValueRef params[2] = { src[0], ctx->ac.i1false, }; result = ac_build_intrinsic(&ctx->ac, "llvm.ctlz.i32", ctx->ac.i32, params, 2, AC_FUNC_ATTR_READNONE); break; - } + } case nir_op_uadd_carry: result = emit_uint_carry(&ctx->ac, "llvm.uadd.with.overflow.i32", src[0], src[1]); break;