mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-18 01:37:56 +00:00
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:
parent
8e58b3e9b8
commit
cd117f736c
@ -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) {
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user