Module: Mesa
Branch: master
Commit: 14af7b30855745b3b3aca7bc33a4507b73467a88
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=14af7b30855745b3b3aca7bc33a4507b73467a88

Author: Iago Toral Quiroga <[email protected]>
Date:   Tue Feb 16 09:07:04 2021 +0100

broadcom/compiler: don't emit redundant ldunif

If we emit a new uniform and that uniform has already been emitted
in the same block we can just reuse that.

There is a balancing game here between reducing ldunif instructions
and not increasing register pressure too much though, so we put
a limit to how far back we are willing to look for a previous
definition of the uniform. Based on shader-db results, 20 instructions
produces best results.

total instructions in shared programs: 14928266 -> 14907432 (-0.14%)
instructions in affected programs: 6431841 -> 6411007 (-0.32%)
helped: 15270
HURT: 10772
Instructions are helped.

total uniforms in shared programs: 3944672 -> 3840276 (-2.65%)
uniforms in affected programs: 1827184 -> 1722788 (-5.71%)
helped: 30423
HURT: 845
Uniforms are helped.

total inst-and-stalls in shared programs: 14957813 -> 14936873 (-0.14%)
inst-and-stalls in affected programs: 6475349 -> 6454409 (-0.32%)
helped: 15287
HURT: 10852
Inst-and-stalls are helped.

v2 (Eric):
 - consider ldunifrf too
 - check that no other instruction writes to the register

Reviewed-by: Alejandro PiƱeiro <[email protected]>
Reviewed-by: Eric Anholt <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9077>

---

 src/broadcom/compiler/v3d_compiler.h          |  7 ++++
 src/broadcom/compiler/vir.c                   | 55 ++++++++++++++++++++++++++-
 src/broadcom/compiler/vir_register_allocate.c |  6 +++
 3 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/src/broadcom/compiler/v3d_compiler.h 
b/src/broadcom/compiler/v3d_compiler.h
index e4f7ab49e98..4bec511346a 100644
--- a/src/broadcom/compiler/v3d_compiler.h
+++ b/src/broadcom/compiler/v3d_compiler.h
@@ -643,6 +643,13 @@ struct v3d_compile {
          */
         bool disable_tmu_pipelining;
 
+        /* Emits ldunif for each new uniform, even if the uniform was already
+         * emitted in the same block. Useful to compile shaders with high
+         * register pressure or to disable the optimization during uniform
+         * spills.
+         */
+        bool disable_ldunif_opt;
+
         /* State for whether we're executing on each channel currently.  0 if
          * yes, otherwise a block number + 1 that the channel jumped to.
          */
diff --git a/src/broadcom/compiler/vir.c b/src/broadcom/compiler/vir.c
index a3db921ce52..da3a0e7858e 100644
--- a/src/broadcom/compiler/vir.c
+++ b/src/broadcom/compiler/vir.c
@@ -1403,14 +1403,67 @@ vir_get_uniform_index(struct v3d_compile *c,
         return uniform;
 }
 
+/* Looks back into the current block to find the ldunif that wrote the uniform
+ * at the requested index. If it finds it, it returns true and writes the
+ * destination register of the ldunif instruction to 'unif'.
+ *
+ * This can impact register pressure and end up leading to worse code, so we
+ * limit the number of instructions we are willing to look back through to
+ * strike a good balance.
+ */
+static bool
+try_opt_ldunif(struct v3d_compile *c, uint32_t index, struct qreg *unif)
+{
+        uint32_t count = 20;
+        struct qinst *prev_inst = NULL;
+        vir_for_each_inst_rev(inst, c->cur_block) {
+                if ((inst->qpu.sig.ldunif || inst->qpu.sig.ldunifrf) &&
+                    inst->uniform == index) {
+                        prev_inst = inst;
+                        break;
+                }
+
+                if (--count == 0)
+                        break;
+        }
+
+        if (!prev_inst)
+                return false;
+
+
+        list_for_each_entry_from(struct qinst, inst, prev_inst->link.next,
+                                 &c->cur_block->instructions, link) {
+                if (inst->dst.file == prev_inst->dst.file &&
+                    inst->dst.index == prev_inst->dst.index) {
+                        return false;
+                }
+        }
+
+        *unif = prev_inst->dst;
+        return true;
+}
+
 struct qreg
 vir_uniform(struct v3d_compile *c,
             enum quniform_contents contents,
             uint32_t data)
 {
+        const int num_uniforms = c->num_uniforms;
+        const int index = vir_get_uniform_index(c, contents, data);
+
+        /* If this is not the first time we see this uniform try to reuse the
+         * result of the last ldunif that loaded it.
+         */
+        const bool is_new_uniform = num_uniforms != c->num_uniforms;
+        if (!is_new_uniform && !c->disable_ldunif_opt) {
+                struct qreg ldunif_dst;
+                if (try_opt_ldunif(c, index, &ldunif_dst))
+                        return ldunif_dst;
+        }
+
         struct qinst *inst = vir_NOP(c);
         inst->qpu.sig.ldunif = true;
-        inst->uniform = vir_get_uniform_index(c, contents, data);
+        inst->uniform = index;
         inst->dst = vir_get_temp(c);
         c->defs[inst->dst.index] = inst;
         return inst->dst;
diff --git a/src/broadcom/compiler/vir_register_allocate.c 
b/src/broadcom/compiler/vir_register_allocate.c
index b29960ae90d..869df9efaba 100644
--- a/src/broadcom/compiler/vir_register_allocate.c
+++ b/src/broadcom/compiler/vir_register_allocate.c
@@ -259,6 +259,10 @@ v3d_spill_reg(struct v3d_compile *c, int spill_temp)
                 uniform_index = orig_unif->uniform;
         }
 
+        /* We must disable the ldunif optimization if we are spilling uniforms 
*/
+        bool had_disable_ldunif_opt = c->disable_ldunif_opt;
+        c->disable_ldunif_opt = true;
+
         struct qinst *start_of_tmu_sequence = NULL;
         struct qinst *postponed_spill = NULL;
         vir_for_each_block(block, c) {
@@ -360,6 +364,8 @@ v3d_spill_reg(struct v3d_compile *c, int spill_temp)
          */
         for (int i = start_num_temps; i < c->num_temps; i++)
                 BITSET_CLEAR(c->spillable, i);
+
+        c->disable_ldunif_opt = had_disable_ldunif_opt;
 }
 
 struct v3d_ra_select_callback_data {

_______________________________________________
mesa-commit mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to