From: Caio Marcelo de Oliveira Filho Date: Wed, 15 Jan 2020 19:51:58 +0000 (-0800) Subject: nir: Make nir_deref_path_init skip trivial casts X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8548fe19f03ecaee711ed9041be3dc05c7c22e56;p=mesa.git nir: Make nir_deref_path_init skip trivial casts In a NIR generated using SPIR-V initializers to variables, copy propagation can end up transforming vec1 32 ssa_33 = deref_var &@1 (shared mat2x4) vec1 32 ssa_35 = mov ssa_33 vec1 32 ssa_7 = deref_cast (mat2x4 *)ssa_35 (shared mat2x4) /* ptr_stride=0 */ into vec1 32 ssa_33 = deref_var &@1 (shared mat2x4) vec1 32 ssa_7 = deref_cast (mat2x4 *)ssa_33 (shared mat2x4) /* ptr_stride=0 */ Before the optimization, the "head" of a path of deref that uses ssa_7 will be the cast. After, it will be the variable in ssa_33. Since the types are the same, this is a trivial cast that would be picked up by nir_opt_deref. If we need to compare such deref-chain after optimization with another deref-chain for the same variable, the compare function will get confused by the cast in the middle. One alternative would be to add nir_opt_deref to places that compare derefs, but that might not scale well, so skip the trivial casts when generating the paths instead. Motivated by the discussion in https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3047#note_383660. Reviewed-by: Jason Ekstrand Tested-by: Marge Bot Part-of: --- diff --git a/src/compiler/nir/nir_deref.c b/src/compiler/nir/nir_deref.c index 02f77d622bd..aa841223a3b 100644 --- a/src/compiler/nir/nir_deref.c +++ b/src/compiler/nir/nir_deref.c @@ -26,6 +26,19 @@ #include "nir_deref.h" #include "util/hash_table.h" +static bool +is_trivial_deref_cast(nir_deref_instr *cast) +{ + nir_deref_instr *parent = nir_src_as_deref(cast->parent); + if (!parent) + return false; + + return cast->mode == parent->mode && + cast->type == parent->type && + cast->dest.ssa.num_components == parent->dest.ssa.num_components && + cast->dest.ssa.bit_size == parent->dest.ssa.bit_size; +} + void nir_deref_path_init(nir_deref_path *path, nir_deref_instr *deref, void *mem_ctx) @@ -44,6 +57,8 @@ nir_deref_path_init(nir_deref_path *path, *tail = NULL; for (nir_deref_instr *d = deref; d; d = nir_deref_instr_parent(d)) { + if (d->deref_type == nir_deref_type_cast && is_trivial_deref_cast(d)) + continue; count++; if (count <= max_short_path_len) *(--head) = d; @@ -64,8 +79,11 @@ nir_deref_path_init(nir_deref_path *path, path->path = ralloc_array(mem_ctx, nir_deref_instr *, count + 1); head = tail = path->path + count; *tail = NULL; - for (nir_deref_instr *d = deref; d; d = nir_deref_instr_parent(d)) + for (nir_deref_instr *d = deref; d; d = nir_deref_instr_parent(d)) { + if (d->deref_type == nir_deref_type_cast && is_trivial_deref_cast(d)) + continue; *(--head) = d; + } done: assert(head == path->path); @@ -735,19 +753,6 @@ nir_rematerialize_derefs_in_use_blocks_impl(nir_function_impl *impl) return state.progress; } -static bool -is_trivial_deref_cast(nir_deref_instr *cast) -{ - nir_deref_instr *parent = nir_src_as_deref(cast->parent); - if (!parent) - return false; - - return cast->mode == parent->mode && - cast->type == parent->type && - cast->dest.ssa.num_components == parent->dest.ssa.num_components && - cast->dest.ssa.bit_size == parent->dest.ssa.bit_size; -} - static bool is_trivial_array_deref_cast(nir_deref_instr *cast) {