aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorEric Christopher <echristo@apple.com>2010-02-11 01:48:54 +0000
committerEric Christopher <echristo@apple.com>2010-02-11 01:48:54 +0000
commit26d0e892e36e8dcc4248a8ccc8bedbd2d235eaee (patch)
tree20faca531f79e04e06ecb6ea03f1ee4cff6945cf /lib
parentf87052a55ac7525dc86932549f2bc4bd69dd5d1b (diff)
downloadexternal_llvm-26d0e892e36e8dcc4248a8ccc8bedbd2d235eaee.zip
external_llvm-26d0e892e36e8dcc4248a8ccc8bedbd2d235eaee.tar.gz
external_llvm-26d0e892e36e8dcc4248a8ccc8bedbd2d235eaee.tar.bz2
Add ConstantExpr handling to Intrinsic::objectsize lowering.
Update testcase accordingly now that we can optimize another section. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@95846 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Transforms/InstCombine/InstCombineCalls.cpp27
1 files changed, 26 insertions, 1 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 4929f40..1371fa7 100644
--- a/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -308,9 +308,14 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
Value *Op1 = II->getOperand(1);
bool Min = (cast<ConstantInt>(II->getOperand(2))->getZExtValue() == 1);
+ // We need target data for just about everything so depend on it.
if (!TD) break;
+
+ // Get to the real allocated thing and offset as fast as possible.
Op1 = Op1->stripPointerCasts();
+ // If we've stripped down to a single global variable that we
+ // can know the size of then just return that.
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Op1)) {
if (GV->hasDefinitiveInitializer()) {
Constant *C = GV->getInitializer();
@@ -320,7 +325,27 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
Constant *RetVal = ConstantInt::get(ReturnTy, Min ? 0 : -1ULL);
return ReplaceInstUsesWith(CI, RetVal);
}
- }
+ } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Op1)) {
+
+ // Only handle constant GEPs here.
+ if (CE->getOpcode() != Instruction::GetElementPtr) break;
+ GEPOperator *GEP = cast<GEPOperator>(CE);
+
+ // Get what we're pointing to and its size.
+ const PointerType *PT =
+ cast<PointerType>(GEP->getPointerOperand()->getType());
+ size_t Size = TD->getTypeAllocSize(PT->getElementType());
+
+ // Get the current byte offset into the thing.
+ SmallVector<Value*, 8> Ops(CE->op_begin()+1, CE->op_end());
+ size_t Offset = TD->getIndexedOffset(PT, &Ops[0], Ops.size());
+
+ assert(Size >= Offset);
+
+ Constant *RetVal = ConstantInt::get(ReturnTy, Size-Offset);
+ return ReplaceInstUsesWith(CI, RetVal);
+
+ }
}
case Intrinsic::bswap:
// bswap(bswap(x)) -> x