Tobias Klausmann
2017-Jul-31 11:21 UTC
[Nouveau] [RFC PATCH] nv50/ir: allow spilling of def values for constrained MERGES/UNIONS
This lets us spill more values and compile a big shader for Civilization 6. Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> --- src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp index b33d7b4010..f29c8a1a95 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp @@ -2344,8 +2344,6 @@ RegAlloc::InsertConstraintsPass::insertConstraintMoves() cst->setSrc(s, mov->getDef(0)); cst->bb->insertBefore(cst, mov); - cst->getDef(0)->asLValue()->noSpill = 1; // doesn't help - if (cst->op == OP_UNION) mov->setPredicate(defi->cc, defi->getPredicate()); } -- 2.13.3
Tobias Klausmann
2017-Aug-01 22:39 UTC
[Nouveau] [RFC PATCH v2] nv50/ir: allow spilling of def values for constrained MERGES/UNIONS
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
Seemingly Similar Threads
- [PATCH 0/5] nvc0: fp64 preparation
- [PATCH] nv50/ir: avoid deleting pseudo instructions too early
- [PATCH] nv50/ir: use unordered_set instead of list to keep track of var defs
- [PATCH] nv50/ir: use unordered_set instead of list to keep our instructions in uses
- NV50 compute support questions