MemoryBuiltins: Properly guard ObjectSizeOffsetVisitor against cycles in the IR.

The previous fix only checked for simple cycles, use a set to catch longer
cycles too.

Drop the broken check from the ObjectSizeOffsetEvaluator. The BoundsChecking
pass doesn't have to deal with invalid IR like InstCombine does.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@162120 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Benjamin Kramer 2012-08-17 19:26:41 +00:00
parent 32811bef95
commit 168843c013
3 changed files with 17 additions and 20 deletions

View File

@ -146,6 +146,7 @@ class ObjectSizeOffsetVisitor
bool RoundToAlign; bool RoundToAlign;
unsigned IntTyBits; unsigned IntTyBits;
APInt Zero; APInt Zero;
SmallPtrSet<Instruction *, 8> SeenInsts;
APInt align(APInt Size, uint64_t Align); APInt align(APInt Size, uint64_t Align);
@ -203,7 +204,6 @@ class ObjectSizeOffsetEvaluator
const TargetData *TD; const TargetData *TD;
LLVMContext &Context; LLVMContext &Context;
BuilderTy Builder; BuilderTy Builder;
ObjectSizeOffsetVisitor Visitor;
IntegerType *IntTy; IntegerType *IntTy;
Value *Zero; Value *Zero;
CacheMapTy CacheMap; CacheMapTy CacheMap;

View File

@ -358,11 +358,16 @@ ObjectSizeOffsetVisitor::ObjectSizeOffsetVisitor(const TargetData *TD,
SizeOffsetType ObjectSizeOffsetVisitor::compute(Value *V) { SizeOffsetType ObjectSizeOffsetVisitor::compute(Value *V) {
V = V->stripPointerCasts(); V = V->stripPointerCasts();
if (Instruction *I = dyn_cast<Instruction>(V)) {
// If we have already seen this instruction, bail out. Cycles can happen in
// unreachable code after constant propagation.
if (!SeenInsts.insert(I))
return unknown();
if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) if (GEPOperator *GEP = dyn_cast<GEPOperator>(V))
return visitGEPOperator(*GEP); return visitGEPOperator(*GEP);
if (Instruction *I = dyn_cast<Instruction>(V))
return visit(*I); return visit(*I);
}
if (Argument *A = dyn_cast<Argument>(V)) if (Argument *A = dyn_cast<Argument>(V))
return visitArgument(*A); return visitArgument(*A);
if (ConstantPointerNull *P = dyn_cast<ConstantPointerNull>(V)) if (ConstantPointerNull *P = dyn_cast<ConstantPointerNull>(V))
@ -371,9 +376,12 @@ SizeOffsetType ObjectSizeOffsetVisitor::compute(Value *V) {
return visitGlobalVariable(*GV); return visitGlobalVariable(*GV);
if (UndefValue *UV = dyn_cast<UndefValue>(V)) if (UndefValue *UV = dyn_cast<UndefValue>(V))
return visitUndefValue(*UV); return visitUndefValue(*UV);
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
if (CE->getOpcode() == Instruction::IntToPtr) if (CE->getOpcode() == Instruction::IntToPtr)
return unknown(); // clueless return unknown(); // clueless
if (CE->getOpcode() == Instruction::GetElementPtr)
return visitGEPOperator(cast<GEPOperator>(*CE));
}
DEBUG(dbgs() << "ObjectSizeOffsetVisitor::compute() unhandled value: " << *V DEBUG(dbgs() << "ObjectSizeOffsetVisitor::compute() unhandled value: " << *V
<< '\n'); << '\n');
@ -473,10 +481,6 @@ ObjectSizeOffsetVisitor::visitExtractValueInst(ExtractValueInst&) {
} }
SizeOffsetType ObjectSizeOffsetVisitor::visitGEPOperator(GEPOperator &GEP) { SizeOffsetType ObjectSizeOffsetVisitor::visitGEPOperator(GEPOperator &GEP) {
// Ignore self-referencing GEPs, they can occur in unreachable code.
if (&GEP == GEP.getPointerOperand())
return unknown();
SizeOffsetType PtrData = compute(GEP.getPointerOperand()); SizeOffsetType PtrData = compute(GEP.getPointerOperand());
if (!bothKnown(PtrData) || !GEP.hasAllConstantIndices()) if (!bothKnown(PtrData) || !GEP.hasAllConstantIndices())
return unknown(); return unknown();
@ -510,10 +514,6 @@ SizeOffsetType ObjectSizeOffsetVisitor::visitPHINode(PHINode&) {
} }
SizeOffsetType ObjectSizeOffsetVisitor::visitSelectInst(SelectInst &I) { SizeOffsetType ObjectSizeOffsetVisitor::visitSelectInst(SelectInst &I) {
// ignore malformed self-looping selects
if (I.getTrueValue() == &I || I.getFalseValue() == &I)
return unknown();
SizeOffsetType TrueSide = compute(I.getTrueValue()); SizeOffsetType TrueSide = compute(I.getTrueValue());
SizeOffsetType FalseSide = compute(I.getFalseValue()); SizeOffsetType FalseSide = compute(I.getFalseValue());
if (bothKnown(TrueSide) && bothKnown(FalseSide) && TrueSide == FalseSide) if (bothKnown(TrueSide) && bothKnown(FalseSide) && TrueSide == FalseSide)
@ -533,8 +533,7 @@ SizeOffsetType ObjectSizeOffsetVisitor::visitInstruction(Instruction &I) {
ObjectSizeOffsetEvaluator::ObjectSizeOffsetEvaluator(const TargetData *TD, ObjectSizeOffsetEvaluator::ObjectSizeOffsetEvaluator(const TargetData *TD,
LLVMContext &Context) LLVMContext &Context)
: TD(TD), Context(Context), Builder(Context, TargetFolder(TD)), : TD(TD), Context(Context), Builder(Context, TargetFolder(TD)) {
Visitor(TD, Context) {
IntTy = TD->getIntPtrType(Context); IntTy = TD->getIntPtrType(Context);
Zero = ConstantInt::get(IntTy, 0); Zero = ConstantInt::get(IntTy, 0);
} }
@ -559,6 +558,7 @@ SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute(Value *V) {
} }
SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute_(Value *V) { SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute_(Value *V) {
ObjectSizeOffsetVisitor Visitor(TD, Context);
SizeOffsetType Const = Visitor.compute(V); SizeOffsetType Const = Visitor.compute(V);
if (Visitor.bothKnown(Const)) if (Visitor.bothKnown(Const))
return std::make_pair(ConstantInt::get(Context, Const.first), return std::make_pair(ConstantInt::get(Context, Const.first),
@ -719,10 +719,6 @@ SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitPHINode(PHINode &PHI) {
} }
SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitSelectInst(SelectInst &I) { SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitSelectInst(SelectInst &I) {
// ignore malformed self-looping selects
if (I.getTrueValue() == &I || I.getFalseValue() == &I)
return unknown();
SizeOffsetEvalType TrueSide = compute_(I.getTrueValue()); SizeOffsetEvalType TrueSide = compute_(I.getTrueValue());
SizeOffsetEvalType FalseSide = compute_(I.getFalseValue()); SizeOffsetEvalType FalseSide = compute_(I.getFalseValue());

View File

@ -247,7 +247,8 @@ entry:
; technically reachable, but this malformed IR may appear as a result of constant propagation ; technically reachable, but this malformed IR may appear as a result of constant propagation
xpto: xpto:
%gep = getelementptr i8* %gep, i32 1 %gep2 = getelementptr i8* %gep, i32 1
%gep = getelementptr i8* %gep2, i32 1
%o = call i32 @llvm.objectsize.i32(i8* %gep, i1 true) %o = call i32 @llvm.objectsize.i32(i8* %gep, i1 true)
; CHECK: ret i32 undef ; CHECK: ret i32 undef
ret i32 %o ret i32 %o