[Nouveau] [RFC PATCH v2] nv50/ir: allow spilling of def values for constrained MERGES/UNIONS
Tobias Klausmann
tobias.johannes.klausmann at mni.thm.de
Tue Aug 1 22:39:42 UTC 2017
This lets us spill more values and compile a Civilization 6 shader with many
local vars. As a precation, only spill those vars as a fallback option if all
other spillable vars are already spilled!
shader-db run shows:
total instructions in shared programs : 4427020 -> 4427388 (0.01%)
total gprs used in shared programs : 522836 -> 522871 (0.01%)
total local used in shared programs : 17128 -> 17464 (1.96%)
local gpr inst bytes
helped 0 0 0 0
hurt 0 0 0 0
The additional instructions (+368) gprs (+35) and local (+336) are contained in
the Civilization 6 shader:
90.shader_test - type: 0, local: 336, gpr: 35, inst: 368, bytes: 3928
Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de>
---
src/gallium/drivers/nouveau/codegen/nv50_ir.cpp | 2 ++
src/gallium/drivers/nouveau/codegen/nv50_ir.h | 3 ++
src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp | 39 ++++++++++++++++------
3 files changed, 34 insertions(+), 10 deletions(-)
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp
index 08181b790f..2fa8c22e33 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp
@@ -233,6 +233,7 @@ LValue::LValue(Function *fn, DataFile file)
ssa = 0;
fixedReg = 0;
noSpill = 0;
+ softNoSpill = 0;
fn->add(this, this->id);
}
@@ -250,6 +251,7 @@ LValue::LValue(Function *fn, LValue *lval)
ssa = 0;
fixedReg = 0;
noSpill = 0;
+ softNoSpill = 0;
fn->add(this, this->id);
}
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir.h b/src/gallium/drivers/nouveau/codegen/nv50_ir.h
index bc15992df0..ca5bcb5362 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir.h
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir.h
@@ -704,6 +704,9 @@ public:
unsigned ssa : 1;
unsigned fixedReg : 1; // set & used by RA, earlier just use (id < 0)
unsigned noSpill : 1; // do not spill (e.g. if spill temporary already)
+ unsigned softNoSpill : 1; /* only spill these values if all other values are
+ * spilled already!
+ */
};
class Symbol : public Value
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp
index b33d7b4010..9d70ec3c9c 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp
@@ -769,7 +769,7 @@ private:
bool coalesce(ArrayList&);
bool doCoalesce(ArrayList&, unsigned int mask);
void calculateSpillWeights();
- bool simplify();
+ bool simplify(bool useSoftNoSpill);
bool selectRegisters();
void cleanup(const bool success);
@@ -1242,7 +1242,7 @@ GCRA::calculateSpillWeights()
}
LValue *val = nodes[i].getValue();
- if (!val->noSpill) {
+ if (!val->noSpill || val->softNoSpill) {
int rc = 0;
for (Value::DefIterator it = val->defs.begin();
it != val->defs.end();
@@ -1304,7 +1304,7 @@ GCRA::simplifyNode(RIG_Node *node)
}
bool
-GCRA::simplify()
+GCRA::simplify(bool useSoftNoSpill)
{
for (;;) {
if (!DLLIST_EMPTY(&lo[0])) {
@@ -1317,17 +1317,32 @@ GCRA::simplify()
} else
if (!DLLIST_EMPTY(&hi)) {
RIG_Node *best = hi.next;
- float bestScore = best->weight / (float)best->degree;
+ bool spillable = false;
+ if (best->getValue()->noSpill && best->getValue()->softNoSpill &&
+ useSoftNoSpill)
+ spillable = true;
+ float bestScore = INFINITY;
+ if (!best->getValue()->noSpill || spillable)
+ bestScore = best->weight / (float)best->degree;
// spill candidate
for (RIG_Node *it = best->next; it != &hi; it = it->next) {
- float score = it->weight / (float)it->degree;
+ float score = INFINITY;
+ bool spillable = false;
+ if (it->getValue()->noSpill && it->getValue()->softNoSpill &&
+ useSoftNoSpill)
+ spillable = true;
+ if (!it->getValue()->noSpill || spillable) {
+ score = it->weight / (float)it->degree;
+ }
if (score < bestScore) {
best = it;
bestScore = score;
}
}
if (isinf(bestScore)) {
- ERROR("no viable spill candidates left\n");
+ if (useSoftNoSpill)
+ ERROR("no viable spill candidates left\n");
+
return false;
}
simplifyNode(best);
@@ -1491,9 +1506,12 @@ GCRA::allocateRegisters(ArrayList& insns)
buildRIG(insns);
calculateSpillWeights();
- ret = simplify();
- if (!ret)
- goto out;
+ ret = simplify(false);
+ if (!ret) {
+ ret = simplify(true);
+ if (!ret)
+ goto out;
+ }
ret = selectRegisters();
if (!ret) {
@@ -2344,7 +2362,8 @@ RegAlloc::InsertConstraintsPass::insertConstraintMoves()
cst->setSrc(s, mov->getDef(0));
cst->bb->insertBefore(cst, mov);
- cst->getDef(0)->asLValue()->noSpill = 1; // doesn't help
+ cst->getDef(0)->asLValue()->softNoSpill = 1;
+ cst->getDef(0)->asLValue()->noSpill = 1; // a precaution
if (cst->op == OP_UNION)
mov->setPredicate(defi->cc, defi->getPredicate());
--
2.13.3
More information about the Nouveau
mailing list