pan/mdg: Analyze helper execution requirements
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Tue, 12 May 2020 17:19:23 +0000 (13:19 -0400)
committerMarge Bot <eric+marge@anholt.net>
Tue, 12 May 2020 22:30:41 +0000 (22:30 +0000)
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5014>

src/panfrost/midgard/compiler.h
src/panfrost/midgard/midgard_helper_invocations.c
src/panfrost/midgard/midgard_print.c
src/panfrost/util/pan_ir.h
src/panfrost/util/pan_liveness.c

index 6db0cfea466bee67315fc4d8d8284ccbe22d2d81..bf125369fde8dc2d392fbbd8f53c6264621b460e 100644 (file)
@@ -107,6 +107,7 @@ typedef struct midgard_instruction {
         /* For textures: should helpers execute this instruction (instead of
          * just helping with derivatives)? Should helpers terminate after? */
         bool helper_terminate;
+        bool helper_execute;
 
         /* I.e. (1 << alu_bit) */
         int unit;
@@ -634,6 +635,7 @@ midgard_lower_derivatives(compiler_context *ctx, midgard_block *block);
 bool mir_op_computes_derivatives(gl_shader_stage stage, unsigned op);
 
 void mir_analyze_helper_terminate(compiler_context *ctx);
+void mir_analyze_helper_requirements(compiler_context *ctx);
 
 /* Final emission */
 
index 9f8c68a81252c3da4ecfb90f658d149e9320a973..6dfb9c099735c386a15921de80af505c953a94db 100644 (file)
@@ -158,3 +158,90 @@ mir_analyze_helper_terminate(compiler_context *ctx)
                 }
         }
 }
+
+static bool
+mir_helper_block_update(BITSET_WORD *deps, pan_block *_block, unsigned temp_count)
+{
+        bool progress = false;
+        midgard_block *block = (midgard_block *) _block;
+
+        mir_foreach_instr_in_block_rev(block, ins) {
+                /* Ensure we write to a helper dependency */
+                if (ins->dest >= temp_count || !BITSET_TEST(deps, ins->dest))
+                        continue;
+
+                /* Then add all of our dependencies */
+                mir_foreach_src(ins, s) {
+                        if (ins->src[s] >= temp_count)
+                                continue;
+
+                        /* Progress if the dependency set changes */
+                        progress |= !BITSET_TEST(deps, ins->src[s]);
+                        BITSET_SET(deps, ins->src[s]);
+                }
+        }
+
+        return progress;
+}
+
+void
+mir_analyze_helper_requirements(compiler_context *ctx)
+{
+        mir_compute_temp_count(ctx);
+        unsigned temp_count = ctx->temp_count;
+        BITSET_WORD *deps = calloc(sizeof(BITSET_WORD), BITSET_WORDS(temp_count));
+
+        /* Initialize with the sources of instructions consuming
+         * derivatives */
+
+        mir_foreach_instr_global(ctx, ins) {
+                if (ins->type != TAG_TEXTURE_4) continue;
+                if (ins->dest >= ctx->temp_count) continue;
+                if (!mir_op_computes_derivatives(ctx->stage, ins->texture.op)) continue;
+
+                mir_foreach_src(ins, s) {
+                        if (ins->src[s] < temp_count)
+                                BITSET_SET(deps, ins->src[s]);
+                }
+        }
+
+        /* Propagate that up */
+
+        struct set *work_list = _mesa_set_create(NULL,
+                        _mesa_hash_pointer,
+                        _mesa_key_pointer_equal);
+
+        struct set *visited = _mesa_set_create(NULL,
+                        _mesa_hash_pointer,
+                        _mesa_key_pointer_equal);
+
+        struct set_entry *cur = _mesa_set_add(work_list, pan_exit_block(&ctx->blocks));
+
+        do {
+                pan_block *blk = (struct pan_block *) cur->key;
+                _mesa_set_remove(work_list, cur);
+
+                bool progress = mir_helper_block_update(deps, blk, temp_count);
+
+                if (progress || !_mesa_set_search(visited, blk)) {
+                        pan_foreach_predecessor(blk, pred)
+                                _mesa_set_add(work_list, pred);
+                }
+
+                _mesa_set_add(visited, blk);
+        } while((cur = _mesa_set_next_entry(work_list, NULL)) != NULL);
+
+        _mesa_set_destroy(visited, NULL);
+        _mesa_set_destroy(work_list, NULL);
+
+        /* Set the execute bits */
+
+        mir_foreach_instr_global(ctx, ins) {
+                if (ins->type != TAG_TEXTURE_4) continue;
+                if (ins->dest >= ctx->temp_count) continue;
+
+                ins->helper_execute = BITSET_TEST(deps, ins->dest);
+        }
+
+        free(deps);
+}
index 002026a16b59622bff9d5250342d72a5d886fa97..1b1ff6a145fe01389d6b611644bf9f6521ecb684 100644 (file)
@@ -332,6 +332,9 @@ mir_print_instruction(midgard_instruction *ins)
                 if (ins->helper_terminate)
                         printf(".terminate");
 
+                if (ins->helper_execute)
+                        printf(".execute");
+
                 break;
         }
 
index c57a8e01c34bc67adcaeac8abc19ef92d3777f79..a45478ae6ecf94e1567f5a70f3d1690a27babc73 100644 (file)
@@ -160,6 +160,13 @@ struct pan_instruction {
                 _entry_##v = _mesa_set_next_entry(blk->predecessors, _entry_##v), \
                 v = (struct pan_block *) (_entry_##v ? _entry_##v->key : NULL))
 
+static inline pan_block *
+pan_exit_block(struct list_head *blocks)
+{
+        pan_block *last = list_last_entry(blocks, pan_block, link);
+        assert(!last->successors[0] && !last->successors[1]);
+        return last;
+}
 
 typedef void (*pan_liveness_update)(uint16_t *, void *, unsigned max);
 
index a46a11d9d3ced74b09f794c0460847e2716b127a..9772feb1a9c412a719e889ea9e2daf8f80409561 100644 (file)
@@ -104,14 +104,6 @@ liveness_block_update(
  * adding the predecessors of the block to the work list if we made progress.
  */
 
-static inline pan_block *
-pan_exit_block(struct list_head *blocks)
-{
-        pan_block *last = list_last_entry(blocks, pan_block, link);
-        assert(!last->successors[0] && !last->successors[1]);
-        return last;
-}
-
 void
 pan_compute_liveness(
                 struct list_head *blocks,