nir/algebraic: Reassociate some iand to eliminate an operation
authorIan Romanick <ian.d.romanick@intel.com>
Tue, 15 Feb 2022 17:24:14 +0000 (09:24 -0800)
committerMarge Bot <emma+marge@anholt.net>
Wed, 14 Dec 2022 06:23:20 +0000 (06:23 +0000)
No shader-db changes on any Intel platform.

All of the helped shaders were presumably regressed by 4676b3d3dd9 (nir:
Use nir_test_mask instead of i2b(iand)).

v2: Add some comments explaining why specific replacements are used.  In
the umin pattern, only markup the first usage of 'b' in the source
pattern.

Tiger Lake, Ice Lake, and Skylake had similar results. (Ice Lake shown)
Instructions in all programs: 141384970 -> 141200966 (-0.1%)
Instructions helped: 45842

Cycles in all programs: 9133648977 -> 9133282672 (-0.0%)
Cycles helped: 26812
Cycles hurt: 6025

Gained: 23
Lost: 135

Acked-by: Jesse Natalie <jenatali@microsoft.com>
Acked-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Tested-by: Daniel Schürmann <daniel@schuermann.dev>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15121>

src/compiler/nir/nir_opt_algebraic.py

index edade80..77fa16b 100644 (file)
@@ -897,6 +897,10 @@ optimizations.extend([
    # This is how SpvOpFOrdNotEqual might be implemented.  If both values are
    # numbers, then it can be replaced with fneu.
    (('ior', ('flt', 'a(is_a_number)', 'b(is_a_number)'), ('flt', b, a)), ('fneu', a, b)),
+
+   # Other patterns may optimize the resulting iand tree further.
+   (('umin', ('iand', a, '#b(is_pos_power_of_two)'), ('iand', c, b)),
+    ('iand', ('iand', a, b), ('iand', c, b))),
 ])
 
 # Float sizes
@@ -1265,6 +1269,12 @@ optimizations.extend([
    (('iand', ('ior', a, b), b), b),
    (('iand', ('iand', a, b), b), ('iand', a, b)),
 
+   # It is common for sequences of (x & 1) to occur in large trees.  Replacing
+   # an expression like ((a & 1) & (b & 1)) with ((a & b) & 1) allows the "&
+   # 1" to eventually bubble up to the top of the tree.
+   (('iand', ('iand(is_used_once)', a, b), ('iand(is_used_once)', a, c)),
+    ('iand', a, ('iand', b, c))),
+
    (('iand@64', a, '#b(is_lower_half_zero)'),
     ('pack_64_2x32_split', 0,
                            ('iand', ('unpack_64_2x32_split_y', a), ('unpack_64_2x32_split_y', b)))),