diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp | 93 |
1 files changed, 71 insertions, 22 deletions
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp index 0cde9794efc..6a6ba044041 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp @@ -295,10 +295,53 @@ private: typedef std::pair<Value *, Value *> ValuePair; +class MergedDefs +{ +private: + std::list<ValueDef *>& entry(Value *val) { + auto it = defs.find(val); + + if (it == defs.end()) { + std::list<ValueDef *> &res = defs[val]; + res = val->defs; + return res; + } else { + return (*it).second; + } + } + + std::unordered_map<Value *, std::list<ValueDef *> > defs; + +public: + std::list<ValueDef *>& operator()(Value *val) { + return entry(val); + } + + void add(Value *val, const std::list<ValueDef *> &vals) { + assert(val); + std::list<ValueDef *> &valdefs = entry(val); + valdefs.insert(valdefs.end(), vals.begin(), vals.end()); + } + + void removeDefsOfInstruction(Instruction *insn) { + for (int d = 0; insn->defExists(d); ++d) { + ValueDef *def = &insn->def(d); + defs.erase(def->get()); + for (auto &p : defs) + p.second.remove(def); + } + } + + void merge() { + for (auto &p : defs) + p.first->defs = p.second; + } +}; + class SpillCodeInserter { public: - SpillCodeInserter(Function *fn) : func(fn), stackSize(0), stackBase(0) { } + SpillCodeInserter(Function *fn, MergedDefs &mergedDefs) : func(fn), mergedDefs(mergedDefs), stackSize(0), stackBase(0) { } bool run(const std::list<ValuePair>&); @@ -308,6 +351,7 @@ public: private: Function *func; + MergedDefs &mergedDefs; struct SpillSlot { @@ -708,7 +752,7 @@ RegAlloc::BuildIntervalsPass::visit(BasicBlock *bb) class GCRA { public: - GCRA(Function *, SpillCodeInserter&); + GCRA(Function *, SpillCodeInserter&, MergedDefs&); ~GCRA(); bool allocateRegisters(ArrayList& insns); @@ -825,6 +869,8 @@ private: SpillCodeInserter& spill; std::list<ValuePair> mustSpill; + + MergedDefs &mergedDefs; }; const GCRA::RelDegree GCRA::relDegree; @@ -954,12 +1000,13 @@ GCRA::coalesceValues(Value *dst, Value *src, bool force) rep->id, rep->reg.data.id, val->id); // set join pointer of all values joined with val - for (ValueDef *def : val->defs) + const std::list<ValueDef *> &defs = mergedDefs(val); + for (ValueDef *def : defs) def->get()->join = rep; assert(rep->join == rep && val->join == rep); // add val's definitions to rep and extend the live interval of its RIG node - rep->defs.insert(rep->defs.end(), val->defs.begin(), val->defs.end()); + mergedDefs.add(rep, defs); nRep->livei.unify(nVal->livei); nRep->degreeLimit = MIN2(nRep->degreeLimit, nVal->degreeLimit); nRep->maxReg = MIN2(nRep->maxReg, nVal->maxReg); @@ -1162,10 +1209,11 @@ GCRA::RIG_Node::addRegPreference(RIG_Node *node) prefRegs.push_back(node); } -GCRA::GCRA(Function *fn, SpillCodeInserter& spill) : +GCRA::GCRA(Function *fn, SpillCodeInserter& spill, MergedDefs& mergedDefs) : func(fn), regs(fn->getProgram()->getTarget()), - spill(spill) + spill(spill), + mergedDefs(mergedDefs) { prog = func->getProgram(); } @@ -1260,7 +1308,7 @@ GCRA::calculateSpillWeights() if (!val->noSpill) { int rc = 0; - for (ValueDef *def : val->defs) + for (ValueDef *def : mergedDefs(val)) rc += def->get()->refCount(); nodes[i].weight = @@ -1362,15 +1410,15 @@ GCRA::checkInterference(const RIG_Node *node, Graph::EdgeIterator& ei) if (intf->reg < 0) return; - const LValue *vA = node->getValue(); - const LValue *vB = intf->getValue(); + LValue *vA = node->getValue(); + LValue *vB = intf->getValue(); const uint8_t intfMask = ((1 << intf->colors) - 1) << (intf->reg & 7); if (vA->compound | vB->compound) { // NOTE: this only works for >aligned< register tuples ! - for (const ValueDef *D : vA->defs) { - for (const ValueDef *d : vB->defs) { + for (const ValueDef *D : mergedDefs(vA)) { + for (const ValueDef *d : mergedDefs(vB)) { const LValue *vD = D->get()->asLValue(); const LValue *vd = d->get()->asLValue(); @@ -1541,6 +1589,7 @@ GCRA::allocateRegisters(ArrayList& insns) if (prog->dbgFlags & NV50_IR_DEBUG_REG_ALLOC) func->print(); } else { + mergedDefs.merge(); prog->maxGPR = std::max(prog->maxGPR, regs.getMaxAssigned(FILE_GPR)); } @@ -1566,14 +1615,10 @@ GCRA::cleanup(const bool success) if (lval->join == lval) continue; - if (success) { + if (success) lval->reg.data.id = lval->join->reg.data.id; - } else { - for (Value::DefIterator d = lval->defs.begin(); d != lval->defs.end(); - ++d) - lval->join->defs.remove(*d); + else lval->join = lval; - } } if (success) @@ -1766,7 +1811,8 @@ SpillCodeInserter::run(const std::list<ValuePair>& lst) // multiple destinations that all need to be spilled (like OP_SPLIT). unordered_set<Instruction *> to_del; - for (Value::DefIterator d = lval->defs.begin(); d != lval->defs.end(); + std::list<ValueDef *> &defs = mergedDefs(lval); + for (Value::DefIterator d = defs.begin(); d != defs.end(); ++d) { Value *slot = mem ? static_cast<Value *>(mem) : new_LValue(func, FILE_GPR); @@ -1802,7 +1848,7 @@ SpillCodeInserter::run(const std::list<ValuePair>& lst) assert(defi); if (defi->isPseudo()) { - d = lval->defs.erase(d); + d = defs.erase(d); --d; if (slot->reg.file == FILE_MEMORY_LOCAL) to_del.insert(defi); @@ -1814,8 +1860,10 @@ SpillCodeInserter::run(const std::list<ValuePair>& lst) } for (unordered_set<Instruction *>::const_iterator it = to_del.begin(); - it != to_del.end(); ++it) + it != to_del.end(); ++it) { + mergedDefs.removeDefsOfInstruction(*it); delete_Instruction(func->getProgram(), *it); + } } // TODO: We're not trying to reuse old slots in a potential next iteration. @@ -1843,13 +1891,14 @@ RegAlloc::exec() bool RegAlloc::execFunc() { + MergedDefs mergedDefs; InsertConstraintsPass insertConstr; PhiMovesPass insertPhiMoves; ArgumentMovesPass insertArgMoves; BuildIntervalsPass buildIntervals; - SpillCodeInserter insertSpills(func); + SpillCodeInserter insertSpills(func, mergedDefs); - GCRA gcra(func, insertSpills); + GCRA gcra(func, insertSpills, mergedDefs); unsigned int i, retries; bool ret; |