nvc0/ir: don't dual-issue ops that depend or interfere with each other
authorKarol Herbst <karolherbst@gmail.com>
Sat, 13 Aug 2016 09:54:45 +0000 (11:54 +0200)
committerIlia Mirkin <imirkin@alum.mit.edu>
Sat, 3 Sep 2016 04:01:06 +0000 (00:01 -0400)
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>
src/gallium/drivers/nouveau/codegen/nv50_ir.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir.h
src/gallium/drivers/nouveau/codegen/nv50_ir_target_nvc0.cpp

index 179ad0b7a97b97c4b5b39e0ee55f2b970e42511f..186c9fdbedf8a7057ae9d7e77b1334177d0c4c49 100644 (file)
@@ -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)
index 6d2ee8bce124b45cf19515593b937421a41e4e1e..d6011d9c2239b8256bd5f807e6cc7091e1f28040 100644 (file)
@@ -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();
index 04ac288fba38037111f79b901cfcd5e51bfe96d8..0cb21e8c82633442fc4598037084cfe800a81dcd 100644 (file)
@@ -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;