[Mesa-dev] [PATCH 10/13] panfrost/midgard: Implement "pipeline register" prepass

Alyssa Rosenzweig alyssa at rosenzweig.io
Sun May 26 02:39:21 UTC 2019


This prepass, run after scheduling but before RA, specializes to
pipeline registers where possible. It walks the IR, checking whether
sources are ever used outside of the immediate bundle in which they are
written. If they are not, they are rewritten to a pipeline register (r24
or r25), valid only within the bundle itself. This has theoretical
benefits for power consumption and register pressure.

Signed-off-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
---
 src/gallium/drivers/panfrost/meson.build      |  1 +
 .../drivers/panfrost/midgard/compiler.h       |  2 +
 .../panfrost/midgard/midgard_ra_pipeline.c    | 87 +++++++++++++++++++
 .../panfrost/midgard/midgard_schedule.c       |  8 +-
 4 files changed, 96 insertions(+), 2 deletions(-)
 create mode 100644 src/gallium/drivers/panfrost/midgard/midgard_ra_pipeline.c

diff --git a/src/gallium/drivers/panfrost/meson.build b/src/gallium/drivers/panfrost/meson.build
index 297bdb341bd..b65f027f2c4 100644
--- a/src/gallium/drivers/panfrost/meson.build
+++ b/src/gallium/drivers/panfrost/meson.build
@@ -32,6 +32,7 @@ files_panfrost = files(
   'midgard/midgard_schedule.c',
   'midgard/midgard_emit.c',
   'midgard/midgard_ra.c',
+  'midgard/midgard_ra_pipeline.c',
   'midgard/midgard_liveness.c',
   'midgard/midgard_ops.c',
 
diff --git a/src/gallium/drivers/panfrost/midgard/compiler.h b/src/gallium/drivers/panfrost/midgard/compiler.h
index 37ed2362263..1191c5cc7b8 100644
--- a/src/gallium/drivers/panfrost/midgard/compiler.h
+++ b/src/gallium/drivers/panfrost/midgard/compiler.h
@@ -430,6 +430,8 @@ struct ra_graph* allocate_registers(compiler_context *ctx);
 void install_registers(compiler_context *ctx, struct ra_graph *g);
 bool mir_is_live_after(compiler_context *ctx, midgard_block *block, midgard_instruction *start, int src);
 
+void mir_create_pipeline_registers(compiler_context *ctx);
+
 /* Final emission */
 
 void emit_binary_bundle(
diff --git a/src/gallium/drivers/panfrost/midgard/midgard_ra_pipeline.c b/src/gallium/drivers/panfrost/midgard/midgard_ra_pipeline.c
new file mode 100644
index 00000000000..4de1b910d85
--- /dev/null
+++ b/src/gallium/drivers/panfrost/midgard/midgard_ra_pipeline.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2019 Alyssa Rosenzweig <alyssa at rosenzweig.io>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "compiler.h"
+
+/* Creates pipeline registers. This is a prepass run before the main register
+ * allocator but after scheduling, once bundles are created. It works by
+ * iterating the scheduled IR, checking if a value is ever used after the end
+ * of the current bundle. If it is not, it is promoted to a bundle-specific
+ * pipeline register.
+ *
+ * Pipeline registers are only written from the first two stages of the
+ * pipeline (vmul/sadd) lasting the duration of the bundle only. There are two
+ * 128-bit pipeline registers available (r24/r25). The upshot is that no actual
+ * register allocation is needed; we can _always_ promote a value to a pipeline
+ * register, liveness permitting. This greatly simplifies the logic of this
+ * passing, negating the need for a proper RA like work registers.
+ */
+
+static bool
+mir_pipeline_ins(
+                compiler_context *ctx,
+                midgard_block *block,
+                midgard_bundle *bundle, unsigned i,
+                unsigned pipeline_count)
+{
+        midgard_instruction *ins = bundle->instructions[i];
+        unsigned dest = ins->ssa_args.dest;
+
+        /* Check to make sure we're legal */
+
+        if (ins->compact_branch)
+                return false;
+
+        if ((dest < 0) || (dest >= SSA_FIXED_MINIMUM))
+                return false;
+
+        /* We want to know if we live after this bundle, so check if
+         * we're live after the last instruction of the bundle */
+
+        midgard_instruction *end = bundle->instructions[
+                bundle->instruction_count - 1];
+
+        if (mir_is_live_after(ctx, block, end, ins->ssa_args.dest))
+                return false;
+
+        /* We're only live in this bundle -- pipeline! */
+
+        mir_rewrite_index(ctx, dest, SSA_FIXED_REGISTER(24 + pipeline_count));
+
+        return true;
+}
+
+void
+mir_create_pipeline_registers(compiler_context *ctx)
+{
+        mir_foreach_block(ctx, block) {
+                mir_foreach_bundle_in_block(block, bundle) {
+                        if (!mir_is_alu_bundle(bundle)) continue;
+                        if (bundle->instruction_count < 2) continue;
+
+                        /* Only first 2 instructions could pipeline */
+                        bool succ = mir_pipeline_ins(ctx, block, bundle, 0, 0);
+                        mir_pipeline_ins(ctx, block, bundle, 1, succ);
+                }
+        }
+}
diff --git a/src/gallium/drivers/panfrost/midgard/midgard_schedule.c b/src/gallium/drivers/panfrost/midgard/midgard_schedule.c
index 385b8bcdbc0..1a562af8142 100644
--- a/src/gallium/drivers/panfrost/midgard/midgard_schedule.c
+++ b/src/gallium/drivers/panfrost/midgard/midgard_schedule.c
@@ -470,10 +470,14 @@ void
 schedule_program(compiler_context *ctx)
 {
         /* We run RA prior to scheduling */
-        struct ra_graph *g = allocate_registers(ctx);
-        install_registers(ctx, g);
 
         mir_foreach_block(ctx, block) {
                 schedule_block(ctx, block);
         }
+
+        /* Pipeline registers creation is a prepass before RA */
+        mir_create_pipeline_registers(ctx);
+
+        struct ra_graph *g = allocate_registers(ctx);
+        install_registers(ctx, g);
 }
-- 
2.20.1



More information about the mesa-dev mailing list