diff options
-rw-r--r-- | src/gallium/drivers/nv50/codegen/nv50_ir_peephole.cpp | 60 |
1 files changed, 32 insertions, 28 deletions
diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_peephole.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir_peephole.cpp index 6f34b1aeb3c..05997b6b568 100644 --- a/src/gallium/drivers/nv50/codegen/nv50_ir_peephole.cpp +++ b/src/gallium/drivers/nv50/codegen/nv50_ir_peephole.cpp @@ -1885,42 +1885,46 @@ FlatteningPass::mayPredicate(const Instruction *insn, const Value *pred) const 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 ! +// +// 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 FlatteningPass::tryPropagateBranch(BasicBlock *bb) { - BasicBlock *bf = NULL; - unsigned int i; + for (Instruction *i = bb->getExit(); i && i->op == OP_BRA; i = i->prev) { + BasicBlock *bf = i->asFlow()->target.bb; - if (bb->cfg.outgoingCount() != 2) - return; - if (!bb->getExit() || bb->getExit()->op != OP_BRA) - return; - Graph::EdgeIterator ei = bb->cfg.outgoing(); + if (bf->getInsnCount() != 1) + continue; - for (i = 0; !ei.end(); ++i, ei.next()) { - bf = BasicBlock::get(ei.getNode()); - if (bf->getInsnCount() == 1) - break; - } - if (ei.end() || !bf->getExit()) - return; - FlowInstruction *bra = bb->getExit()->asFlow(); - FlowInstruction *rep = bf->getExit()->asFlow(); + FlowInstruction *bra = i->asFlow(); + FlowInstruction *rep = bf->getExit()->asFlow(); - if (rep->getPredicate()) - return; - if (rep->op != OP_BRA && - rep->op != OP_JOIN && - rep->op != OP_EXIT) - return; + if (!rep || rep->getPredicate()) + continue; + if (rep->op != OP_BRA && + rep->op != OP_JOIN && + rep->op != OP_EXIT) + continue; - 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); + // 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); + } } bool |