aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/ConstantFolding.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-05-08 04:54:43 +0000
committerChris Lattner <sabre@nondot.org>2008-05-08 04:54:43 +0000
commit268e7d7a9446bb89b80472cdb7b9803f16c0191e (patch)
tree174a213c7be4f0d3f83dcd7c8914ad11e3e5d714 /lib/Analysis/ConstantFolding.cpp
parent7e2ff77ef05c23db6b9c82bc7a4110e170d7f94c (diff)
Add support for constant folding the 'offsetof' pattern even if the
base is not zero. This fixes test/C++Frontend/2008-05-07-CrazyOffsetOf.cpp git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50840 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/ConstantFolding.cpp')
-rw-r--r--lib/Analysis/ConstantFolding.cpp39
1 files changed, 23 insertions, 16 deletions
diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp
index d58d78f077..e9efb292e5 100644
--- a/lib/Analysis/ConstantFolding.cpp
+++ b/lib/Analysis/ConstantFolding.cpp
@@ -122,25 +122,32 @@ static Constant *SymbolicallyEvaluateGEP(Constant* const* Ops, unsigned NumOps,
const Type *ResultTy,
const TargetData *TD) {
Constant *Ptr = Ops[0];
- if (!cast<PointerType>(Ptr->getType())->getElementType()->isSized())
+ if (!TD || !cast<PointerType>(Ptr->getType())->getElementType()->isSized())
return 0;
- if (TD && Ptr->isNullValue()) {
- // If this is a constant expr gep that is effectively computing an
- // "offsetof", fold it into 'cast int Size to T*' instead of 'gep 0, 0, 12'
- bool isFoldableGEP = true;
- for (unsigned i = 1; i != NumOps; ++i)
- if (!isa<ConstantInt>(Ops[i])) {
- isFoldableGEP = false;
- break;
- }
- if (isFoldableGEP) {
- uint64_t Offset = TD->getIndexedOffset(Ptr->getType(),
- (Value**)Ops+1, NumOps-1);
- Constant *C = ConstantInt::get(TD->getIntPtrType(), Offset);
- return ConstantExpr::getIntToPtr(C, ResultTy);
- }
+ uint64_t BasePtr = 0;
+ if (!Ptr->isNullValue()) {
+ // If this is a inttoptr from a constant int, we can fold this as the base,
+ // otherwise we can't.
+ if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr))
+ if (CE->getOpcode() == Instruction::IntToPtr)
+ if (ConstantInt *Base = dyn_cast<ConstantInt>(CE->getOperand(0)))
+ BasePtr = Base->getZExtValue();
+
+ if (BasePtr == 0)
+ return 0;
}
+
+ // If this is a constant expr gep that is effectively computing an
+ // "offsetof", fold it into 'cast int Size to T*' instead of 'gep 0, 0, 12'
+ for (unsigned i = 1; i != NumOps; ++i)
+ if (!isa<ConstantInt>(Ops[i]))
+ return false;
+
+ uint64_t Offset = TD->getIndexedOffset(Ptr->getType(),
+ (Value**)Ops+1, NumOps-1);
+ Constant *C = ConstantInt::get(TD->getIntPtrType(), Offset+BasePtr);
+ return ConstantExpr::getIntToPtr(C, ResultTy);
return 0;
}