Home | History | Annotate | Download | only in nir
      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  * Authors:
     24  *    Connor Abbott (cwabbott0 (at) gmail.com)
     25  *
     26  */
     27 
     28 #include "nir.h"
     29 
     30 static bool
     31 global_to_local(nir_register *reg)
     32 {
     33    nir_function_impl *impl = NULL;
     34 
     35    assert(reg->is_global);
     36 
     37    nir_foreach_def(def_dest, reg) {
     38       nir_instr *instr = def_dest->reg.parent_instr;
     39       nir_function_impl *instr_impl =
     40          nir_cf_node_get_function(&instr->block->cf_node);
     41       if (impl != NULL) {
     42          if (impl != instr_impl)
     43             return false;
     44       } else {
     45          impl = instr_impl;
     46       }
     47    }
     48 
     49    nir_foreach_use(use_src, reg) {
     50       nir_instr *instr = use_src->parent_instr;
     51       nir_function_impl *instr_impl =
     52          nir_cf_node_get_function(&instr->block->cf_node);
     53       if (impl != NULL) {
     54          if (impl != instr_impl)
     55             return false;
     56       } else {
     57          impl = instr_impl;
     58       }
     59    }
     60 
     61    nir_foreach_if_use(use_src, reg) {
     62       nir_if *if_stmt = use_src->parent_if;
     63       nir_function_impl *if_impl = nir_cf_node_get_function(&if_stmt->cf_node);
     64       if (impl != NULL) {
     65          if (impl != if_impl)
     66             return false;
     67       } else {
     68          impl = if_impl;
     69       }
     70    }
     71 
     72    if (impl == NULL) {
     73       /* this instruction is never used/defined, delete it */
     74       nir_reg_remove(reg);
     75       return true;
     76    }
     77 
     78    /*
     79     * if we've gotten to this point, the register is always used/defined in
     80     * the same implementation so we can move it to be local to that
     81     * implementation.
     82     */
     83 
     84    exec_node_remove(&reg->node);
     85    exec_list_push_tail(&impl->registers, &reg->node);
     86    reg->index = impl->reg_alloc++;
     87    reg->is_global = false;
     88    return true;
     89 }
     90 
     91 bool
     92 nir_opt_global_to_local(nir_shader *shader)
     93 {
     94    bool progress = false;
     95 
     96    foreach_list_typed_safe(nir_register, reg, node, &shader->registers) {
     97       if (global_to_local(reg))
     98          progress = true;
     99    }
    100 
    101    return progress;
    102 }
    103