ac/llvm: add better code for isign
authorMarek Olšák <marek.olsak@amd.com>
Thu, 3 Sep 2020 09:51:17 +0000 (05:51 -0400)
committerVivek Pandya <vivekvpandya@gmail.com>
Mon, 7 Sep 2020 15:55:16 +0000 (21:25 +0530)
There are 2 improvements:
- select v_med3_i32
- support vectors

Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6284>

src/amd/llvm/ac_llvm_build.c
src/amd/llvm/ac_llvm_build.h
src/amd/llvm/ac_nir_to_llvm.c

index de9091693c1916fd377e30e777b1ef5cce6422f8..a3fa30fc003b36fc4dcf775f95ea72c906e6c97f 100644 (file)
@@ -2751,19 +2751,29 @@ LLVMValueRef ac_build_fract(struct ac_llvm_context *ctx, LLVMValueRef src0,
                                  AC_FUNC_ATTR_READNONE);
 }
 
-LLVMValueRef ac_build_isign(struct ac_llvm_context *ctx, LLVMValueRef src0,
-                           unsigned bitsize)
+static LLVMValueRef ac_const_uint_vec(struct ac_llvm_context *ctx, LLVMTypeRef type, uint64_t value)
 {
-       LLVMTypeRef type = LLVMIntTypeInContext(ctx->context, bitsize);
-       LLVMValueRef zero = LLVMConstInt(type, 0, false);
-       LLVMValueRef one = LLVMConstInt(type, 1, false);
 
-       LLVMValueRef cmp, val;
-       cmp = LLVMBuildICmp(ctx->builder, LLVMIntSGT, src0, zero, "");
-       val = LLVMBuildSelect(ctx->builder, cmp, one, src0, "");
-       cmp = LLVMBuildICmp(ctx->builder, LLVMIntSGE, val, zero, "");
-       val = LLVMBuildSelect(ctx->builder, cmp, val, LLVMConstInt(type, -1, true), "");
-       return val;
+       if (LLVMGetTypeKind(type) == LLVMVectorTypeKind) {
+               LLVMValueRef scalar = LLVMConstInt(LLVMGetElementType(type), value, 0);
+               unsigned vec_size = LLVMGetVectorSize(type);
+               LLVMValueRef *scalars = alloca(vec_size * sizeof(LLVMValueRef*));
+
+               for (unsigned i = 0; i < vec_size; i++)
+                       scalars[i] = scalar;
+               return LLVMConstVector(scalars, vec_size);
+       }
+       return LLVMConstInt(type, value, 0);
+}
+
+LLVMValueRef ac_build_isign(struct ac_llvm_context *ctx, LLVMValueRef src0)
+{
+       LLVMTypeRef type = LLVMTypeOf(src0);
+       LLVMValueRef val;
+
+       /* v_med3 is selected only when max is first. (LLVM bug?) */
+       val = ac_build_imax(ctx, src0, ac_const_uint_vec(ctx, type, -1));
+       return ac_build_imin(ctx, val, ac_const_uint_vec(ctx, type, 1));
 }
 
 LLVMValueRef ac_build_fsign(struct ac_llvm_context *ctx, LLVMValueRef src0,
index 764b0565a66cd85d9d44577363f7eca5fc95559f..7cb98d06a6eb791fd7b53402fd1ba95450e2fd4e 100644 (file)
@@ -597,10 +597,7 @@ void ac_build_waitcnt(struct ac_llvm_context *ctx, unsigned wait_flags);
 
 LLVMValueRef ac_build_fract(struct ac_llvm_context *ctx, LLVMValueRef src0,
                           unsigned bitsize);
-
-LLVMValueRef ac_build_isign(struct ac_llvm_context *ctx, LLVMValueRef src0,
-                           unsigned bitsize);
-
+LLVMValueRef ac_build_isign(struct ac_llvm_context *ctx, LLVMValueRef src0);
 LLVMValueRef ac_build_fsign(struct ac_llvm_context *ctx, LLVMValueRef src0,
                            unsigned bitsize);
 
index 9ad16fba8d340ed49c2f66e0be38964afd45310a..ddea78180b1462b6685552d3c7f829091a5b37e9 100644 (file)
@@ -822,8 +822,7 @@ static void visit_alu(struct ac_nir_context *ctx, const nir_alu_instr *instr)
                result = ac_build_umin(&ctx->ac, src[0], src[1]);
                break;
        case nir_op_isign:
-               result = ac_build_isign(&ctx->ac, src[0],
-                                       instr->dest.dest.ssa.bit_size);
+               result = ac_build_isign(&ctx->ac, src[0]);
                break;
        case nir_op_fsign:
                src[0] = ac_to_float(&ctx->ac, src[0]);