[llvm] [NFC][AMDGPU] Pre-commit tests for IR variant - isFMAFasterThanFMulAdd (PR #121925)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 7 04:41:16 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-amdgpu

Author: Chinmay Deshpande (chinmaydd)

<details>
<summary>Changes</summary>



---

Patch is 22.44 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/121925.diff


1 Files Affected:

- (added) llvm/test/CodeGen/AMDGPU/prevent-fmul-hoist-ir.ll (+447) 


``````````diff
diff --git a/llvm/test/CodeGen/AMDGPU/prevent-fmul-hoist-ir.ll b/llvm/test/CodeGen/AMDGPU/prevent-fmul-hoist-ir.ll
new file mode 100644
index 00000000000000..6644488ef9375b
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/prevent-fmul-hoist-ir.ll
@@ -0,0 +1,447 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes='simplifycfg<hoist-common-insts>' -mtriple=amdgcn-- --fp-contract=fast -mcpu=gfx1030 < %s | FileCheck -check-prefix=GFX -check-prefix=FP-CONTRACT-FAST %s
+; RUN: opt -S -passes='simplifycfg<hoist-common-insts>' -mtriple=amdgcn-- --fp-contract=off --enable-unsafe-fp-math -mcpu=gfx1030 < %s | FileCheck -check-prefix=GFX -check-prefix=UNSAFE-FP-MATH %s
+; RUN: opt -S -passes='simplifycfg<hoist-common-insts>' -mtriple=amdgcn-- --fp-contract=off -mcpu=gfx1030 < %s | FileCheck -check-prefix=GFX -check-prefix=NO-UNSAFE-FP-MATH %s
+
+define double @is_profitable_f64_contract(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) #0 {
+; GFX-LABEL: define double @is_profitable_f64_contract(
+; GFX-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR0:[0-9]+]] {
+; GFX-NEXT:  [[ENTRY:.*:]]
+; GFX-NEXT:    [[Y:%.*]] = load double, ptr [[PTR_Y]], align 8
+; GFX-NEXT:    [[CMP:%.*]] = fcmp oeq double [[Y]], 0.000000e+00
+; GFX-NEXT:    [[X:%.*]] = load double, ptr [[PTR_X]], align 8
+; GFX-NEXT:    [[A_1:%.*]] = load double, ptr [[PTR_A]], align 8
+; GFX-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; GFX:       [[COMMON_RET:.*]]:
+; GFX-NEXT:    [[COMMON_RET_OP:%.*]] = phi double [ [[ADD:%.*]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
+; GFX-NEXT:    ret double [[COMMON_RET_OP]]
+; GFX:       [[IF_THEN]]:
+; GFX-NEXT:    [[MUL:%.*]] = fmul contract double [[X]], [[A_1]]
+; GFX-NEXT:    [[ADD]] = fadd contract double 1.000000e+00, [[MUL]]
+; GFX-NEXT:    br label %[[COMMON_RET]]
+; GFX:       [[IF_ELSE]]:
+; GFX-NEXT:    [[MUL1:%.*]] = fmul contract double [[X]], [[A_1]]
+; GFX-NEXT:    [[SUB]] = fsub contract double [[MUL1]], [[Y]]
+; GFX-NEXT:    br label %[[COMMON_RET]]
+;
+entry:
+  %y = load double, ptr %ptr_y, align 8
+  %cmp = fcmp oeq double %y, 0.000000e+00
+  %x = load double, ptr %ptr_x, align 8
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %a_1 = load double, ptr %ptr_a, align 8
+  %mul = fmul contract double %x, %a_1
+  %add = fadd contract double 1.000000e+00, %mul
+  ret double %add
+
+if.else:                                          ; preds = %entry
+  %a_2 = load double, ptr %ptr_a, align 8
+  %mul1 = fmul contract double %x, %a_2
+  %sub = fsub contract double %mul1, %y
+  ret double %sub
+}
+
+define double @is_profitable_f64_modifiers(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) #0 {
+; GFX-LABEL: define double @is_profitable_f64_modifiers(
+; GFX-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR0]] {
+; GFX-NEXT:  [[ENTRY:.*:]]
+; GFX-NEXT:    [[Y:%.*]] = load double, ptr [[PTR_Y]], align 8
+; GFX-NEXT:    [[CMP:%.*]] = fcmp oeq double [[Y]], 0.000000e+00
+; GFX-NEXT:    [[X:%.*]] = load double, ptr [[PTR_X]], align 8
+; GFX-NEXT:    [[A_1:%.*]] = load double, ptr [[PTR_A]], align 8
+; GFX-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; GFX:       [[COMMON_RET:.*]]:
+; GFX-NEXT:    [[COMMON_RET_OP:%.*]] = phi double [ [[FNEG:%.*]], %[[IF_THEN]] ], [ [[FABS:%.*]], %[[IF_ELSE]] ]
+; GFX-NEXT:    ret double [[COMMON_RET_OP]]
+; GFX:       [[IF_THEN]]:
+; GFX-NEXT:    [[MUL:%.*]] = fmul contract double [[X]], [[A_1]]
+; GFX-NEXT:    [[ADD:%.*]] = fadd contract double 1.000000e+00, [[MUL]]
+; GFX-NEXT:    [[FNEG]] = fneg double [[ADD]]
+; GFX-NEXT:    br label %[[COMMON_RET]]
+; GFX:       [[IF_ELSE]]:
+; GFX-NEXT:    [[MUL1:%.*]] = fmul contract double [[X]], [[A_1]]
+; GFX-NEXT:    [[SUB:%.*]] = fsub contract double [[MUL1]], [[Y]]
+; GFX-NEXT:    [[FABS]] = call double @llvm.fabs.f64(double [[SUB]])
+; GFX-NEXT:    br label %[[COMMON_RET]]
+;
+entry:
+  %y = load double, ptr %ptr_y, align 8
+  %cmp = fcmp oeq double %y, 0.000000e+00
+  %x = load double, ptr %ptr_x, align 8
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %a_1 = load double, ptr %ptr_a, align 8
+  %mul = fmul contract double %x, %a_1
+  %add = fadd contract double 1.000000e+00, %mul
+  %fneg = fneg double %add
+  ret double %fneg
+
+if.else:                                          ; preds = %entry
+  %a_2 = load double, ptr %ptr_a, align 8
+  %mul1 = fmul contract double %x, %a_2
+  %sub = fsub contract double %mul1, %y
+  %fabs = call double @llvm.fabs.f64(double %sub)
+  ret double %fabs
+}
+
+define float @is_profitable_f32(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) #0 {
+; GFX-LABEL: define float @is_profitable_f32(
+; GFX-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR0]] {
+; GFX-NEXT:  [[ENTRY:.*:]]
+; GFX-NEXT:    [[Y:%.*]] = load float, ptr [[PTR_Y]], align 8
+; GFX-NEXT:    [[CMP:%.*]] = fcmp oeq float [[Y]], 0.000000e+00
+; GFX-NEXT:    [[X:%.*]] = load float, ptr [[PTR_X]], align 8
+; GFX-NEXT:    [[A_1:%.*]] = load float, ptr [[PTR_A]], align 8
+; GFX-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; GFX:       [[COMMON_RET:.*]]:
+; GFX-NEXT:    [[COMMON_RET_OP:%.*]] = phi float [ [[MUL:%.*]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
+; GFX-NEXT:    ret float [[COMMON_RET_OP]]
+; GFX:       [[IF_THEN]]:
+; GFX-NEXT:    [[MUL]] = fmul contract float [[X]], [[A_1]]
+; GFX-NEXT:    [[ADD:%.*]] = fadd contract float 1.000000e+00, [[MUL]]
+; GFX-NEXT:    br label %[[COMMON_RET]]
+; GFX:       [[IF_ELSE]]:
+; GFX-NEXT:    [[MUL1:%.*]] = fmul contract float [[X]], [[A_1]]
+; GFX-NEXT:    [[SUB]] = fsub contract float [[MUL1]], [[Y]]
+; GFX-NEXT:    br label %[[COMMON_RET]]
+;
+entry:
+  %y = load float, ptr %ptr_y, align 8
+  %cmp = fcmp oeq float %y, 0.000000e+00
+  %x = load float, ptr %ptr_x, align 8
+  br i1 %cmp, label %if.then, label %if.else
+
+
+if.then:                                          ; preds = %entry
+  %a_1 = load float, ptr %ptr_a, align 8
+  %mul = fmul contract float %x, %a_1
+  %add = fadd contract float 1.000000e+00, %mul
+  ret float %mul
+
+if.else:                                          ; preds = %entry
+  %a_2 = load float, ptr %ptr_a, align 8
+  %mul1 = fmul contract float %x, %a_2
+  %sub = fsub contract float %mul1, %y
+  ret float %sub
+}
+
+define half @is_profitable_f16_preserve(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) #0 {
+; GFX-LABEL: define half @is_profitable_f16_preserve(
+; GFX-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR0]] {
+; GFX-NEXT:  [[ENTRY:.*:]]
+; GFX-NEXT:    [[Y:%.*]] = load half, ptr [[PTR_Y]], align 8
+; GFX-NEXT:    [[CMP:%.*]] = fcmp oeq half [[Y]], 0xH0000
+; GFX-NEXT:    [[X:%.*]] = load half, ptr [[PTR_X]], align 8
+; GFX-NEXT:    [[A_1:%.*]] = load half, ptr [[PTR_A]], align 8
+; GFX-NEXT:    [[MUL:%.*]] = fmul contract half [[X]], [[A_1]]
+; GFX-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; GFX:       [[COMMON_RET:.*]]:
+; GFX-NEXT:    [[COMMON_RET_OP:%.*]] = phi half [ [[MUL]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
+; GFX-NEXT:    ret half [[COMMON_RET_OP]]
+; GFX:       [[IF_THEN]]:
+; GFX-NEXT:    [[ADD:%.*]] = fadd contract half [[Y]], [[MUL]]
+; GFX-NEXT:    br label %[[COMMON_RET]]
+; GFX:       [[IF_ELSE]]:
+; GFX-NEXT:    [[SUB]] = fsub contract half [[MUL]], [[Y]]
+; GFX-NEXT:    br label %[[COMMON_RET]]
+;
+entry:
+  %y = load half, ptr %ptr_y, align 8
+  %cmp = fcmp oeq half %y, 0.000000e+00
+  %x = load half, ptr %ptr_x, align 8
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %a_1 = load half, ptr %ptr_a, align 8
+  %mul = fmul contract half %x, %a_1
+  %add = fadd contract half %y, %mul
+  ret half %mul
+
+if.else:                                          ; preds = %entry
+  %a_2 = load half, ptr %ptr_a, align 8
+  %mul1 = fmul contract half %x, %a_2
+  %sub = fsub contract half %mul1, %y
+  ret half %sub
+}
+
+define half @is_profitable_f16_ieee(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) #1 {
+; GFX-LABEL: define half @is_profitable_f16_ieee(
+; GFX-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR1:[0-9]+]] {
+; GFX-NEXT:  [[ENTRY:.*:]]
+; GFX-NEXT:    [[Y:%.*]] = load half, ptr [[PTR_Y]], align 8
+; GFX-NEXT:    [[CMP:%.*]] = fcmp oeq half [[Y]], 0xH0000
+; GFX-NEXT:    [[X:%.*]] = load half, ptr [[PTR_X]], align 8
+; GFX-NEXT:    [[A_1:%.*]] = load half, ptr [[PTR_A]], align 8
+; GFX-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; GFX:       [[COMMON_RET:.*]]:
+; GFX-NEXT:    [[COMMON_RET_OP:%.*]] = phi half [ [[MUL:%.*]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
+; GFX-NEXT:    ret half [[COMMON_RET_OP]]
+; GFX:       [[IF_THEN]]:
+; GFX-NEXT:    [[MUL]] = fmul contract half [[X]], [[A_1]]
+; GFX-NEXT:    [[ADD:%.*]] = fadd contract half [[Y]], [[MUL]]
+; GFX-NEXT:    br label %[[COMMON_RET]]
+; GFX:       [[IF_ELSE]]:
+; GFX-NEXT:    [[MUL1:%.*]] = fmul contract half [[X]], [[A_1]]
+; GFX-NEXT:    [[SUB]] = fsub contract half [[MUL1]], [[Y]]
+; GFX-NEXT:    br label %[[COMMON_RET]]
+;
+entry:
+  %y = load half, ptr %ptr_y, align 8
+  %cmp = fcmp oeq half %y, 0.000000e+00
+  %x = load half, ptr %ptr_x, align 8
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %a_1 = load half, ptr %ptr_a, align 8
+  %mul = fmul contract half %x, %a_1
+  %add = fadd contract half %y, %mul
+  ret half %mul
+
+if.else:                                          ; preds = %entry
+  %a_2 = load half, ptr %ptr_a, align 8
+  %mul1 = fmul contract half %x, %a_2
+  %sub = fsub contract half %mul1, %y
+  ret half %sub
+}
+
+define bfloat @is_profitable_bfloat_preserve(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) #0 {
+; GFX-LABEL: define bfloat @is_profitable_bfloat_preserve(
+; GFX-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR0]] {
+; GFX-NEXT:  [[ENTRY:.*:]]
+; GFX-NEXT:    [[Y:%.*]] = load bfloat, ptr [[PTR_Y]], align 8
+; GFX-NEXT:    [[CMP:%.*]] = fcmp oeq bfloat [[Y]], 0xR0000
+; GFX-NEXT:    [[X:%.*]] = load bfloat, ptr [[PTR_X]], align 8
+; GFX-NEXT:    [[A_1:%.*]] = load bfloat, ptr [[PTR_A]], align 8
+; GFX-NEXT:    [[MUL:%.*]] = fmul contract bfloat [[X]], [[A_1]]
+; GFX-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; GFX:       [[COMMON_RET:.*]]:
+; GFX-NEXT:    [[COMMON_RET_OP:%.*]] = phi bfloat [ [[MUL]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
+; GFX-NEXT:    ret bfloat [[COMMON_RET_OP]]
+; GFX:       [[IF_THEN]]:
+; GFX-NEXT:    [[ADD:%.*]] = fadd contract bfloat 0xR3F80, [[MUL]]
+; GFX-NEXT:    br label %[[COMMON_RET]]
+; GFX:       [[IF_ELSE]]:
+; GFX-NEXT:    [[SUB]] = fsub contract bfloat [[MUL]], [[Y]]
+; GFX-NEXT:    br label %[[COMMON_RET]]
+;
+entry:
+  %y = load bfloat, ptr %ptr_y, align 8
+  %cmp = fcmp oeq bfloat %y, 0.000000e+00
+  %x = load bfloat, ptr %ptr_x, align 8
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %a_1 = load bfloat, ptr %ptr_a, align 8
+  %mul = fmul contract bfloat %x, %a_1
+  %add = fadd contract bfloat 1.000000e+00, %mul
+  ret bfloat %mul
+
+if.else:                                          ; preds = %entry
+  %a_2 = load bfloat, ptr %ptr_a, align 8
+  %mul1 = fmul contract bfloat %x, %a_2
+  %sub = fsub contract bfloat %mul1, %y
+  ret bfloat %sub
+}
+
+define bfloat @is_profitable_bfloat_ieee(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) #1 {
+; GFX-LABEL: define bfloat @is_profitable_bfloat_ieee(
+; GFX-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR1]] {
+; GFX-NEXT:  [[ENTRY:.*:]]
+; GFX-NEXT:    [[Y:%.*]] = load bfloat, ptr [[PTR_Y]], align 8
+; GFX-NEXT:    [[CMP:%.*]] = fcmp oeq bfloat [[Y]], 0xR0000
+; GFX-NEXT:    [[X:%.*]] = load bfloat, ptr [[PTR_X]], align 8
+; GFX-NEXT:    [[A_1:%.*]] = load bfloat, ptr [[PTR_A]], align 8
+; GFX-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; GFX:       [[COMMON_RET:.*]]:
+; GFX-NEXT:    [[COMMON_RET_OP:%.*]] = phi bfloat [ [[MUL:%.*]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
+; GFX-NEXT:    ret bfloat [[COMMON_RET_OP]]
+; GFX:       [[IF_THEN]]:
+; GFX-NEXT:    [[MUL]] = fmul contract bfloat [[X]], [[A_1]]
+; GFX-NEXT:    [[ADD:%.*]] = fadd contract bfloat 0xR3F80, [[MUL]]
+; GFX-NEXT:    br label %[[COMMON_RET]]
+; GFX:       [[IF_ELSE]]:
+; GFX-NEXT:    [[MUL1:%.*]] = fmul contract bfloat [[X]], [[A_1]]
+; GFX-NEXT:    [[SUB]] = fsub contract bfloat [[MUL1]], [[Y]]
+; GFX-NEXT:    br label %[[COMMON_RET]]
+;
+entry:
+  %y = load bfloat, ptr %ptr_y, align 8
+  %cmp = fcmp oeq bfloat %y, 0.000000e+00
+  %x = load bfloat, ptr %ptr_x, align 8
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %a_1 = load bfloat, ptr %ptr_a, align 8
+  %mul = fmul contract bfloat %x, %a_1
+  %add = fadd contract bfloat 1.000000e+00, %mul
+  ret bfloat %mul
+
+if.else:                                          ; preds = %entry
+  %a_2 = load bfloat, ptr %ptr_a, align 8
+  %mul1 = fmul contract bfloat %x, %a_2
+  %sub = fsub contract bfloat %mul1, %y
+  ret bfloat %sub
+}
+
+define double @is_profitable_constant(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) #1 {
+; GFX-LABEL: define double @is_profitable_constant(
+; GFX-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR1]] {
+; GFX-NEXT:  [[ENTRY:.*:]]
+; GFX-NEXT:    [[Y:%.*]] = load double, ptr [[PTR_Y]], align 8
+; GFX-NEXT:    [[CMP:%.*]] = fcmp oeq double [[Y]], 0.000000e+00
+; GFX-NEXT:    [[X:%.*]] = load double, ptr [[PTR_X]], align 8
+; GFX-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; GFX:       [[COMMON_RET:.*]]:
+; GFX-NEXT:    [[COMMON_RET_OP:%.*]] = phi double [ [[ADD:%.*]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
+; GFX-NEXT:    ret double [[COMMON_RET_OP]]
+; GFX:       [[IF_THEN]]:
+; GFX-NEXT:    [[MUL:%.*]] = fmul contract double 2.000000e+00, [[X]]
+; GFX-NEXT:    [[ADD]] = fadd contract double 1.000000e+00, [[MUL]]
+; GFX-NEXT:    br label %[[COMMON_RET]]
+; GFX:       [[IF_ELSE]]:
+; GFX-NEXT:    [[MUL1:%.*]] = fmul contract double 3.000000e+00, [[X]]
+; GFX-NEXT:    [[SUB]] = fsub contract double [[MUL1]], [[Y]]
+; GFX-NEXT:    br label %[[COMMON_RET]]
+;
+entry:
+  %y = load double, ptr %ptr_y, align 8
+  %cmp = fcmp oeq double %y, 0.000000e+00
+  %x = load double, ptr %ptr_x, align 8
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %mul = fmul contract double 2.000000e+00, %x
+  %add = fadd contract double 1.000000e+00, %mul
+  ret double %add
+
+if.else:                                          ; preds = %entry
+  %mul1 = fmul contract double 3.000000e+00, %x
+  %sub = fsub contract double %mul1, %y
+  ret double %sub
+}
+
+%vec_type = type <8 x double>
+ at v1_ptr = external addrspace(3) global ptr
+ at v2_ptr = external addrspace(3) global ptr
+
+define %vec_type @is_profitable_vector(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) {
+; GFX-LABEL: define <8 x double> @is_profitable_vector(
+; GFX-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR2:[0-9]+]] {
+; GFX-NEXT:  [[ENTRY:.*:]]
+; GFX-NEXT:    [[Y:%.*]] = load double, ptr [[PTR_Y]], align 8
+; GFX-NEXT:    [[X:%.*]] = load <8 x double>, ptr [[PTR_X]], align 8
+; GFX-NEXT:    [[V1:%.*]] = load <8 x double>, ptr addrspace(3) @v1_ptr, align 64
+; GFX-NEXT:    [[V2:%.*]] = load <8 x double>, ptr addrspace(3) @v2_ptr, align 64
+; GFX-NEXT:    [[CMP:%.*]] = fcmp oeq double [[Y]], 0.000000e+00
+; GFX-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; GFX:       [[COMMON_RET:.*]]:
+; GFX-NEXT:    [[COMMON_RET_OP:%.*]] = phi <8 x double> [ [[ADD:%.*]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
+; GFX-NEXT:    ret <8 x double> [[COMMON_RET_OP]]
+; GFX:       [[IF_THEN]]:
+; GFX-NEXT:    [[MUL:%.*]] = fmul contract <8 x double> [[V1]], [[X]]
+; GFX-NEXT:    [[ADD]] = fadd contract <8 x double> [[V2]], [[MUL]]
+; GFX-NEXT:    br label %[[COMMON_RET]]
+; GFX:       [[IF_ELSE]]:
+; GFX-NEXT:    [[MUL1:%.*]] = fmul contract <8 x double> [[V1]], [[X]]
+; GFX-NEXT:    [[SUB]] = fsub contract <8 x double> [[MUL1]], [[V2]]
+; GFX-NEXT:    br label %[[COMMON_RET]]
+;
+entry:
+  %y = load double, ptr %ptr_y, align 8
+  %x = load %vec_type, ptr %ptr_x, align 8
+  %v1 = load %vec_type, ptr addrspace(3) @v1_ptr
+  %v2 = load %vec_type, ptr addrspace(3) @v2_ptr
+  %cmp = fcmp oeq double %y, 0.000000e+00
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %mul = fmul contract %vec_type %v1, %x
+  %add = fadd contract %vec_type %v2, %mul
+  ret %vec_type %add
+
+if.else:                                          ; preds = %entry
+  %mul1 = fmul contract %vec_type %v1, %x
+  %sub = fsub contract %vec_type %mul1, %v2
+  ret %vec_type %sub
+}
+
+define double @is_profitable_f64_nocontract(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) #0 {
+; FP-CONTRACT-FAST-LABEL: define double @is_profitable_f64_nocontract(
+; FP-CONTRACT-FAST-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR0]] {
+; FP-CONTRACT-FAST-NEXT:    [[Y:%.*]] = load double, ptr [[PTR_Y]], align 8
+; FP-CONTRACT-FAST-NEXT:    [[CMP:%.*]] = fcmp oeq double [[Y]], 0.000000e+00
+; FP-CONTRACT-FAST-NEXT:    [[X:%.*]] = load double, ptr [[PTR_X]], align 8
+; FP-CONTRACT-FAST-NEXT:    [[A_1:%.*]] = load double, ptr [[PTR_A]], align 8
+; FP-CONTRACT-FAST-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; FP-CONTRACT-FAST:       [[COMMON_RET:.*]]:
+; FP-CONTRACT-FAST-NEXT:    [[COMMON_RET_OP:%.*]] = phi double [ [[PTR_ADD:%.*]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
+; FP-CONTRACT-FAST-NEXT:    ret double [[COMMON_RET_OP]]
+; FP-CONTRACT-FAST:       [[IF_THEN]]:
+; FP-CONTRACT-FAST-NEXT:    [[MUL:%.*]] = fmul double [[X]], [[A_1]]
+; FP-CONTRACT-FAST-NEXT:    [[PTR_ADD]] = fadd double 1.000000e+00, [[MUL]]
+; FP-CONTRACT-FAST-NEXT:    br label %[[COMMON_RET]]
+; FP-CONTRACT-FAST:       [[IF_ELSE]]:
+; FP-CONTRACT-FAST-NEXT:    [[MUL1:%.*]] = fmul double [[X]], [[A_1]]
+; FP-CONTRACT-FAST-NEXT:    [[SUB]] = fsub double [[MUL1]], [[Y]]
+; FP-CONTRACT-FAST-NEXT:    br label %[[COMMON_RET]]
+;
+; UNSAFE-FP-MATH-LABEL: define double @is_profitable_f64_nocontract(
+; UNSAFE-FP-MATH-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR0]] {
+; UNSAFE-FP-MATH-NEXT:    [[Y:%.*]] = load double, ptr [[PTR_Y]], align 8
+; UNSAFE-FP-MATH-NEXT:    [[CMP:%.*]] = fcmp oeq double [[Y]], 0.000000e+00
+; UNSAFE-FP-MATH-NEXT:    [[X:%.*]] = load double, ptr [[PTR_X]], align 8
+; UNSAFE-FP-MATH-NEXT:    [[A_1:%.*]] = load double, ptr [[PTR_A]], align 8
+; UNSAFE-FP-MATH-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; UNSAFE-FP-MATH:       [[COMMON_RET:.*]]:
+; UNSAFE-FP-MATH-NEXT:    [[COMMON_RET_OP:%.*]] = phi double [ [[PTR_ADD:%.*]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
+; UNSAFE-FP-MATH-NEXT: ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/121925


More information about the llvm-commits mailing list