X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcompiler%2Fnir%2Fnir_repair_ssa.c;h=8eceadcebb08261ff53b0203ebec2f1d6a9cf29f;hb=ce6f66242ad33be84c0a34519f18bdc15c195950;hp=3ab4f0f6db74b1c97555a1580c933f1c1e631580;hpb=3fd308a357b9057447d21c67718d13524dbbb40d;p=mesa.git diff --git a/src/compiler/nir/nir_repair_ssa.c b/src/compiler/nir/nir_repair_ssa.c index 3ab4f0f6db7..8eceadcebb0 100644 --- a/src/compiler/nir/nir_repair_ssa.c +++ b/src/compiler/nir/nir_repair_ssa.c @@ -70,8 +70,19 @@ repair_ssa_def(nir_ssa_def *def, void *void_state) struct repair_ssa_state *state = void_state; bool is_valid = true; - nir_foreach_use(def, src) { - if (!nir_block_dominates(def->parent_instr->block, get_src_block(src))) { + nir_foreach_use(src, def) { + if (nir_block_is_unreachable(get_src_block(src)) || + !nir_block_dominates(def->parent_instr->block, get_src_block(src))) { + is_valid = false; + break; + } + } + + nir_foreach_if_use(src, def) { + nir_block *block_before_if = + nir_cf_node_as_block(nir_cf_node_prev(&src->parent_if->cf_node)); + if (nir_block_is_unreachable(block_before_if) || + !nir_block_dominates(def->parent_instr->block, block_before_if)) { is_valid = false; break; } @@ -85,26 +96,64 @@ repair_ssa_def(nir_ssa_def *def, void *void_state) BITSET_SET(state->def_set, def->parent_instr->block->index); struct nir_phi_builder_value *val = - nir_phi_builder_add_value(pb, def->num_components, state->def_set); + nir_phi_builder_add_value(pb, def->num_components, def->bit_size, + state->def_set); nir_phi_builder_value_set_block_def(val, def->parent_instr->block, def); - nir_foreach_use_safe(def, src) { + nir_foreach_use_safe(src, def) { nir_block *src_block = get_src_block(src); - if (!nir_block_dominates(def->parent_instr->block, src_block)) { - nir_instr_rewrite_src(src->parent_instr, src, nir_src_for_ssa( - nir_phi_builder_value_get_block_def(val, src_block))); + if (src_block == def->parent_instr->block) { + assert(nir_phi_builder_value_get_block_def(val, src_block) == def); + continue; + } + + nir_ssa_def *block_def = + nir_phi_builder_value_get_block_def(val, src_block); + if (block_def == def) + continue; + + /* If def was a deref and the use we're looking at is a deref that + * isn't a cast, we need to wrap it in a cast so we don't loose any + * deref information. + */ + if (def->parent_instr->type == nir_instr_type_deref && + src->parent_instr->type == nir_instr_type_deref && + nir_instr_as_deref(src->parent_instr)->deref_type != nir_deref_type_cast) { + nir_deref_instr *cast = + nir_deref_instr_create(state->impl->function->shader, + nir_deref_type_cast); + + nir_deref_instr *deref = nir_instr_as_deref(def->parent_instr); + cast->mode = deref->mode; + cast->type = deref->type; + cast->parent = nir_src_for_ssa(block_def); + cast->cast.ptr_stride = nir_deref_instr_ptr_as_array_stride(deref); + + nir_ssa_dest_init(&cast->instr, &cast->dest, + def->num_components, def->bit_size, NULL); + nir_instr_insert(nir_before_instr(src->parent_instr), + &cast->instr); + block_def = &cast->dest.ssa; } + + nir_instr_rewrite_src(src->parent_instr, src, nir_src_for_ssa(block_def)); } - return true; -} + nir_foreach_if_use_safe(src, def) { + nir_block *block_before_if = + nir_cf_node_as_block(nir_cf_node_prev(&src->parent_if->cf_node)); + if (block_before_if == def->parent_instr->block) { + assert(nir_phi_builder_value_get_block_def(val, block_before_if) == def); + continue; + } -static bool -repair_ssa_block(nir_block *block, void *state) -{ - nir_foreach_instr_safe(block, instr) { - nir_foreach_ssa_def(instr, repair_ssa_def, state); + nir_ssa_def *block_def = + nir_phi_builder_value_get_block_def(val, block_before_if); + if (block_def == def) + continue; + + nir_if_rewrite_condition(src->parent_if, nir_src_for_ssa(block_def)); } return true; @@ -122,7 +171,11 @@ nir_repair_ssa_impl(nir_function_impl *impl) nir_metadata_require(impl, nir_metadata_block_index | nir_metadata_dominance); - nir_foreach_block(impl, repair_ssa_block, &state); + nir_foreach_block(block, impl) { + nir_foreach_instr_safe(instr, block) { + nir_foreach_ssa_def(instr, repair_ssa_def, &state); + } + } if (state.progress) nir_metadata_preserve(impl, nir_metadata_block_index | @@ -148,7 +201,7 @@ nir_repair_ssa(nir_shader *shader) { bool progress = false; - nir_foreach_function(shader, function) { + nir_foreach_function(function, shader) { if (function->impl) progress = nir_repair_ssa_impl(function->impl) || progress; }