SCEVExpander incorrectly marks generated subtractions as nuw/nsw
authorSanjoy Das <sanjoy@playingwithpointers.com>
Thu, 26 Feb 2015 19:51:35 +0000 (19:51 +0000)
committerSanjoy Das <sanjoy@playingwithpointers.com>
Thu, 26 Feb 2015 19:51:35 +0000 (19:51 +0000)
It is not sound to mark the increment operation as `nuw` or `nsw`
based on a proof off of the add recurrence if the increment operation
we emit happens to be a `sub` instruction.

I could not come up with a test case for this -- the cases where
SCEVExpander decides to emit a `sub` instruction is quite small, and I
cannot think of a way I'd be able to get SCEV to prove that the
increment does not overflow in those cases.

Differential Revision: http://reviews.llvm.org/D7899

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@230673 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/ScalarEvolutionExpander.cpp

index 61527283f68755128f04f40f40e19f151273975d..2625cf3f958466e651c87345d239db4a3806706c 100644 (file)
@@ -1182,9 +1182,6 @@ SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized,
     }
   }
 
-  bool IncrementIsNUW = IsIncrementNUW(SE, Normalized);
-  bool IncrementIsNSW = IsIncrementNSW(SE, Normalized);
-
   // Save the original insertion point so we can restore it when we're done.
   BuilderType::InsertPointGuard Guard(Builder);
 
@@ -1219,6 +1216,12 @@ SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized,
   // Expand the step somewhere that dominates the loop header.
   Value *StepV = expandCodeFor(Step, IntTy, L->getHeader()->begin());
 
+  // The no-wrap behavior proved by IsIncrement(NUW|NSW) is only applicable if
+  // we actually do emit an addition.  It does not apply if we emit a
+  // subtraction.
+  bool IncrementIsNUW = !useSubtract && IsIncrementNUW(SE, Normalized);
+  bool IncrementIsNSW = !useSubtract && IsIncrementNSW(SE, Normalized);
+
   // Create the PHI.
   BasicBlock *Header = L->getHeader();
   Builder.SetInsertPoint(Header, Header->begin());