diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp
index 898653c..1bb5194 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp
@@ -25,8 +25,21 @@
 
 #include <stack>
 #include <limits>
+#include <tr1/unordered_map>
 #include <tr1/unordered_set>
 
+namespace std {
+namespace tr1 {
+template <typename T, typename U>
+struct hash<std::pair<T*, U*> > {
+public:
+   size_t operator()(std::pair<T*, U*> val) const {
+      return hash<T*>()(val.first) * 31 + hash<U*>()(val.second);
+   }
+};
+}
+}
+
 namespace nv50_ir {
 
 #define MAX_REGISTER_FILE_SIZE 256
@@ -359,14 +372,25 @@ RegAlloc::PhiMovesPass::visit(BasicBlock *bb)
 {
    Instruction *phi, *mov;
    BasicBlock *pb, *pn;
+   int j;
 
    std::stack<BasicBlock *> stack;
 
-   for (Graph::EdgeIterator ei = bb->cfg.incident(); !ei.end(); ei.next()) {
+   // We're about to, potentially, reorder the inbound edges. This means that
+   // we need to hold on to the (phi, bb) -> src mapping, so that we can
+   // later insert the movs.
+   typedef std::tr1::unordered_map<
+      std::pair<Instruction *, BasicBlock *>, Value *> PhiMap;
+   PhiMap phis;
+
+   j = 0;
+   for (Graph::EdgeIterator ei = bb->cfg.incident(); !ei.end(); ei.next(), ++j) {
       pb = BasicBlock::get(ei.getNode());
       assert(pb);
       if (needNewElseBlock(bb, pb))
          stack.push(pb);
+      for (phi = bb->getPhi(); phi && phi->op == OP_PHI; phi = phi->next)
+         phis.insert(std::make_pair(std::make_pair(phi, pb), phi->getSrc(j)));
    }
    while (!stack.empty()) {
       pb = stack.top();
@@ -380,10 +404,17 @@ RegAlloc::PhiMovesPass::visit(BasicBlock *bb)
       assert(pb->getExit()->op != OP_CALL);
       if (pb->getExit()->asFlow()->target.bb == bb)
          pb->getExit()->asFlow()->target.bb = pn;
+
+      for (phi = bb->getPhi(); phi && phi->op == OP_PHI; phi = phi->next) {
+         PhiMap::iterator it = phis.find(std::make_pair(phi, pb));
+         assert(it != phis.end());
+         phis.insert(std::make_pair(std::make_pair(phi, pn), it->second));
+         phis.erase(it);
+      }
    }
 
    // insert MOVs (phi->src(j) should stem from j-th in-BB)
-   int j = 0;
+   j = 0;
    for (Graph::EdgeIterator ei = bb->cfg.incident(); !ei.end(); ei.next()) {
       pb = BasicBlock::get(ei.getNode());
       if (!pb->isTerminated())
@@ -393,7 +424,9 @@ RegAlloc::PhiMovesPass::visit(BasicBlock *bb)
          LValue *tmp = new_LValue(func, phi->getDef(0)->asLValue());
          mov = new_Instruction(func, OP_MOV, typeOfSize(tmp->reg.size));
 
-         mov->setSrc(0, phi->getSrc(j));
+         PhiMap::const_iterator it = phis.find(std::make_pair(phi, pb));
+         assert(it != phis.end());
+         mov->setSrc(0, it->second);
          mov->setDef(0, tmp);
          phi->setSrc(j, tmp);