aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms
diff options
context:
space:
mode:
authorNuno Lopes <nunoplopes@sapo.pt>2012-05-22 15:25:31 +0000
committerNuno Lopes <nunoplopes@sapo.pt>2012-05-22 15:25:31 +0000
commit23e75da7e0622528be3c3908b5fe3ae8857cdf65 (patch)
tree953e680c141920c0bb5b29a2edfcbcf084614ddd /lib/Transforms
parent76ff7418361c1c80ce9d018bce63511a70bd7390 (diff)
downloadexternal_llvm-23e75da7e0622528be3c3908b5fe3ae8857cdf65.zip
external_llvm-23e75da7e0622528be3c3908b5fe3ae8857cdf65.tar.gz
external_llvm-23e75da7e0622528be3c3908b5fe3ae8857cdf65.tar.bz2
revert my previous patches that introduced an additional parameter to the objectsize intrinsic.
After a lot of discussion, we realized it's not the best option for run-time bounds checking git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@157255 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r--lib/Transforms/InstCombine/InstCombineCalls.cpp166
1 files changed, 60 insertions, 106 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp
index c9b45d0..aa1cb41 100644
--- a/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -165,73 +165,6 @@ Instruction *InstCombiner::SimplifyMemSet(MemSetInst *MI) {
return 0;
}
-/// computeAllocSize - compute the object size allocated by an allocation
-/// site. Returns 0 if the size is not constant (in SizeValue), 1 if the size
-/// is constant (in Size), and 2 if the size could not be determined within the
-/// given maximum Penalty that the computation would incurr at run-time.
-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->hasDefinitiveInitializer()) {
- Constant *C = GV->getInitializer();
- Size = TD->getTypeAllocSize(C->getType());
- return 1;
- }
- // Can't determine size of the GV.
- return 2;
-
- } else if (AllocaInst *AI = dyn_cast<AllocaInst>(Alloc)) {
- if (!AI->getAllocatedType()->isSized())
- return 2;
-
- Size = TD->getTypeAllocSize(AI->getAllocatedType());
- if (!AI->isArrayAllocation())
- return 1; // we are done
-
- Value *ArraySize = AI->getArraySize();
- if (const ConstantInt *C = dyn_cast<ConstantInt>(ArraySize)) {
- Size *= C->getZExtValue();
- return 1;
- }
-
- if (Penalty < 2)
- return 2;
-
- SizeValue = ConstantInt::get(ArraySize->getType(), Size);
- SizeValue = Builder->CreateMul(SizeValue, ArraySize);
- return 0;
-
- } else if (CallInst *MI = extractMallocCall(Alloc)) {
- SizeValue = MI->getArgOperand(0);
- if (ConstantInt *CI = dyn_cast<ConstantInt>(SizeValue)) {
- Size = CI->getZExtValue();
- return 1;
- }
- return Penalty >= 2 ? 0 : 2;
-
- } else if (CallInst *MI = extractCallocCall(Alloc)) {
- Value *Arg1 = MI->getArgOperand(0);
- Value *Arg2 = MI->getArgOperand(1);
- if (ConstantInt *CI1 = dyn_cast<ConstantInt>(Arg1)) {
- if (ConstantInt *CI2 = dyn_cast<ConstantInt>(Arg2)) {
- Size = (CI1->getValue() * CI2->getValue()).getZExtValue();
- return 1;
- }
- }
-
- if (Penalty < 2)
- return 2;
-
- SizeValue = Builder->CreateMul(Arg1, Arg2);
- return 0;
- }
-
- DEBUG(errs() << "computeAllocSize failed:\n");
- DEBUG(Alloc->dump());
- return 2;
-}
-
/// visitCallInst - CallInst simplification. This mostly only handles folding
/// of intrinsic instructions. For normal calls, it allows visitCallSite to do
/// the heavy lifting.
@@ -317,59 +250,80 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
if (!TD) return 0;
Type *ReturnTy = CI.getType();
- uint64_t Penalty = cast<ConstantInt>(II->getArgOperand(2))->getZExtValue();
+ uint64_t DontKnow = II->getArgOperand(1) == Builder->getTrue() ? 0 : -1ULL;
// Get to the real allocated thing and offset as fast as possible.
Value *Op1 = II->getArgOperand(0)->stripPointerCasts();
- GEPOperator *GEP;
- if ((GEP = dyn_cast<GEPOperator>(Op1))) {
- // check if we will be able to get the offset
- if (!GEP->hasAllConstantIndices() && Penalty < 2)
+ uint64_t Offset = 0;
+ uint64_t Size = -1ULL;
+
+ // 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())
return 0;
+ Offset = TD->getIndexedOffset(GEP->getPointerOperandType(), Ops);
+
Op1 = GEP->getPointerOperand()->stripPointerCasts();
+
+ // Make sure we're not a constant offset from an external
+ // global.
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Op1))
+ if (!GV->hasDefinitiveInitializer()) return 0;
}
- uint64_t Size;
- Value *SizeValue;
- int ConstAlloc = computeAllocSize(Op1, Size, SizeValue, Penalty, TD,
- Builder);
+ // 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();
+ Size = TD->getTypeAllocSize(C->getType());
+ } else {
+ // Can't determine size of the GV.
+ Constant *RetVal = ConstantInt::get(ReturnTy, DontKnow);
+ return ReplaceInstUsesWith(CI, RetVal);
+ }
+ } else if (AllocaInst *AI = dyn_cast<AllocaInst>(Op1)) {
+ // Get alloca size.
+ if (AI->getAllocatedType()->isSized()) {
+ Size = TD->getTypeAllocSize(AI->getAllocatedType());
+ if (AI->isArrayAllocation()) {
+ const ConstantInt *C = dyn_cast<ConstantInt>(AI->getArraySize());
+ if (!C) return 0;
+ Size *= C->getZExtValue();
+ }
+ }
+ } else if (CallInst *MI = extractMallocCall(Op1)) {
+ // Get allocation size.
+ Value *Arg = MI->getArgOperand(0);
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(Arg))
+ Size = CI->getZExtValue();
+
+ } else if (CallInst *MI = extractCallocCall(Op1)) {
+ // Get allocation size.
+ Value *Arg1 = MI->getArgOperand(0);
+ Value *Arg2 = MI->getArgOperand(1);
+ if (ConstantInt *CI1 = dyn_cast<ConstantInt>(Arg1))
+ if (ConstantInt *CI2 = dyn_cast<ConstantInt>(Arg2))
+ Size = (CI1->getValue() * CI2->getValue()).getZExtValue();
+ }
// Do not return "I don't know" here. Later optimization passes could
// make it possible to evaluate objectsize to a constant.
- if (ConstAlloc == 2)
+ if (Size == -1ULL)
return 0;
- 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));
+ if (Size < Offset) {
+ // Out of bound reference? Negative index normalized to large
+ // index? Just return "I don't know".
+ return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, DontKnow));
}
-
- if (!OffsetValue)
- OffsetValue = ConstantInt::get(ReturnTy, Offset);
- if (ConstAlloc)
- SizeValue = ConstantInt::get(ReturnTy, Size);
-
- 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);
+ return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, Size-Offset));
}
case Intrinsic::bswap:
// bswap(bswap(x)) -> x