diff options
author | Chris Lattner <sabre@nondot.org> | 2008-05-08 04:54:43 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-05-08 04:54:43 +0000 |
commit | 268e7d7a9446bb89b80472cdb7b9803f16c0191e (patch) | |
tree | 174a213c7be4f0d3f83dcd7c8914ad11e3e5d714 /lib/Analysis/ConstantFolding.cpp | |
parent | 7e2ff77ef05c23db6b9c82bc7a4110e170d7f94c (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.cpp | 39 |
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; } |