nv50/ir/opt: Fix tryPropagateBranch for BBs with several exit branches.
Comments and "if (bf->cfg.incidentCount() == 1)" condition added by Christoph Bumiller.
This commit is contained in:
parent
572bf83ec0
commit
5959d4247a
|
@ -1885,42 +1885,46 @@ FlatteningPass::mayPredicate(const Instruction *insn, const Value *pred) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we conditionally skip over or to a branch instruction, replace it.
|
// If we jump to BRA/RET/EXIT, replace the jump with it.
|
||||||
// NOTE: We do not update the CFG anymore here !
|
// NOTE: We do not update the CFG anymore here !
|
||||||
|
//
|
||||||
|
// TODO: Handle cases where we skip over a branch (maybe do that elsewhere ?):
|
||||||
|
// BB:0
|
||||||
|
// @p0 bra BB:2 -> @!p0 bra BB:3 iff (!) BB:2 immediately adjoins BB:1
|
||||||
|
// BB1:
|
||||||
|
// bra BB:3
|
||||||
|
// BB2:
|
||||||
|
// ...
|
||||||
|
// BB3:
|
||||||
|
// ...
|
||||||
void
|
void
|
||||||
FlatteningPass::tryPropagateBranch(BasicBlock *bb)
|
FlatteningPass::tryPropagateBranch(BasicBlock *bb)
|
||||||
{
|
{
|
||||||
BasicBlock *bf = NULL;
|
for (Instruction *i = bb->getExit(); i && i->op == OP_BRA; i = i->prev) {
|
||||||
unsigned int i;
|
BasicBlock *bf = i->asFlow()->target.bb;
|
||||||
|
|
||||||
if (bb->cfg.outgoingCount() != 2)
|
if (bf->getInsnCount() != 1)
|
||||||
return;
|
continue;
|
||||||
if (!bb->getExit() || bb->getExit()->op != OP_BRA)
|
|
||||||
return;
|
|
||||||
Graph::EdgeIterator ei = bb->cfg.outgoing();
|
|
||||||
|
|
||||||
for (i = 0; !ei.end(); ++i, ei.next()) {
|
FlowInstruction *bra = i->asFlow();
|
||||||
bf = BasicBlock::get(ei.getNode());
|
FlowInstruction *rep = bf->getExit()->asFlow();
|
||||||
if (bf->getInsnCount() == 1)
|
|
||||||
break;
|
if (!rep || rep->getPredicate())
|
||||||
|
continue;
|
||||||
|
if (rep->op != OP_BRA &&
|
||||||
|
rep->op != OP_JOIN &&
|
||||||
|
rep->op != OP_EXIT)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// TODO: If there are multiple branches to @rep, only the first would
|
||||||
|
// be replaced, so only remove them after this pass is done ?
|
||||||
|
// Also, need to check all incident blocks for fall-through exits and
|
||||||
|
// add the branch there.
|
||||||
|
bra->op = rep->op;
|
||||||
|
bra->target.bb = rep->target.bb;
|
||||||
|
if (bf->cfg.incidentCount() == 1)
|
||||||
|
bf->remove(rep);
|
||||||
}
|
}
|
||||||
if (ei.end() || !bf->getExit())
|
|
||||||
return;
|
|
||||||
FlowInstruction *bra = bb->getExit()->asFlow();
|
|
||||||
FlowInstruction *rep = bf->getExit()->asFlow();
|
|
||||||
|
|
||||||
if (rep->getPredicate())
|
|
||||||
return;
|
|
||||||
if (rep->op != OP_BRA &&
|
|
||||||
rep->op != OP_JOIN &&
|
|
||||||
rep->op != OP_EXIT)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bra->op = rep->op;
|
|
||||||
bra->target.bb = rep->target.bb;
|
|
||||||
if (i) // 2nd out block means branch not taken
|
|
||||||
bra->cc = inverseCondCode(bra->cc);
|
|
||||||
bf->remove(rep);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
Loading…
Reference in New Issue