Skip to content

Commit

Permalink
[Reassociate] Don't canonicalize x + (-Constant * y) -> x - (Constant…
Browse files Browse the repository at this point in the history
… * 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

llvm-svn: 311554
  • Loading branch information
Chad Rosier committed Aug 23, 2017
1 parent 06ed529 commit 8db41e9
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 0 deletions.
6 changes: 6 additions & 0 deletions llvm/lib/Transforms/Scalar/Reassociate.cpp
Expand Up @@ -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();
Expand Down
22 changes: 22 additions & 0 deletions llvm/test/Transforms/Reassociate/canonicalize-neg-const.ll
Expand Up @@ -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
}

0 comments on commit 8db41e9

Please sign in to comment.