r300: add some early safe bool lowering
authorPavel Ondračka <pavel.ondracka@gmail.com>
Thu, 15 Jun 2023 07:27:59 +0000 (09:27 +0200)
committerMarge Bot <emma+marge@anholt.net>
Wed, 5 Jul 2023 18:34:37 +0000 (18:34 +0000)
This lowers some of the bool-producing comparisons and following bcsels
if the bool comparison results is only used in the bcsel.
This is a temporary solution before we can fork ntt and optimize
the pass sequence there. Right now if we have something like
bcsel(a,b,0.0) we lower it to flrp in nir_lower_bool_to_float. The
flrp goes to backend where it will be lowered to 2 MADs. However in this
case with one of the arguments being a constant one MAD is enough. The
backend can figure this out in the constant folding pass, however this
is actually one of the last things we need it for. So if we do early
translation of the bcsels, than the algebraic pass can clean it up and
we can remove more backend code in the next patch.

no significant change with RV370 shader-db:
total instructions in shared programs: 82497 -> 82496 (<.01%)
instructions in affected programs: 1029 -> 1028 (-0.10%)
helped: 4
HURT: 3
total temps in shared programs: 12351 -> 12355 (0.03%)
temps in affected programs: 10 -> 14 (40.00%)
helped: 0
HURT: 4

Reviewed-by: Filip Gawin <filip.gawin@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/23927>

src/gallium/drivers/r300/compiler/r300_nir.c
src/gallium/drivers/r300/compiler/r300_nir.h
src/gallium/drivers/r300/compiler/r300_nir_algebraic.py

index 2e8e5da..1c27ede 100644 (file)
@@ -60,6 +60,8 @@ r300_should_vectorize_io(unsigned align, unsigned bit_size,
 static void
 r300_optimize_nir(struct nir_shader *s, struct pipe_screen *screen)
 {
+   bool is_r500 = r300_screen(screen)->caps.is_r500;
+
    bool progress;
    do {
       progress = false;
@@ -68,8 +70,11 @@ r300_optimize_nir(struct nir_shader *s, struct pipe_screen *screen)
 
       NIR_PASS(progress, s, nir_copy_prop);
       NIR_PASS(progress, s, nir_opt_algebraic);
-      if (s->info.stage == MESA_SHADER_VERTEX)
+      if (s->info.stage == MESA_SHADER_VERTEX) {
+         if (!is_r500)
+            NIR_PASS(progress, s, r300_nir_lower_bool_to_float);
          NIR_PASS(progress, s, r300_nir_fuse_fround_d3d9);
+      }
       NIR_PASS(progress, s, nir_opt_constant_folding);
       NIR_PASS(progress, s, nir_opt_remove_phis);
       NIR_PASS(progress, s, nir_opt_conditional_discard);
@@ -81,8 +86,7 @@ r300_optimize_nir(struct nir_shader *s, struct pipe_screen *screen)
       NIR_PASS(progress, s, nir_opt_dead_write_vars);
 
       NIR_PASS(progress, s, nir_opt_if, nir_opt_if_aggressive_last_continue | nir_opt_if_optimize_phi_true_false);
-      NIR_PASS(progress, s, nir_opt_peephole_select,
-               r300_screen(screen)->caps.is_r500 ? 8 : ~0 , true, true);
+      NIR_PASS(progress, s, nir_opt_peephole_select, is_r500 ? 8 : ~0, true, true);
       NIR_PASS(progress, s, nir_opt_algebraic);
       NIR_PASS(progress, s, nir_opt_constant_folding);
       nir_load_store_vectorize_options vectorize_opts = {
index f1f4184..111bf84 100644 (file)
@@ -34,4 +34,6 @@ extern bool r300_transform_fs_trig_input(struct nir_shader *shader);
 
 extern bool r300_nir_fuse_fround_d3d9(struct nir_shader *shader);
 
+extern bool r300_nir_lower_bool_to_float(struct nir_shader *shader);
+
 #endif /* R300_NIR_H */
index c164779..c4ce7d2 100644 (file)
@@ -25,6 +25,13 @@ import argparse
 import sys
 from math import pi
 
+# Convenience variables
+a = 'a'
+b = 'b'
+c = 'c'
+d = 'd'
+e = 'e'
+
 # Transform input to range [-PI, PI]:
 #
 # y = frac(x / 2PI + 0.5) * 2PI - PI
@@ -64,6 +71,22 @@ def main():
     sys.path.insert(0, args.import_path)
 
     import nir_algebraic  # pylint: disable=import-error
+    ignore_exact = nir_algebraic.ignore_exact
+
+    r300_nir_lower_bool_to_float = [
+        (('bcsel@32(is_only_used_as_float)', ignore_exact('feq', 'a@32', 'b@32'), c, d),
+             ('fadd', ('fmul', c, ('seq', a, b)), ('fsub', d, ('fmul', d, ('seq', a, b)))),
+             "!options->has_fused_comp_and_csel"),
+        (('bcsel@32(is_only_used_as_float)', ignore_exact('fneu', 'a@32', 'b@32'), c, d),
+             ('fadd', ('fmul', c, ('sne', a, b)), ('fsub', d, ('fmul', d, ('sne', a, b)))),
+          "!options->has_fused_comp_and_csel"),
+        (('bcsel@32(is_only_used_as_float)', ignore_exact('flt', 'a@32', 'b@32'), c, d),
+             ('fadd', ('fmul', c, ('slt', a, b)), ('fsub', d, ('fmul', d, ('slt', a, b)))),
+          "!options->has_fused_comp_and_csel"),
+        (('bcsel@32(is_only_used_as_float)', ignore_exact('fge', 'a@32', 'b@32'), c, d),
+             ('fadd', ('fmul', c, ('sge', a, b)), ('fsub', d, ('fmul', d, ('sge', a, b)))),
+          "!options->has_fused_comp_and_csel"),
+]
 
     with open(args.output, 'w') as f:
         f.write('#include "compiler/r300_nir.h"')
@@ -77,5 +100,8 @@ def main():
         f.write(nir_algebraic.AlgebraicPass("r300_nir_fuse_fround_d3d9",
                                             r300_nir_fuse_fround_d3d9).render())
 
+        f.write(nir_algebraic.AlgebraicPass("r300_nir_lower_bool_to_float",
+                                            r300_nir_lower_bool_to_float).render())
+
 if __name__ == '__main__':
     main()