diff options
-rw-r--r-- | src/compiler/nir/nir_algebraic.py | 9 | ||||
-rw-r--r-- | src/compiler/nir/nir_opt_algebraic.py | 9 | ||||
-rw-r--r-- | src/compiler/nir/nir_search.c | 4 | ||||
-rw-r--r-- | src/compiler/nir/nir_search.h | 6 |
4 files changed, 26 insertions, 2 deletions
diff --git a/src/compiler/nir/nir_algebraic.py b/src/compiler/nir/nir_algebraic.py index 1818877a216..d05564f779c 100644 --- a/src/compiler/nir/nir_algebraic.py +++ b/src/compiler/nir/nir_algebraic.py @@ -69,6 +69,7 @@ static const ${val.c_type} ${val.name} = { ${'true' if val.is_constant else 'false'}, ${val.type() or 'nir_type_invalid' }, % elif isinstance(val, Expression): + ${'true' if val.inexact else 'false'}, nir_op_${val.opcode}, { ${', '.join(src.c_ptr for src in val.sources)} }, % endif @@ -145,12 +146,18 @@ class Variable(Value): elif self.required_type == 'float': return "nir_type_float" +_opcode_re = re.compile(r"(?P<inexact>~)?(?P<opcode>\w+)") + class Expression(Value): def __init__(self, expr, name_base, varset): Value.__init__(self, name_base, "expression") assert isinstance(expr, tuple) - self.opcode = expr[0] + m = _opcode_re.match(expr[0]) + assert m and m.group('opcode') is not None + + self.opcode = m.group('opcode') + self.inexact = m.group('inexact') 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 0f2bd18dd69..d788b7b1a0c 100644 --- a/src/compiler/nir/nir_opt_algebraic.py +++ b/src/compiler/nir/nir_opt_algebraic.py @@ -34,10 +34,17 @@ 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. # +# If the opcode in a search expression is prefixed by a '~' character, this +# indicates that the operation is inexact. Such operations will only get +# applied to SSA values that do not have the exact bit set. This should be +# used by by any optimizations that are not bit-for-bit exact. It should not, +# however, be used for backend-requested lowering operations as those need to +# happen regardless of precision. +# # Variable names are specified as "[#]name[@type]" 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 6f6a9425c18..110ab5e2362 100644 --- a/src/compiler/nir/nir_search.c +++ b/src/compiler/nir/nir_search.c @@ -238,6 +238,10 @@ match_expression(const nir_search_expression *expr, nir_alu_instr *instr, if (instr->op != expr->opcode) return false; + assert(instr->dest.dest.is_ssa); + if (expr->inexact && instr->exact) + return false; + assert(!instr->dest.saturate); assert(nir_op_infos[instr->op].num_inputs > 0); diff --git a/src/compiler/nir/nir_search.h b/src/compiler/nir/nir_search.h index 321d6d00355..61742f129b1 100644 --- a/src/compiler/nir/nir_search.h +++ b/src/compiler/nir/nir_search.h @@ -83,6 +83,12 @@ typedef struct { typedef struct { nir_search_value value; + /* When set on a search expression, the expression will only match an SSA + * value that does *not* have the exact bit set. If unset, the exact bit + * on the SSA value is ignored. + */ + bool inexact; + nir_op opcode; const nir_search_value *srcs[4]; } nir_search_expression; |