Home | History | Annotate | Download | only in i965
      1 /*
      2  * Copyright  2014 Intel Corporation
      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 #include "brw_vec4.h"
     25 #include "brw_vec4_live_variables.h"
     26 #include "brw_cfg.h"
     27 
     28 /** @file brw_vec4_dead_code_eliminate.cpp
     29  *
     30  * Dataflow-aware dead code elimination.
     31  *
     32  * Walks the instruction list from the bottom, removing instructions that
     33  * have results that both aren't used in later blocks and haven't been read
     34  * yet in the tail end of this block.
     35  */
     36 
     37 using namespace brw;
     38 
     39 bool
     40 vec4_visitor::dead_code_eliminate()
     41 {
     42    bool progress = false;
     43 
     44    calculate_live_intervals();
     45 
     46    int num_vars = live_intervals->num_vars;
     47    BITSET_WORD *live = rzalloc_array(NULL, BITSET_WORD, BITSET_WORDS(num_vars));
     48    BITSET_WORD *flag_live = rzalloc_array(NULL, BITSET_WORD, 1);
     49 
     50    foreach_block_reverse_safe(block, cfg) {
     51       memcpy(live, live_intervals->block_data[block->num].liveout,
     52              sizeof(BITSET_WORD) * BITSET_WORDS(num_vars));
     53       memcpy(flag_live, live_intervals->block_data[block->num].flag_liveout,
     54              sizeof(BITSET_WORD));
     55 
     56       foreach_inst_in_block_reverse_safe(vec4_instruction, inst, block) {
     57          if ((inst->dst.file == VGRF && !inst->has_side_effects()) ||
     58              (inst->dst.is_null() && inst->writes_flag())){
     59             bool result_live[4] = { false };
     60             if (inst->dst.file == VGRF) {
     61                for (unsigned i = 0; i < DIV_ROUND_UP(inst->size_written, 16); i++) {
     62                   for (int c = 0; c < 4; c++) {
     63                      const unsigned v = var_from_reg(alloc, inst->dst, c, i);
     64                      result_live[c] |= BITSET_TEST(live, v);
     65                   }
     66                }
     67             } else {
     68                for (unsigned c = 0; c < 4; c++)
     69                   result_live[c] = BITSET_TEST(flag_live, c);
     70             }
     71 
     72             /* If the instruction can't do writemasking, then it's all or
     73              * nothing.
     74              */
     75             if (!inst->can_do_writemask(devinfo)) {
     76                bool result = result_live[0] | result_live[1] |
     77                              result_live[2] | result_live[3];
     78                result_live[0] = result;
     79                result_live[1] = result;
     80                result_live[2] = result;
     81                result_live[3] = result;
     82             }
     83 
     84             for (int c = 0; c < 4; c++) {
     85                if (!result_live[c] && inst->dst.writemask & (1 << c)) {
     86                   inst->dst.writemask &= ~(1 << c);
     87                   progress = true;
     88 
     89                   if (inst->dst.writemask == 0) {
     90                      if (inst->writes_accumulator || inst->writes_flag()) {
     91                         inst->dst = dst_reg(retype(brw_null_reg(), inst->dst.type));
     92                      } else {
     93                         inst->opcode = BRW_OPCODE_NOP;
     94                         break;
     95                      }
     96                   }
     97                }
     98             }
     99          }
    100 
    101          if (inst->dst.is_null() && inst->writes_flag()) {
    102             bool combined_live = false;
    103             for (unsigned c = 0; c < 4; c++)
    104                combined_live |= BITSET_TEST(flag_live, c);
    105 
    106             if (!combined_live) {
    107                inst->opcode = BRW_OPCODE_NOP;
    108                progress = true;
    109             }
    110          }
    111 
    112          if (inst->dst.file == VGRF && !inst->predicate &&
    113              !inst->is_align1_partial_write()) {
    114             for (unsigned i = 0; i < DIV_ROUND_UP(inst->size_written, 16); i++) {
    115                for (int c = 0; c < 4; c++) {
    116                   if (inst->dst.writemask & (1 << c)) {
    117                      const unsigned v = var_from_reg(alloc, inst->dst, c, i);
    118                      BITSET_CLEAR(live, v);
    119                   }
    120                }
    121             }
    122          }
    123 
    124          if (inst->writes_flag() && !inst->predicate) {
    125             for (unsigned c = 0; c < 4; c++)
    126                BITSET_CLEAR(flag_live, c);
    127          }
    128 
    129          if (inst->opcode == BRW_OPCODE_NOP) {
    130             inst->remove(block);
    131             continue;
    132          }
    133 
    134          for (int i = 0; i < 3; i++) {
    135             if (inst->src[i].file == VGRF) {
    136                for (unsigned j = 0; j < DIV_ROUND_UP(inst->size_read(i), 16); j++) {
    137                   for (int c = 0; c < 4; c++) {
    138                      const unsigned v = var_from_reg(alloc, inst->src[i], c, j);
    139                      BITSET_SET(live, v);
    140                   }
    141                }
    142             }
    143          }
    144 
    145          for (unsigned c = 0; c < 4; c++) {
    146             if (inst->reads_flag(c)) {
    147                BITSET_SET(flag_live, c);
    148             }
    149          }
    150       }
    151    }
    152 
    153    ralloc_free(live);
    154    ralloc_free(flag_live);
    155 
    156    if (progress)
    157       invalidate_live_intervals();
    158 
    159    return progress;
    160 }
    161