diff options
author | Eric Anholt <[email protected]> | 2014-09-24 21:37:12 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2014-09-29 11:33:34 -0700 |
commit | 3311513041b81fe4e2fcf2c0e8a363a6d292c7b1 (patch) | |
tree | 3c19e82e6f093aeea57c809e65a8c5f3b5652275 | |
parent | 730267eb23b418637c78662a77de0a93af91be35 (diff) |
vc4: Turn a SEL_X_Y(x, 0) into SEL_X_0(x).
This may reduce register pressure and uniform counts. Drops a bunch of 0
uniform loads on vs-temp-array-mat4-index-col-row-wr.shader_test, which is
failing to register allocate.
-rw-r--r-- | src/gallium/drivers/vc4/vc4_opt_algebraic.c | 75 |
1 files changed, 61 insertions, 14 deletions
diff --git a/src/gallium/drivers/vc4/vc4_opt_algebraic.c b/src/gallium/drivers/vc4/vc4_opt_algebraic.c index df57e5de2df..868677acbde 100644 --- a/src/gallium/drivers/vc4/vc4_opt_algebraic.c +++ b/src/gallium/drivers/vc4/vc4_opt_algebraic.c @@ -34,39 +34,86 @@ #include "vc4_qir.h" +static bool debug; + +static void +dump_from(struct qinst *inst) +{ + if (!debug) + return; + + fprintf(stderr, "optimizing: "); + qir_dump_inst(inst); + fprintf(stderr, "\n"); +} + +static void +dump_to(struct qinst *inst) +{ + if (!debug) + return; + + fprintf(stderr, "to: "); + qir_dump_inst(inst); + fprintf(stderr, "\n"); +} + +static struct qreg +follow_movs(struct qinst **defs, struct qreg reg) +{ + while (reg.file == QFILE_TEMP && defs[reg.index]->op == QOP_MOV) + reg = defs[reg.index]->src[0]; + + return reg; +} + +static bool +is_zero(struct vc4_compile *c, struct qinst **defs, struct qreg reg) +{ + reg = follow_movs(defs, reg); + + return (reg.file == QFILE_UNIF && + c->uniform_contents[reg.index] == QUNIFORM_CONSTANT && + c->uniform_data[reg.index] == 0); +} + bool qir_opt_algebraic(struct vc4_compile *c) { bool progress = false; struct simple_node *node; - bool debug = false; + struct qinst *defs[c->num_temps]; foreach(node, &c->instructions) { struct qinst *inst = (struct qinst *)node; + if (inst->dst.file == QFILE_TEMP) + defs[inst->dst.index] = inst; + switch (inst->op) { case QOP_SEL_X_Y_ZS: case QOP_SEL_X_Y_ZC: case QOP_SEL_X_Y_NS: case QOP_SEL_X_Y_NC: - /* Turn "dst = (sf == x) ? a : a)" into "dst = a" */ if (qir_reg_equals(inst->src[0], inst->src[1])) { - if (debug) { - fprintf(stderr, "optimizing: "); - qir_dump_inst(inst); - fprintf(stderr, "\n"); - } - + /* Turn "dst = (sf == x) ? a : a)" into + * "dst = a" + */ + dump_from(inst); inst->op = QOP_MOV; inst->src[0] = inst->src[1]; inst->src[1] = c->undef; progress = true; - - if (debug) { - fprintf(stderr, "to: "); - qir_dump_inst(inst); - fprintf(stderr, "\n"); - } + dump_to(inst); + } else if (is_zero(c, defs, inst->src[1])) { + /* Replace references to a 0 uniform value + * with the SEL_X_0 equivalent. + */ + dump_from(inst); + inst->op -= (QOP_SEL_X_Y_ZS - QOP_SEL_X_0_ZS); + inst->src[1] = c->undef; + progress = true; + dump_to(inst); } break; |