From d0cf7a6beb4470d945bccb4e753cc7eb6ca5dda8 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Sat, 13 Aug 2016 11:54:45 +0200 Subject: [PATCH] nvc0/ir: don't dual-issue ops that depend or interfere with each other Signed-off-by: Karol Herbst Reviewed-by: Tobias Klausmann [imirkin: rewrite to split up the helpers and move more logic to target] Signed-off-by: Ilia Mirkin --- .../drivers/nouveau/codegen/nv50_ir.cpp | 27 +++++++++---------- src/gallium/drivers/nouveau/codegen/nv50_ir.h | 4 +++ .../nouveau/codegen/nv50_ir_target_nvc0.cpp | 6 +++++ 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp index 179ad0b7a97..186c9fdbedf 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp @@ -870,22 +870,22 @@ Instruction::writesPredicate() const return false; } -static bool -insnCheckCommutationDefSrc(const Instruction *a, const Instruction *b) +bool +Instruction::canCommuteDefSrc(const Instruction *i) const { - for (int d = 0; a->defExists(d); ++d) - for (int s = 0; b->srcExists(s); ++s) - if (a->getDef(d)->interfers(b->getSrc(s))) + for (int d = 0; defExists(d); ++d) + for (int s = 0; i->srcExists(s); ++s) + if (getDef(d)->interfers(i->getSrc(s))) return false; return true; } -static bool -insnCheckCommutationDefDef(const Instruction *a, const Instruction *b) +bool +Instruction::canCommuteDefDef(const Instruction *i) const { - for (int d = 0; a->defExists(d); ++d) - for (int c = 0; b->defExists(c); ++c) - if (a->getDef(d)->interfers(b->getDef(c))) + for (int d = 0; defExists(d); ++d) + for (int c = 0; i->defExists(c); ++c) + if (getDef(d)->interfers(i->getDef(c))) return false; return true; } @@ -893,10 +893,9 @@ insnCheckCommutationDefDef(const Instruction *a, const Instruction *b) bool Instruction::isCommutationLegal(const Instruction *i) const { - bool ret = insnCheckCommutationDefDef(this, i); - ret = ret && insnCheckCommutationDefSrc(this, i); - ret = ret && insnCheckCommutationDefSrc(i, this); - return ret; + return canCommuteDefDef(i) && + canCommuteDefSrc(i) && + i->canCommuteDefSrc(this); } TexInstruction::TexInstruction(Function *fn, operation op) diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir.h b/src/gallium/drivers/nouveau/codegen/nv50_ir.h index 6d2ee8bce12..d6011d9c223 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir.h +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir.h @@ -834,6 +834,10 @@ public: bool isActionEqual(const Instruction *) const; bool isResultEqual(const Instruction *) const; + // check whether the defs interfere with srcs and defs of another instruction + bool canCommuteDefDef(const Instruction *) const; + bool canCommuteDefSrc(const Instruction *) const; + void print() const; inline CmpInstruction *asCmp(); diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_target_nvc0.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_target_nvc0.cpp index 04ac288fba3..0cb21e8c826 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_target_nvc0.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_target_nvc0.cpp @@ -615,6 +615,12 @@ bool TargetNVC0::canDualIssue(const Instruction *a, const Instruction *b) const // not if the 2nd instruction isn't necessarily executed if (clA == OPCLASS_TEXTURE || clA == OPCLASS_FLOW) return false; + + // Check that a and b don't write to the same sources, nor that b reads + // anything that a writes. + if (!a->canCommuteDefDef(b) || !a->canCommuteDefSrc(b)) + return false; + // anything with MOV if (a->op == OP_MOV || b->op == OP_MOV) return true; -- 2.30.2