
canonicalize-neg-const.ll had some issues. The script somehow decided to delete half the run line and merge it with the example expression (which it also deleted most of).
581 lines
20 KiB
LLVM
581 lines
20 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
;
|
|
; Test numbering remains continuous across:
|
|
; - InstCombine/fast-basictest.ll
|
|
; - PhaseOrdering/fast-basictest.ll
|
|
; - PhaseOrdering/fast-reassociate-gvn.ll
|
|
; - Reassociate/fast-basictest.ll
|
|
;
|
|
; RUN: opt < %s -passes=reassociate -S | FileCheck %s
|
|
|
|
; ((a + (-3)) + b) + 3 -> a + b
|
|
; That only works with both instcombine and reassociate passes enabled.
|
|
; Check that reassociate is not enough.
|
|
|
|
; TODO: check if we can eliminate zero add.
|
|
define float @test2(float %reg109, float %reg1111) {
|
|
; CHECK-LABEL: @test2(
|
|
; CHECK-NEXT: [[REG116:%.*]] = fadd fast float [[REG109:%.*]], 0.000000e+00
|
|
; CHECK-NEXT: [[REG117:%.*]] = fadd fast float [[REG116]], [[REG1111:%.*]]
|
|
; CHECK-NEXT: ret float [[REG117]]
|
|
;
|
|
%reg115 = fadd fast float %reg109, -3.000000e+01
|
|
%reg116 = fadd fast float %reg115, %reg1111
|
|
%reg117 = fadd fast float %reg116, 3.000000e+01
|
|
ret float %reg117
|
|
}
|
|
|
|
define float @test2_no_FMF(float %reg109, float %reg1111) {
|
|
; CHECK-LABEL: @test2_no_FMF(
|
|
; CHECK-NEXT: [[REG115:%.*]] = fadd float [[REG109:%.*]], -3.000000e+01
|
|
; CHECK-NEXT: [[REG116:%.*]] = fadd float [[REG115]], [[REG1111:%.*]]
|
|
; CHECK-NEXT: [[REG117:%.*]] = fadd float [[REG116]], 3.000000e+01
|
|
; CHECK-NEXT: ret float [[REG117]]
|
|
;
|
|
%reg115 = fadd float %reg109, -3.000000e+01
|
|
%reg116 = fadd float %reg115, %reg1111
|
|
%reg117 = fadd float %reg116, 3.000000e+01
|
|
ret float %reg117
|
|
}
|
|
|
|
define float @test2_reassoc(float %reg109, float %reg1111) {
|
|
; CHECK-LABEL: @test2_reassoc(
|
|
; CHECK-NEXT: [[REG115:%.*]] = fadd reassoc float [[REG109:%.*]], -3.000000e+01
|
|
; CHECK-NEXT: [[REG116:%.*]] = fadd reassoc float [[REG115]], [[REG1111:%.*]]
|
|
; CHECK-NEXT: [[REG117:%.*]] = fadd reassoc float [[REG116]], 3.000000e+01
|
|
; CHECK-NEXT: ret float [[REG117]]
|
|
;
|
|
%reg115 = fadd reassoc float %reg109, -3.000000e+01
|
|
%reg116 = fadd reassoc float %reg115, %reg1111
|
|
%reg117 = fadd reassoc float %reg116, 3.000000e+01
|
|
ret float %reg117
|
|
}
|
|
|
|
@fe = external global float
|
|
@fa = external global float
|
|
@fb = external global float
|
|
@fc = external global float
|
|
@ff = external global float
|
|
|
|
; If two sums of the same operands in different order are counted with 'fast'
|
|
; flag and then stored to global variables, we can reuse the same value twice.
|
|
; Sums:
|
|
; - test3: (a+b)+c and (a+c)+b
|
|
; - test4: c+(a+b) and (c+a)+b
|
|
; - test5: c+(b+a) and (c+a)+b
|
|
;
|
|
; That only works with both gvn and reassociate passes enabled.
|
|
; Check that reassociate is not enough.
|
|
|
|
define void @test3() {
|
|
; CHECK-LABEL: @test3(
|
|
; CHECK-NEXT: [[A:%.*]] = load float, ptr @fa, align 4
|
|
; CHECK-NEXT: [[B:%.*]] = load float, ptr @fb, align 4
|
|
; CHECK-NEXT: [[C:%.*]] = load float, ptr @fc, align 4
|
|
; CHECK-NEXT: [[T1:%.*]] = fadd fast float [[B]], [[A]]
|
|
; CHECK-NEXT: [[T2:%.*]] = fadd fast float [[T1]], [[C]]
|
|
; CHECK-NEXT: [[T3:%.*]] = fadd fast float [[B]], [[A]]
|
|
; CHECK-NEXT: [[T4:%.*]] = fadd fast float [[T3]], [[C]]
|
|
; CHECK-NEXT: store float [[T2]], ptr @fe, align 4
|
|
; CHECK-NEXT: store float [[T4]], ptr @ff, align 4
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%A = load float, ptr @fa
|
|
%B = load float, ptr @fb
|
|
%C = load float, ptr @fc
|
|
%t1 = fadd fast float %A, %B
|
|
%t2 = fadd fast float %t1, %C
|
|
%t3 = fadd fast float %A, %C
|
|
%t4 = fadd fast float %t3, %B
|
|
; e = (a+b)+c;
|
|
store float %t2, ptr @fe
|
|
; f = (a+c)+b
|
|
store float %t4, ptr @ff
|
|
ret void
|
|
}
|
|
|
|
define void @test4() {
|
|
; CHECK-LABEL: @test4(
|
|
; CHECK-NEXT: [[A:%.*]] = load float, ptr @fa, align 4
|
|
; CHECK-NEXT: [[B:%.*]] = load float, ptr @fb, align 4
|
|
; CHECK-NEXT: [[C:%.*]] = load float, ptr @fc, align 4
|
|
; CHECK-NEXT: [[T1:%.*]] = fadd fast float [[B]], [[A]]
|
|
; CHECK-NEXT: [[T2:%.*]] = fadd fast float [[T1]], [[C]]
|
|
; CHECK-NEXT: [[T3:%.*]] = fadd fast float [[B]], [[A]]
|
|
; CHECK-NEXT: [[T4:%.*]] = fadd fast float [[T3]], [[C]]
|
|
; CHECK-NEXT: store float [[T2]], ptr @fe, align 4
|
|
; CHECK-NEXT: store float [[T4]], ptr @ff, align 4
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%A = load float, ptr @fa
|
|
%B = load float, ptr @fb
|
|
%C = load float, ptr @fc
|
|
%t1 = fadd fast float %A, %B
|
|
%t2 = fadd fast float %C, %t1
|
|
%t3 = fadd fast float %C, %A
|
|
%t4 = fadd fast float %t3, %B
|
|
; e = c+(a+b)
|
|
store float %t2, ptr @fe
|
|
; f = (c+a)+b
|
|
store float %t4, ptr @ff
|
|
ret void
|
|
}
|
|
|
|
define void @test5() {
|
|
; CHECK-LABEL: @test5(
|
|
; CHECK-NEXT: [[A:%.*]] = load float, ptr @fa, align 4
|
|
; CHECK-NEXT: [[B:%.*]] = load float, ptr @fb, align 4
|
|
; CHECK-NEXT: [[C:%.*]] = load float, ptr @fc, align 4
|
|
; CHECK-NEXT: [[T1:%.*]] = fadd fast float [[B]], [[A]]
|
|
; CHECK-NEXT: [[T2:%.*]] = fadd fast float [[T1]], [[C]]
|
|
; CHECK-NEXT: [[T3:%.*]] = fadd fast float [[B]], [[A]]
|
|
; CHECK-NEXT: [[T4:%.*]] = fadd fast float [[T3]], [[C]]
|
|
; CHECK-NEXT: store float [[T2]], ptr @fe, align 4
|
|
; CHECK-NEXT: store float [[T4]], ptr @ff, align 4
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%A = load float, ptr @fa
|
|
%B = load float, ptr @fb
|
|
%C = load float, ptr @fc
|
|
%t1 = fadd fast float %B, %A
|
|
%t2 = fadd fast float %C, %t1
|
|
%t3 = fadd fast float %C, %A
|
|
%t4 = fadd fast float %t3, %B
|
|
; e = c+(b+a)
|
|
store float %t2, ptr @fe
|
|
; f = (c+a)+b
|
|
store float %t4, ptr @ff
|
|
ret void
|
|
}
|
|
|
|
define float @test6(float %A, float %B, float %C) {
|
|
; CHECK-LABEL: @test6(
|
|
; CHECK-NEXT: [[REASS_ADD1:%.*]] = fadd fast float [[C:%.*]], [[B:%.*]]
|
|
; CHECK-NEXT: [[REASS_MUL2:%.*]] = fmul fast float [[A:%.*]], [[A]]
|
|
; CHECK-NEXT: [[REASS_MUL:%.*]] = fmul fast float [[REASS_MUL2]], [[REASS_ADD1]]
|
|
; CHECK-NEXT: ret float [[REASS_MUL]]
|
|
;
|
|
%aa = fmul fast float %A, %A
|
|
%aab = fmul fast float %aa, %B
|
|
%ac = fmul fast float %A, %C
|
|
%aac = fmul fast float %ac, %A
|
|
%r = fadd fast float %aab, %aac
|
|
ret float %r
|
|
}
|
|
|
|
define float @test6_reassoc(float %A, float %B, float %C) {
|
|
; CHECK-LABEL: @test6_reassoc(
|
|
; CHECK-NEXT: [[AA:%.*]] = fmul reassoc float [[A:%.*]], [[A]]
|
|
; CHECK-NEXT: [[AAB:%.*]] = fmul reassoc float [[AA]], [[B:%.*]]
|
|
; CHECK-NEXT: [[AC:%.*]] = fmul reassoc float [[A]], [[C:%.*]]
|
|
; CHECK-NEXT: [[AAC:%.*]] = fmul reassoc float [[A]], [[AC]]
|
|
; CHECK-NEXT: [[R:%.*]] = fadd reassoc float [[AAB]], [[AAC]]
|
|
; CHECK-NEXT: ret float [[R]]
|
|
;
|
|
%aa = fmul reassoc float %A, %A
|
|
%aab = fmul reassoc float %aa, %B
|
|
%ac = fmul reassoc float %A, %C
|
|
%aac = fmul reassoc float %ac, %A
|
|
%r = fadd reassoc float %aab, %aac
|
|
ret float %r
|
|
}
|
|
|
|
; (-X)*Y + Z -> Z-X*Y
|
|
define float @test7(float %X, float %Y, float %Z) {
|
|
; CHECK-LABEL: @test7(
|
|
; CHECK-NEXT: [[B:%.*]] = fmul fast float [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[Z:%.*]], [[B]]
|
|
; CHECK-NEXT: ret float [[TMP1]]
|
|
;
|
|
%A = fsub fast float 0.0, %X
|
|
%B = fmul fast float %A, %Y
|
|
%C = fadd fast float %B, %Z
|
|
ret float %C
|
|
}
|
|
|
|
define float @test7_unary_fneg(float %X, float %Y, float %Z) {
|
|
; CHECK-LABEL: @test7_unary_fneg(
|
|
; CHECK-NEXT: [[B:%.*]] = fmul fast float [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[Z:%.*]], [[B]]
|
|
; CHECK-NEXT: ret float [[TMP1]]
|
|
;
|
|
%A = fneg fast float %X
|
|
%B = fmul fast float %A, %Y
|
|
%C = fadd fast float %B, %Z
|
|
ret float %C
|
|
}
|
|
|
|
define float @test7_reassoc_nsz(float %X, float %Y, float %Z) {
|
|
; CHECK-LABEL: @test7_reassoc_nsz(
|
|
; CHECK-NEXT: [[B:%.*]] = fmul reassoc nsz float [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[Z:%.*]], [[B]]
|
|
; CHECK-NEXT: ret float [[TMP1]]
|
|
;
|
|
%A = fsub reassoc nsz float 0.0, %X
|
|
%B = fmul reassoc nsz float %A, %Y
|
|
%C = fadd reassoc nsz float %B, %Z
|
|
ret float %C
|
|
}
|
|
|
|
; Verify that fold is not done only with 'reassoc' ('nsz' is required)
|
|
define float @test7_reassoc(float %X, float %Y, float %Z) {
|
|
; CHECK-LABEL: @test7_reassoc(
|
|
; CHECK-NEXT: [[A:%.*]] = fsub reassoc float 0.000000e+00, [[X:%.*]]
|
|
; CHECK-NEXT: [[B:%.*]] = fmul reassoc float [[A]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[C:%.*]] = fadd reassoc float [[B]], [[Z:%.*]]
|
|
; CHECK-NEXT: ret float [[C]]
|
|
;
|
|
%A = fsub reassoc float 0.0, %X
|
|
%B = fmul reassoc float %A, %Y
|
|
%C = fadd reassoc float %B, %Z
|
|
ret float %C
|
|
}
|
|
|
|
; Integer version of:
|
|
; (-X)*Y + Z -> Z-X*Y
|
|
; TODO: check if we can change the mul of -1 and the add to a sub.
|
|
define i32 @test7_int(i32 %X, i32 %Y, i32 %Z) {
|
|
; CHECK-LABEL: @test7_int(
|
|
; CHECK-NEXT: [[A:%.*]] = mul i32 [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[B:%.*]] = mul i32 [[A]], -1
|
|
; CHECK-NEXT: [[C:%.*]] = add i32 [[B]], [[Z:%.*]]
|
|
; CHECK-NEXT: ret i32 [[C]]
|
|
;
|
|
%A = sub i32 0, %X
|
|
%B = mul i32 %A, %Y
|
|
%C = add i32 %B, %Z
|
|
ret i32 %C
|
|
}
|
|
|
|
define float @test8(float %X) {
|
|
; CHECK-LABEL: @test8(
|
|
; CHECK-NEXT: [[FACTOR:%.*]] = fmul fast float [[X:%.*]], 9.400000e+01
|
|
; CHECK-NEXT: ret float [[FACTOR]]
|
|
;
|
|
%Y = fmul fast float %X, 4.700000e+01
|
|
%Z = fadd fast float %Y, %Y
|
|
ret float %Z
|
|
}
|
|
|
|
; Side note: (x + x + x) and (3*x) each have only a single rounding. So
|
|
; transforming x+x+x to 3*x is always safe, even without any FMF.
|
|
; To avoid that special-case, we have the addition of 'x' four times, here.
|
|
define float @test9(float %X) {
|
|
; CHECK-LABEL: @test9(
|
|
; CHECK-NEXT: [[FACTOR:%.*]] = fmul fast float [[X:%.*]], 4.000000e+00
|
|
; CHECK-NEXT: ret float [[FACTOR]]
|
|
;
|
|
%Y = fadd fast float %X ,%X
|
|
%Z = fadd fast float %Y, %X
|
|
%W = fadd fast float %Z, %X
|
|
ret float %W
|
|
}
|
|
|
|
define float @test10(float %W) {
|
|
; CHECK-LABEL: @test10(
|
|
; CHECK-NEXT: [[FACTOR:%.*]] = fmul fast float [[W:%.*]], 3.810000e+02
|
|
; CHECK-NEXT: ret float [[FACTOR]]
|
|
;
|
|
%X = fmul fast float %W, 127.0
|
|
%Y = fadd fast float %X ,%X
|
|
%Z = fadd fast float %Y, %X
|
|
ret float %Z
|
|
}
|
|
|
|
define float @test11(float %X) {
|
|
; CHECK-LABEL: @test11(
|
|
; CHECK-NEXT: [[FACTOR:%.*]] = fmul fast float [[X:%.*]], -3.000000e+00
|
|
; CHECK-NEXT: [[Z:%.*]] = fadd fast float [[FACTOR]], 6.000000e+00
|
|
; CHECK-NEXT: ret float [[Z]]
|
|
;
|
|
%A = fsub fast float 1.000000e+00, %X
|
|
%B = fsub fast float 2.000000e+00, %X
|
|
%C = fsub fast float 3.000000e+00, %X
|
|
%Y = fadd fast float %A ,%B
|
|
%Z = fadd fast float %Y, %C
|
|
ret float %Z
|
|
}
|
|
|
|
define float @test12(float %X1, float %X2, float %X3) {
|
|
; CHECK-LABEL: @test12(
|
|
; CHECK-NEXT: [[B:%.*]] = fmul fast float [[X2:%.*]], [[X1:%.*]]
|
|
; CHECK-NEXT: [[C:%.*]] = fmul fast float [[X3:%.*]], [[X1]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[C]], [[B]]
|
|
; CHECK-NEXT: ret float [[TMP1]]
|
|
;
|
|
%A = fsub fast float 0.000000e+00, %X1
|
|
%B = fmul fast float %A, %X2 ; -X1*X2
|
|
%C = fmul fast float %X1, %X3 ; X1*X3
|
|
%D = fadd fast float %B, %C ; -X1*X2 + X1*X3 -> X1*(X3-X2)
|
|
ret float %D
|
|
}
|
|
|
|
define float @test12_unary_fneg(float %X1, float %X2, float %X3) {
|
|
; CHECK-LABEL: @test12_unary_fneg(
|
|
; CHECK-NEXT: [[B:%.*]] = fmul fast float [[X2:%.*]], [[X1:%.*]]
|
|
; CHECK-NEXT: [[C:%.*]] = fmul fast float [[X3:%.*]], [[X1]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[C]], [[B]]
|
|
; CHECK-NEXT: ret float [[TMP1]]
|
|
;
|
|
%A = fneg fast float %X1
|
|
%B = fmul fast float %A, %X2 ; -X1*X2
|
|
%C = fmul fast float %X1, %X3 ; X1*X3
|
|
%D = fadd fast float %B, %C ; -X1*X2 + X1*X3 -> X1*(X3-X2)
|
|
ret float %D
|
|
}
|
|
|
|
define float @test12_reassoc_nsz(float %X1, float %X2, float %X3) {
|
|
; CHECK-LABEL: @test12_reassoc_nsz(
|
|
; CHECK-NEXT: [[B:%.*]] = fmul reassoc nsz float [[X2:%.*]], [[X1:%.*]]
|
|
; CHECK-NEXT: [[C:%.*]] = fmul reassoc nsz float [[X3:%.*]], [[X1]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[C]], [[B]]
|
|
; CHECK-NEXT: ret float [[TMP1]]
|
|
;
|
|
%A = fsub reassoc nsz float 0.000000e+00, %X1
|
|
%B = fmul reassoc nsz float %A, %X2 ; -X1*X2
|
|
%C = fmul reassoc nsz float %X1, %X3 ; X1*X3
|
|
%D = fadd reassoc nsz float %B, %C ; -X1*X2 + X1*X3 -> X1*(X3-X2)
|
|
ret float %D
|
|
}
|
|
|
|
; TODO: check if 'nsz' is technically required. Currently the optimization
|
|
; is not done with only 'reassoc' without 'nsz'.
|
|
define float @test12_reassoc(float %X1, float %X2, float %X3) {
|
|
; CHECK-LABEL: @test12_reassoc(
|
|
; CHECK-NEXT: [[A:%.*]] = fsub reassoc float 0.000000e+00, [[X1:%.*]]
|
|
; CHECK-NEXT: [[B:%.*]] = fmul reassoc float [[A]], [[X2:%.*]]
|
|
; CHECK-NEXT: [[C:%.*]] = fmul reassoc float [[X1]], [[X3:%.*]]
|
|
; CHECK-NEXT: [[D:%.*]] = fadd reassoc float [[B]], [[C]]
|
|
; CHECK-NEXT: ret float [[D]]
|
|
;
|
|
%A = fsub reassoc float 0.000000e+00, %X1
|
|
%B = fmul reassoc float %A, %X2 ; -X1*X2
|
|
%C = fmul reassoc float %X1, %X3 ; X1*X3
|
|
%D = fadd reassoc float %B, %C ; -X1*X2 + X1*X3 -> X1*(X3-X2)
|
|
ret float %D
|
|
}
|
|
|
|
; (x1 * 47) + (x2 * -47) => (x1 - x2) * 47
|
|
; That only works with both instcombine and reassociate passes enabled.
|
|
; Check that reassociate is not enough.
|
|
|
|
define float @test13(float %X1, float %X2) {
|
|
; CHECK-LABEL: @test13(
|
|
; CHECK-NEXT: [[B:%.*]] = fmul fast float [[X1:%.*]], 4.700000e+01
|
|
; CHECK-NEXT: [[C:%.*]] = fmul fast float [[X2:%.*]], 4.700000e+01
|
|
; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[B]], [[C]]
|
|
; CHECK-NEXT: ret float [[TMP1]]
|
|
;
|
|
%B = fmul fast float %X1, 47. ; X1*47
|
|
%C = fmul fast float %X2, -47. ; X2*-47
|
|
%D = fadd fast float %B, %C ; X1*47 + X2*-47 -> 47*(X1-X2)
|
|
ret float %D
|
|
}
|
|
|
|
define float @test13_reassoc_nsz(float %X1, float %X2) {
|
|
; CHECK-LABEL: @test13_reassoc_nsz(
|
|
; CHECK-NEXT: [[B:%.*]] = fmul reassoc nsz float [[X1:%.*]], 4.700000e+01
|
|
; CHECK-NEXT: [[C:%.*]] = fmul reassoc nsz float [[X2:%.*]], 4.700000e+01
|
|
; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[B]], [[C]]
|
|
; CHECK-NEXT: ret float [[TMP1]]
|
|
;
|
|
%B = fmul reassoc nsz float %X1, 47. ; X1*47
|
|
%C = fmul reassoc nsz float %X2, -47. ; X2*-47
|
|
%D = fadd reassoc nsz float %B, %C ; X1*47 + X2*-47 -> 47*(X1-X2)
|
|
ret float %D
|
|
}
|
|
|
|
define float @test13_reassoc(float %X1, float %X2) {
|
|
; CHECK-LABEL: @test13_reassoc(
|
|
; CHECK-NEXT: [[B:%.*]] = fmul reassoc float [[X1:%.*]], 4.700000e+01
|
|
; CHECK-NEXT: [[C:%.*]] = fmul reassoc float [[X2:%.*]], 4.700000e+01
|
|
; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc float [[B]], [[C]]
|
|
; CHECK-NEXT: ret float [[TMP1]]
|
|
;
|
|
%B = fmul reassoc float %X1, 47. ; X1*47
|
|
%C = fmul reassoc float %X2, -47. ; X2*-47
|
|
%D = fadd reassoc float %B, %C ; X1*47 + X2*-47 -> 47*(X1-X2)
|
|
ret float %D
|
|
}
|
|
|
|
define float @test14(float %arg) {
|
|
; CHECK-LABEL: @test14(
|
|
; CHECK-NEXT: [[T2:%.*]] = fmul fast float [[ARG:%.*]], 1.440000e+02
|
|
; CHECK-NEXT: ret float [[T2]]
|
|
;
|
|
%t1 = fmul fast float 1.200000e+01, %arg
|
|
%t2 = fmul fast float %t1, 1.200000e+01
|
|
ret float %t2
|
|
}
|
|
|
|
; TODO: check if we can transform the code with 'reassoc' only.
|
|
; The same IR is transformed to one fmul in instcombine pass.
|
|
define float @test14_reassoc(float %arg) {
|
|
; CHECK-LABEL: @test14_reassoc(
|
|
; CHECK-NEXT: [[T1:%.*]] = fmul reassoc float [[ARG:%.*]], 1.200000e+01
|
|
; CHECK-NEXT: [[T2:%.*]] = fmul reassoc float [[T1]], 1.200000e+01
|
|
; CHECK-NEXT: ret float [[T2]]
|
|
;
|
|
%t1 = fmul reassoc float 1.200000e+01, %arg
|
|
%t2 = fmul reassoc float %t1, 1.200000e+01
|
|
ret float %t2
|
|
}
|
|
|
|
; (b+(a+1234))+-a -> b+1234
|
|
; That only works with both instcombine and reassociate passes enabled.
|
|
; Check that reassociate is not enough.
|
|
|
|
; TODO: check if we can remove dead fsub.
|
|
define float @test15(float %b, float %a) {
|
|
; CHECK-LABEL: @test15(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float 0.000000e+00, [[A:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = fadd fast float [[B:%.*]], 1.234000e+03
|
|
; CHECK-NEXT: ret float [[TMP2]]
|
|
;
|
|
%1 = fadd fast float %a, 1234.0
|
|
%2 = fadd fast float %b, %1
|
|
%3 = fsub fast float 0.0, %a
|
|
%4 = fadd fast float %2, %3
|
|
ret float %4
|
|
}
|
|
|
|
; TODO: check if we can remove dead fneg.
|
|
define float @test15_unary_fneg(float %b, float %a) {
|
|
; CHECK-LABEL: @test15_unary_fneg(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = fneg fast float [[A:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = fadd fast float [[B:%.*]], 1.234000e+03
|
|
; CHECK-NEXT: ret float [[TMP2]]
|
|
;
|
|
%1 = fadd fast float %a, 1234.0
|
|
%2 = fadd fast float %b, %1
|
|
%3 = fneg fast float %a
|
|
%4 = fadd fast float %2, %3
|
|
ret float %4
|
|
}
|
|
|
|
; TODO: check if we can remove dead fsub.
|
|
define float @test15_reassoc_nsz(float %b, float %a) {
|
|
; CHECK-LABEL: @test15_reassoc_nsz(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float 0.000000e+00, [[A:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = fadd reassoc nsz float [[B:%.*]], 1.234000e+03
|
|
; CHECK-NEXT: ret float [[TMP2]]
|
|
;
|
|
%1 = fadd reassoc nsz float %a, 1234.0
|
|
%2 = fadd reassoc nsz float %b, %1
|
|
%3 = fsub reassoc nsz float 0.0, %a
|
|
%4 = fadd reassoc nsz float %2, %3
|
|
ret float %4
|
|
}
|
|
|
|
define float @test15_reassoc(float %b, float %a) {
|
|
; CHECK-LABEL: @test15_reassoc(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc float [[A:%.*]], 1.234000e+03
|
|
; CHECK-NEXT: [[TMP2:%.*]] = fadd reassoc float [[B:%.*]], [[TMP1]]
|
|
; CHECK-NEXT: [[TMP3:%.*]] = fsub reassoc float 0.000000e+00, [[A]]
|
|
; CHECK-NEXT: [[TMP4:%.*]] = fadd reassoc float [[TMP3]], [[TMP2]]
|
|
; CHECK-NEXT: ret float [[TMP4]]
|
|
;
|
|
%1 = fadd reassoc float %a, 1234.0
|
|
%2 = fadd reassoc float %b, %1
|
|
%3 = fsub reassoc float 0.0, %a
|
|
%4 = fadd reassoc float %2, %3
|
|
ret float %4
|
|
}
|
|
|
|
; Test that we can turn things like X*-(Y*Z) -> X*-1*Y*Z.
|
|
; That only works with both instcombine and reassociate passes enabled.
|
|
; Check that reassociate is not enough.
|
|
|
|
define float @test16(float %a, float %b, float %z) {
|
|
; CHECK-LABEL: @test16(
|
|
; CHECK-NEXT: [[C:%.*]] = fmul fast float [[A:%.*]], 1.234500e+04
|
|
; CHECK-NEXT: [[E:%.*]] = fmul fast float [[C]], [[B:%.*]]
|
|
; CHECK-NEXT: [[F:%.*]] = fmul fast float [[E]], [[Z:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = fadd fast float [[F]], 0.000000e+00
|
|
; CHECK-NEXT: ret float [[TMP1]]
|
|
;
|
|
%c = fsub fast float 0.000000e+00, %z
|
|
%d = fmul fast float %a, %b
|
|
%e = fmul fast float %c, %d
|
|
%f = fmul fast float %e, 1.234500e+04
|
|
%g = fsub fast float 0.000000e+00, %f
|
|
ret float %g
|
|
}
|
|
|
|
define float @test16_unary_fneg(float %a, float %b, float %z) {
|
|
; CHECK-LABEL: @test16_unary_fneg(
|
|
; CHECK-NEXT: [[E:%.*]] = fmul fast float [[A:%.*]], 1.234500e+04
|
|
; CHECK-NEXT: [[F:%.*]] = fmul fast float [[E]], [[B:%.*]]
|
|
; CHECK-NEXT: [[G:%.*]] = fmul fast float [[F]], [[Z:%.*]]
|
|
; CHECK-NEXT: ret float [[G]]
|
|
;
|
|
%c = fneg fast float %z
|
|
%d = fmul fast float %a, %b
|
|
%e = fmul fast float %c, %d
|
|
%f = fmul fast float %e, 1.234500e+04
|
|
%g = fneg fast float %f
|
|
ret float %g
|
|
}
|
|
|
|
define float @test16_reassoc(float %a, float %b, float %z) {
|
|
; CHECK-LABEL: @test16_reassoc(
|
|
; CHECK-NEXT: [[C:%.*]] = fsub reassoc float 0.000000e+00, [[Z:%.*]]
|
|
; CHECK-NEXT: [[D:%.*]] = fmul reassoc float [[A:%.*]], [[B:%.*]]
|
|
; CHECK-NEXT: [[E:%.*]] = fmul reassoc float [[D]], [[C]]
|
|
; CHECK-NEXT: [[F:%.*]] = fmul reassoc float [[E]], 1.234500e+04
|
|
; CHECK-NEXT: [[G:%.*]] = fsub reassoc float 0.000000e+00, [[F]]
|
|
; CHECK-NEXT: ret float [[G]]
|
|
;
|
|
%c = fsub reassoc float 0.000000e+00, %z
|
|
%d = fmul reassoc float %a, %b
|
|
%e = fmul reassoc float %c, %d
|
|
%f = fmul reassoc float %e, 1.234500e+04
|
|
%g = fsub reassoc float 0.000000e+00, %f
|
|
ret float %g
|
|
}
|
|
|
|
; TODO: check if we can remove:
|
|
; - fadd fast x, 0
|
|
; ... as 'fast' implies 'nsz'
|
|
define float @test17(float %a, float %b, float %z) {
|
|
; CHECK-LABEL: @test17(
|
|
; CHECK-NEXT: [[C:%.*]] = fmul fast float [[A:%.*]], 4.000000e+01
|
|
; CHECK-NEXT: [[E:%.*]] = fmul fast float [[C]], [[Z:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = fadd fast float [[E]], 0.000000e+00
|
|
; CHECK-NEXT: ret float [[TMP1]]
|
|
;
|
|
%d = fmul fast float %z, 4.000000e+01
|
|
%c = fsub fast float 0.000000e+00, %d
|
|
%e = fmul fast float %a, %c
|
|
%f = fsub fast float 0.000000e+00, %e
|
|
ret float %f
|
|
}
|
|
|
|
define float @test17_unary_fneg(float %a, float %b, float %z) {
|
|
; CHECK-LABEL: @test17_unary_fneg(
|
|
; CHECK-NEXT: [[E:%.*]] = fmul fast float [[A:%.*]], 4.000000e+01
|
|
; CHECK-NEXT: [[F:%.*]] = fmul fast float [[E]], [[Z:%.*]]
|
|
; CHECK-NEXT: ret float [[F]]
|
|
;
|
|
%d = fmul fast float %z, 4.000000e+01
|
|
%c = fneg fast float %d
|
|
%e = fmul fast float %a, %c
|
|
%f = fneg fast float %e
|
|
ret float %f
|
|
}
|
|
|
|
; With sub reassociation, constant folding can eliminate the 12 and -12 constants.
|
|
; TODO: check if we can remove fadd fast x, 0 as 'fast' implies 'nsz'
|
|
define float @test18(float %A, float %B) {
|
|
; CHECK-LABEL: @test18(
|
|
; CHECK-NEXT: [[B_NEG:%.*]] = fneg fast float [[B:%.*]]
|
|
; CHECK-NEXT: [[Y:%.*]] = fadd fast float [[A:%.*]], 0.000000e+00
|
|
; CHECK-NEXT: [[Z:%.*]] = fadd fast float [[Y]], [[B_NEG]]
|
|
; CHECK-NEXT: ret float [[Z]]
|
|
;
|
|
%X = fadd fast float -1.200000e+01, %A
|
|
%Y = fsub fast float %X, %B
|
|
%Z = fadd fast float %Y, 1.200000e+01
|
|
ret float %Z
|
|
}
|