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);