Module: Mesa
Branch: main
Commit: c5712410ec3d65ae6cd759661883868912a903dd
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=c5712410ec3d65ae6cd759661883868912a903dd

Author: Emma Anholt <[email protected]>
Date:   Tue Oct  3 10:04:04 2023 -0700

nir: Flatten ifs with discards in nir_opt_peephole_select for HW without CF.

i915g and r300-r400 don't have if statements, and discards are all
nir_intrinsic_discard_if.  We can flatten those discards here, saving a
separate GLSL pass to try to do so.

i915g:
GAINED: shaders/closed/xcom-enemy-unknown/413.shader_test FS

rv370:
GAINED: shaders/closed/xcom-enemy-unknown/12.shader_test FS
GAINED: shaders/closed/xcom-enemy-unknown/122.shader_test FS
GAINED: shaders/closed/xcom-enemy-unknown/132.shader_test FS
GAINED: shaders/closed/xcom-enemy-unknown/145.shader_test FS
GAINED: shaders/closed/xcom-enemy-unknown/146.shader_test FS
GAINED: shaders/closed/xcom-enemy-unknown/19.shader_test FS
GAINED: shaders/closed/xcom-enemy-unknown/413.shader_test FS
GAINED: shaders/closed/xcom-enemy-unknown/415.shader_test FS

Closes: #9918
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24763>

---

 src/compiler/nir/nir_opt_peephole_select.c | 46 ++++++++++++++++++++++++++++--
 1 file changed, 43 insertions(+), 3 deletions(-)

diff --git a/src/compiler/nir/nir_opt_peephole_select.c 
b/src/compiler/nir/nir_opt_peephole_select.c
index 9de5402d7f7..043e1bad041 100644
--- a/src/compiler/nir/nir_opt_peephole_select.c
+++ b/src/compiler/nir/nir_opt_peephole_select.c
@@ -23,6 +23,7 @@
 
 #include "nir/nir_builder.h"
 #include "nir.h"
+#include "nir_builder.h"
 #include "nir_control_flow.h"
 #include "nir_search_helpers.h"
 
@@ -74,10 +75,21 @@ block_check_for_allowed_instrs(nir_block *block, unsigned 
*count,
          case nir_instr_type_tex:
             break;
 
-         case nir_instr_type_intrinsic:
-            if (!nir_intrinsic_can_reorder(nir_instr_as_intrinsic(instr)))
-               return false;
+         case nir_instr_type_intrinsic: {
+            nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
+            switch (intr->intrinsic) {
+            case nir_intrinsic_discard:
+            case nir_intrinsic_discard_if:
+              /* For non-CF hardware, we need to be able to move discards up
+               * and flatten, so let them pass.
+               */
+              continue;
+            default:
+               if (!nir_intrinsic_can_reorder(intr))
+                  return false;
+            }
             break;
+         }
 
          case nir_instr_type_call:
          case nir_instr_type_jump:
@@ -362,6 +374,32 @@ nir_opt_collapse_if(nir_if *if_stmt, nir_shader *shader, 
unsigned limit,
    return true;
 }
 
+/* If we're moving discards out of the if for non-CF hardware, we need to add
+ * the if's condition to it
+ */
+static void
+rewrite_discard_conds(nir_instr *instr, nir_def *if_cond, bool is_else)
+{
+   if (instr->type != nir_instr_type_intrinsic)
+      return;
+   nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
+
+   if (intr->intrinsic != nir_intrinsic_discard_if && intr->intrinsic != 
nir_intrinsic_discard)
+      return;
+
+   nir_builder b = nir_builder_at(nir_before_instr(instr));
+
+   if (is_else)
+      if_cond = nir_inot(&b, if_cond);
+
+   if (intr->intrinsic == nir_intrinsic_discard_if) {
+      nir_src_rewrite(&intr->src[0], nir_iand(&b, intr->src[0].ssa, if_cond));
+   } else {
+      nir_discard_if(&b, if_cond);
+      nir_instr_remove(instr);
+   }
+}
+
 static bool
 nir_opt_peephole_select_block(nir_block *block, nir_shader *shader,
                               unsigned limit, bool indirect_load_ok,
@@ -434,12 +472,14 @@ nir_opt_peephole_select_block(nir_block *block, 
nir_shader *shader,
       exec_node_remove(&instr->node);
       instr->block = prev_block;
       exec_list_push_tail(&prev_block->instr_list, &instr->node);
+      rewrite_discard_conds(instr, if_stmt->condition.ssa, false);
    }
 
    nir_foreach_instr_safe(instr, else_block) {
       exec_node_remove(&instr->node);
       instr->block = prev_block;
       exec_list_push_tail(&prev_block->instr_list, &instr->node);
+      rewrite_discard_conds(instr, if_stmt->condition.ssa, true);
    }
 
    nir_foreach_phi_safe(phi, block) {

Reply via email to