aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlyssa Rosenzweig <[email protected]>2019-09-28 12:13:52 -0400
committerAlyssa Rosenzweig <[email protected]>2019-09-30 08:40:13 -0400
commit10037ce52320df38d1cc652f4d1be78053b11ed8 (patch)
tree3343cf8abe8418e8ba881de5c4b0aeab6a4d2aed
parenta3ca283bc171e5d241bbd619dd52773f1d0f892d (diff)
pan/midgard: Tightly pack 32-bit constants
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 <[email protected]>
-rw-r--r--src/panfrost/midgard/midgard_schedule.c129
1 files changed, 113 insertions, 16 deletions
diff --git a/src/panfrost/midgard/midgard_schedule.c b/src/panfrost/midgard/midgard_schedule.c
index d09726bf449..7ed36a5e739 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 *