diff options
| -rw-r--r-- | llvm/lib/Transforms/Scalar/Reassociate.cpp | 6 | ||||
| -rw-r--r-- | llvm/test/Transforms/Reassociate/canonicalize-neg-const.ll | 22 | 
2 files changed, 28 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Scalar/Reassociate.cpp b/llvm/lib/Transforms/Scalar/Reassociate.cpp index 9825a590847..e0ef8cfe46b 100644 --- a/llvm/lib/Transforms/Scalar/Reassociate.cpp +++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp @@ -1938,6 +1938,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/llvm/test/Transforms/Reassociate/canonicalize-neg-const.ll b/llvm/test/Transforms/Reassociate/canonicalize-neg-const.ll index 465460cb53b..7cb2c3a10e2 100644 --- a/llvm/test/Transforms/Reassociate/canonicalize-neg-const.ll +++ b/llvm/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 +}  | 

