diff options
author | Ian Romanick <[email protected]> | 2018-05-22 18:19:16 -0700 |
---|---|---|
committer | Ian Romanick <[email protected]> | 2019-03-28 15:35:53 -0700 |
commit | 2cf59861a8128a91bfdd6fe62bf69cb4593373e3 (patch) | |
tree | 33daec3329c0ccb028e108649ffbdc6dc5881879 /src/compiler/nir/nir_search_helpers.h | |
parent | c6ee46a7532291fc8583400e174e77b1833daf23 (diff) |
nir: Add partial redundancy elimination for compares
This pass attempts to dectect code sequences like
if (x < y) {
z = y - x;
...
}
and replace them with sequences like
t = x - y;
if (t < 0) {
z = -t;
...
}
On architectures where the subtract can generate the flags used by the
if-statement, this saves an instruction. It's also possible that moving
an instruction out of the if-statement will allow
nir_opt_peephole_select to convert the whole thing to a bcsel.
Currently only floating point compares and adds are supported. Adding
support for integer will be a challenge due to integer overflow. There
are a couple possible solutions, but they may not apply to all
architectures.
v2: Fix a typo in the commit message and a couple typos in comments.
Fix possible NULL pointer deref from result of push_block(). Add
missing (-A + B) case. Suggested by Caio.
v3: Fix is_not_const_zero to work correctly with types other than
nir_type_float32. Suggested by Ken.
v4: Add some comments explaining how this works. Suggested by Ken.
Reviewed-by: Kenneth Graunke <[email protected]>
Diffstat (limited to 'src/compiler/nir/nir_search_helpers.h')
-rw-r--r-- | src/compiler/nir/nir_search_helpers.h | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/src/compiler/nir/nir_search_helpers.h b/src/compiler/nir/nir_search_helpers.h index 456de81e175..1624508993d 100644 --- a/src/compiler/nir/nir_search_helpers.h +++ b/src/compiler/nir/nir_search_helpers.h @@ -110,6 +110,33 @@ is_zero_to_one(nir_alu_instr *instr, unsigned src, unsigned num_components, } static inline bool +is_not_const_zero(nir_alu_instr *instr, unsigned src, unsigned num_components, + const uint8_t *swizzle) +{ + if (nir_src_as_const_value(instr->src[src].src) == NULL) + return true; + + for (unsigned i = 0; i < num_components; i++) { + switch (nir_op_infos[instr->op].input_types[src]) { + case nir_type_float: + if (nir_src_comp_as_float(instr->src[src].src, swizzle[i]) == 0.0) + return false; + break; + case nir_type_bool: + case nir_type_int: + case nir_type_uint: + if (nir_src_comp_as_uint(instr->src[src].src, swizzle[i]) == 0) + return false; + break; + default: + return false; + } + } + + return true; +} + +static inline bool is_not_const(nir_alu_instr *instr, unsigned src, UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) { |