Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 vc4_opt_dead_code.c
  26.  *
  27.  * This is a simmple dead code eliminator for QIR with no control flow.
  28.  *
  29.  * It walks from the bottom of the instruction list, removing instructions
  30.  * with a destination that is never used, and marking the sources of non-dead
  31.  * instructions as used.
  32.  */
  33.  
  34. #include "vc4_qir.h"
  35.  
  36. static bool debug;
  37.  
  38. static void
  39. dce(struct vc4_compile *c, struct qinst *inst)
  40. {
  41.         if (debug) {
  42.                 fprintf(stderr, "Removing: ");
  43.                 qir_dump_inst(c, inst);
  44.                 fprintf(stderr, "\n");
  45.         }
  46.         assert(!inst->sf);
  47.         qir_remove_instruction(c, inst);
  48. }
  49.  
  50. static bool
  51. has_nonremovable_reads(struct vc4_compile *c, struct qinst *inst)
  52. {
  53.         for (int i = 0; i < qir_get_op_nsrc(inst->op); i++) {
  54.                 if (inst->src[i].file == QFILE_VPM) {
  55.                         uint32_t attr = inst->src[i].index / 4;
  56.                         uint32_t offset = (inst->src[i].index % 4) * 4;
  57.  
  58.                         if (c->vattr_sizes[attr] != offset + 4)
  59.                                 return true;
  60.  
  61.                         /* Can't get rid of the last VPM read, or the
  62.                          * simulator (at least) throws an error.
  63.                          */
  64.                         uint32_t total_size = 0;
  65.                         for (uint32_t i = 0; i < ARRAY_SIZE(c->vattr_sizes); i++)
  66.                                 total_size += c->vattr_sizes[i];
  67.                         if (total_size == 4)
  68.                                 return true;
  69.                 }
  70.  
  71.                 if (inst->src[i].file == QFILE_VARY &&
  72.                     c->input_semantics[inst->src[i].index].semantic == 0xff) {
  73.                         return true;
  74.                 }
  75.         }
  76.  
  77.         return false;
  78. }
  79.  
  80. bool
  81. qir_opt_dead_code(struct vc4_compile *c)
  82. {
  83.         bool progress = false;
  84.         bool *used = calloc(c->num_temps, sizeof(bool));
  85.         bool sf_used = false;
  86.         /* Whether we're eliminating texture setup currently. */
  87.         bool dce_tex = false;
  88.  
  89.         struct simple_node *node, *t;
  90.         for (node = c->instructions.prev, t = node->prev;
  91.              &c->instructions != node;
  92.              node = t, t = t->prev) {
  93.                 struct qinst *inst = (struct qinst *)node;
  94.  
  95.                 if (inst->dst.file == QFILE_TEMP &&
  96.                     !used[inst->dst.index] &&
  97.                     !inst->sf &&
  98.                     (!qir_has_side_effects(c, inst) ||
  99.                      inst->op == QOP_TEX_RESULT) &&
  100.                     !has_nonremovable_reads(c, inst)) {
  101.                         if (inst->op == QOP_TEX_RESULT) {
  102.                                 dce_tex = true;
  103.                                 c->num_texture_samples--;
  104.                         }
  105.  
  106.                         for (int i = 0; i < qir_get_op_nsrc(inst->op); i++) {
  107.                                 if (inst->src[i].file != QFILE_VPM)
  108.                                         continue;
  109.                                 uint32_t attr = inst->src[i].index / 4;
  110.                                 uint32_t offset = (inst->src[i].index % 4) * 4;
  111.  
  112.                                 if (c->vattr_sizes[attr] == offset + 4) {
  113.                                         c->num_inputs--;
  114.                                         c->vattr_sizes[attr] -= 4;
  115.                                 }
  116.                         }
  117.  
  118.                         dce(c, inst);
  119.                         progress = true;
  120.                         continue;
  121.                 }
  122.  
  123.                 if (qir_depends_on_flags(inst))
  124.                         sf_used = true;
  125.                 if (inst->sf) {
  126.                         if (!sf_used) {
  127.                                 if (debug) {
  128.                                         fprintf(stderr, "Removing SF on: ");
  129.                                         qir_dump_inst(c, inst);
  130.                                         fprintf(stderr, "\n");
  131.                                 }
  132.  
  133.                                 inst->sf = false;
  134.                                 progress = true;
  135.                         }
  136.                         sf_used = false;
  137.                 }
  138.  
  139.                 if (inst->op == QOP_TEX_RESULT)
  140.                         dce_tex = false;
  141.  
  142.                 if (dce_tex && (inst->op == QOP_TEX_S ||
  143.                                 inst->op == QOP_TEX_T ||
  144.                                 inst->op == QOP_TEX_R ||
  145.                                 inst->op == QOP_TEX_B ||
  146.                                 inst->op == QOP_TEX_DIRECT)) {
  147.                         dce(c, inst);
  148.                         progress = true;
  149.                         continue;
  150.                 }
  151.  
  152.                 for (int i = 0; i < qir_get_op_nsrc(inst->op); i++) {
  153.                         if (inst->src[i].file == QFILE_TEMP)
  154.                                 used[inst->src[i].index] = true;
  155.                 }
  156.         }
  157.  
  158.         free(used);
  159.  
  160.         return progress;
  161. }
  162.