diff options
author | Nuno Lopes <nunoplopes@sapo.pt> | 2012-05-10 23:17:35 +0000 |
---|---|---|
committer | Nuno Lopes <nunoplopes@sapo.pt> | 2012-05-10 23:17:35 +0000 |
commit | 9d236f909cec671ef2ff186c8fce6d2e1540a0a9 (patch) | |
tree | 49729dbb18282aae564c029b4effaf97f90f7b01 /lib/Transforms | |
parent | deaa3f3e523183b611249bba636876cb05c5881a (diff) |
objectsize: add support for GEPs with non-constant indexes
add an additional parameter to InstCombiner::EmitGEPOffset() to force it to *not* emit operations with NUW flag
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156585 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r-- | lib/Transforms/InstCombine/InstCombine.h | 2 | ||||
-rw-r--r-- | lib/Transforms/InstCombine/InstCombineAddSub.cpp | 5 | ||||
-rw-r--r-- | lib/Transforms/InstCombine/InstCombineCalls.cpp | 61 |
3 files changed, 34 insertions, 34 deletions
diff --git a/lib/Transforms/InstCombine/InstCombine.h b/lib/Transforms/InstCombine/InstCombine.h index 199df519ce..41b2456e72 100644 --- a/lib/Transforms/InstCombine/InstCombine.h +++ b/lib/Transforms/InstCombine/InstCombine.h @@ -226,7 +226,7 @@ private: bool DoXform = true); Instruction *transformSExtICmp(ICmpInst *ICI, Instruction &CI); bool WillNotOverflowSignedAdd(Value *LHS, Value *RHS); - Value *EmitGEPOffset(User *GEP); + Value *EmitGEPOffset(User *GEP, bool NoNUW = false); public: // InsertNewInstBefore - insert an instruction New before instruction Old diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 6a39fc33d4..8420a6a96e 100644 --- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -423,7 +423,8 @@ Instruction *InstCombiner::visitFAdd(BinaryOperator &I) { /// EmitGEPOffset - Given a getelementptr instruction/constantexpr, emit the /// code necessary to compute the offset from the base pointer (without adding /// in the base pointer). Return the result as a signed integer of intptr size. -Value *InstCombiner::EmitGEPOffset(User *GEP) { +/// If NoNUW is true, then the NUW flag is not used. +Value *InstCombiner::EmitGEPOffset(User *GEP, bool NoNUW) { TargetData &TD = *getTargetData(); gep_type_iterator GTI = gep_type_begin(GEP); Type *IntPtrTy = TD.getIntPtrType(GEP->getContext()); @@ -431,7 +432,7 @@ Value *InstCombiner::EmitGEPOffset(User *GEP) { // If the GEP is inbounds, we know that none of the addressing operations will // overflow in an unsigned sense. - bool isInBounds = cast<GEPOperator>(GEP)->isInBounds(); + bool isInBounds = cast<GEPOperator>(GEP)->isInBounds() && !NoNUW; // Build a mask for high order bits. unsigned IntPtrWidth = TD.getPointerSizeInBits(); diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index 82487a020f..ea3f95ed23 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -173,7 +173,7 @@ static int computeAllocSize(Value *Alloc, uint64_t &Size, Value* &SizeValue, uint64_t Penalty, TargetData *TD, InstCombiner::BuilderTy *Builder) { if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Alloc)) { - if (GV->hasUniqueInitializer()) { + if (GV->hasDefinitiveInitializer()) { Constant *C = GV->getInitializer(); Size = TD->getTypeAllocSize(C->getType()); return 1; @@ -198,7 +198,8 @@ static int computeAllocSize(Value *Alloc, uint64_t &Size, Value* &SizeValue, if (Penalty < 2) return 2; - SizeValue = Builder->CreateMul(Builder->getInt64(Size), ArraySize); + SizeValue = ConstantInt::get(ArraySize->getType(), Size); + SizeValue = Builder->CreateMul(SizeValue, ArraySize); return 0; } else if (CallInst *MI = extractMallocCall(Alloc)) { @@ -320,22 +321,12 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { // Get to the real allocated thing and offset as fast as possible. Value *Op1 = II->getArgOperand(0)->stripPointerCasts(); + GEPOperator *GEP; - uint64_t Offset = 0; - Value *OffsetValue; - bool ConstOffset = true; - - // Try to look through constant GEPs. - if (GEPOperator *GEP = dyn_cast<GEPOperator>(Op1)) { - if (!GEP->hasAllConstantIndices()) return 0; - - // Get the current byte offset into the thing. Use the original - // operand in case we're looking through a bitcast. - SmallVector<Value*, 8> Ops(GEP->idx_begin(), GEP->idx_end()); - if (!GEP->getPointerOperandType()->isPointerTy()) + if ((GEP = dyn_cast<GEPOperator>(Op1))) { + // check if we will be able to get the offset + if (!GEP->hasAllConstantIndices() && Penalty < 2) return 0; - Offset = TD->getIndexedOffset(GEP->getPointerOperandType(), Ops); - Op1 = GEP->getPointerOperand()->stripPointerCasts(); } @@ -349,28 +340,36 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { if (ConstAlloc == 2) return 0; - if (ConstOffset && ConstAlloc) { + uint64_t Offset = 0; + Value *OffsetValue = 0; + + if (GEP) { + if (GEP->hasAllConstantIndices()) { + SmallVector<Value*, 8> Ops(GEP->idx_begin(), GEP->idx_end()); + assert(GEP->getPointerOperandType()->isPointerTy()); + Offset = TD->getIndexedOffset(GEP->getPointerOperandType(), Ops); + } else + OffsetValue = EmitGEPOffset(GEP, true /*NoNUW*/); + } + + if (!OffsetValue && ConstAlloc) { if (Size < Offset) { // Out of bounds return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, 0)); } return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, Size-Offset)); + } - } else if (Penalty >= 2) { - if (ConstOffset) - OffsetValue = Builder->getInt64(Offset); - if (ConstAlloc) - SizeValue = Builder->getInt64(Size); - - Value *Val = Builder->CreateSub(SizeValue, OffsetValue); - Val = Builder->CreateTrunc(Val, ReturnTy); - // return 0 if there's an overflow - Value *Cmp = Builder->CreateICmpULT(SizeValue, OffsetValue); - Val = Builder->CreateSelect(Cmp, ConstantInt::get(ReturnTy, 0), Val); - return ReplaceInstUsesWith(CI, Val); + if (!OffsetValue) + OffsetValue = ConstantInt::get(ReturnTy, Offset); + if (ConstAlloc) + SizeValue = ConstantInt::get(ReturnTy, Size); - } else - return 0; + Value *Val = Builder->CreateSub(SizeValue, OffsetValue); + // return 0 if there's an overflow + Value *Cmp = Builder->CreateICmpULT(SizeValue, OffsetValue); + Val = Builder->CreateSelect(Cmp, ConstantInt::get(ReturnTy, 0), Val); + return ReplaceInstUsesWith(CI, Val); } case Intrinsic::bswap: // bswap(bswap(x)) -> x |