mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-15 05:24:01 +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:
@ -132,7 +132,7 @@ namespace {
|
|||||||
private:
|
private:
|
||||||
void BuildRankMap(Function &F);
|
void BuildRankMap(Function &F);
|
||||||
unsigned getRank(Value *V);
|
unsigned getRank(Value *V);
|
||||||
Value *ReassociateExpression(BinaryOperator *I);
|
void ReassociateExpression(BinaryOperator *I);
|
||||||
void RewriteExprTree(BinaryOperator *I, SmallVectorImpl<ValueEntry> &Ops);
|
void RewriteExprTree(BinaryOperator *I, SmallVectorImpl<ValueEntry> &Ops);
|
||||||
Value *OptimizeExpression(BinaryOperator *I,
|
Value *OptimizeExpression(BinaryOperator *I,
|
||||||
SmallVectorImpl<ValueEntry> &Ops);
|
SmallVectorImpl<ValueEntry> &Ops);
|
||||||
@ -1480,12 +1480,14 @@ void Reassociate::EraseInst(Instruction *I) {
|
|||||||
ValueRankMap.erase(I);
|
ValueRankMap.erase(I);
|
||||||
I->eraseFromParent();
|
I->eraseFromParent();
|
||||||
// Optimize its operands.
|
// Optimize its operands.
|
||||||
|
SmallPtrSet<Instruction *, 8> Visited; // Detect self-referential nodes.
|
||||||
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
|
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
|
||||||
if (Instruction *Op = dyn_cast<Instruction>(Ops[i])) {
|
if (Instruction *Op = dyn_cast<Instruction>(Ops[i])) {
|
||||||
// If this is a node in an expression tree, climb to the expression root
|
// If this is a node in an expression tree, climb to the expression root
|
||||||
// and add that since that's where optimization actually happens.
|
// and add that since that's where optimization actually happens.
|
||||||
unsigned Opcode = Op->getOpcode();
|
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();
|
Op = Op->use_back();
|
||||||
RedoInsts.insert(Op);
|
RedoInsts.insert(Op);
|
||||||
}
|
}
|
||||||
@ -1585,7 +1587,7 @@ void Reassociate::OptimizeInst(Instruction *I) {
|
|||||||
ReassociateExpression(BO);
|
ReassociateExpression(BO);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *Reassociate::ReassociateExpression(BinaryOperator *I) {
|
void Reassociate::ReassociateExpression(BinaryOperator *I) {
|
||||||
|
|
||||||
// First, walk the expression tree, linearizing the tree, collecting the
|
// First, walk the expression tree, linearizing the tree, collecting the
|
||||||
// operand information.
|
// operand information.
|
||||||
@ -1612,6 +1614,9 @@ Value *Reassociate::ReassociateExpression(BinaryOperator *I) {
|
|||||||
// OptimizeExpression - Now that we have the expression tree in a convenient
|
// OptimizeExpression - Now that we have the expression tree in a convenient
|
||||||
// sorted form, optimize it globally if possible.
|
// sorted form, optimize it globally if possible.
|
||||||
if (Value *V = OptimizeExpression(I, Ops)) {
|
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,
|
// This expression tree simplified to something that isn't a tree,
|
||||||
// eliminate it.
|
// eliminate it.
|
||||||
DEBUG(dbgs() << "Reassoc to scalar: " << *V << '\n');
|
DEBUG(dbgs() << "Reassoc to scalar: " << *V << '\n');
|
||||||
@ -1620,7 +1625,7 @@ Value *Reassociate::ReassociateExpression(BinaryOperator *I) {
|
|||||||
VI->setDebugLoc(I->getDebugLoc());
|
VI->setDebugLoc(I->getDebugLoc());
|
||||||
RedoInsts.insert(I);
|
RedoInsts.insert(I);
|
||||||
++NumAnnihil;
|
++NumAnnihil;
|
||||||
return V;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want to sink immediates as deeply as possible except in the case where
|
// 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');
|
DEBUG(dbgs() << "RAOut:\t"; PrintOps(I, Ops); dbgs() << '\n');
|
||||||
|
|
||||||
if (Ops.size() == 1) {
|
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,
|
// This expression tree simplified to something that isn't a tree,
|
||||||
// eliminate it.
|
// eliminate it.
|
||||||
I->replaceAllUsesWith(Ops[0].Op);
|
I->replaceAllUsesWith(Ops[0].Op);
|
||||||
if (Instruction *OI = dyn_cast<Instruction>(Ops[0].Op))
|
if (Instruction *OI = dyn_cast<Instruction>(Ops[0].Op))
|
||||||
OI->setDebugLoc(I->getDebugLoc());
|
OI->setDebugLoc(I->getDebugLoc());
|
||||||
RedoInsts.insert(I);
|
RedoInsts.insert(I);
|
||||||
return Ops[0].Op;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we ordered and optimized the expressions, splat them back into
|
// Now that we ordered and optimized the expressions, splat them back into
|
||||||
// the expression tree, removing any unneeded nodes.
|
// the expression tree, removing any unneeded nodes.
|
||||||
RewriteExprTree(I, Ops);
|
RewriteExprTree(I, Ops);
|
||||||
return I;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Reassociate::runOnFunction(Function &F) {
|
bool Reassociate::runOnFunction(Function &F) {
|
||||||
|
@ -83,3 +83,28 @@ define i128 @foo() {
|
|||||||
%mul = mul i128 0, 0
|
%mul = mul i128 0, 0
|
||||||
ret i128 %mul
|
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
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user