ac: add support for trinary_minmax instructions
authorDaniel Schürmann <daniel.schuermann@campus.tu-berlin.de>
Thu, 8 Mar 2018 21:45:04 +0000 (22:45 +0100)
committerBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Wed, 28 Mar 2018 23:29:35 +0000 (01:29 +0200)
v2: Add missing break (Bas)

Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
src/amd/common/ac_nir_to_llvm.c

index 2da73a7bfb1a8aba3070f2955cc01bd51135640b..7efbe4b31aa07030cd65106b63493eb19bcc5150 100644 (file)
@@ -963,6 +963,60 @@ static void visit_alu(struct ac_nir_context *ctx, const nir_alu_instr *instr)
                break;
        }
 
+       case nir_op_fmin3:
+               result = emit_intrin_2f_param(&ctx->ac, "llvm.minnum",
+                                               ac_to_float_type(&ctx->ac, def_type), src[0], src[1]);
+               result = emit_intrin_2f_param(&ctx->ac, "llvm.minnum",
+                                               ac_to_float_type(&ctx->ac, def_type), result, src[2]);
+               break;
+       case nir_op_umin3:
+               result = emit_minmax_int(&ctx->ac, LLVMIntULT, src[0], src[1]);
+               result = emit_minmax_int(&ctx->ac, LLVMIntULT, result, src[2]);
+               break;
+       case nir_op_imin3:
+               result = emit_minmax_int(&ctx->ac, LLVMIntSLT, src[0], src[1]);
+               result = emit_minmax_int(&ctx->ac, LLVMIntSLT, result, src[2]);
+               break;
+       case nir_op_fmax3:
+               result = emit_intrin_2f_param(&ctx->ac, "llvm.maxnum",
+                                               ac_to_float_type(&ctx->ac, def_type), src[0], src[1]);
+               result = emit_intrin_2f_param(&ctx->ac, "llvm.maxnum",
+                                               ac_to_float_type(&ctx->ac, def_type), result, src[2]);
+               break;
+       case nir_op_umax3:
+               result = emit_minmax_int(&ctx->ac, LLVMIntUGT, src[0], src[1]);
+               result = emit_minmax_int(&ctx->ac, LLVMIntUGT, result, src[2]);
+               break;
+       case nir_op_imax3:
+               result = emit_minmax_int(&ctx->ac, LLVMIntSGT, src[0], src[1]);
+               result = emit_minmax_int(&ctx->ac, LLVMIntSGT, result, src[2]);
+               break;
+       case nir_op_fmed3: {
+               LLVMValueRef tmp1 = emit_intrin_2f_param(&ctx->ac, "llvm.minnum",
+                                               ac_to_float_type(&ctx->ac, def_type), src[0], src[1]);
+               LLVMValueRef tmp2 = emit_intrin_2f_param(&ctx->ac, "llvm.maxnum",
+                                               ac_to_float_type(&ctx->ac, def_type), src[0], src[1]);
+               tmp2 = emit_intrin_2f_param(&ctx->ac, "llvm.minnum",
+                                               ac_to_float_type(&ctx->ac, def_type), tmp2, src[2]);
+               result = emit_intrin_2f_param(&ctx->ac, "llvm.maxnum",
+                                               ac_to_float_type(&ctx->ac, def_type), tmp1, tmp2);
+               break;
+       }
+       case nir_op_imed3: {
+               LLVMValueRef tmp1 = emit_minmax_int(&ctx->ac, LLVMIntSLT, src[0], src[1]);
+               LLVMValueRef tmp2 = emit_minmax_int(&ctx->ac, LLVMIntSGT, src[0], src[1]);
+               tmp2 = emit_minmax_int(&ctx->ac, LLVMIntSLT, tmp2, src[2]);
+               result = emit_minmax_int(&ctx->ac, LLVMIntSGT, tmp1, tmp2);
+               break;
+       }
+       case nir_op_umed3: {
+               LLVMValueRef tmp1 = emit_minmax_int(&ctx->ac, LLVMIntULT, src[0], src[1]);
+               LLVMValueRef tmp2 = emit_minmax_int(&ctx->ac, LLVMIntUGT, src[0], src[1]);
+               tmp2 = emit_minmax_int(&ctx->ac, LLVMIntULT, tmp2, src[2]);
+               result = emit_minmax_int(&ctx->ac, LLVMIntUGT, tmp1, tmp2);
+               break;
+       }
+
        default:
                fprintf(stderr, "Unknown NIR alu instr: ");
                nir_print_instr(&instr->instr, stderr);