X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcompiler%2Fnir%2Fnir_opt_gcm.c;h=879a77a884b046e8b307d97996a46a9f745cfb9c;hb=d7114454305a64f9624d7b1fcc726d97d7f1835a;hp=a87a0067230da12aee5bf1f7703eabe291104f99;hpb=8564916d01b31ca5665a27366e483738541ba5a3;p=mesa.git diff --git a/src/compiler/nir/nir_opt_gcm.c b/src/compiler/nir/nir_opt_gcm.c index a87a0067230..879a77a884b 100644 --- a/src/compiler/nir/nir_opt_gcm.c +++ b/src/compiler/nir/nir_opt_gcm.c @@ -26,6 +26,7 @@ */ #include "nir.h" +#include "nir_instr_set.h" /* * Implements Global Code Motion. A description of GCM can be found in @@ -277,7 +278,7 @@ gcm_schedule_late_def(nir_ssa_def *def, void *void_state) nir_block *lca = NULL; - nir_foreach_use(def, use_src) { + nir_foreach_use(use_src, def) { nir_instr *use_instr = use_src->parent_instr; gcm_schedule_late_instr(use_instr, state); @@ -301,7 +302,7 @@ gcm_schedule_late_def(nir_ssa_def *def, void *void_state) } } - nir_foreach_if_use(def, use_src) { + nir_foreach_if_use(use_src, def) { nir_if *if_stmt = use_src->parent_if; /* For if statements, we consider the block to be the one immediately @@ -319,18 +320,19 @@ gcm_schedule_late_def(nir_ssa_def *def, void *void_state) if (lca == NULL) return true; - /* We know have the LCA of all of the uses. If our invariants hold, + /* We now have the LCA of all of the uses. If our invariants hold, * this is dominated by the block that we chose when scheduling early. * We now walk up the dominance tree and pick the lowest block that is * as far outside loops as we can get. */ nir_block *best = lca; - while (lca != def->parent_instr->block) { - assert(lca); - if (state->blocks[lca->index].loop_depth < + for (nir_block *block = lca; block != NULL; block = block->imm_dom) { + if (state->blocks[block->index].loop_depth < state->blocks[best->index].loop_depth) - best = lca; - lca = lca->imm_dom; + best = block; + + if (block == def->parent_instr->block) + break; } def->parent_instr->block = best; @@ -374,7 +376,7 @@ gcm_place_instr(nir_instr *instr, struct gcm_state *state); static bool gcm_place_instr_def(nir_ssa_def *def, void *state) { - nir_foreach_use(def, use_src) + nir_foreach_use(use_src, def) gcm_place_instr(use_src->parent_instr, state); return false; @@ -451,9 +453,12 @@ gcm_place_instr(nir_instr *instr, struct gcm_state *state) block_info->last_instr = instr; } -static void -opt_gcm_impl(nir_function_impl *impl) +static bool +opt_gcm_impl(nir_function_impl *impl, bool value_number) { + nir_metadata_require(impl, nir_metadata_block_index | + nir_metadata_dominance); + struct gcm_state state; state.impl = impl; @@ -461,15 +466,24 @@ opt_gcm_impl(nir_function_impl *impl) exec_list_make_empty(&state.instrs); state.blocks = rzalloc_array(NULL, struct gcm_block_info, impl->num_blocks); - nir_metadata_require(impl, nir_metadata_block_index | - nir_metadata_dominance); - gcm_build_block_info(&impl->body, &state, 0); nir_foreach_block(block, impl) { gcm_pin_instructions_block(block, &state); } + bool progress = false; + if (value_number) { + struct set *gvn_set = nir_instr_set_create(NULL); + foreach_list_typed_safe(nir_instr, instr, node, &state.instrs) { + if (nir_instr_set_add_or_rewrite(gvn_set, instr)) { + nir_instr_remove(instr); + progress = true; + } + } + nir_instr_set_destroy(gvn_set); + } + foreach_list_typed(nir_instr, instr, node, &state.instrs) gcm_schedule_early_instr(instr, &state); @@ -478,18 +492,27 @@ opt_gcm_impl(nir_function_impl *impl) while (!exec_list_is_empty(&state.instrs)) { nir_instr *instr = exec_node_data(nir_instr, - state.instrs.tail_pred, node); + state.instrs.tail_sentinel.prev, node); gcm_place_instr(instr, &state); } ralloc_free(state.blocks); + + nir_metadata_preserve(impl, nir_metadata_block_index | + nir_metadata_dominance); + + return progress; } -void -nir_opt_gcm(nir_shader *shader) +bool +nir_opt_gcm(nir_shader *shader, bool value_number) { - nir_foreach_function(shader, function) { + bool progress = false; + + nir_foreach_function(function, shader) { if (function->impl) - opt_gcm_impl(function->impl); + progress |= opt_gcm_impl(function->impl, value_number); } + + return progress; }