[Mesa-dev] [PATCH v3 09/12] nvc0/ir: add atomics support on shared memory for Kepler
Ilia Mirkin
imirkin at alum.mit.edu
Fri Apr 1 17:24:35 UTC 2016
On Fri, Apr 1, 2016 at 12:56 PM, Samuel Pitoiset
<samuel.pitoiset at gmail.com> wrote:
> Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
> ---
> .../nouveau/codegen/nv50_ir_lowering_nvc0.cpp | 114 ++++++++++++++++++++-
> .../nouveau/codegen/nv50_ir_lowering_nvc0.h | 1 +
> 2 files changed, 114 insertions(+), 1 deletion(-)
>
> 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 5a08fc7..26fc27f 100644
> --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp
> +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp
> @@ -1081,6 +1081,114 @@ NVC0LoweringPass::handleSUQ(Instruction *suq)
> }
>
> void
> +NVC0LoweringPass::handleSharedATOMNVE4(Instruction *atom)
> +{
> + assert(atom->src(0).getFile() == FILE_MEMORY_SHARED);
> +
> + BasicBlock *currBB = atom->bb;
> + BasicBlock *tryLockBB = atom->bb->splitBefore(atom, false);
> + BasicBlock *joinBB = atom->bb->splitAfter(atom);
> + BasicBlock *setAndUnlockBB = new BasicBlock(func);
> + BasicBlock *failLockBB = new BasicBlock(func);
> +
> + bld.setPosition(currBB, true);
> + assert(!currBB->joinAt);
> + currBB->joinAt = bld.mkFlow(OP_JOINAT, joinBB, CC_ALWAYS, NULL);
> +
> + CmpInstruction *pred =
> + bld.mkCmp(OP_SET, CC_EQ, TYPE_U32, bld.getSSA(1, FILE_PREDICATE),
> + TYPE_U32, bld.mkImm(0), bld.mkImm(1));
> +
> + bld.mkFlow(OP_BRA, tryLockBB, CC_ALWAYS, NULL);
> + currBB->cfg.attach(&tryLockBB->cfg, Graph::Edge::TREE);
> +
> + bld.setPosition(tryLockBB, true);
> +
> + Instruction *ld =
> + bld.mkLoad(TYPE_U32, atom->getDef(0),
> + bld.mkSymbol(FILE_MEMORY_SHARED, 0, TYPE_U32, 0), NULL);
> + ld->setDef(1, bld.getSSA(1, FILE_PREDICATE));
> + ld->subOp = NV50_IR_SUBOP_LOAD_LOCKED;
> +
> + bld.mkFlow(OP_BRA, setAndUnlockBB, CC_P, ld->getDef(1));
> + bld.mkFlow(OP_BRA, failLockBB, CC_ALWAYS, NULL);
> + tryLockBB->cfg.attach(&failLockBB->cfg, Graph::Edge::CROSS);
> + tryLockBB->cfg.attach(&setAndUnlockBB->cfg, Graph::Edge::TREE);
> +
> + tryLockBB->cfg.detach(&joinBB->cfg);
> + bld.remove(atom);
> +
> + bld.setPosition(setAndUnlockBB, true);
> + Value *stVal;
> + if (atom->subOp == NV50_IR_SUBOP_ATOM_EXCH) {
> + // Read the old value, and write the new one.
> + stVal = atom->getSrc(1);
> + } else if (atom->subOp == NV50_IR_SUBOP_ATOM_CAS) {
> + CmpInstruction *set =
> + bld.mkCmp(OP_SET, CC_EQ, TYPE_U32, bld.getSSA(),
> + TYPE_U32, ld->getDef(0), atom->getSrc(1));
> +
> + CmpInstruction *slct =
> + bld.mkCmp(OP_SLCT, CC_NE, TYPE_U32, bld.getSSA(),
> + TYPE_U32, atom->getSrc(2), ld->getDef(0), set->getDef(0));
Up to you, but a common way of doing this elsewhere is
bld.mkCmp(..., (stVal = bld.getSSA()), ...)
And then you don't need the getDef().
> +
> + stVal = slct->getDef(0);
> + } else {
> + operation op;
> +
> + switch (atom->subOp) {
> + case NV50_IR_SUBOP_ATOM_ADD:
> + op = OP_ADD;
> + break;
> + case NV50_IR_SUBOP_ATOM_AND:
> + op = OP_AND;
> + break;
> + case NV50_IR_SUBOP_ATOM_OR:
> + op = OP_OR;
> + break;
> + case NV50_IR_SUBOP_ATOM_XOR:
> + op = OP_XOR;
> + break;
> + case NV50_IR_SUBOP_ATOM_MIN:
> + op = OP_MIN;
> + break;
> + case NV50_IR_SUBOP_ATOM_MAX:
> + op = OP_MAX;
> + break;
> + default:
> + assert(0);
> + return;
> + }
> +
> + Instruction *i =
> + bld.mkOp2(op, atom->dType, bld.getSSA(), ld->getDef(0),
> + atom->getSrc(1));
> +
> + stVal = i->getDef(0);
Or just do bld.mkOp2v, which returns the value (and no need for the
Instruction var).
Either way,
Reviewed-by: Ilia Mirkin <imirkin at alum.mit.edu>
> + }
> +
> + Instruction *st =
> + bld.mkStore(OP_STORE, TYPE_U32,
> + bld.mkSymbol(FILE_MEMORY_SHARED, 0, TYPE_U32, 0),
> + NULL, stVal);
> + st->setDef(0, pred->getDef(0));
> + st->subOp = NV50_IR_SUBOP_STORE_UNLOCKED;
> +
> + bld.mkFlow(OP_BRA, failLockBB, CC_ALWAYS, NULL);
> + setAndUnlockBB->cfg.attach(&failLockBB->cfg, Graph::Edge::TREE);
> +
> + // Lock until the store has not been performed.
> + bld.setPosition(failLockBB, true);
> + bld.mkFlow(OP_BRA, tryLockBB, CC_NOT_P, pred->getDef(0));
> + bld.mkFlow(OP_BRA, joinBB, CC_ALWAYS, NULL);
> + failLockBB->cfg.attach(&tryLockBB->cfg, Graph::Edge::BACK);
> + failLockBB->cfg.attach(&joinBB->cfg, Graph::Edge::TREE);
> +
> + bld.setPosition(joinBB, false);
> + bld.mkFlow(OP_JOIN, NULL, CC_ALWAYS, NULL)->fixed = 1;
> +}
> +
> +void
> NVC0LoweringPass::handleSharedATOM(Instruction *atom)
> {
> assert(atom->src(0).getFile() == FILE_MEMORY_SHARED);
> @@ -1186,7 +1294,11 @@ NVC0LoweringPass::handleATOM(Instruction *atom)
> sv = SV_LBASE;
> break;
> case FILE_MEMORY_SHARED:
> - handleSharedATOM(atom);
> + if (targ->getChipset() >= NVISA_GK104_CHIPSET) {
> + handleSharedATOMNVE4(atom);
> + } else {
> + handleSharedATOM(atom);
> + }
> return true;
> default:
> assert(atom->src(0).getFile() == FILE_MEMORY_GLOBAL);
> diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.h b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.h
> index aa19249..d5c2cb5 100644
> --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.h
> +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.h
> @@ -106,6 +106,7 @@ protected:
> bool handleCasExch(Instruction *, bool needCctl);
> void handleSurfaceOpNVE4(TexInstruction *);
> void handleSharedATOM(Instruction *);
> + void handleSharedATOMNVE4(Instruction *);
> void handleLDST(Instruction *);
>
> void checkPredicate(Instruction *);
> --
> 2.7.4
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list