ac/nir: handle abs modifier
authorMarek Olšák <marek.olsak@amd.com>
Wed, 24 Jul 2019 21:44:51 +0000 (17:44 -0400)
committerMarek Olšák <marek.olsak@amd.com>
Wed, 31 Jul 2019 02:06:23 +0000 (22:06 -0400)
src/amd/common/ac_nir_to_llvm.c

index f3cb9e879ed8074efbe5bc46147f5040bb735b47..34d9b83e85bcc556fe243bb7bd43925856d63694 100644 (file)
@@ -153,6 +153,12 @@ static LLVMBasicBlockRef get_block(struct ac_nir_context *nir,
        return (LLVMBasicBlockRef)entry->data;
 }
 
+static LLVMValueRef emit_iabs(struct ac_llvm_context *ctx,
+                             LLVMValueRef src0)
+{
+       return ac_build_imax(ctx, src0, LLVMBuildNeg(ctx->builder, src0, ""));
+}
+
 static LLVMValueRef get_alu_src(struct ac_nir_context *ctx,
                                 nir_alu_src src,
                                 unsigned num_components)
@@ -188,18 +194,37 @@ static LLVMValueRef get_alu_src(struct ac_nir_context *ctx,
                }
        }
 
-       if (src.negate) {
-               LLVMTypeRef type = LLVMTypeOf(value);
-               if (LLVMGetTypeKind(type) == LLVMVectorTypeKind)
-                       type = LLVMGetElementType(type);
+       LLVMTypeRef type = LLVMTypeOf(value);
+       if (LLVMGetTypeKind(type) == LLVMVectorTypeKind)
+               type = LLVMGetElementType(type);
+
+       if (src.abs) {
+               if (LLVMGetTypeKind(type) == LLVMIntegerTypeKind) {
+                       value = emit_iabs(&ctx->ac, value);
+               } else {
+                       char name[128];
+                       unsigned fsize = type == ctx->ac.f16 ? 16 :
+                                        type == ctx->ac.f32 ? 32 : 64;
+
+                       if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMVectorTypeKind) {
+                               snprintf(name, sizeof(name), "llvm.fabs.v%uf%u",
+                                        LLVMGetVectorSize(LLVMTypeOf(value)), fsize);
+                       } else {
+                               snprintf(name, sizeof(name), "llvm.fabs.f%u", fsize);
+                       }
+
+                       value = ac_build_intrinsic(&ctx->ac, name, LLVMTypeOf(value),
+                                                  &value, 1, AC_FUNC_ATTR_READNONE);
+               }
+       }
 
+       if (src.negate) {
                if (LLVMGetTypeKind(type) == LLVMIntegerTypeKind)
                        value = LLVMBuildNeg(ctx->ac.builder, value, "");
                else
                        value = LLVMBuildFNeg(ctx->ac.builder, value, "");
        }
 
-       assert(!src.abs);
        return value;
 }
 
@@ -289,12 +314,6 @@ static LLVMValueRef emit_bcsel(struct ac_llvm_context *ctx,
                               ac_to_integer_or_pointer(ctx, src2), "");
 }
 
-static LLVMValueRef emit_iabs(struct ac_llvm_context *ctx,
-                             LLVMValueRef src0)
-{
-       return ac_build_imax(ctx, src0, LLVMBuildNeg(ctx->builder, src0, ""));
-}
-
 static LLVMValueRef emit_uint_carry(struct ac_llvm_context *ctx,
                                    const char *intrin,
                                    LLVMValueRef src0, LLVMValueRef src1)