[SCEV] Prove no-overflow via constant ranges
Exploit ScalarEvolution::getRange's newly acquired smartness (since
r262438) by using that to infer nsw and nuw when possible.
llvm-svn: 262639
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 0365862..2f03477 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -1454,6 +1454,11 @@
unsigned BitWidth = getTypeSizeInBits(AR->getType());
const Loop *L = AR->getLoop();
+ if (!AR->hasNoUnsignedWrap()) {
+ auto NewFlags = proveNoWrapViaConstantRanges(AR);
+ const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(NewFlags);
+ }
+
// If we have special knowledge that this addrec won't overflow,
// we don't need to do any further analysis.
if (AR->hasNoUnsignedWrap())
@@ -1663,6 +1668,11 @@
unsigned BitWidth = getTypeSizeInBits(AR->getType());
const Loop *L = AR->getLoop();
+ if (!AR->hasNoSignedWrap()) {
+ auto NewFlags = proveNoWrapViaConstantRanges(AR);
+ const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(NewFlags);
+ }
+
// If we have special knowledge that this addrec won't overflow,
// we don't need to do any further analysis.
if (AR->hasNoSignedWrap())
@@ -3757,6 +3767,37 @@
};
} // end anonymous namespace
+SCEV::NoWrapFlags
+ScalarEvolution::proveNoWrapViaConstantRanges(const SCEVAddRecExpr *AR) {
+ if (!AR->isAffine())
+ return SCEV::FlagAnyWrap;
+
+ typedef OverflowingBinaryOperator OBO;
+ SCEV::NoWrapFlags Result = SCEV::FlagAnyWrap;
+
+ if (!AR->hasNoSignedWrap()) {
+ ConstantRange AddRecRange = getSignedRange(AR);
+ ConstantRange IncRange = getSignedRange(AR->getStepRecurrence(*this));
+
+ auto NSWRegion = ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Add, IncRange, OBO::NoSignedWrap);
+ if (NSWRegion.contains(AddRecRange))
+ Result = ScalarEvolution::setFlags(Result, SCEV::FlagNSW);
+ }
+
+ if (!AR->hasNoUnsignedWrap()) {
+ ConstantRange AddRecRange = getUnsignedRange(AR);
+ ConstantRange IncRange = getUnsignedRange(AR->getStepRecurrence(*this));
+
+ auto NUWRegion = ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Add, IncRange, OBO::NoUnsignedWrap);
+ if (NUWRegion.contains(AddRecRange))
+ Result = ScalarEvolution::setFlags(Result, SCEV::FlagNUW);
+ }
+
+ return Result;
+}
+
const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
const Loop *L = LI.getLoopFor(PN->getParent());
if (!L || L->getHeader() != PN->getParent())