1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2016 Intel Corporation 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21b8e80941Smrg * IN THE SOFTWARE. 22b8e80941Smrg */ 23b8e80941Smrg 24b8e80941Smrg#include "nir.h" 25b8e80941Smrg#include "nir_phi_builder.h" 26b8e80941Smrg 27b8e80941Smrgstruct repair_ssa_state { 28b8e80941Smrg nir_function_impl *impl; 29b8e80941Smrg 30b8e80941Smrg BITSET_WORD *def_set; 31b8e80941Smrg struct nir_phi_builder *phi_builder; 32b8e80941Smrg 33b8e80941Smrg bool progress; 34b8e80941Smrg}; 35b8e80941Smrg 36b8e80941Smrg/* Get ready to build a phi and return the builder */ 37b8e80941Smrgstatic struct nir_phi_builder * 38b8e80941Smrgprep_build_phi(struct repair_ssa_state *state) 39b8e80941Smrg{ 40b8e80941Smrg const unsigned num_words = BITSET_WORDS(state->impl->num_blocks); 41b8e80941Smrg 42b8e80941Smrg /* We create the phi builder on-demand. */ 43b8e80941Smrg if (state->phi_builder == NULL) { 44b8e80941Smrg state->phi_builder = nir_phi_builder_create(state->impl); 45b8e80941Smrg state->def_set = ralloc_array(NULL, BITSET_WORD, num_words); 46b8e80941Smrg } 47b8e80941Smrg 48b8e80941Smrg /* We're going to build a phi. That's progress. */ 49b8e80941Smrg state->progress = true; 50b8e80941Smrg 51b8e80941Smrg /* Set the defs set to empty */ 52b8e80941Smrg memset(state->def_set, 0, num_words * sizeof(*state->def_set)); 53b8e80941Smrg 54b8e80941Smrg return state->phi_builder; 55b8e80941Smrg} 56b8e80941Smrg 57b8e80941Smrgstatic nir_block * 58b8e80941Smrgget_src_block(nir_src *src) 59b8e80941Smrg{ 60b8e80941Smrg if (src->parent_instr->type == nir_instr_type_phi) { 61b8e80941Smrg return exec_node_data(nir_phi_src, src, src)->pred; 62b8e80941Smrg } else { 63b8e80941Smrg return src->parent_instr->block; 64b8e80941Smrg } 65b8e80941Smrg} 66b8e80941Smrg 67b8e80941Smrgstatic bool 68b8e80941Smrgrepair_ssa_def(nir_ssa_def *def, void *void_state) 69b8e80941Smrg{ 70b8e80941Smrg struct repair_ssa_state *state = void_state; 71b8e80941Smrg 72b8e80941Smrg bool is_valid = true; 73b8e80941Smrg nir_foreach_use(src, def) { 74b8e80941Smrg if (nir_block_is_unreachable(get_src_block(src)) || 75b8e80941Smrg !nir_block_dominates(def->parent_instr->block, get_src_block(src))) { 76b8e80941Smrg is_valid = false; 77b8e80941Smrg break; 78b8e80941Smrg } 79b8e80941Smrg } 80b8e80941Smrg 81b8e80941Smrg nir_foreach_if_use(src, def) { 82b8e80941Smrg nir_block *block_before_if = 83b8e80941Smrg nir_cf_node_as_block(nir_cf_node_prev(&src->parent_if->cf_node)); 84b8e80941Smrg if (nir_block_is_unreachable(block_before_if) || 85b8e80941Smrg !nir_block_dominates(def->parent_instr->block, block_before_if)) { 86b8e80941Smrg is_valid = false; 87b8e80941Smrg break; 88b8e80941Smrg } 89b8e80941Smrg } 90b8e80941Smrg 91b8e80941Smrg if (is_valid) 92b8e80941Smrg return true; 93b8e80941Smrg 94b8e80941Smrg struct nir_phi_builder *pb = prep_build_phi(state); 95b8e80941Smrg 96b8e80941Smrg BITSET_SET(state->def_set, def->parent_instr->block->index); 97b8e80941Smrg 98b8e80941Smrg struct nir_phi_builder_value *val = 99b8e80941Smrg nir_phi_builder_add_value(pb, def->num_components, def->bit_size, 100b8e80941Smrg state->def_set); 101b8e80941Smrg 102b8e80941Smrg nir_phi_builder_value_set_block_def(val, def->parent_instr->block, def); 103b8e80941Smrg 104b8e80941Smrg nir_foreach_use_safe(src, def) { 105b8e80941Smrg nir_block *src_block = get_src_block(src); 106b8e80941Smrg if (nir_block_is_unreachable(src_block) || 107b8e80941Smrg !nir_block_dominates(def->parent_instr->block, src_block)) { 108b8e80941Smrg nir_ssa_def *block_def = 109b8e80941Smrg nir_phi_builder_value_get_block_def(val, src_block); 110b8e80941Smrg 111b8e80941Smrg /* If def was a deref and the use we're looking at is a deref that 112b8e80941Smrg * isn't a cast, we need to wrap it in a cast so we don't loose any 113b8e80941Smrg * deref information. 114b8e80941Smrg */ 115b8e80941Smrg if (def->parent_instr->type == nir_instr_type_deref && 116b8e80941Smrg src->parent_instr->type == nir_instr_type_deref && 117b8e80941Smrg nir_instr_as_deref(src->parent_instr)->deref_type != nir_deref_type_cast) { 118b8e80941Smrg nir_deref_instr *cast = 119b8e80941Smrg nir_deref_instr_create(state->impl->function->shader, 120b8e80941Smrg nir_deref_type_cast); 121b8e80941Smrg 122b8e80941Smrg nir_deref_instr *deref = nir_instr_as_deref(def->parent_instr); 123b8e80941Smrg cast->mode = deref->mode; 124b8e80941Smrg cast->type = deref->type; 125b8e80941Smrg cast->parent = nir_src_for_ssa(block_def); 126b8e80941Smrg cast->cast.ptr_stride = nir_deref_instr_ptr_as_array_stride(deref); 127b8e80941Smrg 128b8e80941Smrg nir_ssa_dest_init(&cast->instr, &cast->dest, 129b8e80941Smrg def->num_components, def->bit_size, NULL); 130b8e80941Smrg nir_instr_insert(nir_before_instr(src->parent_instr), 131b8e80941Smrg &cast->instr); 132b8e80941Smrg block_def = &cast->dest.ssa; 133b8e80941Smrg } 134b8e80941Smrg 135b8e80941Smrg nir_instr_rewrite_src(src->parent_instr, src, 136b8e80941Smrg nir_src_for_ssa(block_def)); 137b8e80941Smrg } 138b8e80941Smrg } 139b8e80941Smrg 140b8e80941Smrg nir_foreach_if_use_safe(src, def) { 141b8e80941Smrg nir_block *block_before_if = 142b8e80941Smrg nir_cf_node_as_block(nir_cf_node_prev(&src->parent_if->cf_node)); 143b8e80941Smrg if (nir_block_is_unreachable(block_before_if) || 144b8e80941Smrg !nir_block_dominates(def->parent_instr->block, block_before_if)) { 145b8e80941Smrg nir_if_rewrite_condition(src->parent_if, nir_src_for_ssa( 146b8e80941Smrg nir_phi_builder_value_get_block_def(val, block_before_if))); 147b8e80941Smrg } 148b8e80941Smrg } 149b8e80941Smrg 150b8e80941Smrg return true; 151b8e80941Smrg} 152b8e80941Smrg 153b8e80941Smrgbool 154b8e80941Smrgnir_repair_ssa_impl(nir_function_impl *impl) 155b8e80941Smrg{ 156b8e80941Smrg struct repair_ssa_state state; 157b8e80941Smrg 158b8e80941Smrg state.impl = impl; 159b8e80941Smrg state.phi_builder = NULL; 160b8e80941Smrg state.progress = false; 161b8e80941Smrg 162b8e80941Smrg nir_metadata_require(impl, nir_metadata_block_index | 163b8e80941Smrg nir_metadata_dominance); 164b8e80941Smrg 165b8e80941Smrg nir_foreach_block(block, impl) { 166b8e80941Smrg nir_foreach_instr_safe(instr, block) { 167b8e80941Smrg nir_foreach_ssa_def(instr, repair_ssa_def, &state); 168b8e80941Smrg } 169b8e80941Smrg } 170b8e80941Smrg 171b8e80941Smrg if (state.progress) 172b8e80941Smrg nir_metadata_preserve(impl, nir_metadata_block_index | 173b8e80941Smrg nir_metadata_dominance); 174b8e80941Smrg 175b8e80941Smrg if (state.phi_builder) { 176b8e80941Smrg nir_phi_builder_finish(state.phi_builder); 177b8e80941Smrg ralloc_free(state.def_set); 178b8e80941Smrg } 179b8e80941Smrg 180b8e80941Smrg return state.progress; 181b8e80941Smrg} 182b8e80941Smrg 183b8e80941Smrg/** This pass can be used to repair SSA form in a shader. 184b8e80941Smrg * 185b8e80941Smrg * Sometimes a transformation (such as return lowering) will have to make 186b8e80941Smrg * changes to a shader which, while still correct, break some of NIR's SSA 187b8e80941Smrg * invariants. This pass will insert ssa_undefs and phi nodes as needed to 188b8e80941Smrg * get the shader back into SSA that the validator will like. 189b8e80941Smrg */ 190b8e80941Smrgbool 191b8e80941Smrgnir_repair_ssa(nir_shader *shader) 192b8e80941Smrg{ 193b8e80941Smrg bool progress = false; 194b8e80941Smrg 195b8e80941Smrg nir_foreach_function(function, shader) { 196b8e80941Smrg if (function->impl) 197b8e80941Smrg progress = nir_repair_ssa_impl(function->impl) || progress; 198b8e80941Smrg } 199b8e80941Smrg 200b8e80941Smrg return progress; 201b8e80941Smrg} 202