From de60b463d767ac9e2c26021f6a76a11e0da5be62 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 31 Mar 2020 15:37:00 -0700 Subject: [PATCH] nir/algebraic: Simplify various trivial bfi These are mostly just obvious patterns that somebody will eventually want to add. DG2, Tiger Lake, Ice Lake, Skylake, Broadwell, and Haswell had similar results (Ice Lake shown) total instructions in shared programs: 20570033 -> 20570026 (<.01%) instructions in affected programs: 7363 -> 7356 (-0.10%) helped: 6 / HURT: 0 total cycles in shared programs: 902118781 -> 902118854 (<.01%) cycles in affected programs: 419132 -> 419205 (0.02%) helped: 4 / HURT: 2 DG2, Tiger Lake, Ice Lake, and Skylake had similar results (Ice Lake shown) Totals: Instrs: 152819500 -> 152819380 (-0.00%) Cycles: 15014627187 -> 15014624437 (-0.00%) Totals from 115 (0.02% of 662497) affected shaders: Instrs: 28963 -> 28843 (-0.41%) Cycles: 404582 -> 401832 (-0.68%) Reviewed-by: Matt Turner Part-of: --- src/compiler/nir/nir_opt_algebraic.py | 21 +++++++++++++++++++ src/compiler/nir/nir_search_helpers.h | 29 +++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/src/compiler/nir/nir_opt_algebraic.py b/src/compiler/nir/nir_opt_algebraic.py index 611fc10ab65..55c052ace7f 100644 --- a/src/compiler/nir/nir_opt_algebraic.py +++ b/src/compiler/nir/nir_opt_algebraic.py @@ -1386,6 +1386,27 @@ optimizations.extend([ (('uror@32', a, b), ('ior', ('ushr', a, b), ('ishl', a, ('isub', 32, b))), 'options->lower_rotate'), (('uror@64', a, b), ('ior', ('ushr', a, b), ('ishl', a, ('isub', 64, b))), 'options->lower_rotate'), + # bfi(X, a, b) = (b & ~X) | (a & X) + # If X = ~0: (b & 0) | (a & 0xffffffff) = a + # If X = 0: (b & 0xffffffff) | (a & 0) = b + (('bfi', 0xffffffff, a, b), a), + (('bfi', 0x00000000, a, b), b), + + # The result of -int(some_bool) is 0 or 0xffffffff, so the result of the + # bfi is either b or c. + (('bfi', ('ineg', ('b2i', 'a@1')), b, c), ('bcsel', a, b, c)), + + # bfi(a, a, b) = ((a << find_lsb(a)) & a) | (b & ~a) + # = (a & a) | (b & ~a) If a is odd, find_lsb(a) == 0 + # = a | (b & ~a) + # = a | b + (('bfi', '#a(is_odd)', a, b), ('ior', a, b)), + + # bfi(a, b, 0) = ((b << find_lsb(a)) & a) | (0 & ~a) + # = ((b << find_lsb(a)) & a) + # = (b & a) If a is odd, find_lsb(a) == 0 + (('bfi', '#a(is_odd)', b, 0), ('iand', a, b)), + # Because 'a' is a positive power of two, the result of the bfi is either 0 # or 'a' depending on whether or not 'b' is odd. Use 'b&1' for the zero # value to help platforms that can't have two constants in a bcsel. diff --git a/src/compiler/nir/nir_search_helpers.h b/src/compiler/nir/nir_search_helpers.h index 06abe924391..a9d19963a7a 100644 --- a/src/compiler/nir/nir_search_helpers.h +++ b/src/compiler/nir/nir_search_helpers.h @@ -196,6 +196,35 @@ is_gt_0_and_lt_1(UNUSED struct hash_table *ht, const nir_alu_instr *instr, return true; } +/** + * x & 1 != 0 + */ +static inline bool +is_odd(UNUSED struct hash_table *ht, const nir_alu_instr *instr, + unsigned src, unsigned num_components, + const uint8_t *swizzle) +{ + /* only constant srcs: */ + if (!nir_src_is_const(instr->src[src].src)) + return false; + + for (unsigned i = 0; i < num_components; i++) { + nir_alu_type type = nir_op_infos[instr->op].input_types[src]; + switch (nir_alu_type_get_base_type(type)) { + case nir_type_int: + case nir_type_uint: { + if ((nir_src_comp_as_uint(instr->src[src].src, swizzle[i]) & 1) == 0) + return false; + break; + } + default: + return false; + } + } + + return true; +} + static inline bool is_not_const_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr, unsigned src, unsigned num_components,