pan/mdg: Add a nir pass to reorder store_output intrinsics
authorIcecream95 <ixn@keemail.me>
Mon, 6 Jul 2020 11:52:40 +0000 (23:52 +1200)
committerMarge Bot <eric+marge@anholt.net>
Wed, 15 Jul 2020 01:30:00 +0000 (01:30 +0000)
Real writeout stores, which break execution, need to be moved to after
dual-source stores, which are just standard register writes.

v2: Don't move stores forward, to avoid moving them to before where
    their source is written.

v3: Only reorder past dual-source stores.

Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5620>

src/panfrost/midgard/midgard_compile.c

index a535ccd266ed4d5a9cec396e8ac38c5f82ae708a..2ae7950bd2968bbfc571d54907a39506e1428b54 100644 (file)
@@ -445,6 +445,50 @@ midgard_nir_lower_zs_store(nir_shader *nir)
         return progress;
 }
 
+/* Real writeout stores, which break execution, need to be moved to after
+ * dual-source stores, which are just standard register writes. */
+static bool
+midgard_nir_reorder_writeout(nir_shader *nir)
+{
+        bool progress = false;
+
+        nir_foreach_function(function, nir) {
+                if (!function->impl) continue;
+
+                nir_foreach_block(block, function->impl) {
+                        nir_instr *last_writeout = NULL;
+
+                        nir_foreach_instr_reverse_safe(instr, block) {
+                                if (instr->type != nir_instr_type_intrinsic)
+                                        continue;
+
+                                nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
+                                if (intr->intrinsic != nir_intrinsic_store_output)
+                                        continue;
+
+                                const nir_variable *var = search_var(&nir->outputs, nir_intrinsic_base(intr));
+
+                                if (var->data.index) {
+                                        if (!last_writeout)
+                                                last_writeout = instr;
+                                        continue;
+                                }
+
+                                if (!last_writeout)
+                                        continue;
+
+                                /* This is a real store, so move it to after dual-source stores */
+                                exec_node_remove(&instr->node);
+                                exec_node_insert_after(&last_writeout->node, &instr->node);
+
+                                progress = true;
+                        }
+                }
+        }
+
+        return progress;
+}
+
 /* Flushes undefined values to zero */
 
 static void
@@ -2818,6 +2862,8 @@ midgard_compile_shader_nir(nir_shader *nir, panfrost_program *program, bool is_b
 
         optimise_nir(nir, ctx->quirks, is_blend);
 
+        NIR_PASS_V(nir, midgard_nir_reorder_writeout);
+
         if (midgard_debug & MIDGARD_DBG_SHADERS) {
                 nir_print_shader(nir, stdout);
         }