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 | f4b42f545b77a81f5db3af7b84131a77a1d2aae3 (patch) | |
tree | f8b41c2db67127604420cde967f6ce0390a19a83 /llvm/lib/Analysis/ConstantFolding.cpp | |
parent | 2b88c1e4c43838d570aca37fefd53a1c590604ad (diff) | |
download | bcm5719-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.cpp | 39 |
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; } |