"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/broadcom/compiler/vir_opt_dead_code.c" (16 Sep 2020, 6906 Bytes) of package /linux/misc/mesa-20.1.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "vir_opt_dead_code.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright © 2014 Broadcom
    3  *
    4  * Permission is hereby granted, free of charge, to any person obtaining a
    5  * copy of this software and associated documentation files (the "Software"),
    6  * to deal in the Software without restriction, including without limitation
    7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
    8  * and/or sell copies of the Software, and to permit persons to whom the
    9  * Software is furnished to do so, subject to the following conditions:
   10  *
   11  * The above copyright notice and this permission notice (including the next
   12  * paragraph) shall be included in all copies or substantial portions of the
   13  * Software.
   14  *
   15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
   18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
   21  * IN THE SOFTWARE.
   22  */
   23 
   24 /**
   25  * @file v3d_opt_dead_code.c
   26  *
   27  * This is a simple dead code eliminator for SSA values in VIR.
   28  *
   29  * It walks all the instructions finding what temps are used, then walks again
   30  * to remove instructions writing unused temps.
   31  *
   32  * This is an inefficient implementation if you have long chains of
   33  * instructions where the entire chain is dead, but we expect those to have
   34  * been eliminated at the NIR level, and here we're just cleaning up small
   35  * problems produced by NIR->VIR.
   36  */
   37 
   38 #include "v3d_compiler.h"
   39 
   40 static bool debug;
   41 
   42 static void
   43 dce(struct v3d_compile *c, struct qinst *inst)
   44 {
   45         if (debug) {
   46                 fprintf(stderr, "Removing: ");
   47                 vir_dump_inst(c, inst);
   48                 fprintf(stderr, "\n");
   49         }
   50         assert(!v3d_qpu_writes_flags(&inst->qpu));
   51         vir_remove_instruction(c, inst);
   52 }
   53 
   54 static bool
   55 has_nonremovable_reads(struct v3d_compile *c, struct qinst *inst)
   56 {
   57         for (int i = 0; i < vir_get_nsrc(inst); i++) {
   58                 if (inst->src[i].file == QFILE_VPM)
   59                         return true;
   60         }
   61 
   62         return false;
   63 }
   64 
   65 static bool
   66 can_write_to_null(struct v3d_compile *c, struct qinst *inst)
   67 {
   68         /* The SFU instructions must write to a physical register. */
   69         if (c->devinfo->ver >= 41 && v3d_qpu_uses_sfu(&inst->qpu))
   70                 return false;
   71 
   72         return true;
   73 }
   74 
   75 static void
   76 vir_dce_flags(struct v3d_compile *c, struct qinst *inst)
   77 {
   78         if (debug) {
   79                 fprintf(stderr,
   80                         "Removing flags write from: ");
   81                 vir_dump_inst(c, inst);
   82                 fprintf(stderr, "\n");
   83         }
   84 
   85         assert(inst->qpu.type == V3D_QPU_INSTR_TYPE_ALU);
   86 
   87         inst->qpu.flags.apf = V3D_QPU_PF_NONE;
   88         inst->qpu.flags.mpf = V3D_QPU_PF_NONE;
   89         inst->qpu.flags.auf = V3D_QPU_UF_NONE;
   90         inst->qpu.flags.muf = V3D_QPU_UF_NONE;
   91 }
   92 
   93 bool
   94 vir_opt_dead_code(struct v3d_compile *c)
   95 {
   96         bool progress = false;
   97         bool *used = calloc(c->num_temps, sizeof(bool));
   98 
   99         /* Defuse the "are you removing the cursor?" assertion in the core.
  100          * You'll need to set up a new cursor for any new instructions after
  101          * doing DCE (which we would expect, anyway).
  102          */
  103         c->cursor.link = NULL;
  104 
  105         vir_for_each_inst_inorder(inst, c) {
  106                 for (int i = 0; i < vir_get_nsrc(inst); i++) {
  107                         if (inst->src[i].file == QFILE_TEMP)
  108                                 used[inst->src[i].index] = true;
  109                 }
  110         }
  111 
  112         vir_for_each_block(block, c) {
  113                 struct qinst *last_flags_write = NULL;
  114 
  115                 vir_for_each_inst_safe(inst, block) {
  116                         /* If this instruction reads the flags, we can't
  117                          * remove the flags generation for it.
  118                          */
  119                         if (v3d_qpu_reads_flags(&inst->qpu))
  120                                 last_flags_write = NULL;
  121 
  122                         if (inst->dst.file != QFILE_NULL &&
  123                             !(inst->dst.file == QFILE_TEMP &&
  124                               !used[inst->dst.index])) {
  125                                 continue;
  126                         }
  127 
  128                         if (vir_has_side_effects(c, inst))
  129                                 continue;
  130 
  131                         if (v3d_qpu_writes_flags(&inst->qpu)) {
  132                                 /* If we obscure a previous flags write,
  133                                  * drop it.
  134                                  */
  135                                 if (last_flags_write &&
  136                                     (inst->qpu.flags.apf != V3D_QPU_PF_NONE ||
  137                                      inst->qpu.flags.mpf != V3D_QPU_PF_NONE)) {
  138                                         vir_dce_flags(c, last_flags_write);
  139                                         progress = true;
  140                                 }
  141 
  142                                 last_flags_write = inst;
  143                         }
  144 
  145                         if (v3d_qpu_writes_flags(&inst->qpu) ||
  146                             has_nonremovable_reads(c, inst)) {
  147                                 /* If we can't remove the instruction, but we
  148                                  * don't need its destination value, just
  149                                  * remove the destination.  The register
  150                                  * allocator would trivially color it and it
  151                                  * wouldn't cause any register pressure, but
  152                                  * it's nicer to read the VIR code without
  153                                  * unused destination regs.
  154                                  */
  155                                 if (inst->dst.file == QFILE_TEMP &&
  156                                     can_write_to_null(c, inst)) {
  157                                         if (debug) {
  158                                                 fprintf(stderr,
  159                                                         "Removing dst from: ");
  160                                                 vir_dump_inst(c, inst);
  161                                                 fprintf(stderr, "\n");
  162                                         }
  163                                         c->defs[inst->dst.index] = NULL;
  164                                         inst->dst.file = QFILE_NULL;
  165                                         progress = true;
  166                                 }
  167                                 continue;
  168                         }
  169 
  170                         assert(inst != last_flags_write);
  171                         dce(c, inst);
  172                         progress = true;
  173                         continue;
  174                 }
  175         }
  176 
  177         free(used);
  178 
  179         return progress;
  180 }