summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarol Herbst <karolherbst@gmail.com>2016-08-13 11:54:45 +0200
committerIlia Mirkin <imirkin@alum.mit.edu>2016-09-03 00:01:06 -0400
commitd0cf7a6beb4470d945bccb4e753cc7eb6ca5dda8 (patch)
tree049f59432143c1017559f63d665525961bf2f1cd
parentaad4f15506c2b5ff9f3304a467b51b45dd77554d (diff)
downloadexternal_mesa3d-d0cf7a6beb4470d945bccb4e753cc7eb6ca5dda8.zip
external_mesa3d-d0cf7a6beb4470d945bccb4e753cc7eb6ca5dda8.tar.gz
external_mesa3d-d0cf7a6beb4470d945bccb4e753cc7eb6ca5dda8.tar.bz2
nvc0/ir: don't dual-issue ops that depend or interfere with each other
Signed-off-by: Karol Herbst <karolherbst@gmail.com> Reviewed-by: Tobias Klausmann <tobias.johannes.klausmann@mni.thm.de> [imirkin: rewrite to split up the helpers and move more logic to target] Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir.cpp27
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir.h4
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_target_nvc0.cpp6
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 179ad0b..186c9fd 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 6d2ee8b..d6011d9 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 04ac288..0cb21e8 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;