diff options
author | Nuno Lopes <nunoplopes@sapo.pt> | 2012-05-22 15:25:31 +0000 |
---|---|---|
committer | Nuno Lopes <nunoplopes@sapo.pt> | 2012-05-22 15:25:31 +0000 |
commit | 23e75da7e0622528be3c3908b5fe3ae8857cdf65 (patch) | |
tree | 953e680c141920c0bb5b29a2edfcbcf084614ddd /lib/Transforms | |
parent | 76ff7418361c1c80ce9d018bce63511a70bd7390 (diff) | |
download | external_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.cpp | 166 |
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 |