X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fvc4%2Fvc4_opt_dead_code.c;h=f04d0ff97ab7cbb2fd27e7de883d98602e79de8b;hb=1a99fc0fd022018ed056cd42f299d5ad1a02c264;hp=9e79a2d1b2e0b11d691f967931a551df0ada5011;hpb=005c8e01062e8e88a86904b955d5422742bd32e7;p=mesa.git diff --git a/src/gallium/drivers/vc4/vc4_opt_dead_code.c b/src/gallium/drivers/vc4/vc4_opt_dead_code.c index 9e79a2d1b2e..f04d0ff97ab 100644 --- a/src/gallium/drivers/vc4/vc4_opt_dead_code.c +++ b/src/gallium/drivers/vc4/vc4_opt_dead_code.c @@ -24,11 +24,15 @@ /** * @file vc4_opt_dead_code.c * - * This is a simmple dead code eliminator for QIR with no control flow. + * This is a simple dead code eliminator for SSA values in QIR. * - * It walks from the bottom of the instruction list, removing instructions - * with a destination that is never used, and marking the sources of non-dead - * instructions as used. + * It walks all the instructions finding what temps are used, then walks again + * to remove instructions writing unused temps. + * + * This is an inefficient implementation if you have long chains of + * instructions where the entire chain is dead, but we expect those to have + * been eliminated at the NIR level, and here we're just cleaning up small + * problems produced by NIR->QIR. */ #include "vc4_qir.h" @@ -50,7 +54,7 @@ dce(struct vc4_compile *c, struct qinst *inst) static bool has_nonremovable_reads(struct vc4_compile *c, struct qinst *inst) { - for (int i = 0; i < qir_get_op_nsrc(inst->op); i++) { + for (int i = 0; i < qir_get_nsrc(inst); i++) { if (inst->src[i].file == QFILE_VPM) { uint32_t attr = inst->src[i].index / 4; uint32_t offset = (inst->src[i].index % 4) * 4; @@ -82,28 +86,50 @@ qir_opt_dead_code(struct vc4_compile *c) { bool progress = false; bool *used = calloc(c->num_temps, sizeof(bool)); - bool sf_used = false; - /* Whether we're eliminating texture setup currently. */ - bool dce_tex = false; - - struct list_head *node, *t; - for (node = c->instructions.prev, t = node->prev; - &c->instructions != node; - node = t, t = t->prev) { - struct qinst *inst = (struct qinst *)node; - - if (inst->dst.file == QFILE_TEMP && - !used[inst->dst.index] && - !inst->sf && - (!qir_has_side_effects(c, inst) || - inst->op == QOP_TEX_RESULT) && - !has_nonremovable_reads(c, inst)) { - if (inst->op == QOP_TEX_RESULT) { - dce_tex = true; - c->num_texture_samples--; + + qir_for_each_inst_inorder(inst, c) { + for (int i = 0; i < qir_get_nsrc(inst); i++) { + if (inst->src[i].file == QFILE_TEMP) + used[inst->src[i].index] = true; + } + } + + qir_for_each_block(block, c) { + qir_for_each_inst_safe(inst, block) { + if (inst->dst.file != QFILE_NULL && + !(inst->dst.file == QFILE_TEMP && + !used[inst->dst.index])) { + continue; } - for (int i = 0; i < qir_get_op_nsrc(inst->op); i++) { + if (qir_has_side_effects(c, inst)) + continue; + + if (inst->sf || + has_nonremovable_reads(c, inst)) { + /* If we can't remove the instruction, but we + * don't need its destination value, just + * remove the destination. The register + * allocator would trivially color it and it + * wouldn't cause any register pressure, but + * it's nicer to read the QIR code without + * unused destination regs. + */ + if (inst->dst.file == QFILE_TEMP) { + if (debug) { + fprintf(stderr, + "Removing dst from: "); + qir_dump_inst(c, inst); + fprintf(stderr, "\n"); + } + c->defs[inst->dst.index] = NULL; + inst->dst.file = QFILE_NULL; + progress = true; + } + continue; + } + + for (int i = 0; i < qir_get_nsrc(inst); i++) { if (inst->src[i].file != QFILE_VPM) continue; uint32_t attr = inst->src[i].index / 4; @@ -119,40 +145,6 @@ qir_opt_dead_code(struct vc4_compile *c) progress = true; continue; } - - if (qir_depends_on_flags(inst)) - sf_used = true; - if (inst->sf) { - if (!sf_used) { - if (debug) { - fprintf(stderr, "Removing SF on: "); - qir_dump_inst(c, inst); - fprintf(stderr, "\n"); - } - - inst->sf = false; - progress = true; - } - sf_used = false; - } - - if (inst->op == QOP_TEX_RESULT) - dce_tex = false; - - if (dce_tex && (inst->op == QOP_TEX_S || - inst->op == QOP_TEX_T || - inst->op == QOP_TEX_R || - inst->op == QOP_TEX_B || - inst->op == QOP_TEX_DIRECT)) { - dce(c, inst); - progress = true; - continue; - } - - for (int i = 0; i < qir_get_op_nsrc(inst->op); i++) { - if (inst->src[i].file == QFILE_TEMP) - used[inst->src[i].index] = true; - } } free(used);