Reassociate x + -0.1234 * y into x - 0.1234 * y
This does not require -ffast-math, and it gives CSE/GVN more options to
eliminate duplicate expressions in, e.g.:
return ((x + 0.1234 * y) * (x - 0.1234 * y));
Differential Revision: http://reviews.llvm.org/D4904
llvm-svn: 216169
diff --git a/llvm/test/Transforms/Reassociate/fast-basictest.ll b/llvm/test/Transforms/Reassociate/fast-basictest.ll
index 72808cd..67b07f4 100644
--- a/llvm/test/Transforms/Reassociate/fast-basictest.ll
+++ b/llvm/test/Transforms/Reassociate/fast-basictest.ll
@@ -193,7 +193,7 @@
define float @test14(float %X1, float %X2) {
; CHECK-LABEL: @test14
; CHECK-NEXT: fsub fast float %X1, %X2
-; CHECK-NEXT: fmul fast float %tmp, 4.700000e+01
+; CHECK-NEXT: fmul fast float %1, 4.700000e+01
; CHECK-NEXT: ret float
%B = fmul fast float %X1, 47. ; X1*47
diff --git a/llvm/test/Transforms/Reassociate/liftsign.ll b/llvm/test/Transforms/Reassociate/liftsign.ll
new file mode 100644
index 0000000..e8b728c
--- /dev/null
+++ b/llvm/test/Transforms/Reassociate/liftsign.ll
@@ -0,0 +1,69 @@
+; RUN: opt -reassociate -gvn -S < %s | FileCheck %s
+
+; (x + 0.1234 * y) * (x + -0.1234 * y) -> (x + 0.1234 * y) * (x - 0.1234 * y)
+; so CSE can simplify it further
+define double @lift_sign1(double %x, double %y) nounwind readnone ssp uwtable {
+; CHECK-LABEL: @lift_sign1(
+ %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
+; CHECK-NOT: %mul1 = fmul double -1.234000e-01, %y
+; CHECK-NOT: %add2 = fadd %mul1, %x
+; CHECK: %add2.repl = fsub double %x, %mul
+; CHECK: %mul3 = fmul double %add, %add2
+ret double %mul3
+}
+
+; (x + -0.1234 * y) * (x + -0.1234 * y) -> (x - 0.1234 * y) * (x - 0.1234 * y)
+; GVN can then rewrite it even further
+define double @lift_sign2(double %x, double %y) nounwind readnone ssp uwtable {
+; CHECK-LABEL: @lift_sign2(
+ %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
+; CHECK-NOT: %mul = fmul double %y, -1.234000e-01
+; CHECK-NOT: %add = fadd double %mul, %x
+; CHECK-NOT: %mul1 = fmul double %y, -1.234000e-01
+; CHECK-NOT: %add2 = fadd double %mul1, %x
+; CHECK-NOT: %mul3 = fmul double %add, %add2
+; CHECK: %mul = fmul double 1.234000e-01, %y
+; CHECK: %add.repl = fsub double %x, %mul
+; CHECK: %mul3 = fmul double %add.repl, %add.repl
+ ret double %mul3
+}
+
+; (x + 0.1234 * y) * (x - -0.1234 * y) -> (x + 0.1234 * y) * (x + 0.1234 * y)
+define double @lift_sign3(double %x, double %y) nounwind readnone ssp uwtable {
+; CHECK-LABEL: @lift_sign3(
+ %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
+; CHECK-NOT: %mul1 = fmul double %y, -1.234000e-01
+; CHECK-NOT: %add2 = fsub double %x, %mul1
+; CHECK-NOT: %mul3 = fmul double %add, %add2
+; CHECK: %mul3 = fmul double %add, %add
+ ret double %mul3
+}
+
+; (x + 0.1234 / y) * (x + -0.1234 / y) -> (x + 0.1234 / y) * (x - 0.1234 / y)
+; so CSE can simplify it further
+define double @lift_sign4(double %x, double %y) nounwind readnone ssp uwtable {
+; CHECK-LABEL: @lift_sign4(
+ %div = fdiv double 1.234000e-01, %y
+ %add = fadd double %div, %x
+ %div1 = fdiv double -1.234000e-01, %y
+ %add2 = fadd double %div1, %x
+ %mul3 = fmul double %add, %add2
+; CHECK-NOT: %div1 = fdiv double -1.234000e-01, %y
+; CHECK-NOT: %add2 = fadd double %div1, %x
+; CHECK-NOT: %mul3 = fmul double %add, %add2
+; CHECK: %add2.repl = fsub double %x, %div
+; CHECK: %mul3 = fmul double %add, %add2.repl
+ ret double %mul3
+}