vc4: Don't bother lowering uniforms when the same value is used twice.
authorEric Anholt <eric@anholt.net>
Thu, 12 Nov 2015 01:09:40 +0000 (17:09 -0800)
committerEric Anholt <eric@anholt.net>
Wed, 18 Nov 2015 01:45:23 +0000 (17:45 -0800)
DEQP likes to do math on uniforms, and the "fmaxabs dst, uni, uni" to get
the absolute value would get lowered.  The lowering doesn't bother to try
to restrict the lifetime of the lowered uniforms, so we'd end up register
allocation failng due to this on 5 of the tests (More tests still fail in
RA, which look like we'll need to reduce lowered uniform lifetimes to
fix).

No changes on shader-db, though fewer extra MOVs are generated on even
glxgears (MOVs pair well enough that it ends up being the same instruction
count).

src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c

index 29e3ee3120167ddf2a9e5a5c33222be56e7f9f70..a57e100593c8bb9a333817262ed40c4e4f96200c 100644 (file)
@@ -81,6 +81,33 @@ is_lowerable_uniform(struct qinst *inst, int i)
         return true;
 }
 
+/* Returns the number of different uniform values referenced by the
+ * instruction.
+ */
+static uint32_t
+qir_get_instruction_uniform_count(struct qinst *inst)
+{
+        uint32_t count = 0;
+
+        for (int i = 0; i < qir_get_op_nsrc(inst->op); i++) {
+                if (inst->src[i].file != QFILE_UNIF)
+                        continue;
+
+                bool is_duplicate = false;
+                for (int j = 0; j < i; j++) {
+                        if (inst->src[j].file == QFILE_UNIF &&
+                            inst->src[j].index == inst->src[i].index) {
+                                is_duplicate = true;
+                                break;
+                        }
+                }
+                if (!is_duplicate)
+                        count++;
+        }
+
+        return count;
+}
+
 void
 qir_lower_uniforms(struct vc4_compile *c)
 {
@@ -94,13 +121,7 @@ qir_lower_uniforms(struct vc4_compile *c)
         list_for_each_entry(struct qinst, inst, &c->instructions, link) {
                 uint32_t nsrc = qir_get_op_nsrc(inst->op);
 
-                uint32_t count = 0;
-                for (int i = 0; i < nsrc; i++) {
-                        if (inst->src[i].file == QFILE_UNIF)
-                                count++;
-                }
-
-                if (count <= 1)
+                if (qir_get_instruction_uniform_count(inst) <= 1)
                         continue;
 
                 for (int i = 0; i < nsrc; i++) {
@@ -136,23 +157,22 @@ qir_lower_uniforms(struct vc4_compile *c)
                 list_for_each_entry(struct qinst, inst, &c->instructions, link) {
                         uint32_t nsrc = qir_get_op_nsrc(inst->op);
 
-                        uint32_t count = 0;
-                        for (int i = 0; i < nsrc; i++) {
-                                if (inst->src[i].file == QFILE_UNIF)
-                                        count++;
-                        }
+                        uint32_t count = qir_get_instruction_uniform_count(inst);
 
                         if (count <= 1)
                                 continue;
 
+                        bool removed = false;
                         for (int i = 0; i < nsrc; i++) {
                                 if (is_lowerable_uniform(inst, i) &&
                                     inst->src[i].index == max_index) {
                                         inst->src[i] = temp;
                                         remove_uniform(ht, unif);
-                                        count--;
+                                        removed = true;
                                 }
                         }
+                        if (removed)
+                                count--;
 
                         /* If the instruction doesn't need lowering any more,
                          * then drop it from the list.