Fix issues (infinite loop and/or crash) with self-referential instructions, for

example degenerate phi nodes and binops that use themselves in unreachable code.
Thanks to Charles Davis for the testcase that uncovered this can of worms.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@158508 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan Sands 2012-06-15 08:37:50 +00:00
parent 8e58b3e9b8
commit cd117f736c
2 changed files with 39 additions and 6 deletions

View File

@ -132,7 +132,7 @@ namespace {
private:
void BuildRankMap(Function &F);
unsigned getRank(Value *V);
Value *ReassociateExpression(BinaryOperator *I);
void ReassociateExpression(BinaryOperator *I);
void RewriteExprTree(BinaryOperator *I, SmallVectorImpl<ValueEntry> &Ops);
Value *OptimizeExpression(BinaryOperator *I,
SmallVectorImpl<ValueEntry> &Ops);
@ -1480,12 +1480,14 @@ void Reassociate::EraseInst(Instruction *I) {
ValueRankMap.erase(I);
I->eraseFromParent();
// Optimize its operands.
SmallPtrSet<Instruction *, 8> Visited; // Detect self-referential nodes.
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
if (Instruction *Op = dyn_cast<Instruction>(Ops[i])) {
// If this is a node in an expression tree, climb to the expression root
// and add that since that's where optimization actually happens.
unsigned Opcode = Op->getOpcode();
while (Op->hasOneUse() && Op->use_back()->getOpcode() == Opcode)
while (Op->hasOneUse() && Op->use_back()->getOpcode() == Opcode &&
Visited.insert(Op))
Op = Op->use_back();
RedoInsts.insert(Op);
}
@ -1585,7 +1587,7 @@ void Reassociate::OptimizeInst(Instruction *I) {
ReassociateExpression(BO);
}
Value *Reassociate::ReassociateExpression(BinaryOperator *I) {
void Reassociate::ReassociateExpression(BinaryOperator *I) {
// First, walk the expression tree, linearizing the tree, collecting the
// operand information.
@ -1612,6 +1614,9 @@ Value *Reassociate::ReassociateExpression(BinaryOperator *I) {
// OptimizeExpression - Now that we have the expression tree in a convenient
// sorted form, optimize it globally if possible.
if (Value *V = OptimizeExpression(I, Ops)) {
if (V == I)
// Self-referential expression in unreachable code.
return;
// This expression tree simplified to something that isn't a tree,
// eliminate it.
DEBUG(dbgs() << "Reassoc to scalar: " << *V << '\n');
@ -1620,7 +1625,7 @@ Value *Reassociate::ReassociateExpression(BinaryOperator *I) {
VI->setDebugLoc(I->getDebugLoc());
RedoInsts.insert(I);
++NumAnnihil;
return V;
return;
}
// We want to sink immediates as deeply as possible except in the case where
@ -1638,19 +1643,22 @@ Value *Reassociate::ReassociateExpression(BinaryOperator *I) {
DEBUG(dbgs() << "RAOut:\t"; PrintOps(I, Ops); dbgs() << '\n');
if (Ops.size() == 1) {
if (Ops[0].Op == I)
// Self-referential expression in unreachable code.
return;
// This expression tree simplified to something that isn't a tree,
// eliminate it.
I->replaceAllUsesWith(Ops[0].Op);
if (Instruction *OI = dyn_cast<Instruction>(Ops[0].Op))
OI->setDebugLoc(I->getDebugLoc());
RedoInsts.insert(I);
return Ops[0].Op;
return;
}
// Now that we ordered and optimized the expressions, splat them back into
// the expression tree, removing any unneeded nodes.
RewriteExprTree(I, Ops);
return I;
}
bool Reassociate::runOnFunction(Function &F) {

View File

@ -83,3 +83,28 @@ define i128 @foo() {
%mul = mul i128 0, 0
ret i128 %mul
}
define void @infinite_loop() {
entry:
br label %loop
loop:
%x = phi i32 [undef, %entry], [%x, %loop]
%dead = add i32 %x, 0
br label %loop
unreachable1:
%y1 = add i32 %y1, 0
%z1 = add i32 %y1, 0
ret void
unreachable2:
%y2 = add i32 %y2, 0
%z2 = add i32 %y2, %y2
ret void
unreachable3:
%y3 = add i32 %y3, %y3
%z3 = add i32 %y3, 0
ret void
unreachable4:
%y4 = add i32 %y4, %y4
%z4 = add i32 %y4, %y4
ret void
}