summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp93
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;