pan/bi: Mark message-passing sources/dests live
authorAlyssa Rosenzweig <alyssa@collabora.com>
Sun, 7 Mar 2021 01:58:46 +0000 (01:58 +0000)
committerAlyssa Rosenzweig <alyssa@collabora.com>
Sun, 7 Mar 2021 15:10:12 +0000 (15:10 +0000)
More general, same data race.

Fixes: 44726101d1e ("pan/bi: Don't fill garbage")
Signed-off-by: Alyssa Rosenzweig <alyssa@collabora.com>
Tested-by: Icecream95 <ixn@disroot.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9446>

src/panfrost/bifrost/bi_ra.c

index 2843b04..cde291c 100644 (file)
 #include "panfrost/util/lcra.h"
 #include "util/u_memory.h"
 
-/* A clause may contain 1 message-passing instruction writing to a staging
- * register. No instruction following it in the clause may access that staging
- * register to prevent data races. Scheduling ensures this is possible but RA
- * needs to preserve this. The simplest solution is forcing the staging
- * register live in _all_ words at the end (and consequently throughout) the
- * clause, addressing corner cases where a single component is masked out */
+/* A clause may contain 1 message-passing instruction.  No subsequent
+ * instruction in the clause may access its registers due to data races.
+ * Scheduling ensures this is possible but RA needs to preserve this. The
+ * simplest solution is forcing accessed registers live in _all_ words at the
+ * end (and consequently throughout) the clause, addressing corner cases where
+ * a single component is masked out */
 
 static void
-bi_mark_sr_live(bi_block *block, bi_clause *clause, unsigned node_count, uint16_t *live)
+bi_mark_msg_live(bi_block *block, bi_clause *clause, unsigned node_count, uint16_t *live)
 {
         bi_foreach_instr_in_clause(block, clause, ins) {
-                if (!bi_opcode_props[ins->op].sr_write) continue;
+                if (!bi_opcode_props[ins->op].message) continue;
 
-                /* Set liveness for dest 0 which is the staging register */
-                unsigned node = bi_get_node(ins->dest[0]);
-                if (node < node_count)
-                        live[node] = bi_writemask(ins, 0);
+                bi_foreach_dest(ins, d) {
+                        unsigned node = bi_get_node(ins->dest[d]);
+                        if (node < node_count)
+                                live[node] |= bi_writemask(ins, d);
+                }
+
+                bi_foreach_src(ins, s) {
+                        unsigned node = bi_get_node(ins->src[s]);
+                        if (node < node_count) {
+                                unsigned count = bi_count_read_registers(ins, s);
+                                unsigned rmask = (1 << (4 * count)) - 1;
+                                live[node] |= (rmask << (4 * ins->src[s].offset));
+                        }
+                }
 
                 break;
         }
@@ -102,7 +112,7 @@ bi_compute_interference(bi_context *ctx, struct lcra_state *l)
                 uint16_t *live = mem_dup(_blk->live_out, node_count * sizeof(uint16_t));
 
                 bi_foreach_clause_in_block_rev(blk, clause) {
-                        bi_mark_sr_live(blk, clause, node_count, live);
+                        bi_mark_msg_live(blk, clause, node_count, live);
                         bi_mark_interference(blk, clause, l, live, node_count,
                                              ctx->inputs->is_blend);
                 }