Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2013 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. /** @file brw_dead_control_flow.cpp
  25.  *
  26.  * This file implements the dead control flow elimination optimization pass.
  27.  */
  28.  
  29. #include "brw_shader.h"
  30. #include "brw_cfg.h"
  31.  
  32. /* Look for and eliminate dead control flow:
  33.  *
  34.  *   - if/endif
  35.  *   . else in else/endif
  36.  *   - if/else/endif
  37.  */
  38. bool
  39. dead_control_flow_eliminate(backend_visitor *v)
  40. {
  41.    bool progress = false;
  42.  
  43.    foreach_block_safe (block, v->cfg) {
  44.       bblock_t *if_block = NULL, *else_block = NULL, *endif_block = block;
  45.       bool found = false;
  46.  
  47.       /* ENDIF instructions, by definition, can only be found at the start of
  48.        * basic blocks.
  49.        */
  50.       backend_instruction *endif_inst = endif_block->start();
  51.       if (endif_inst->opcode != BRW_OPCODE_ENDIF)
  52.          continue;
  53.  
  54.       backend_instruction *if_inst = NULL, *else_inst = NULL;
  55.       backend_instruction *prev_inst = endif_block->prev()->end();
  56.       if (prev_inst->opcode == BRW_OPCODE_ELSE) {
  57.          else_inst = prev_inst;
  58.          else_block = endif_block->prev();
  59.          found = true;
  60.  
  61.          if (else_block->start_ip == else_block->end_ip)
  62.             prev_inst = else_block->prev()->end();
  63.       }
  64.  
  65.       if (prev_inst->opcode == BRW_OPCODE_IF) {
  66.          if_inst = prev_inst;
  67.          if_block = else_block != NULL ? else_block->prev()
  68.                                        : endif_block->prev();
  69.          found = true;
  70.       } else {
  71.          /* Don't remove the ENDIF if we didn't find a dead IF. */
  72.          endif_inst = NULL;
  73.       }
  74.  
  75.       if (found) {
  76.          bblock_t *earlier_block = NULL, *later_block = NULL;
  77.  
  78.          if (if_inst) {
  79.             if (if_block->start_ip == if_block->end_ip) {
  80.                earlier_block = if_block->prev();
  81.             } else {
  82.                earlier_block = if_block;
  83.             }
  84.             if_inst->remove(if_block);
  85.          }
  86.  
  87.          if (else_inst) {
  88.             else_inst->remove(else_block);
  89.          }
  90.  
  91.          if (endif_inst) {
  92.             if (endif_block->start_ip == endif_block->end_ip) {
  93.                later_block = endif_block->next();
  94.             } else {
  95.                later_block = endif_block;
  96.             }
  97.             endif_inst->remove(endif_block);
  98.          }
  99.  
  100.          assert((earlier_block == NULL) == (later_block == NULL));
  101.          if (earlier_block && earlier_block->can_combine_with(later_block)) {
  102.             earlier_block->combine_with(later_block);
  103.  
  104.             /* If ENDIF was in its own block, then we've now deleted it and
  105.              * merged the two surrounding blocks, the latter of which the
  106.              * __next block pointer was pointing to.
  107.              */
  108.             if (endif_block != later_block) {
  109.                __next = earlier_block->next();
  110.             }
  111.          }
  112.  
  113.          progress = true;
  114.       }
  115.    }
  116.  
  117.    if (progress)
  118.       v->invalidate_live_intervals();
  119.  
  120.    return progress;
  121. }
  122.