[Mesa-dev] [PATCH 5/5] nir/cse: use the instr_hash helper
Jason Ekstrand
jason at jlekstrand.net
Tue Aug 18 10:49:51 PDT 2015
I really like this. It's nice, straight-forward, and to-the-point.
Once the other issues have been cleared up,
Reviewed-by: Jason Ekstrand <jason at jlekstrand.net>
On Fri, May 22, 2015 at 11:24 AM, Connor Abbott <cwabbott0 at gmail.com> wrote:
> This replaces an O(n^2) algorithm with an O(n) one, while allowing us to
> import most of the infrastructure required for GVN. The idea is to walk
> the dominance tree depth-first, similar when converting to SSA, and
> remove the instructions from the set when we're done visiting the
> sub-tree of the dominance tree so that the only instructions in the set
> are the instructions that dominate the current block.
>
> No piglit regressions. No changes in the result of the public shader-db.
>
> Difference at 95.0% confidence
> -0.998 +/- 0.312663
> -5.96961% +/- 1.87022%
> (Student's t, pooled s = 0.332763)
>
> Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
> ---
> src/glsl/nir/nir_opt_cse.c | 134 ++++++++-------------------------------------
> 1 file changed, 24 insertions(+), 110 deletions(-)
>
> diff --git a/src/glsl/nir/nir_opt_cse.c b/src/glsl/nir/nir_opt_cse.c
> index a6a4a21..7894147 100644
> --- a/src/glsl/nir/nir_opt_cse.c
> +++ b/src/glsl/nir/nir_opt_cse.c
> @@ -22,10 +22,11 @@
> *
> * Authors:
> * Jason Ekstrand (jason at jlekstrand.net)
> + * Connor Abbott (cwabbott0 at gmail.com)
> *
> */
>
> -#include "nir.h"
> +#include "nir_instr_hash.h"
>
> /*
> * Implements common subexpression elimination
> @@ -33,141 +34,54 @@
>
> struct cse_state {
> void *mem_ctx;
> + struct set *instr_set;
> bool progress;
> };
>
> -static bool
> -src_is_ssa(nir_src *src, void *data)
> -{
> - (void) data;
> - return src->is_ssa;
> -}
> -
> -static bool
> -dest_is_ssa(nir_dest *dest, void *data)
> -{
> - (void) data;
> - return dest->is_ssa;
> -}
> +/*
> + * Visits and CSE's the given block and all its descendants in the dominance
> + * tree recursively. Note that the instr_set is guaranteed to only ever
> + * contain instructions that dominate the current block.
> + */
>
> static bool
> -nir_instr_can_cse(nir_instr *instr)
> +cse_block(nir_block *block, struct set *instr_set)
> {
> - /* We only handle SSA. */
> - if (!nir_foreach_dest(instr, dest_is_ssa, NULL) ||
> - !nir_foreach_src(instr, src_is_ssa, NULL))
> - return false;
> -
> - switch (instr->type) {
> - case nir_instr_type_alu:
> - case nir_instr_type_load_const:
> - case nir_instr_type_phi:
> - return true;
> - case nir_instr_type_tex:
> - return false; /* TODO */
> - case nir_instr_type_intrinsic: {
> - const nir_intrinsic_info *info =
> - &nir_intrinsic_infos[nir_instr_as_intrinsic(instr)->intrinsic];
> - return (info->flags & NIR_INTRINSIC_CAN_ELIMINATE) &&
> - (info->flags & NIR_INTRINSIC_CAN_REORDER) &&
> - info->num_variables == 0; /* not implemented yet */
> - }
> - case nir_instr_type_call:
> - case nir_instr_type_jump:
> - case nir_instr_type_ssa_undef:
> - return false;
> - case nir_instr_type_parallel_copy:
> - default:
> - unreachable("Invalid instruction type");
> - }
> -
> - return false;
> -}
> -
> -static nir_ssa_def *
> -nir_instr_get_dest_ssa_def(nir_instr *instr)
> -{
> - switch (instr->type) {
> - case nir_instr_type_alu:
> - assert(nir_instr_as_alu(instr)->dest.dest.is_ssa);
> - return &nir_instr_as_alu(instr)->dest.dest.ssa;
> - case nir_instr_type_load_const:
> - return &nir_instr_as_load_const(instr)->def;
> - case nir_instr_type_phi:
> - assert(nir_instr_as_phi(instr)->dest.is_ssa);
> - return &nir_instr_as_phi(instr)->dest.ssa;
> - case nir_instr_type_intrinsic:
> - assert(nir_instr_as_intrinsic(instr)->dest.is_ssa);
> - return &nir_instr_as_intrinsic(instr)->dest.ssa;
> - default:
> - unreachable("We never ask for any of these");
> - }
> -}
> + bool progress = false;
>
> -static void
> -nir_opt_cse_instr(nir_instr *instr, struct cse_state *state)
> -{
> - if (!nir_instr_can_cse(instr))
> - return;
> -
> - for (struct exec_node *node = instr->node.prev;
> - !exec_node_is_head_sentinel(node); node = node->prev) {
> - nir_instr *other = exec_node_data(nir_instr, node, node);
> - if (nir_instrs_equal(instr, other)) {
> - nir_ssa_def *other_def = nir_instr_get_dest_ssa_def(other);
> - nir_ssa_def_rewrite_uses(nir_instr_get_dest_ssa_def(instr),
> - nir_src_for_ssa(other_def),
> - state->mem_ctx);
> + nir_foreach_instr_safe(block, instr) {
> + if (nir_instr_set_add(instr_set, instr)) {
> + progress = true;
> nir_instr_remove(instr);
> - state->progress = true;
> - return;
> }
> }
>
> - for (nir_block *block = instr->block->imm_dom;
> - block != NULL; block = block->imm_dom) {
> - nir_foreach_instr_reverse(block, other) {
> - if (nir_instrs_equal(instr, other)) {
> - nir_ssa_def *other_def = nir_instr_get_dest_ssa_def(other);
> - nir_ssa_def_rewrite_uses(nir_instr_get_dest_ssa_def(instr),
> - nir_src_for_ssa(other_def),
> - state->mem_ctx);
> - nir_instr_remove(instr);
> - state->progress = true;
> - return;
> - }
> - }
> + for (unsigned i = 0; i < block->num_dom_children; i++) {
> + nir_block *child = block->dom_children[i];
> + progress |= cse_block(child, instr_set);
> }
> -}
>
> -static bool
> -nir_opt_cse_block(nir_block *block, void *void_state)
> -{
> - struct cse_state *state = void_state;
> -
> - nir_foreach_instr_safe(block, instr)
> - nir_opt_cse_instr(instr, state);
> + nir_foreach_instr(block, instr)
> + nir_instr_set_remove(instr_set, instr);
>
> - return true;
> + return progress;
> }
>
> static bool
> nir_opt_cse_impl(nir_function_impl *impl)
> {
> - struct cse_state state;
> -
> - state.mem_ctx = ralloc_parent(impl);
> - state.progress = false;
> + struct set *instr_set = nir_instr_set_create(NULL);
>
> nir_metadata_require(impl, nir_metadata_dominance);
>
> - nir_foreach_block(impl, nir_opt_cse_block, &state);
> + bool progress = cse_block(impl->start_block, instr_set);
>
> - if (state.progress)
> + if (progress)
> nir_metadata_preserve(impl, nir_metadata_block_index |
> nir_metadata_dominance);
>
> - return state.progress;
> + nir_instr_set_destroy(instr_set);
> + return progress;
> }
>
> bool
> --
> 2.1.0
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list