summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRhys Perry <pendingchaos02@gmail.com>2021-10-15 16:39:35 +0100
committerMarge Bot <emma+marge@anholt.net>2022-01-20 22:54:42 +0000
commit312a2849807f577f0bbdf10b4e5e5fd1c3546b02 (patch)
tree138c696d3774f06e7c315f87aac7631c3b65c7f7
parentf68797ead72c29678a54aae457dbd9e9b7946588 (diff)
downloadmesa-312a2849807f577f0bbdf10b4e5e5fd1c3546b02.tar.gz
nir/algebraic: add ignore_exact() wrapper
Signed-off-by: Rhys Perry <pendingchaos02@gmail.com> Reviewed-by: Timur Kristóf <timur.kristof@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13436>
-rw-r--r--src/compiler/nir/nir_algebraic.py40
-rw-r--r--src/compiler/nir/nir_opt_algebraic.py2
-rw-r--r--src/compiler/nir/nir_search.c2
-rw-r--r--src/compiler/nir/nir_search.h5
4 files changed, 42 insertions, 7 deletions
diff --git a/src/compiler/nir/nir_algebraic.py b/src/compiler/nir/nir_algebraic.py
index bfe00d6ed85..9a4e8054345 100644
--- a/src/compiler/nir/nir_algebraic.py
+++ b/src/compiler/nir/nir_algebraic.py
@@ -98,13 +98,33 @@ class VarSet(object):
def lock(self):
self.immutable = True
+class SearchExpression(object):
+ def __init__(self, expr):
+ self.opcode = expr[0]
+ self.sources = expr[1:]
+ self.ignore_exact = False
+
+ @staticmethod
+ def create(val):
+ if isinstance(val, tuple):
+ return SearchExpression(val)
+ else:
+ assert(isinstance(val, SearchExpression))
+ return val
+
+ def __repr__(self):
+ l = [self.opcode, *self.sources]
+ if self.ignore_exact:
+ l.append('ignore_exact')
+ return repr((*l,))
+
class Value(object):
@staticmethod
def create(val, name_base, varset, algebraic_pass):
if isinstance(val, bytes):
val = val.decode('utf-8')
- if isinstance(val, tuple):
+ if isinstance(val, tuple) or isinstance(val, SearchExpression):
return Expression(val, name_base, varset, algebraic_pass)
elif isinstance(val, Expression):
return val
@@ -185,7 +205,9 @@ class Value(object):
${val.cond_index},
${val.swizzle()},
% elif isinstance(val, Expression):
- ${'true' if val.inexact else 'false'}, ${'true' if val.exact else 'false'},
+ ${'true' if val.inexact else 'false'},
+ ${'true' if val.exact else 'false'},
+ ${'true' if val.ignore_exact else 'false'},
${val.c_opcode()},
${val.comm_expr_idx}, ${val.comm_exprs},
{ ${', '.join(src.array_index for src in val.sources)} },
@@ -339,15 +361,17 @@ _opcode_re = re.compile(r"(?P<inexact>~)?(?P<exact>!)?(?P<opcode>\w+)(?:@(?P<bit
class Expression(Value):
def __init__(self, expr, name_base, varset, algebraic_pass):
Value.__init__(self, expr, name_base, "expression")
- assert isinstance(expr, tuple)
- m = _opcode_re.match(expr[0])
+ expr = SearchExpression.create(expr)
+
+ m = _opcode_re.match(expr.opcode)
assert m and m.group('opcode') is not None
self.opcode = m.group('opcode')
self._bit_size = int(m.group('bits')) if m.group('bits') else None
self.inexact = m.group('inexact') is not None
self.exact = m.group('exact') is not None
+ self.ignore_exact = expr.ignore_exact
self.cond = m.group('cond')
assert not self.inexact or not self.exact, \
@@ -372,7 +396,7 @@ class Expression(Value):
self.cond_index = get_cond_index(algebraic_pass.expression_cond, self.cond)
self.sources = [ Value.create(src, "{0}_{1}".format(name_base, i), varset, algebraic_pass)
- for (i, src) in enumerate(expr[1:]) ]
+ for (i, src) in enumerate(expr.sources) ]
# nir_search_expression::srcs is hard-coded to 4
assert len(self.sources) <= 4
@@ -1235,3 +1259,9 @@ class AlgebraicPass(object):
variable_cond = sorted(self.variable_cond.items(), key=lambda kv: kv[1]),
get_c_opcode=get_c_opcode,
itertools=itertools)
+
+# The replacement expression isn't necessarily exact if the search expression is exact.
+def ignore_exact(*expr):
+ expr = SearchExpression.create(expr)
+ expr.ignore_exact = True
+ return expr
diff --git a/src/compiler/nir/nir_opt_algebraic.py b/src/compiler/nir/nir_opt_algebraic.py
index 949e0f24278..147e0dd345d 100644
--- a/src/compiler/nir/nir_opt_algebraic.py
+++ b/src/compiler/nir/nir_opt_algebraic.py
@@ -41,6 +41,8 @@ e = 'e'
signed_zero_inf_nan_preserve_16 = 'nir_is_float_control_signed_zero_inf_nan_preserve(info->float_controls_execution_mode, 16)'
signed_zero_inf_nan_preserve_32 = 'nir_is_float_control_signed_zero_inf_nan_preserve(info->float_controls_execution_mode, 32)'
+ignore_exact = nir_algebraic.ignore_exact
+
# 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>)
diff --git a/src/compiler/nir/nir_search.c b/src/compiler/nir/nir_search.c
index 3246d13ec8a..4fd7ad66143 100644
--- a/src/compiler/nir/nir_search.c
+++ b/src/compiler/nir/nir_search.c
@@ -408,7 +408,7 @@ match_expression(const nir_algebraic_table *table, const nir_search_expression *
return false;
state->inexact_match = expr->inexact || state->inexact_match;
- state->has_exact_alu = instr->exact || state->has_exact_alu;
+ state->has_exact_alu = (instr->exact && !expr->ignore_exact) || state->has_exact_alu;
if (state->inexact_match && state->has_exact_alu)
return false;
diff --git a/src/compiler/nir/nir_search.h b/src/compiler/nir/nir_search.h
index 2a7e9a2f0fe..fb56592cdd4 100644
--- a/src/compiler/nir/nir_search.h
+++ b/src/compiler/nir/nir_search.h
@@ -142,8 +142,11 @@ typedef struct {
/** In a replacement, requests that the instruction be marked exact. */
bool exact : 1;
+ /** Don't make the replacement exact if the search expression is exact. */
+ bool ignore_exact : 1;
+
/* One of nir_op or nir_search_op */
- uint16_t opcode : 14;
+ uint16_t opcode : 13;
/* Commutative expression index. This is assigned by opt_algebraic.py when
* search structures are constructed and is a unique (to this structure)