summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/vc4
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2016-07-08 17:10:38 -0700
committerEric Anholt <[email protected]>2016-07-12 15:47:26 -0700
commit46ec025ba9fdb78346ec0eb671a0c4218ab632a1 (patch)
treed880a247e475c6ee02e09a8e21f76d910e6c23ca /src/gallium/drivers/vc4
parent0c923e6c33059b3ba0c29cbc920c2918e55f54db (diff)
vc4: Convert uniforms lowering to work with multiple blocks.
We still decide which uniform to lower based on how many instructions-that-need-lowering use that uniform, but now we emit a new temporary uniform load in each of the basic blocks containing an instruction being lowered. This commit is best reviewed with diff -b.
Diffstat (limited to 'src/gallium/drivers/vc4')
-rw-r--r--src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c73
1 files changed, 44 insertions, 29 deletions
diff --git a/src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c b/src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c
index 7c8cbd14666..8ec6c797396 100644
--- a/src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c
+++ b/src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c
@@ -146,41 +146,56 @@ qir_lower_uniforms(struct vc4_compile *c)
}
}
+ struct qreg unif = qir_reg(QFILE_UNIF, max_index);
+
/* Now, find the instructions using this uniform and make them
* reference a temp instead.
*/
- struct qreg temp = qir_get_temp(c);
- struct qreg unif = qir_reg(QFILE_UNIF, max_index);
- struct qinst *mov = qir_inst(QOP_MOV, temp, unif, c->undef);
- list_add(&mov->link, &c->cur_block->instructions);
- c->defs[temp.index] = mov;
- qir_for_each_inst_inorder(inst, c) {
- uint32_t nsrc = qir_get_op_nsrc(inst->op);
-
- 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);
- removed = true;
+ qir_for_each_block(block, c) {
+ struct qinst *mov = NULL;
+
+ qir_for_each_inst(inst, block) {
+ uint32_t nsrc = qir_get_op_nsrc(inst->op);
+
+ uint32_t count = qir_get_instruction_uniform_count(inst);
+
+ if (count <= 1)
+ continue;
+
+ /* If the block doesn't have a load of hte
+ * uniform yet, add it. We could potentially
+ * do better and CSE MOVs from multiple blocks
+ * into dominating blocks, except that may
+ * cause troubles for register allocation.
+ */
+ if (!mov) {
+ mov = qir_inst(QOP_MOV, qir_get_temp(c),
+ unif, c->undef);
+ list_add(&mov->link,
+ &block->instructions);
+ c->defs[mov->dst.index] = mov;
}
- }
- if (removed)
- count--;
- /* If the instruction doesn't need lowering any more,
- * then drop it from the list.
- */
- if (count <= 1) {
+ bool removed = false;
for (int i = 0; i < nsrc; i++) {
- if (is_lowerable_uniform(inst, i))
- remove_uniform(ht, inst->src[i]);
+ if (is_lowerable_uniform(inst, i) &&
+ inst->src[i].index == max_index) {
+ inst->src[i] = mov->dst;
+ remove_uniform(ht, unif);
+ removed = true;
+ }
+ }
+ if (removed)
+ count--;
+
+ /* If the instruction doesn't need lowering any more,
+ * then drop it from the list.
+ */
+ if (count <= 1) {
+ for (int i = 0; i < nsrc; i++) {
+ if (is_lowerable_uniform(inst, i))
+ remove_uniform(ht, inst->src[i]);
+ }
}
}
}