From 8c5dcdbccb68b73d2856d9c1faafadc536e682e3 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 30 Mar 2015 10:38:21 -0700 Subject: [PATCH] vc4: Add a constant folding pass. This cleans up some pointless operations generated by the in-driver mul24 lowering (commonly generated by making a vec4 index for a matrix in a uniform array). I could fill in other operations, but pretty much anything else ought to be getting handled at the NIR level, I think. total uniforms in shared programs: 13423 -> 13421 (-0.01%) uniforms in affected programs: 346 -> 344 (-0.58%) --- src/gallium/drivers/vc4/Makefile.sources | 1 + .../drivers/vc4/vc4_opt_constant_folding.c | 110 ++++++++++++++++++ src/gallium/drivers/vc4/vc4_qir.c | 1 + src/gallium/drivers/vc4/vc4_qir.h | 1 + 4 files changed, 113 insertions(+) create mode 100644 src/gallium/drivers/vc4/vc4_opt_constant_folding.c diff --git a/src/gallium/drivers/vc4/Makefile.sources b/src/gallium/drivers/vc4/Makefile.sources index c7254ea1473..ec0f25ca34a 100644 --- a/src/gallium/drivers/vc4/Makefile.sources +++ b/src/gallium/drivers/vc4/Makefile.sources @@ -12,6 +12,7 @@ C_SOURCES := \ vc4_fence.c \ vc4_formats.c \ vc4_opt_algebraic.c \ + vc4_opt_constant_folding.c \ vc4_opt_copy_propagation.c \ vc4_opt_cse.c \ vc4_opt_dead_code.c \ diff --git a/src/gallium/drivers/vc4/vc4_opt_constant_folding.c b/src/gallium/drivers/vc4/vc4_opt_constant_folding.c new file mode 100644 index 00000000000..ac9be5c9642 --- /dev/null +++ b/src/gallium/drivers/vc4/vc4_opt_constant_folding.c @@ -0,0 +1,110 @@ +/* + * Copyright © 2015 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_constant_folding.c + * + * Simple constant folding pass to clean up operations on only constants, + * which we might have generated within vc4_program.c. + */ + +#include "vc4_qir.h" +#include "util/u_math.h" + +static bool debug; + +static void +dump_from(struct vc4_compile *c, struct qinst *inst) +{ + if (!debug) + return; + + fprintf(stderr, "optimizing: "); + qir_dump_inst(c, inst); + fprintf(stderr, "\n"); +} + +static void +dump_to(struct vc4_compile *c, struct qinst *inst) +{ + if (!debug) + return; + + fprintf(stderr, "to: "); + qir_dump_inst(c, inst); + fprintf(stderr, "\n"); +} + +static bool +constant_fold(struct vc4_compile *c, struct qinst *inst) +{ + int nsrc = qir_get_op_nsrc(inst->op); + uint32_t ui[nsrc]; + + for (int i = 0; i < nsrc; i++) { + struct qreg reg = inst->src[i]; + if (reg.file == QFILE_UNIF && + c->uniform_contents[reg.index] == QUNIFORM_CONSTANT) { + ui[i] = c->uniform_data[reg.index]; + } else if (reg.file == QFILE_SMALL_IMM) { + ui[i] = reg.index; + } else { + return false; + } + } + + uint32_t result = 0; + switch (inst->op) { + case QOP_SHR: + result = ui[0] >> ui[1]; + break; + + default: + return false; + } + + dump_from(c, inst); + + inst->src[0] = qir_uniform_ui(c, result); + for (int i = 1; i < nsrc; i++) + inst->src[i] = c->undef; + inst->op = QOP_MOV; + + dump_to(c, inst); + return true; +} + +bool +qir_opt_constant_folding(struct vc4_compile *c) +{ + bool progress = false; + struct simple_node *node; + + foreach(node, &c->instructions) { + struct qinst *inst = (struct qinst *)node; + if (constant_fold(c, inst)) + progress = true; + } + + return progress; +} diff --git a/src/gallium/drivers/vc4/vc4_qir.c b/src/gallium/drivers/vc4/vc4_qir.c index e453d848096..93be98a5b6a 100644 --- a/src/gallium/drivers/vc4/vc4_qir.c +++ b/src/gallium/drivers/vc4/vc4_qir.c @@ -512,6 +512,7 @@ qir_optimize(struct vc4_compile *c) OPTPASS(qir_opt_algebraic); OPTPASS(qir_opt_cse); + OPTPASS(qir_opt_constant_folding); OPTPASS(qir_opt_copy_propagation); OPTPASS(qir_opt_dead_code); OPTPASS(qir_opt_small_immediates); diff --git a/src/gallium/drivers/vc4/vc4_qir.h b/src/gallium/drivers/vc4/vc4_qir.h index 4f910e3c3df..6cc8dbefea4 100644 --- a/src/gallium/drivers/vc4/vc4_qir.h +++ b/src/gallium/drivers/vc4/vc4_qir.h @@ -396,6 +396,7 @@ const char *qir_get_stage_name(enum qstage stage); void qir_optimize(struct vc4_compile *c); bool qir_opt_algebraic(struct vc4_compile *c); +bool qir_opt_constant_folding(struct vc4_compile *c); bool qir_opt_copy_propagation(struct vc4_compile *c); bool qir_opt_cse(struct vc4_compile *c); bool qir_opt_dead_code(struct vc4_compile *c);