[Mesa-dev] [PATCH 27/30] pan/midgard: Tightly pack 32-bit constants

Alyssa Rosenzweig alyssa.rosenzweig at collabora.com
Sat Sep 28 19:02:32 UTC 2019


If we can reuse constant slots from other instructions, we would like to
do so to include more instructions per bundle.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig at collabora.com>
---
 src/panfrost/midgard/midgard_schedule.c | 129 +++++++++++++++++++++---
 1 file changed, 113 insertions(+), 16 deletions(-)

diff --git a/src/panfrost/midgard/midgard_schedule.c b/src/panfrost/midgard/midgard_schedule.c
index a35699893bd..2d20b617d1a 100644
--- a/src/panfrost/midgard/midgard_schedule.c
+++ b/src/panfrost/midgard/midgard_schedule.c
@@ -370,26 +370,123 @@ mir_adjust_constants(midgard_instruction *ins,
         if (!ins->has_constants)
                 return true;
 
-        /* TODO: Deduplicate; permit multiple constants within a bundle */
-
-        if (destructive && !pred->constant_count) {
-                if (ins->alu.reg_mode == midgard_reg_mode_16) {
-                      /* TODO: Fix packing XXX */
-                        uint16_t *bundles = (uint16_t *) pred->constants;
-                        uint32_t *constants = (uint32_t *) ins->constants;
-
-                        /* Copy them wholesale */
-                        for (unsigned i = 0; i < 4; ++i)
-                                bundles[i] = constants[i];
-                } else {
-                        memcpy(pred->constants, ins->constants, 16);
-                }
+        if (ins->alu.reg_mode == midgard_reg_mode_16) {
+                /* TODO: 16-bit constant combining */
+                if (pred->constant_count)
+                        return false;
+
+                uint16_t *bundles = (uint16_t *) pred->constants;
+                uint32_t *constants = (uint32_t *) ins->constants;
+
+                /* Copy them wholesale */
+                for (unsigned i = 0; i < 4; ++i)
+                        bundles[i] = constants[i];
 
                 pred->constant_count = 16;
-                return true;
+        } else {
+                /* Pack 32-bit constants */
+                uint32_t *bundles = (uint32_t *) pred->constants;
+                uint32_t *constants = (uint32_t *) ins->constants;
+                unsigned r_constant = SSA_FIXED_REGISTER(REGISTER_CONSTANT);
+                unsigned mask = mir_mask_of_read_components(ins, r_constant);
+
+                /* First, check if it fits */
+                unsigned count = DIV_ROUND_UP(pred->constant_count, sizeof(uint32_t));
+                unsigned existing_count = count;
+
+                for (unsigned i = 0; i < 4; ++i) {
+                        if (!(mask & (1 << i)))
+                                continue;
+
+                        bool ok = false;
+
+                        /* Look for existing constant */
+                        for (unsigned j = 0; j < existing_count; ++j) {
+                                if (bundles[j] == constants[i]) {
+                                        ok = true;
+                                        break;
+                                }
+                        }
+
+                        if (ok)
+                                continue;
+
+                        /* If the constant is new, check ourselves */
+                        for (unsigned j = 0; j < i; ++j) {
+                                if (constants[j] == constants[i]) {
+                                        ok = true;
+                                        break;
+                                }
+                        }
+
+                        if (ok)
+                                continue;
+
+                        /* Otherwise, this is a new constant */
+                        count++;
+                }
+
+                /* Check if we have space */
+                if (count > 4)
+                        return false;
+
+                /* If non-destructive, we're done */
+                if (!destructive)
+                        return true;
+
+                /* If destructive, let's copy in the new constants and adjust
+                 * swizzles to pack it in. */
+
+                uint32_t indices[4] = { 0 };
+
+                /* Reset count */
+                count = existing_count;
+
+                for (unsigned i = 0; i < 4; ++i) {
+                        if (!(mask & (1 << i)))
+                                continue;
+
+                        uint32_t cons = constants[i];
+                        bool constant_found = false;
+
+                        /* Search for the constant */
+                        for (unsigned j = 0; j < count; ++j) {
+                                if (bundles[j] != cons)
+                                        continue;
+
+                                /* We found it, reuse */
+                                indices[i] = j;
+                                constant_found = true;
+                                break;
+                        }
+
+                        if (constant_found)
+                                continue;
+
+                        /* We didn't find it, so allocate it */
+                        unsigned idx = count++;
+
+                        /* We have space, copy it in! */
+                        bundles[idx] = cons;
+                        indices[i] = idx;
+                }
+
+                pred->constant_count = count * sizeof(uint32_t);
+
+                /* Cool, we have it in. So use indices as a
+                 * swizzle */
+
+                unsigned swizzle = SWIZZLE_FROM_ARRAY(indices);
+
+                if (ins->src[0] == r_constant)
+                        ins->alu.src1 = vector_alu_apply_swizzle(ins->alu.src1, swizzle);
+
+                if (ins->src[1] == r_constant)
+                        ins->alu.src2 = vector_alu_apply_swizzle(ins->alu.src2, swizzle);
+
         }
 
-        return !pred->constant_count;
+        return true;
 }
 
 static midgard_instruction *
-- 
2.23.0



More information about the mesa-dev mailing list