aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2017-08-23 21:33:38 +0000
committerHans Wennborg <hans@hanshq.net>2017-08-23 21:33:38 +0000
commit2d30972995d07a49b04560f76470274822009af3 (patch)
tree931390411c2aaa1a28a1c8809eba4584ac9865d0
parent703f013ff4b83c7fd29880bb89160743ab439127 (diff)
------------------------------------------------------------------------ r311554 | mcrosier | 2017-08-23 07:10:06 -0700 (Wed, 23 Aug 2017) | 10 lines [Reassociate] Don't canonicalize x + (-Constant * y) -> x - (Constant * y).. ..if the resulting subtract will be broken up later. This can cause us to get into an infinite loop. x + (-5.0 * y) -> x - (5.0 * y) ; Canonicalize neg const x - (5.0 * y) -> x + (0 - (5.0 * y)) ; Break up subtract x + (0 - (5.0 * y)) -> x + (-5.0 * y) ; Replace 0-X with X*-1. PR34078 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_50@311603 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Scalar/Reassociate.cpp6
-rw-r--r--test/Transforms/Reassociate/canonicalize-neg-const.ll22
2 files changed, 28 insertions, 0 deletions
diff --git a/lib/Transforms/Scalar/Reassociate.cpp b/lib/Transforms/Scalar/Reassociate.cpp
index 29d1ba406ae..e235e5eb1a0 100644
--- a/lib/Transforms/Scalar/Reassociate.cpp
+++ b/lib/Transforms/Scalar/Reassociate.cpp
@@ -1941,6 +1941,12 @@ Instruction *ReassociatePass::canonicalizeNegConstExpr(Instruction *I) {
if (!User->isCommutative() && User->getOperand(1) != I)
return nullptr;
+ // Don't canonicalize x + (-Constant * y) -> x - (Constant * y), if the
+ // resulting subtract will be broken up later. This can get us into an
+ // infinite loop during reassociation.
+ if (UserOpcode == Instruction::FAdd && ShouldBreakUpSubtract(User))
+ return nullptr;
+
// Change the sign of the constant.
APFloat Val = CF->getValueAPF();
Val.changeSign();
diff --git a/test/Transforms/Reassociate/canonicalize-neg-const.ll b/test/Transforms/Reassociate/canonicalize-neg-const.ll
index 465460cb53b..7cb2c3a10e2 100644
--- a/test/Transforms/Reassociate/canonicalize-neg-const.ll
+++ b/test/Transforms/Reassociate/canonicalize-neg-const.ll
@@ -154,3 +154,25 @@ define i4 @test13(i4 %x) {
%add = add i4 %mul, 3
ret i4 %add
}
+
+; This tests used to cause an infinite loop where we would loop between
+; canonicalizing the negated constant (i.e., (X + Y*-5.0) -> (X - Y*5.0)) and
+; breaking up a subtract (i.e., (X - Y*5.0) -> X + (0 - Y*5.0)). To break the
+; cycle, we don't canonicalize the negative constant if we're going to later
+; break up the subtract.
+;
+; Check to make sure we don't canonicalize
+; (%pow2*-5.0 + %sub) -> (%sub - %pow2*5.0)
+; as we would later break up this subtract causing a cycle.
+;
+; CHECK-LABEL: @pr34078
+; CHECK: %mul5.neg = fmul fast double %pow2, -5.000000e-01
+; CHECK: %sub1 = fadd fast double %mul5.neg, %sub
+define double @pr34078(double %A) {
+ %sub = fsub fast double 1.000000e+00, %A
+ %pow2 = fmul double %A, %A
+ %mul5 = fmul fast double %pow2, 5.000000e-01
+ %sub1 = fsub fast double %sub, %mul5
+ %add = fadd fast double %sub1, %sub1
+ ret double %add
+}