diff options
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r-- | src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c | 73 |
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]); + } } } } |