Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NFC][AMDGPU] Pre-commit tests for IR variant - isFMAFasterThanFMulAdd #121925

Merged
merged 1 commit into from
Jan 9, 2025

Conversation

chinmaydd
Copy link
Contributor

@chinmaydd chinmaydd commented Jan 7, 2025

Pre-commit tests for #121465

@llvmbot
Copy link
Member

llvmbot commented Jan 7, 2025

@llvm/pr-subscribers-backend-amdgpu

Author: Chinmay Deshpande (chinmaydd)

Changes

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 --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>
+@v1_ptr = external addrspace(3) global ptr
+@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]

br i1 %cmp, label %if.then, label %if.else

if.then: ; preds = %entry
%mul = fmul contract %vec_type %v1, %x
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use <8 x double> directly?

Also the half vectors are the most interesting cases

@chinmaydd chinmaydd force-pushed the chinmaydd/precommit-fma-test branch from bcf4ff8 to 097a2da Compare January 7, 2025 13:01
%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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this to be a useful test, the modifier would need to be separating the add and the mul, not the use of it. i.e. add (fneg (fmul x, y)), z)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. In that case, I will have to update the main PR to work through that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can handle the modifiers in a follow up, but still good to get the baseline test in

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arsenm gentle ping

…ndFAdd

Change-Id: I2bdf11d08ac659d6b14a021eadc5b86752112c73
@chinmaydd chinmaydd force-pushed the chinmaydd/precommit-fma-test branch from 097a2da to caa028a Compare January 7, 2025 13:15
@chinmaydd
Copy link
Contributor Author

Test failure is unrelated and was reverted here: ab5133b

@chinmaydd chinmaydd merged commit 659cd2a into llvm:main Jan 9, 2025
6 of 8 checks passed
@chinmaydd chinmaydd deleted the chinmaydd/precommit-fma-test branch January 9, 2025 10:21
Mel-Chen pushed a commit to Mel-Chen/llvm-project that referenced this pull request Jan 13, 2025
DKLoehr pushed a commit to DKLoehr/llvm-project that referenced this pull request Jan 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants