aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/ScalarEvolution.cpp
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2009-12-18 02:09:29 +0000
committerDan Gohman <gohman@apple.com>2009-12-18 02:09:29 +0000
commitd281ed2d03654b9cdb290a2d7c73dfe7b826e554 (patch)
tree8be22c3822bd10a9d53c89607be45bf060f4b864 /lib/Analysis/ScalarEvolution.cpp
parentc7928f8f4eb5d15b70337fd8a6527fd6c4ed7893 (diff)
Preserve NSW information in more places.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@91656 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/ScalarEvolution.cpp')
-rw-r--r--lib/Analysis/ScalarEvolution.cpp27
1 files changed, 19 insertions, 8 deletions
diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp
index babfc858dd..551c25f07c 100644
--- a/lib/Analysis/ScalarEvolution.cpp
+++ b/lib/Analysis/ScalarEvolution.cpp
@@ -1460,7 +1460,9 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
AddRec->op_end());
AddRecOps[0] = getAddExpr(LIOps);
- const SCEV *NewRec = getAddRecExpr(AddRecOps, AddRec->getLoop());
+ const SCEV *NewRec = getAddRecExpr(AddRecOps, AddRec->getLoop(),
+ AddRec->hasNoUnsignedWrap() && HasNUW,
+ AddRec->hasNoSignedWrap() && HasNSW);
// If all of the other operands were loop invariant, we are done.
if (Ops.size() == 1) return NewRec;
@@ -1636,7 +1638,9 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
}
}
- const SCEV *NewRec = getAddRecExpr(NewOps, AddRec->getLoop());
+ const SCEV *NewRec = getAddRecExpr(NewOps, AddRec->getLoop(),
+ AddRec->hasNoUnsignedWrap() && HasNUW,
+ AddRec->hasNoSignedWrap() && HasNSW);
// If all of the other operands were loop invariant, we are done.
if (Ops.size() == 1) return NewRec;
@@ -2592,8 +2596,9 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) {
/// createNodeForGEP - Expand GEP instructions into add and multiply
/// operations. This allows them to be analyzed by regular SCEV code.
///
-const SCEV *ScalarEvolution::createNodeForGEP(Operator *GEP) {
+const SCEV *ScalarEvolution::createNodeForGEP(GEPOperator *GEP) {
+ bool InBounds = GEP->isInBounds();
const Type *IntPtrTy = getEffectiveSCEVType(GEP->getType());
Value *Base = GEP->getOperand(0);
// Don't attempt to analyze GEPs over unsized objects.
@@ -2610,18 +2615,24 @@ const SCEV *ScalarEvolution::createNodeForGEP(Operator *GEP) {
// For a struct, add the member offset.
unsigned FieldNo = cast<ConstantInt>(Index)->getZExtValue();
TotalOffset = getAddExpr(TotalOffset,
- getFieldOffsetExpr(STy, FieldNo));
+ getFieldOffsetExpr(STy, FieldNo),
+ /*HasNUW=*/false, /*HasNSW=*/InBounds);
} else {
// For an array, add the element offset, explicitly scaled.
const SCEV *LocalOffset = getSCEV(Index);
if (!isa<PointerType>(LocalOffset->getType()))
// Getelementptr indicies are signed.
LocalOffset = getTruncateOrSignExtend(LocalOffset, IntPtrTy);
- LocalOffset = getMulExpr(LocalOffset, getAllocSizeExpr(*GTI));
- TotalOffset = getAddExpr(TotalOffset, LocalOffset);
+ // Lower "inbounds" GEPs to NSW arithmetic.
+ bool HasNSW = GEP->isInBounds();
+ LocalOffset = getMulExpr(LocalOffset, getAllocSizeExpr(*GTI),
+ /*HasNUW=*/false, /*HasNSW=*/InBounds);
+ TotalOffset = getAddExpr(TotalOffset, LocalOffset,
+ /*HasNUW=*/false, /*HasNSW=*/InBounds);
}
}
- return getAddExpr(getSCEV(Base), TotalOffset);
+ return getAddExpr(getSCEV(Base), TotalOffset,
+ /*HasNUW=*/false, /*HasNSW=*/InBounds);
}
/// GetMinTrailingZeros - Determine the minimum number of zero bits that S is
@@ -3130,7 +3141,7 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
// expressions we handle are GEPs and address literals.
case Instruction::GetElementPtr:
- return createNodeForGEP(U);
+ return createNodeForGEP(cast<GEPOperator>(U));
case Instruction::PHI:
return createNodeForPHI(cast<PHINode>(U));