extsrc/mesa/src/gallium/drivers/nv50/codegen/nv50_ir_ra.cpp
// For each operand of each PHI in b, generate a new value by inserting a MOV
// at the end of the block it is coming from and replace the operand with its
// result. This eliminates liveness conflicts and enables us to let values be
// copied to the right register if such a conflict exists nonetheless.
//
// These MOVs are also crucial in making sure the live intervals of phi srces
// are extended until the end of the loop, since they are not included in the
// live-in sets.
For each operand of each PHI in b, generate a new value by inserting a MOV
at the end of the block it is coming from and replace the operand with its
result. This eliminates liveness conflicts and enables us to let values be
copied to the right register if such a conflict exists nonetheless.

These MOVs are also crucial in making sure the live intervals of phi srces
are extended until the end of the loop, since they are not included in the
live-in sets.
For each operand of each PHI in b generate a new value by inserting a MOV at the end of the block it is coming from and replace the operand with its result . This eliminates liveness conflicts and enables us to let values be copied to the right register if such a conflict exists nonetheless . These MOVs are also crucial in making sure the live intervals of phi srces are extended until the end of the loop since they are not included in the live - in sets .
bool
RegAlloc::PhiMovesPass::visit(BasicBlock *bb)
{
   Instruction *phi, *mov;
   BasicBlock *pb, *pn;
   for (Graph::EdgeIterator ei = bb->cfg.incident(); !ei.end(); ei.next()) {
      pb = pn = BasicBlock::get(ei.getNode());
      assert(pb);
      if (needNewElseBlock(bb, pb)) {
         pn = new BasicBlock(func);
         pb->cfg.detach(&bb->cfg);
         pb->cfg.attach(&pn->cfg, Graph::Edge::TREE);
         pn->cfg.attach(&bb->cfg, Graph::Edge::FORWARD); 
         assert(pb->getExit()->op != OP_CALL);
         if (pb->getExit()->asFlow()->target.bb == bb)
            pb->getExit()->asFlow()->target.bb = pn;
         break;
      }
   }
   int j = 0;
   for (Graph::EdgeIterator ei = bb->cfg.incident(); !ei.end(); ei.next()) {
      pb = BasicBlock::get(ei.getNode());
      if (!pb->isTerminated())
         pb->insertTail(new_FlowInstruction(func, OP_BRA, bb));
      for (phi = bb->getPhi(); phi && phi->op == OP_PHI; phi = phi->next) {
         mov = new_Instruction(func, OP_MOV, TYPE_U32);
         mov->setSrc(0, phi->getSrc(j));
         mov->setDef(0, new_LValue(func, phi->getDef(0)->asLValue()));
         phi->setSrc(j, mov->getDef(0));
         pb->insertBefore(pb->getExit(), mov);
      }
      ++j;
   }
   return true;
}
bool RegAlloc :: PhiMovesPass :: visit ( BasicBlock * bb ) { Instruction * phi , * mov ; BasicBlock * pb , * pn ; for ( Graph :: EdgeIterator ei = bb -> cfg . incident ( ) ; ! ei . end ( ) ; ei . next ( ) ) { pb = pn = BasicBlock :: get ( ei . getNode ( ) ) ; assert ( pb ) ; if ( needNewElseBlock ( bb , pb ) ) { pn = new BasicBlock ( func ) ; pb -> cfg . detach ( & bb -> cfg ) ; pb -> cfg . attach ( & pn -> cfg , Graph :: Edge :: TREE ) ; pn -> cfg . attach ( & bb -> cfg , Graph :: Edge :: FORWARD ) ; assert ( pb -> getExit ( ) -> op != OP_CALL ) ; if ( pb -> getExit ( ) -> asFlow ( ) -> target . bb == bb ) pb -> getExit ( ) -> asFlow ( ) -> target . bb = pn ; break ; } } int j = 0 ; for ( Graph :: EdgeIterator ei = bb -> cfg . incident ( ) ; ! ei . end ( ) ; ei . next ( ) ) { pb = BasicBlock :: get ( ei . getNode ( ) ) ; if ( ! pb -> isTerminated ( ) ) pb -> insertTail ( new_FlowInstruction ( func , OP_BRA , bb ) ) ; for ( phi = bb -> getPhi ( ) ; phi && phi -> op == OP_PHI ; phi = phi -> next ) { mov = new_Instruction ( func , OP_MOV , TYPE_U32 ) ; mov -> setSrc ( 0 , phi -> getSrc ( j ) ) ; mov -> setDef ( 0 , new_LValue ( func , phi -> getDef ( 0 ) -> asLValue ( ) ) ) ; phi -> setSrc ( j , mov -> getDef ( 0 ) ) ; pb -> insertBefore ( pb -> getExit ( ) , mov ) ; } ++ j ; } return true ; }
For each operand of each PHI in b, generate a new value by inserting a MOV
at the end of the block it is coming from and replace the operand with its
result.
For each operand of each PHI in b generate a new value by inserting a MOV at the end of the block it is coming from and replace the operand with its result .
// deletes an edge, iterator is invalid after this: // XXX: check order ! // insert MOVs (phi->src[j] should stem from j-th in-BB)