From: Alyssa Rosenzweig Date: Tue, 12 May 2020 00:22:16 +0000 (-0400) Subject: pan/mdg: Analyze helper invocation termination X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=3228b3106a672e79093f2186f3e040a7579cd7b4;p=mesa.git pan/mdg: Analyze helper invocation termination Signed-off-by: Alyssa Rosenzweig Part-of: --- diff --git a/src/panfrost/Makefile.sources b/src/panfrost/Makefile.sources index 2e9a026f27d..06062b16749 100644 --- a/src/panfrost/Makefile.sources +++ b/src/panfrost/Makefile.sources @@ -47,6 +47,7 @@ midgard_FILES := \ midgard/midgard_emit.c \ midgard/midgard.h \ midgard/midgard_liveness.c \ + midgard/midgard_helper_invocations.c \ midgard/midgard_nir.h \ midgard/midgard_ops.c \ midgard/midgard_ops.h \ diff --git a/src/panfrost/midgard/compiler.h b/src/panfrost/midgard/compiler.h index 5158ea6a85c..6db0cfea466 100644 --- a/src/panfrost/midgard/compiler.h +++ b/src/panfrost/midgard/compiler.h @@ -104,6 +104,10 @@ typedef struct midgard_instruction { /* Special fields for an ALU instruction */ midgard_reg_info registers; + /* For textures: should helpers execute this instruction (instead of + * just helping with derivatives)? Should helpers terminate after? */ + bool helper_terminate; + /* I.e. (1 << alu_bit) */ int unit; @@ -179,6 +183,9 @@ typedef struct midgard_block { /* Indicates this is a fixed-function fragment epilogue block */ bool epilogue; + + /* Are helper invocations required by this block? */ + bool helpers_in; } midgard_block; typedef struct midgard_bundle { @@ -626,6 +633,8 @@ 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); + /* Final emission */ void emit_binary_bundle( diff --git a/src/panfrost/midgard/meson.build b/src/panfrost/midgard/meson.build index fc0cd85f4df..b719af8bda9 100644 --- a/src/panfrost/midgard/meson.build +++ b/src/panfrost/midgard/meson.build @@ -27,6 +27,7 @@ libpanfrost_midgard_files = files( 'midgard_schedule.c', 'midgard_derivatives.c', 'midgard_emit.c', + 'midgard_helper_invocations.c', 'midgard_ra.c', 'midgard_ra_pipeline.c', 'midgard_liveness.c', diff --git a/src/panfrost/midgard/midgard_helper_invocations.c b/src/panfrost/midgard/midgard_helper_invocations.c index 32bcbd4d823..9f8c68a8125 100644 --- a/src/panfrost/midgard/midgard_helper_invocations.c +++ b/src/panfrost/midgard/midgard_helper_invocations.c @@ -61,3 +61,100 @@ * with union as the join operation and the generating set being the union of * sources of instructions writing executed values. */ + +/* Does a block use helpers directly */ +static bool +mir_block_uses_helpers(gl_shader_stage stage, midgard_block *block) +{ + mir_foreach_instr_in_block(block, ins) { + if (ins->type != TAG_TEXTURE_4) continue; + if (mir_op_computes_derivatives(stage, ins->texture.op)) + return true; + } + + return false; +} + +static bool +mir_block_terminates_helpers(midgard_block *block) +{ + /* Can't terminate if there are no helpers */ + if (!block->helpers_in) + return false; + + /* Can't terminate if a successor needs helpers */ + pan_foreach_successor((&block->base), succ) { + if (((midgard_block *) succ)->helpers_in) + return false; + } + + /* Otherwise we terminate */ + return true; +} + +void +mir_analyze_helper_terminate(compiler_context *ctx) +{ + /* Set blocks as directly requiring helpers, and if they do add them to + * the worklist to propagate to their predecessors */ + + struct set *worklist = _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); + + mir_foreach_block(ctx, _block) { + midgard_block *block = (midgard_block *) _block; + block->helpers_in |= mir_block_uses_helpers(ctx->stage, block); + + if (block->helpers_in) + _mesa_set_add(worklist, _block); + } + + /* Next, propagate back. Since there are a finite number of blocks, the + * worklist (a subset of all the blocks) is finite. Since a block can + * only be added to the worklist if it is not on the visited list and + * the visited list - also a subset of the blocks - grows every + * iteration, the algorithm must terminate. */ + + struct set_entry *cur; + + while((cur = _mesa_set_next_entry(worklist, NULL)) != NULL) { + /* Pop off a block requiring helpers */ + pan_block *blk = (struct pan_block *) cur->key; + _mesa_set_remove(worklist, cur); + + /* Its predecessors also require helpers */ + pan_foreach_predecessor(blk, pred) { + if (!_mesa_set_search(visited, pred)) { + ((midgard_block *) pred)->helpers_in = true; + _mesa_set_add(worklist, pred); + } + } + + _mesa_set_add(visited, blk); + } + + _mesa_set_destroy(visited, NULL); + _mesa_set_destroy(worklist, NULL); + + /* Finally, set helper_terminate on the last derivative-calculating + * instruction in a block that terminates helpers */ + mir_foreach_block(ctx, _block) { + midgard_block *block = (midgard_block *) _block; + + if (!mir_block_terminates_helpers(block)) + continue; + + mir_foreach_instr_in_block_rev(block, ins) { + if (ins->type != TAG_TEXTURE_4) continue; + if (!mir_op_computes_derivatives(ctx->stage, ins->texture.op)) continue; + + ins->helper_terminate = true; + break; + } + } +} diff --git a/src/panfrost/midgard/midgard_print.c b/src/panfrost/midgard/midgard_print.c index 89b853ce3cb..002026a16b5 100644 --- a/src/panfrost/midgard/midgard_print.c +++ b/src/panfrost/midgard/midgard_print.c @@ -328,6 +328,10 @@ mir_print_instruction(midgard_instruction *ins) case TAG_TEXTURE_4: { printf("texture"); + + if (ins->helper_terminate) + printf(".terminate"); + break; }