From d9d1c14430aaeb5b22aa66b269ba288e3df24103 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 4 Jul 2014 09:48:23 -0700 Subject: vc4: Add dead code elimination. This cleans up a bunch of noise in the compiled coordinate shaders (since we don't need the varying outputs), and also from writemasked instructions with negated src operands. --- src/gallium/drivers/vc4/Makefile.sources | 1 + src/gallium/drivers/vc4/vc4_opt_dead_code.c | 74 +++++++++++++++++++++++++++++ src/gallium/drivers/vc4/vc4_qir.c | 20 ++++++-- src/gallium/drivers/vc4/vc4_qir.h | 2 + 4 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 src/gallium/drivers/vc4/vc4_opt_dead_code.c (limited to 'src/gallium/drivers/vc4') diff --git a/src/gallium/drivers/vc4/Makefile.sources b/src/gallium/drivers/vc4/Makefile.sources index 1a1b4d00d71..6977a067bd7 100644 --- a/src/gallium/drivers/vc4/Makefile.sources +++ b/src/gallium/drivers/vc4/Makefile.sources @@ -5,6 +5,7 @@ C_SOURCES := \ vc4_draw.c \ vc4_emit.c \ vc4_opt_algebraic.c \ + vc4_opt_dead_code.c \ vc4_program.c \ vc4_qir.c \ vc4_qpu_emit.c \ diff --git a/src/gallium/drivers/vc4/vc4_opt_dead_code.c b/src/gallium/drivers/vc4/vc4_opt_dead_code.c new file mode 100644 index 00000000000..26e4ddfd233 --- /dev/null +++ b/src/gallium/drivers/vc4/vc4_opt_dead_code.c @@ -0,0 +1,74 @@ +/* + * Copyright © 2014 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/** + * @file vc4_opt_dead_code.c + * + * This is a simmple dead code eliminator for QIR with no control flow. + * + * 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. + */ + +#include +#include +#include "vc4_qir.h" + +bool +qir_opt_dead_code(struct qcompile *c) +{ + bool progress = false; + bool debug = false; + bool *used = calloc(c->num_temps, sizeof(bool)); + + struct simple_node *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] && + !qir_has_side_effects(inst)) { + if (debug) { + fprintf(stderr, "Removing: "); + qir_dump_inst(inst); + fprintf(stderr, "\n"); + } + remove_from_list(&inst->link); + free(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); + + return progress; +} diff --git a/src/gallium/drivers/vc4/vc4_qir.c b/src/gallium/drivers/vc4/vc4_qir.c index 308154ff34a..13714115214 100644 --- a/src/gallium/drivers/vc4/vc4_qir.c +++ b/src/gallium/drivers/vc4/vc4_qir.c @@ -32,6 +32,7 @@ struct qir_op_info { const char *name; uint8_t ndst, nsrc; + bool has_side_effects; }; static const struct qir_op_info qir_op_info[] = { @@ -57,9 +58,9 @@ static const struct qir_op_info qir_op_info[] = { [QOP_LOG2] = { "log2", 1, 2 }, [QOP_PACK_COLORS] = { "pack_colors", 1, 4 }, [QOP_PACK_SCALED] = { "pack_scaled", 1, 2 }, - [QOP_VPM_WRITE] = { "vpm_write", 0, 1 }, - [QOP_VPM_READ] = { "vpm_read", 0, 1 }, - [QOP_TLB_COLOR_WRITE] = { "tlb_color", 0, 1 }, + [QOP_VPM_WRITE] = { "vpm_write", 0, 1, true }, + [QOP_VPM_READ] = { "vpm_read", 0, 1, true }, + [QOP_TLB_COLOR_WRITE] = { "tlb_color", 0, 1, true }, [QOP_VARY_ADD_C] = { "vary_add_c", 1, 1 }, }; @@ -81,6 +82,18 @@ qir_get_op_nsrc(enum qop qop) abort(); } +bool +qir_has_side_effects(struct qinst *inst) +{ + for (int i = 0; i < qir_get_op_nsrc(inst->op); i++) { + if (inst->src[i].file == QFILE_VARY || + inst->src[i].file == QFILE_UNIF) + return true; + } + + return qir_op_info[inst->op].has_side_effects; +} + static void qir_print_reg(struct qreg reg) { @@ -228,6 +241,7 @@ qir_optimize(struct qcompile *c) bool progress = false; OPTPASS(qir_opt_algebraic); + OPTPASS(qir_opt_dead_code); if (!progress) break; diff --git a/src/gallium/drivers/vc4/vc4_qir.h b/src/gallium/drivers/vc4/vc4_qir.h index c0e0f85dede..c6c2a6476c4 100644 --- a/src/gallium/drivers/vc4/vc4_qir.h +++ b/src/gallium/drivers/vc4/vc4_qir.h @@ -147,6 +147,7 @@ void qir_emit(struct qcompile *c, struct qinst *inst); struct qreg qir_get_temp(struct qcompile *c); int qir_get_op_nsrc(enum qop qop); bool qir_reg_equals(struct qreg a, struct qreg b); +bool qir_has_side_effects(struct qinst *inst); void qir_dump(struct qcompile *c); void qir_dump_inst(struct qinst *inst); @@ -154,6 +155,7 @@ const char *qir_get_stage_name(enum qstage stage); void qir_optimize(struct qcompile *c); bool qir_opt_algebraic(struct qcompile *c); +bool qir_opt_dead_code(struct qcompile *c); #define QIR_ALU1(name) \ static inline struct qreg \ -- cgit v1.2.3