[Mesa-dev] [RFC 1/2] nir/algebraic: Add support for declaring that a given expression is unique

Timothy Arceri timothy.arceri at collabora.com
Fri Dec 30 09:49:30 UTC 2016


From: Jason Ekstrand <jason.ekstrand at intel.com>

Some algebraic transformations are only useful if you know for certain that
they won't generate more instructions by accident.  One fairly limited way
of ensuring this is to ensure that some subexpression is only used in the
particular tree being matched.
---
 src/compiler/nir/nir_algebraic.py     | 4 +++-
 src/compiler/nir/nir_opt_algebraic.py | 6 +++++-
 src/compiler/nir/nir_search.c         | 5 +++++
 src/compiler/nir/nir_search.h         | 3 +++
 4 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/src/compiler/nir/nir_algebraic.py b/src/compiler/nir/nir_algebraic.py
index 19ac6ee..03e7efe 100644
--- a/src/compiler/nir/nir_algebraic.py
+++ b/src/compiler/nir/nir_algebraic.py
@@ -90,6 +90,7 @@ static const ${val.c_type} ${val.name} = {
    ${'true' if val.inexact else 'false'},
    nir_op_${val.opcode},
    { ${', '.join(src.c_ptr for src in val.sources)} },
+   ${'true' if val.is_unique else 'false'}
 % endif
 };""")
 
@@ -185,7 +186,7 @@ class Variable(Value):
       elif self.required_type == 'float':
          return "nir_type_float"
 
-_opcode_re = re.compile(r"(?P<inexact>~)?(?P<opcode>\w+)(?:@(?P<bits>\d+))?")
+_opcode_re = re.compile(r"(?P<inexact>~)?(?P<unique>!)?(?P<opcode>\w+)(?:@(?P<bits>\d+))?")
 
 class Expression(Value):
    def __init__(self, expr, name_base, varset):
@@ -198,6 +199,7 @@ class Expression(Value):
       self.opcode = m.group('opcode')
       self.bit_size = int(m.group('bits')) if m.group('bits') else 0
       self.inexact = m.group('inexact') is not None
+      self.is_unique = m.group('unique') is not None
       self.sources = [ Value.create(src, "{0}_{1}".format(name_base, i), varset)
                        for (i, src) in enumerate(expr[1:]) ]
 
diff --git a/src/compiler/nir/nir_opt_algebraic.py b/src/compiler/nir/nir_opt_algebraic.py
index ff10d70..982f8b2 100644
--- a/src/compiler/nir/nir_opt_algebraic.py
+++ b/src/compiler/nir/nir_opt_algebraic.py
@@ -34,7 +34,7 @@ d = 'd'
 
 # Written in the form (<search>, <replace>) where <search> is an expression
 # and <replace> is either an expression or a value.  An expression is
-# defined as a tuple of the form ([~]<op>, <src0>, <src1>, <src2>, <src3>)
+# defined as a tuple of the form ([~,!]<op>, <src0>, <src1>, <src2>, <src3>)
 # where each source is either an expression or a value.  A value can be
 # either a numeric constant or a string representing a variable name.
 #
@@ -45,6 +45,10 @@ d = 'd'
 # however, be used for backend-requested lowering operations as those need to
 # happen regardless of precision.
 #
+# If the opcode in a search expression is prefixed by a '!' character, this
+# indicates that the this expression is unique i.e. the result of the
+# expression has a single use.
+#
 # Variable names are specified as "[#]name[@type][(cond)]" where "#" inicates
 # that the given variable will only match constants and the type indicates that
 # the given variable will only match values from ALU instructions with the
diff --git a/src/compiler/nir/nir_search.c b/src/compiler/nir/nir_search.c
index b34b13f..34e39e1 100644
--- a/src/compiler/nir/nir_search.c
+++ b/src/compiler/nir/nir_search.c
@@ -257,6 +257,11 @@ match_expression(const nir_search_expression *expr, nir_alu_instr *instr,
                  unsigned num_components, const uint8_t *swizzle,
                  struct match_state *state)
 {
+   if (expr->is_unique &&
+       (!list_empty(&instr->dest.dest.ssa.if_uses) ||
+        !list_is_singular(&instr->dest.dest.ssa.uses)))
+      return false;
+
    if (instr->op != expr->opcode)
       return false;
 
diff --git a/src/compiler/nir/nir_search.h b/src/compiler/nir/nir_search.h
index dec19d5..be32a37 100644
--- a/src/compiler/nir/nir_search.h
+++ b/src/compiler/nir/nir_search.h
@@ -103,6 +103,9 @@ typedef struct {
 
    nir_op opcode;
    const nir_search_value *srcs[4];
+
+   /* Specifies that this expression is only used once */
+   bool is_unique;
 } nir_search_expression;
 
 NIR_DEFINE_CAST(nir_search_value_as_variable, nir_search_value,
-- 
2.9.3



More information about the mesa-dev mailing list