aboutsummaryrefslogtreecommitdiffstats
path: root/test/Transforms/Reassociate
diff options
context:
space:
mode:
Diffstat (limited to 'test/Transforms/Reassociate')
-rw-r--r--test/Transforms/Reassociate/2006-04-27-ReassociateVector.ll2
-rw-r--r--test/Transforms/Reassociate/basictest.ll2
-rw-r--r--test/Transforms/Reassociate/canonicalize-neg-const.ll158
-rw-r--r--test/Transforms/Reassociate/commute.ll19
-rw-r--r--test/Transforms/Reassociate/fast-AgressiveSubMove.ll24
-rw-r--r--test/Transforms/Reassociate/fast-ArrayOutOfBounds.ll65
-rw-r--r--test/Transforms/Reassociate/fast-MissedTree.ll11
-rw-r--r--test/Transforms/Reassociate/fast-ReassociateVector.ll73
-rw-r--r--test/Transforms/Reassociate/fast-SubReassociate.ll70
-rw-r--r--test/Transforms/Reassociate/fast-basictest.ll285
-rw-r--r--test/Transforms/Reassociate/fast-fp-commute.ll44
-rw-r--r--test/Transforms/Reassociate/fast-mightymul.ll35
-rw-r--r--test/Transforms/Reassociate/fast-multistep.ll32
-rw-r--r--test/Transforms/Reassociate/mixed-fast-nonfast-fp.ll18
-rw-r--r--test/Transforms/Reassociate/multistep.ll2
-rw-r--r--test/Transforms/Reassociate/negation1.ll15
-rw-r--r--test/Transforms/Reassociate/pr21205.ll21
-rw-r--r--test/Transforms/Reassociate/wrap-flags.ll34
18 files changed, 907 insertions, 3 deletions
diff --git a/test/Transforms/Reassociate/2006-04-27-ReassociateVector.ll b/test/Transforms/Reassociate/2006-04-27-ReassociateVector.ll
index f783955..ea86984 100644
--- a/test/Transforms/Reassociate/2006-04-27-ReassociateVector.ll
+++ b/test/Transforms/Reassociate/2006-04-27-ReassociateVector.ll
@@ -3,7 +3,7 @@
define <4 x float> @test1() {
; CHECK-LABEL: test1
; CHECK-NEXT: %tmp1 = fsub <4 x float> zeroinitializer, zeroinitializer
-; CHECK-NEXT: %tmp2 = fmul <4 x float> zeroinitializer, %tmp1
+; CHECK-NEXT: %tmp2 = fmul <4 x float> %tmp1, zeroinitializer
; CHECK-NEXT: ret <4 x float> %tmp2
%tmp1 = fsub <4 x float> zeroinitializer, zeroinitializer
diff --git a/test/Transforms/Reassociate/basictest.ll b/test/Transforms/Reassociate/basictest.ll
index d70bfcb..0194ce2 100644
--- a/test/Transforms/Reassociate/basictest.ll
+++ b/test/Transforms/Reassociate/basictest.ll
@@ -203,7 +203,7 @@ define i32 @test14(i32 %X1, i32 %X2) {
; CHECK-LABEL: @test14
; CHECK-NEXT: sub i32 %X1, %X2
-; CHECK-NEXT: mul i32 %tmp, 47
+; CHECK-NEXT: mul i32 %B2, 47
; CHECK-NEXT: ret i32
}
diff --git a/test/Transforms/Reassociate/canonicalize-neg-const.ll b/test/Transforms/Reassociate/canonicalize-neg-const.ll
new file mode 100644
index 0000000..e85a963
--- /dev/null
+++ b/test/Transforms/Reassociate/canonicalize-neg-const.ll
@@ -0,0 +1,158 @@
+; RUN: opt -reassociate -gvn -S < %s | FileCheck %s
+
+; (x + 0.1234 * y) * (x + -0.1234 * y) -> (x + 0.1234 * y) * (x - 0.1234 * y)
+define double @test1(double %x, double %y) {
+; CHECK-LABEL: @test1
+; CHECK-NEXT: fmul double %y, 1.234000e-01
+; CHECK-NEXT: fadd double %x, %mul
+; CHECK-NEXT: fsub double %x, %mul
+; CHECK-NEXT: fmul double %add{{.*}}, %add{{.*}}
+; CHECK-NEXT: ret double %mul
+
+ %mul = fmul double 1.234000e-01, %y
+ %add = fadd double %mul, %x
+ %mul1 = fmul double -1.234000e-01, %y
+ %add2 = fadd double %mul1, %x
+ %mul3 = fmul double %add, %add2
+ ret double %mul3
+}
+
+; (x + -0.1234 * y) * (x + -0.1234 * y) -> (x - 0.1234 * y) * (x - 0.1234 * y)
+define double @test2(double %x, double %y) {
+; CHECK-LABEL: @test2
+; CHECK-NEXT: fmul double %y, 1.234000e-01
+; CHECK-NEXT: fsub double %x, %mul
+; CHECK-NEXT: fmul double %add{{.*}}, %add{{.*}}
+; CHECK-NEXT: ret double %mul
+
+ %mul = fmul double %y, -1.234000e-01
+ %add = fadd double %mul, %x
+ %mul1 = fmul double %y, -1.234000e-01
+ %add2 = fadd double %mul1, %x
+ %mul3 = fmul double %add, %add2
+ ret double %mul3
+}
+
+; (x + 0.1234 * y) * (x - -0.1234 * y) -> (x + 0.1234 * y) * (x + 0.1234 * y)
+define double @test3(double %x, double %y) {
+; CHECK-LABEL: @test3
+; CHECK-NEXT: fmul double %y, 1.234000e-01
+; CHECK-NEXT: fadd double %x, %mul
+; CHECK-NEXT: fmul double %add{{.*}}, %add{{.*}}
+; CHECK-NEXT: ret double
+
+ %mul = fmul double %y, 1.234000e-01
+ %add = fadd double %mul, %x
+ %mul1 = fmul double %y, -1.234000e-01
+ %add2 = fsub double %x, %mul1
+ %mul3 = fmul double %add, %add2
+ ret double %mul3
+}
+
+; Canonicalize (x - -1234 * y)
+define i64 @test4(i64 %x, i64 %y) {
+; CHECK-LABEL: @test4
+; CHECK-NEXT: mul i64 %y, 1234
+; CHECK-NEXT: add i64 %mul, %x
+; CHECK-NEXT: ret i64 %sub
+
+ %mul = mul i64 %y, -1234
+ %sub = sub i64 %x, %mul
+ ret i64 %sub
+}
+
+; Canonicalize (x - -0.1234 * y)
+define double @test5(double %x, double %y) {
+; CHECK-LABEL: @test5
+; CHECK-NEXT: fmul double %y, 1.234000e-01
+; CHECK-NEXT: fadd double %x, %mul
+; CHECK-NEXT: ret double
+
+ %mul = fmul double -1.234000e-01, %y
+ %sub = fsub double %x, %mul
+ ret double %sub
+}
+
+; Don't modify (-0.1234 * y - x)
+define double @test6(double %x, double %y) {
+; CHECK-LABEL: @test6
+; CHECK-NEXT: fmul double %y, -1.234000e-01
+; CHECK-NEXT: fsub double %mul, %x
+; CHECK-NEXT: ret double %sub
+
+ %mul = fmul double -1.234000e-01, %y
+ %sub = fsub double %mul, %x
+ ret double %sub
+}
+
+; Canonicalize (-0.1234 * y + x) -> (x - 0.1234 * y)
+define double @test7(double %x, double %y) {
+; CHECK-LABEL: @test7
+; CHECK-NEXT: fmul double %y, 1.234000e-01
+; CHECK-NEXT: fsub double %x, %mul
+; CHECK-NEXT: ret double %add
+
+ %mul = fmul double -1.234000e-01, %y
+ %add = fadd double %mul, %x
+ ret double %add
+}
+
+; Canonicalize (y * -0.1234 + x) -> (x - 0.1234 * y)
+define double @test8(double %x, double %y) {
+; CHECK-LABEL: @test8
+; CHECK-NEXT: fmul double %y, 1.234000e-01
+; CHECK-NEXT: fsub double %x, %mul
+; CHECK-NEXT: ret double %add
+
+ %mul = fmul double %y, -1.234000e-01
+ %add = fadd double %mul, %x
+ ret double %add
+}
+
+; Canonicalize (x - -0.1234 / y)
+define double @test9(double %x, double %y) {
+; CHECK-LABEL: @test9
+; CHECK-NEXT: fdiv double 1.234000e-01, %y
+; CHECK-NEXT: fadd double %x, %div
+; CHECK-NEXT: ret double
+
+ %div = fdiv double -1.234000e-01, %y
+ %sub = fsub double %x, %div
+ ret double %sub
+}
+
+; Don't modify (-0.1234 / y - x)
+define double @test10(double %x, double %y) {
+; CHECK-LABEL: @test10
+; CHECK-NEXT: fdiv double -1.234000e-01, %y
+; CHECK-NEXT: fsub double %div, %x
+; CHECK-NEXT: ret double %sub
+
+ %div = fdiv double -1.234000e-01, %y
+ %sub = fsub double %div, %x
+ ret double %sub
+}
+
+; Canonicalize (-0.1234 / y + x) -> (x - 0.1234 / y)
+define double @test11(double %x, double %y) {
+; CHECK-LABEL: @test11
+; CHECK-NEXT: fdiv double 1.234000e-01, %y
+; CHECK-NEXT: fsub double %x, %div
+; CHECK-NEXT: ret double %add
+
+ %div = fdiv double -1.234000e-01, %y
+ %add = fadd double %div, %x
+ ret double %add
+}
+
+; Canonicalize (y / -0.1234 + x) -> (x - y / 0.1234)
+define double @test12(double %x, double %y) {
+; CHECK-LABEL: @test12
+; CHECK-NEXT: fdiv double %y, 1.234000e-01
+; CHECK-NEXT: fsub double %x, %div
+; CHECK-NEXT: ret double %add
+
+ %div = fdiv double %y, -1.234000e-01
+ %add = fadd double %div, %x
+ ret double %add
+}
diff --git a/test/Transforms/Reassociate/commute.ll b/test/Transforms/Reassociate/commute.ll
new file mode 100644
index 0000000..760e51b
--- /dev/null
+++ b/test/Transforms/Reassociate/commute.ll
@@ -0,0 +1,19 @@
+; RUN: opt -reassociate -S < %s | FileCheck %s
+
+declare void @use(i32)
+
+define void @test1(i32 %x, i32 %y) {
+; CHECK-LABEL: test1
+; CHECK: mul i32 %y, %x
+; CHECK: mul i32 %y, %x
+; CHECK: sub i32 %1, %2
+; CHECK: call void @use(i32 %{{.*}})
+; CHECK: call void @use(i32 %{{.*}})
+
+ %1 = mul i32 %x, %y
+ %2 = mul i32 %y, %x
+ %3 = sub i32 %1, %2
+ call void @use(i32 %1)
+ call void @use(i32 %3)
+ ret void
+}
diff --git a/test/Transforms/Reassociate/fast-AgressiveSubMove.ll b/test/Transforms/Reassociate/fast-AgressiveSubMove.ll
new file mode 100644
index 0000000..0c28ed1
--- /dev/null
+++ b/test/Transforms/Reassociate/fast-AgressiveSubMove.ll
@@ -0,0 +1,24 @@
+; RUN: opt < %s -reassociate -S | FileCheck %s
+
+define float @test1(float %A) {
+; CHECK-LABEL: test1
+; CHECK-NEXT: %X = fadd float %A, 1.000000e+00
+; CHECK-NEXT: %Y = fadd float %A, 1.000000e+00
+; CHECK-NEXT: %r = fsub float %X, %Y
+; CHECK-NEXT: ret float %r
+
+ %X = fadd float %A, 1.000000e+00
+ %Y = fadd float %A, 1.000000e+00
+ %r = fsub float %X, %Y
+ ret float %r
+}
+
+define float @test2(float %A) {
+; CHECK-LABEL: test2
+; CHECK-NEXT: ret float 0.000000e+00
+
+ %X = fadd fast float 1.000000e+00, %A
+ %Y = fadd fast float 1.000000e+00, %A
+ %r = fsub fast float %X, %Y
+ ret float %r
+}
diff --git a/test/Transforms/Reassociate/fast-ArrayOutOfBounds.ll b/test/Transforms/Reassociate/fast-ArrayOutOfBounds.ll
new file mode 100644
index 0000000..0109e4f
--- /dev/null
+++ b/test/Transforms/Reassociate/fast-ArrayOutOfBounds.ll
@@ -0,0 +1,65 @@
+; RUN: opt < %s -reassociate -instcombine -S | FileCheck %s
+
+; Not marked as fast, so must not change.
+define float @test1(float %a0, float %a1, float %a2, float %a3, float %a4) {
+; CHECK-LABEL: test1
+; CHECK-NEXT: %tmp.2 = fadd float %a3, %a4
+; CHECK-NEXT: %tmp.4 = fadd float %tmp.2, %a2
+; CHECK-NEXT: %tmp.6 = fadd float %tmp.4, %a1
+; CHECK-NEXT: %tmp.8 = fadd float %tmp.6, %a0
+; CHECK-NEXT: %tmp.11 = fadd float %a2, %a3
+; CHECK-NEXT: %tmp.13 = fadd float %tmp.11, %a1
+; CHECK-NEXT: %tmp.15 = fadd float %tmp.13, %a0
+; CHECK-NEXT: %tmp.18 = fadd float %a1, %a2
+; CHECK-NEXT: %tmp.20 = fadd float %tmp.18, %a0
+; CHECK-NEXT: %tmp.23 = fadd float %a0, %a1
+; CHECK-NEXT: %tmp.26 = fsub float %tmp.8, %tmp.15
+; CHECK-NEXT: %tmp.28 = fadd float %tmp.20, %tmp.26
+; CHECK-NEXT: %tmp.30 = fsub float %tmp.28, %tmp.23
+; CHECK-NEXT: %tmp.32 = fsub float %tmp.30, %a4
+; CHECK-NEXT: %tmp.34 = fsub float %tmp.32, %a2
+; CHECK-NEXT: %T = fmul float %tmp.34, %tmp.34
+; CHECK-NEXT: ret float %T
+
+ %tmp.2 = fadd float %a4, %a3
+ %tmp.4 = fadd float %tmp.2, %a2
+ %tmp.6 = fadd float %tmp.4, %a1
+ %tmp.8 = fadd float %tmp.6, %a0
+ %tmp.11 = fadd float %a3, %a2
+ %tmp.13 = fadd float %tmp.11, %a1
+ %tmp.15 = fadd float %tmp.13, %a0
+ %tmp.18 = fadd float %a2, %a1
+ %tmp.20 = fadd float %tmp.18, %a0
+ %tmp.23 = fadd float %a1, %a0
+ %tmp.26 = fsub float %tmp.8, %tmp.15
+ %tmp.28 = fadd float %tmp.26, %tmp.20
+ %tmp.30 = fsub float %tmp.28, %tmp.23
+ %tmp.32 = fsub float %tmp.30, %a4
+ %tmp.34 = fsub float %tmp.32, %a2
+ %T = fmul float %tmp.34, %tmp.34
+ ret float %T
+}
+
+; Should be able to eliminate everything.
+define float @test2(float %a0, float %a1, float %a2, float %a3, float %a4) {
+; CHECK-LABEL: test2
+; CHECK: ret float 0.000000e+00
+
+ %tmp.2 = fadd fast float %a4, %a3
+ %tmp.4 = fadd fast float %tmp.2, %a2
+ %tmp.6 = fadd fast float %tmp.4, %a1
+ %tmp.8 = fadd fast float %tmp.6, %a0
+ %tmp.11 = fadd fast float %a3, %a2
+ %tmp.13 = fadd fast float %tmp.11, %a1
+ %tmp.15 = fadd fast float %tmp.13, %a0
+ %tmp.18 = fadd fast float %a2, %a1
+ %tmp.20 = fadd fast float %tmp.18, %a0
+ %tmp.23 = fadd fast float %a1, %a0
+ %tmp.26 = fsub fast float %tmp.8, %tmp.15
+ %tmp.28 = fadd fast float %tmp.26, %tmp.20
+ %tmp.30 = fsub fast float %tmp.28, %tmp.23
+ %tmp.32 = fsub fast float %tmp.30, %a4
+ %tmp.34 = fsub fast float %tmp.32, %a2
+ %T = fmul fast float %tmp.34, %tmp.34
+ ret float %T
+}
diff --git a/test/Transforms/Reassociate/fast-MissedTree.ll b/test/Transforms/Reassociate/fast-MissedTree.ll
new file mode 100644
index 0000000..689fd6c
--- /dev/null
+++ b/test/Transforms/Reassociate/fast-MissedTree.ll
@@ -0,0 +1,11 @@
+; RUN: opt < %s -reassociate -instcombine -S | FileCheck %s
+
+define float @test1(float %A, float %B) {
+; CHECK-LABEL: test1
+; CHECK: %Z = fadd fast float %A, %B
+; CHECK: ret float %Z
+ %W = fadd fast float %B, -5.0
+ %Y = fadd fast float %A, 5.0
+ %Z = fadd fast float %W, %Y
+ ret float %Z
+}
diff --git a/test/Transforms/Reassociate/fast-ReassociateVector.ll b/test/Transforms/Reassociate/fast-ReassociateVector.ll
new file mode 100644
index 0000000..eeae096
--- /dev/null
+++ b/test/Transforms/Reassociate/fast-ReassociateVector.ll
@@ -0,0 +1,73 @@
+; RUN: opt < %s -reassociate -S | FileCheck %s
+
+; Canonicalize operands, but don't optimize floating point vector operations.
+define <4 x float> @test1() {
+; CHECK-LABEL: test1
+; CHECK-NEXT: %tmp1 = fsub fast <4 x float> zeroinitializer, zeroinitializer
+; CHECK-NEXT: %tmp2 = fmul fast <4 x float> %tmp1, zeroinitializer
+
+ %tmp1 = fsub fast <4 x float> zeroinitializer, zeroinitializer
+ %tmp2 = fmul fast <4 x float> zeroinitializer, %tmp1
+ ret <4 x float> %tmp2
+}
+
+; Commute integer vector operations.
+define <2 x i32> @test2(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: test2
+; CHECK-NEXT: %tmp1 = add <2 x i32> %x, %y
+; CHECK-NEXT: %tmp2 = add <2 x i32> %x, %y
+; CHECK-NEXT: %tmp3 = add <2 x i32> %tmp1, %tmp2
+
+ %tmp1 = add <2 x i32> %x, %y
+ %tmp2 = add <2 x i32> %y, %x
+ %tmp3 = add <2 x i32> %tmp1, %tmp2
+ ret <2 x i32> %tmp3
+}
+
+define <2 x i32> @test3(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: test3
+; CHECK-NEXT: %tmp1 = mul <2 x i32> %x, %y
+; CHECK-NEXT: %tmp2 = mul <2 x i32> %x, %y
+; CHECK-NEXT: %tmp3 = mul <2 x i32> %tmp1, %tmp2
+
+ %tmp1 = mul <2 x i32> %x, %y
+ %tmp2 = mul <2 x i32> %y, %x
+ %tmp3 = mul <2 x i32> %tmp1, %tmp2
+ ret <2 x i32> %tmp3
+}
+
+define <2 x i32> @test4(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: test4
+; CHECK-NEXT: %tmp1 = and <2 x i32> %x, %y
+; CHECK-NEXT: %tmp2 = and <2 x i32> %x, %y
+; CHECK-NEXT: %tmp3 = and <2 x i32> %tmp1, %tmp2
+
+ %tmp1 = and <2 x i32> %x, %y
+ %tmp2 = and <2 x i32> %y, %x
+ %tmp3 = and <2 x i32> %tmp1, %tmp2
+ ret <2 x i32> %tmp3
+}
+
+define <2 x i32> @test5(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: test5
+; CHECK-NEXT: %tmp1 = or <2 x i32> %x, %y
+; CHECK-NEXT: %tmp2 = or <2 x i32> %x, %y
+; CHECK-NEXT: %tmp3 = or <2 x i32> %tmp1, %tmp2
+
+ %tmp1 = or <2 x i32> %x, %y
+ %tmp2 = or <2 x i32> %y, %x
+ %tmp3 = or <2 x i32> %tmp1, %tmp2
+ ret <2 x i32> %tmp3
+}
+
+define <2 x i32> @test6(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: test6
+; CHECK-NEXT: %tmp1 = xor <2 x i32> %x, %y
+; CHECK-NEXT: %tmp2 = xor <2 x i32> %x, %y
+; CHECK-NEXT: %tmp3 = xor <2 x i32> %tmp1, %tmp2
+
+ %tmp1 = xor <2 x i32> %x, %y
+ %tmp2 = xor <2 x i32> %y, %x
+ %tmp3 = xor <2 x i32> %tmp1, %tmp2
+ ret <2 x i32> %tmp3
+}
diff --git a/test/Transforms/Reassociate/fast-SubReassociate.ll b/test/Transforms/Reassociate/fast-SubReassociate.ll
new file mode 100644
index 0000000..db4191a
--- /dev/null
+++ b/test/Transforms/Reassociate/fast-SubReassociate.ll
@@ -0,0 +1,70 @@
+; RUN: opt < %s -reassociate -constprop -instcombine -S | FileCheck %s
+
+define float @test1(float %A, float %B) {
+; CHECK-LABEL: test1
+; CHECK-NEXT: %W = fadd float %B, 5.000000e+00
+; CHECK-NEXT: %X = fadd float %A, -7.000000e+00
+; CHECK-NEXT: %Y = fsub float %X, %W
+; CHECK-NEXT: %Z = fadd float %Y, 1.200000e+01
+; CHECK-NEXT: ret float %Z
+
+ %W = fadd float 5.0, %B
+ %X = fadd float -7.0, %A
+ %Y = fsub float %X, %W
+ %Z = fadd float %Y, 12.0
+ ret float %Z
+}
+
+; With sub reassociation, constant folding can eliminate all of the constants.
+define float @test2(float %A, float %B) {
+; CHECK-LABEL: test2
+; CHECK-NEXT: %Z = fsub fast float %A, %B
+; CHECK-NEXT: ret float %Z
+
+ %W = fadd fast float %B, 5.000000e+00
+ %X = fadd fast float %A, -7.000000e+00
+ %Y = fsub fast float %X, %W
+ %Z = fadd fast float %Y, 1.200000e+01
+ ret float %Z
+
+}
+
+define float @test3(float %A, float %B, float %C, float %D) {
+; CHECK-LABEL: test3
+; CHECK-NEXT: %M = fadd float %A, 1.200000e+01
+; CHECK-NEXT: %N = fadd float %M, %B
+; CHECK-NEXT: %O = fadd float %N, %C
+; CHECK-NEXT: %P = fsub float %D, %O
+; CHECK-NEXT: %Q = fadd float %P, 1.200000e+01
+; CHECK-NEXT: ret float %Q
+
+ %M = fadd float %A, 1.200000e+01
+ %N = fadd float %M, %B
+ %O = fadd float %N, %C
+ %P = fsub float %D, %O
+ %Q = fadd float %P, 1.200000e+01
+ ret float %Q
+}
+
+; With sub reassociation, constant folding can eliminate the two 12 constants.
+define float @test4(float %A, float %B, float %C, float %D) {
+; CHECK-LABEL: test4
+; CHECK-NEXT: %B.neg = fsub fast float -0.000000e+00, %B
+; CHECK-NEXT: %O.neg = fsub fast float %B.neg, %A
+; CHECK-NEXT: %P = fsub fast float %O.neg, %C
+; CHECK-NEXT: %Q = fadd fast float %P, %D
+; CHECK-NEXT: ret float %Q
+
+; FIXME: InstCombine should be able to get us to the following:
+; %sum = fadd fast float %B, %A
+; %sum1 = fadd fast float %sum, %C
+; %Q = fsub fast float %D, %sum1
+; ret i32 %Q
+
+ %M = fadd fast float 1.200000e+01, %A
+ %N = fadd fast float %M, %B
+ %O = fadd fast float %N, %C
+ %P = fsub fast float %D, %O
+ %Q = fadd fast float 1.200000e+01, %P
+ ret float %Q
+}
diff --git a/test/Transforms/Reassociate/fast-basictest.ll b/test/Transforms/Reassociate/fast-basictest.ll
new file mode 100644
index 0000000..67b07f4
--- /dev/null
+++ b/test/Transforms/Reassociate/fast-basictest.ll
@@ -0,0 +1,285 @@
+; RUN: opt < %s -reassociate -gvn -instcombine -S | FileCheck %s
+
+; With reassociation, constant folding can eliminate the 12 and -12 constants.
+define float @test1(float %arg) {
+; CHECK-LABEL: @test1
+; CHECK-NEXT: fsub fast float -0.000000e+00, %arg
+; CHECK-NEXT: ret float
+
+ %tmp1 = fsub fast float -1.200000e+01, %arg
+ %tmp2 = fadd fast float %tmp1, 1.200000e+01
+ ret float %tmp2
+}
+
+define float @test2(float %reg109, float %reg1111) {
+; CHECK-LABEL: @test2
+; CHECK-NEXT: fadd float %reg109, -3.000000e+01
+; CHECK-NEXT: fadd float %reg115, %reg1111
+; CHECK-NEXT: fadd float %reg116, 3.000000e+01
+; CHECK-NEXT: ret float
+
+ %reg115 = fadd float %reg109, -3.000000e+01
+ %reg116 = fadd float %reg115, %reg1111
+ %reg117 = fadd float %reg116, 3.000000e+01
+ ret float %reg117
+}
+
+define float @test3(float %reg109, float %reg1111) {
+; CHECK-LABEL: @test3
+; CHECK-NEXT: %reg117 = fadd fast float %reg109, %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
+}
+
+@fe = external global float
+@fa = external global float
+@fb = external global float
+@fc = external global float
+@ff = external global float
+
+define void @test4() {
+; CHECK-LABEL: @test4
+; CHECK: fadd fast float
+; CHECK: fadd fast float
+; CHECK-NOT: fadd fast float
+; CHECK: ret void
+
+ %A = load float* @fa
+ %B = load float* @fb
+ %C = load float* @fc
+ %t1 = fadd fast float %A, %B
+ %t2 = fadd fast float %t1, %C
+ %t3 = fadd fast float %C, %A
+ %t4 = fadd fast float %t3, %B
+ ; e = (a+b)+c;
+ store float %t2, float* @fe
+ ; f = (a+c)+b
+ store float %t4, float* @ff
+ ret void
+}
+
+define void @test5() {
+; CHECK-LABEL: @test5
+; CHECK: fadd fast float
+; CHECK: fadd fast float
+; CHECK-NOT: fadd
+; CHECK: ret void
+
+ %A = load float* @fa
+ %B = load float* @fb
+ %C = load float* @fc
+ %t1 = fadd fast float %A, %B
+ %t2 = fadd fast float %t1, %C
+ %t3 = fadd fast float %C, %A
+ %t4 = fadd fast float %t3, %B
+ ; e = c+(a+b)
+ store float %t2, float* @fe
+ ; f = (c+a)+b
+ store float %t4, float* @ff
+ ret void
+}
+
+define void @test6() {
+; CHECK-LABEL: @test6
+; CHECK: fadd fast float
+; CHECK: fadd fast float
+; CHECK-NOT: fadd
+; CHECK: ret void
+
+ %A = load float* @fa
+ %B = load float* @fb
+ %C = load float* @fc
+ %t1 = fadd fast float %B, %A
+ %t2 = fadd fast float %t1, %C
+ %t3 = fadd fast float %C, %A
+ %t4 = fadd fast float %t3, %B
+ ; e = c+(b+a)
+ store float %t2, float* @fe
+ ; f = (c+a)+b
+ store float %t4, float* @ff
+ ret void
+}
+
+define float @test7(float %A, float %B, float %C) {
+; CHECK-LABEL: @test7
+; CHECK-NEXT: fadd fast float %C, %B
+; CHECK-NEXT: fmul fast float %A, %A
+; CHECK-NEXT: fmul fast float %1, %tmp2
+; CHECK-NEXT: ret float
+
+ %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 @test8(float %X, float %Y, float %Z) {
+; CHECK-LABEL: @test8
+; CHECK-NEXT: fmul fast float %Y, %X
+; CHECK-NEXT: fsub fast float %Z
+; CHECK-NEXT: ret float
+
+ %A = fsub fast float 0.0, %X
+ %B = fmul fast float %A, %Y
+ ; (-X)*Y + Z -> Z-X*Y
+ %C = fadd fast float %B, %Z
+ ret float %C
+}
+
+define float @test9(float %X) {
+; CHECK-LABEL: @test9
+; CHECK-NEXT: fmul fast float %X, 9.400000e+01
+; CHECK-NEXT: ret float
+
+ %Y = fmul fast float %X, 4.700000e+01
+ %Z = fadd fast float %Y, %Y
+ ret float %Z
+}
+
+define float @test10(float %X) {
+; CHECK-LABEL: @test10
+; CHECK-NEXT: fmul fast float %X, 3.000000e+00
+; CHECK-NEXT: ret float
+
+ %Y = fadd fast float %X ,%X
+ %Z = fadd fast float %Y, %X
+ ret float %Z
+}
+
+define float @test11(float %W) {
+; CHECK-LABEL: test11
+; CHECK-NEXT: fmul fast float %W, 3.810000e+02
+; CHECK-NEXT: ret float
+
+ %X = fmul fast float %W, 127.0
+ %Y = fadd fast float %X ,%X
+ %Z = fadd fast float %Y, %X
+ ret float %Z
+}
+
+define float @test12(float %X) {
+; CHECK-LABEL: @test12
+; CHECK-NEXT: fmul fast float %X, -3.000000e+00
+; CHECK-NEXT: fadd fast float %factor, 6.000000e+00
+; CHECK-NEXT: ret float
+
+ %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 @test13(float %X1, float %X2, float %X3) {
+; CHECK-LABEL: @test13
+; CHECK-NEXT: fsub fast float %X3, %X2
+; CHECK-NEXT: fmul fast float {{.*}}, %X1
+; CHECK-NEXT: ret float
+
+ %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 @test14(float %X1, float %X2) {
+; CHECK-LABEL: @test14
+; CHECK-NEXT: fsub fast float %X1, %X2
+; CHECK-NEXT: fmul fast float %1, 4.700000e+01
+; CHECK-NEXT: ret float
+
+ %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 @test15(float %arg) {
+; CHECK-LABEL: test15
+; CHECK-NEXT: fmul fast float %arg, 1.440000e+02
+; CHECK-NEXT: ret float %tmp2
+
+ %tmp1 = fmul fast float 1.200000e+01, %arg
+ %tmp2 = fmul fast float %tmp1, 1.200000e+01
+ ret float %tmp2
+}
+
+; (b+(a+1234))+-a -> b+1234
+define float @test16(float %b, float %a) {
+; CHECK-LABEL: @test16
+; CHECK-NEXT: fadd fast float %b, 1.234000e+03
+; CHECK-NEXT: ret float
+
+ %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
+}
+
+; Test that we can turn things like X*-(Y*Z) -> X*-1*Y*Z.
+
+define float @test17(float %a, float %b, float %z) {
+; CHECK-LABEL: test17
+; CHECK-NEXT: fmul fast float %a, 1.234500e+04
+; CHECK-NEXT: fmul fast float %e, %b
+; CHECK-NEXT: fmul fast float %f, %z
+; CHECK-NEXT: ret float
+
+ %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 @test18(float %a, float %b, float %z) {
+; CHECK-LABEL: test18
+; CHECK-NEXT: fmul fast float %a, 4.000000e+01
+; CHECK-NEXT: fmul fast float %e, %z
+; CHECK-NEXT: ret float
+
+ %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
+}
+
+; With sub reassociation, constant folding can eliminate the 12 and -12 constants.
+define float @test19(float %A, float %B) {
+; CHECK-LABEL: @test19
+; CHECK-NEXT: fsub fast float %A, %B
+; CHECK-NEXT: ret float
+ %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
+}
+
+; With sub reassociation, constant folding can eliminate the uses of %a.
+define float @test20(float %a, float %b, float %c) nounwind {
+; CHECK-LABEL: @test20
+; CHECK-NEXT: fsub fast float -0.000000e+00, %b
+; CHECK-NEXT: fsub fast float %b.neg, %c
+; CHECK-NEXT: ret float
+
+; FIXME: Should be able to generate the below, which may expose more
+; opportunites for FAdd reassociation.
+; %sum = fadd fast float %c, %b
+; %tmp7 = fsub fast float 0, %sum
+
+ %tmp3 = fsub fast float %a, %b
+ %tmp5 = fsub fast float %tmp3, %c
+ %tmp7 = fsub fast float %tmp5, %a
+ ret float %tmp7
+}
diff --git a/test/Transforms/Reassociate/fast-fp-commute.ll b/test/Transforms/Reassociate/fast-fp-commute.ll
new file mode 100644
index 0000000..ad89607
--- /dev/null
+++ b/test/Transforms/Reassociate/fast-fp-commute.ll
@@ -0,0 +1,44 @@
+; RUN: opt -reassociate -S < %s | FileCheck %s
+
+declare void @use(float)
+
+define void @test1(float %x, float %y) {
+; CHECK-LABEL: test1
+; CHECK: fmul fast float %y, %x
+; CHECK: fmul fast float %y, %x
+; CHECK: fsub fast float %1, %2
+; CHECK: call void @use(float %{{.*}})
+; CHECK: call void @use(float %{{.*}})
+
+ %1 = fmul fast float %x, %y
+ %2 = fmul fast float %y, %x
+ %3 = fsub fast float %1, %2
+ call void @use(float %1)
+ call void @use(float %3)
+ ret void
+}
+
+define float @test2(float %x, float %y) {
+; CHECK-LABEL: test2
+; CHECK-NEXT: fmul fast float %y, %x
+; CHECK-NEXT: fmul fast float %y, %x
+; CHECK-NEXT: fsub fast float %1, %2
+; CHECK-NEXT: ret float %3
+
+ %1 = fmul fast float %x, %y
+ %2 = fmul fast float %y, %x
+ %3 = fsub fast float %1, %2
+ ret float %3
+}
+
+define float @test3(float %x, float %y) {
+; CHECK-LABEL: test3
+; CHECK-NEXT: %factor = fmul fast float %y, 2.000000e+00
+; CHECK-NEXT: %tmp1 = fmul fast float %factor, %x
+; CHECK-NEXT: ret float %tmp1
+
+ %1 = fmul fast float %x, %y
+ %2 = fmul fast float %y, %x
+ %3 = fadd fast float %1, %2
+ ret float %3
+}
diff --git a/test/Transforms/Reassociate/fast-mightymul.ll b/test/Transforms/Reassociate/fast-mightymul.ll
new file mode 100644
index 0000000..98bdf7a
--- /dev/null
+++ b/test/Transforms/Reassociate/fast-mightymul.ll
@@ -0,0 +1,35 @@
+; RUN: opt < %s -reassociate -disable-output
+; PR13021
+
+define float @test2(float %x) {
+ %t0 = fmul fast float %x, %x
+ %t1 = fmul fast float %t0, %t0
+ %t2 = fmul fast float %t1, %t1
+ %t3 = fmul fast float %t2, %t2
+ %t4 = fmul fast float %t3, %t3
+ %t5 = fmul fast float %t4, %t4
+ %t6 = fmul fast float %t5, %t5
+ %t7 = fmul fast float %t6, %t6
+ %t8 = fmul fast float %t7, %t7
+ %t9 = fmul fast float %t8, %t8
+ %t10 = fmul fast float %t9, %t9
+ %t11 = fmul fast float %t10, %t10
+ %t12 = fmul fast float %t11, %t11
+ %t13 = fmul fast float %t12, %t12
+ %t14 = fmul fast float %t13, %t13
+ %t15 = fmul fast float %t14, %t14
+ %t16 = fmul fast float %t15, %t15
+ %t17 = fmul fast float %t16, %t16
+ %t18 = fmul fast float %t17, %t17
+ %t19 = fmul fast float %t18, %t18
+ %t20 = fmul fast float %t19, %t19
+ %t21 = fmul fast float %t20, %t20
+ %t22 = fmul fast float %t21, %t21
+ %t23 = fmul fast float %t22, %t22
+ %t24 = fmul fast float %t23, %t23
+ %t25 = fmul fast float %t24, %t24
+ %t26 = fmul fast float %t25, %t25
+ %t27 = fmul fast float %t26, %t26
+ %t28 = fmul fast float %t27, %t27
+ ret float %t28
+}
diff --git a/test/Transforms/Reassociate/fast-multistep.ll b/test/Transforms/Reassociate/fast-multistep.ll
new file mode 100644
index 0000000..45e15c7
--- /dev/null
+++ b/test/Transforms/Reassociate/fast-multistep.ll
@@ -0,0 +1,32 @@
+; RUN: opt < %s -reassociate -S | FileCheck %s
+
+define float @fmultistep1(float %a, float %b, float %c) {
+; Check that a*a*b+a*a*c is turned into a*(a*(b+c)).
+; CHECK-LABEL: @fmultistep1
+; CHECK-NEXT: fadd fast float %c, %b
+; CHECK-NEXT: fmul fast float %a, %tmp2
+; CHECK-NEXT: fmul fast float %tmp3, %a
+; CHECK-NEXT: ret float
+
+ %t0 = fmul fast float %a, %b
+ %t1 = fmul fast float %a, %t0 ; a*(a*b)
+ %t2 = fmul fast float %a, %c
+ %t3 = fmul fast float %a, %t2 ; a*(a*c)
+ %t4 = fadd fast float %t1, %t3
+ ret float %t4
+}
+
+define float @fmultistep2(float %a, float %b, float %c, float %d) {
+; Check that a*b+a*c+d is turned into a*(b+c)+d.
+; CHECK-LABEL: @fmultistep2
+; CHECK-NEXT: fadd fast float %c, %b
+; CHECK-NEXT: fmul fast float %tmp, %a
+; CHECK-NEXT: fadd fast float %tmp1, %d
+; CHECK-NEXT: ret float
+
+ %t0 = fmul fast float %a, %b
+ %t1 = fmul fast float %a, %c
+ %t2 = fadd fast float %t1, %d ; a*c+d
+ %t3 = fadd fast float %t0, %t2 ; a*b+(a*c+d)
+ ret float %t3
+}
diff --git a/test/Transforms/Reassociate/mixed-fast-nonfast-fp.ll b/test/Transforms/Reassociate/mixed-fast-nonfast-fp.ll
new file mode 100644
index 0000000..f51c0c1
--- /dev/null
+++ b/test/Transforms/Reassociate/mixed-fast-nonfast-fp.ll
@@ -0,0 +1,18 @@
+; RUN: opt -reassociate %s -S | FileCheck %s
+
+define float @foo(float %a,float %b, float %c) {
+; CHECK: %mul3 = fmul float %a, %b
+; CHECK-NEXT: fmul fast float %c, 2.000000e+00
+; CHECK-NEXT: fadd fast float %factor, %b
+; CHECK-NEXT: fmul fast float %tmp1, %a
+; CHECK-NEXT: fadd fast float %tmp2, %mul3
+; CHECK-NEXT: ret float
+ %mul1 = fmul fast float %a, %c
+ %mul2 = fmul fast float %a, %b
+ %mul3 = fmul float %a, %b
+ %mul4 = fmul fast float %a, %c
+ %add1 = fadd fast float %mul1, %mul3
+ %add2 = fadd fast float %mul4, %mul2
+ %add3 = fadd fast float %add1, %add2
+ ret float %add3
+}
diff --git a/test/Transforms/Reassociate/multistep.ll b/test/Transforms/Reassociate/multistep.ll
index 12eaeee..c499646 100644
--- a/test/Transforms/Reassociate/multistep.ll
+++ b/test/Transforms/Reassociate/multistep.ll
@@ -9,7 +9,7 @@ define i64 @multistep1(i64 %a, i64 %b, i64 %c) {
%t3 = mul i64 %a, %t2 ; a*(a*c)
%t4 = add i64 %t1, %t3
; CHECK-NEXT: add i64 %c, %b
-; CHECK-NEXT: mul i64 %tmp{{.*}}, %a
+; CHECK-NEXT: mul i64 %a, %tmp{{.*}}
; CHECK-NEXT: mul i64 %tmp{{.*}}, %a
; CHECK-NEXT: ret
ret i64 %t4
diff --git a/test/Transforms/Reassociate/negation1.ll b/test/Transforms/Reassociate/negation1.ll
new file mode 100644
index 0000000..34b943c
--- /dev/null
+++ b/test/Transforms/Reassociate/negation1.ll
@@ -0,0 +1,15 @@
+; RUN: opt < %s -reassociate -instcombine -S | FileCheck %s
+
+; Test that we can turn things like A*B + X - A*B -> X.
+
+define i32 @test1(i32 %a, i32 %b, i32 %x) {
+; CHECK-LABEL: test1
+; CHECK: ret i32 %x
+
+ %c = mul i32 %a, %b
+ %d = add i32 %c, %x
+ %c1 = mul i32 %a, %b
+ %f = sub i32 %d, %c1
+ ret i32 %f
+}
+
diff --git a/test/Transforms/Reassociate/pr21205.ll b/test/Transforms/Reassociate/pr21205.ll
new file mode 100644
index 0000000..fcc7150
--- /dev/null
+++ b/test/Transforms/Reassociate/pr21205.ll
@@ -0,0 +1,21 @@
+; RUN: opt -reassociate -S < %s | FileCheck %s
+; PR21205
+
+@a = common global i32 0, align 4
+@b = common global i32 0, align 4
+
+; Don't canonicalize %conv - undef into %conv + (-undef).
+; CHECK-LABEL: @test1
+; CHECK: %sub = fsub fast float %conv, undef
+; CHECK: %sub1 = fadd fast float %sub, -1.000000e+00
+
+define i32 @test1() {
+entry:
+ %0 = load i32* @a, align 4
+ %conv = sitofp i32 %0 to float
+ %sub = fsub fast float %conv, undef
+ %sub1 = fadd fast float %sub, -1.000000e+00
+ %conv2 = fptosi float %sub1 to i32
+ store i32 %conv2, i32* @b, align 4
+ ret i32 undef
+}
diff --git a/test/Transforms/Reassociate/wrap-flags.ll b/test/Transforms/Reassociate/wrap-flags.ll
new file mode 100644
index 0000000..e3304b6
--- /dev/null
+++ b/test/Transforms/Reassociate/wrap-flags.ll
@@ -0,0 +1,34 @@
+; RUN: opt < %s -reassociate -dce -S | FileCheck %s
+; PR12985
+
+; Verify the nsw flags are preserved when converting shl to mul.
+
+; CHECK-LABEL: @shl_to_mul_nsw(
+; CHECK: %mul = mul i32 %i, -2147483648
+; CHECK: add i32 %mul, 1
+define i32 @shl_to_mul_nsw(i32 %i) {
+entry:
+ %mul = shl nsw i32 %i, 31
+ %mul2 = add i32 %mul, 1
+ ret i32 %mul2
+}
+
+; CHECK-LABEL: @shl_to_mul_nuw(
+; CHECK: %mul = mul nuw i32 %i, 4
+; CHECK: add i32 %mul, 1
+define i32 @shl_to_mul_nuw(i32 %i) {
+entry:
+ %mul = shl nuw i32 %i, 2
+ %mul2 = add i32 %mul, 1
+ ret i32 %mul2
+}
+
+; CHECK-LABEL: @shl_to_mul_nuw_nsw(
+; CHECK: %mul = mul nuw nsw i32 %i, 4
+; CHECK: add i32 %mul, 1
+define i32 @shl_to_mul_nuw_nsw(i32 %i) {
+entry:
+ %mul = shl nuw nsw i32 %i, 2
+ %mul2 = add i32 %mul, 1
+ ret i32 %mul2
+}