summaryrefslogtreecommitdiffstats
path: root/llvm/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
commitf4b42f545b77a81f5db3af7b84131a77a1d2aae3 (patch)
treef8b41c2db67127604420cde967f6ce0390a19a83 /llvm/lib/Analysis/ConstantFolding.cpp
parent2b88c1e4c43838d570aca37fefd53a1c590604ad (diff)
downloadbcm5719-llvm-f4b42f545b77a81f5db3af7b84131a77a1d2aae3.tar.gz
bcm5719-llvm-f4b42f545b77a81f5db3af7b84131a77a1d2aae3.zip
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 llvm-svn: 50840
Diffstat (limited to 'llvm/lib/Analysis/ConstantFolding.cpp')
-rw-r--r--llvm/lib/Analysis/ConstantFolding.cpp39
1 files changed, 23 insertions, 16 deletions
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index d58d78f0773..e9efb292e5b 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/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;
}
OpenPOWER on IntegriCloud