[Nouveau] [PATCH RESEND] nv50/ir: use unordered_set instead of list to keep track of var defs
Tobias Klausmann
tobias.johannes.klausmann at mni.thm.de
Tue Dec 2 12:19:01 PST 2014
The set of variable defs does not need to be ordered in any way, and
removing/adding elements is a fairly common operation in various
optimization passes.
This shortens runtime of piglit test fp-long-alu to ~11s from ~22s
No piglit regressions observed on nvc0!
Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de>
---
src/gallium/drivers/nouveau/codegen/nv50_ir.cpp | 4 ++--
src/gallium/drivers/nouveau/codegen/nv50_ir.h | 7 +++---
.../drivers/nouveau/codegen/nv50_ir_inlines.h | 28 +++++++++++++---------
.../nouveau/codegen/nv50_ir_lowering_nv50.cpp | 4 ++--
.../nouveau/codegen/nv50_ir_lowering_nvc0.cpp | 6 ++---
.../drivers/nouveau/codegen/nv50_ir_peephole.cpp | 4 ++--
src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp | 17 +++++++------
7 files changed, 38 insertions(+), 32 deletions(-)
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp
index ca3c806..3138118 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp
@@ -154,9 +154,9 @@ ValueDef::set(Value *defVal)
if (value == defVal)
return;
if (value)
- value->defs.remove(this);
+ value->defs.erase(this);
if (defVal)
- defVal->defs.push_back(this);
+ defVal->defs.insert(this);
value = defVal;
}
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir.h b/src/gallium/drivers/nouveau/codegen/nv50_ir.h
index 0ff5e5d..56033f1 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir.h
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir.h
@@ -567,6 +567,7 @@ public:
inline Value *rep() const { return join; }
+ inline Instruction *getUniqueInsnMerged() const;
inline Instruction *getUniqueInsn() const;
inline Instruction *getInsn() const; // use when uniqueness is certain
@@ -583,11 +584,11 @@ public:
static inline Value *get(Iterator&);
std::tr1::unordered_set<ValueRef *> uses;
- std::list<ValueDef *> defs;
+ std::tr1::unordered_set<ValueDef *> defs;
typedef std::tr1::unordered_set<ValueRef *>::iterator UseIterator;
typedef std::tr1::unordered_set<ValueRef *>::const_iterator UseCIterator;
- typedef std::list<ValueDef *>::iterator DefIterator;
- typedef std::list<ValueDef *>::const_iterator DefCIterator;
+ typedef std::tr1::unordered_set<ValueDef *>::iterator DefIterator;
+ typedef std::tr1::unordered_set<ValueDef *>::const_iterator DefCIterator;
int id;
Storage reg;
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h b/src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h
index 255324f..471d47f 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h
@@ -205,21 +205,26 @@ const LValue *ValueDef::preSSA() const
Instruction *Value::getInsn() const
{
- return defs.empty() ? NULL : defs.front()->getInsn();
+ return defs.empty() ? NULL : (*defs.begin())->getInsn();
}
-Instruction *Value::getUniqueInsn() const
+Instruction *Value::getUniqueInsnMerged() const
{
if (defs.empty())
return NULL;
+ /* It is not guaranteed that this is the first in the set, lets find it */
+ for (DefCIterator it = defs.begin(); it != defs.end(); ++it)
+ if ((*it)->get() == this)
+ return (*it)->getInsn();
+ /* We should never hit this assert */
+ assert(0);
+ return NULL;
+}
- // after regalloc, the definitions of coalesced values are linked
- if (join != this) {
- for (DefCIterator it = defs.begin(); it != defs.end(); ++it)
- if ((*it)->get() == this)
- return (*it)->getInsn();
- // should be unreachable and trigger assertion at the end
- }
+Instruction *Value::getUniqueInsn() const
+{
+ if (defs.empty())
+ return NULL;
#ifdef DEBUG
if (reg.data.id < 0) {
int n = 0;
@@ -230,8 +235,9 @@ Instruction *Value::getUniqueInsn() const
WARN("value %%%i not uniquely defined\n", id); // return NULL ?
}
#endif
- assert(defs.front()->get() == this);
- return defs.front()->getInsn();
+ ValueDef *def = *defs.begin();
+ assert(def->get() == this);
+ return def->getInsn();
}
inline bool Instruction::constrainedDefs() const
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nv50.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nv50.cpp
index e283424..f13e0d4 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nv50.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nv50.cpp
@@ -211,7 +211,7 @@ NV50LegalizePostRA::visit(Function *fn)
if (outWrites) {
for (std::list<Instruction *>::iterator it = outWrites->begin();
it != outWrites->end(); ++it)
- (*it)->getSrc(1)->defs.front()->getInsn()->setDef(0, (*it)->getSrc(0));
+ (*(*it)->getSrc(1)->defs.begin())->getInsn()->setDef(0, (*it)->getSrc(0));
// instructions will be deleted on exit
outWrites->clear();
}
@@ -343,7 +343,7 @@ NV50LegalizeSSA::propagateWriteToOutput(Instruction *st)
return;
// check def instruction can store
- Instruction *di = st->getSrc(1)->defs.front()->getInsn();
+ Instruction *di =(*st->getSrc(1)->defs.begin())->getInsn();
// TODO: move exports (if beneficial) in common opt pass
if (di->isPseudo() || isTextureOp(di->op) || di->defCount(0xff, true) > 1)
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp
index 9c06d04..ab28f3a 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp
@@ -148,7 +148,7 @@ NVC0LegalizePostRA::findOverwritingDefs(const Instruction *texi,
std::list<TexUse> &uses)
{
while (insn->op == OP_MOV && insn->getDef(0)->equals(insn->getSrc(0)))
- insn = insn->getSrc(0)->getUniqueInsn();
+ insn = insn->getSrc(0)->getUniqueInsnMerged();
if (!insn->bb->reachableBy(texi->bb, term))
return;
@@ -163,7 +163,7 @@ NVC0LegalizePostRA::findOverwritingDefs(const Instruction *texi,
case OP_UNION:
/* recurse again */
for (int s = 0; insn->srcExists(s); ++s)
- findOverwritingDefs(texi, insn->getSrc(s)->getUniqueInsn(), term,
+ findOverwritingDefs(texi, insn->getSrc(s)->getUniqueInsnMerged(), term,
uses);
break;
default:
@@ -200,7 +200,7 @@ NVC0LegalizePostRA::findFirstUses(
if (usei->op == OP_PHI || usei->op == OP_UNION) {
// need a barrier before WAW cases
for (int s = 0; usei->srcExists(s); ++s) {
- Instruction *defi = usei->getSrc(s)->getUniqueInsn();
+ Instruction *defi = usei->getSrc(s)->getUniqueInsnMerged();
if (defi && &usei->src(s) != *u)
findOverwritingDefs(texi, defi, usei->bb, uses);
}
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_peephole.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_peephole.cpp
index f520dc6..ff3f8c3 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_peephole.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_peephole.cpp
@@ -2144,7 +2144,7 @@ FlatteningPass::isConstantCondition(Value *pred)
return false;
for (int s = 0; s < 2 && insn->srcExists(s); ++s) {
- Instruction *ld = insn->getSrc(s)->getUniqueInsn();
+ Instruction *ld = insn->getSrc(s)->getUniqueInsnMerged();
DataFile file;
if (ld) {
if (ld->op != OP_MOV && ld->op != OP_LOAD)
@@ -2185,7 +2185,7 @@ FlatteningPass::removeFlow(Instruction *insn)
delete_Instruction(prog, term);
if (pred && pred->refCount() == 0) {
- Instruction *pSet = pred->getUniqueInsn();
+ Instruction *pSet = pred->getUniqueInsnMerged();
pred->join->reg.data.id = -1; // deallocate
if (pSet->isDead())
delete_Instruction(prog, pSet);
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp
index 898653c..8961237 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp
@@ -313,7 +313,7 @@ RegAlloc::BuildIntervalsPass::addLiveRange(Value *val,
const BasicBlock *bb,
int end)
{
- Instruction *insn = val->getUniqueInsn();
+ Instruction *insn = val->getUniqueInsnMerged();
if (!insn)
insn = bb->getFirst();
@@ -579,7 +579,7 @@ RegAlloc::BuildIntervalsPass::visit(BasicBlock *bb)
for (int s = 0; i->srcExists(s); ++s) {
assert(i->src(s).getInsn());
- if (i->getSrc(s)->getUniqueInsn()->bb == bb) // XXX: reachableBy ?
+ if (i->getSrc(s)->getUniqueInsnMerged()->bb == bb) // XXX: reachableBy ?
bb->liveSet.set(i->getSrc(s)->id);
else
bb->liveSet.clr(i->getSrc(s)->id);
@@ -835,7 +835,7 @@ GCRA::coalesceValues(Value *dst, Value *src, bool force)
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());
+ rep->defs.insert(val->defs.begin(), val->defs.end());
nRep->livei.unify(nVal->livei);
return true;
}
@@ -989,7 +989,7 @@ GCRA::doCoalesce(ArrayList& insns, unsigned int mask)
// if this is a contraint-move there will only be a single use
if (i && i->op == OP_MERGE) // do we really still need this ?
break;
- i = insn->getSrc(0)->getUniqueInsn();
+ i = insn->getSrc(0)->getUniqueInsnMerged();
if (i && !i->constrainedDefs()) {
if (coalesceValues(insn->getDef(0), insn->getSrc(0), false))
copyCompound(insn->getSrc(0), insn->getDef(0));
@@ -1410,7 +1410,7 @@ GCRA::cleanup(const bool success)
} else {
for (Value::DefIterator d = lval->defs.begin(); d != lval->defs.end();
++d)
- lval->join->defs.remove(*d);
+ lval->join->defs.erase(*d);
lval->join = lval;
}
}
@@ -1553,8 +1553,7 @@ SpillCodeInserter::run(const std::list<ValuePair>& lst)
// multiple destinations that all need to be spilled (like OP_SPLIT).
std::tr1::unordered_set<Instruction *> to_del;
- for (Value::DefIterator d = lval->defs.begin(); d != lval->defs.end();
- ++d) {
+ for (Value::DefIterator d = lval->defs.begin(); d != lval->defs.end();) {
Value *slot = mem ?
static_cast<Value *>(mem) : new_LValue(func, FILE_GPR);
Value *tmp = NULL;
@@ -1583,13 +1582,13 @@ SpillCodeInserter::run(const std::list<ValuePair>& lst)
assert(defi);
if (defi->isPseudo()) {
d = lval->defs.erase(d);
- --d;
if (slot->reg.file == FILE_MEMORY_LOCAL)
to_del.insert(defi);
else
defi->setDef(0, slot);
} else {
spill(defi, slot, dval);
+ ++d;
}
}
@@ -2118,7 +2117,7 @@ RegAlloc::InsertConstraintsPass::insertConstraintMoves()
}
assert(cst->getSrc(s)->defs.size() == 1); // still SSA
- Instruction *defi = cst->getSrc(s)->defs.front()->getInsn();
+ Instruction *defi =(*cst->getSrc(s)->defs.begin())->getInsn();
// catch some cases where don't really need MOVs
if (cst->getSrc(s)->refCount() == 1 && !defi->constrainedDefs())
continue;
--
2.1.3
More information about the Nouveau
mailing list