From: Jason Ekstrand Date: Thu, 20 Jun 2019 16:12:54 +0000 (-0500) Subject: nir: Add some helpers for chasing SSA values properly X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8f7405ed9d473c1729d48c5add4f0d9fe147c75a;p=mesa.git nir: Add some helpers for chasing SSA values properly There are various cases in which we want to chase SSA values through ALU ops ranging from hand-written optimizations to back-end translation code. In all these cases, it can be very tricky to do properly because of swizzles. This set of helpers lets you easily work with a single component of an SSA def and chase through ALU ops safely. Reviewed-by: Timothy Arceri --- diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 3d50c89bf0b..4fa50940e17 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -2002,6 +2002,86 @@ NIR_DEFINE_SRC_AS_CONST(double, float) #undef NIR_DEFINE_SRC_AS_CONST +typedef struct { + nir_ssa_def *def; + unsigned comp; +} nir_ssa_scalar; + +static inline bool +nir_ssa_scalar_is_const(nir_ssa_scalar s) +{ + return s.def->parent_instr->type == nir_instr_type_load_const; +} + +static inline nir_const_value +nir_ssa_scalar_as_const_value(nir_ssa_scalar s) +{ + assert(s.comp < s.def->num_components); + nir_load_const_instr *load = nir_instr_as_load_const(s.def->parent_instr); + return load->value[s.comp]; +} + +#define NIR_DEFINE_SCALAR_AS_CONST(type, suffix) \ +static inline type \ +nir_ssa_scalar_as_##suffix(nir_ssa_scalar s) \ +{ \ + return nir_const_value_as_##suffix( \ + nir_ssa_scalar_as_const_value(s), s.def->bit_size); \ +} + +NIR_DEFINE_SCALAR_AS_CONST(int64_t, int) +NIR_DEFINE_SCALAR_AS_CONST(uint64_t, uint) +NIR_DEFINE_SCALAR_AS_CONST(bool, bool) +NIR_DEFINE_SCALAR_AS_CONST(double, float) + +#undef NIR_DEFINE_SCALAR_AS_CONST + +static inline bool +nir_ssa_scalar_is_alu(nir_ssa_scalar s) +{ + return s.def->parent_instr->type == nir_instr_type_alu; +} + +static inline nir_op +nir_ssa_scalar_alu_op(nir_ssa_scalar s) +{ + return nir_instr_as_alu(s.def->parent_instr)->op; +} + +static inline nir_ssa_scalar +nir_ssa_scalar_chase_alu_src(nir_ssa_scalar s, unsigned alu_src_idx) +{ + nir_ssa_scalar out = { NULL, 0 }; + + nir_alu_instr *alu = nir_instr_as_alu(s.def->parent_instr); + assert(alu_src_idx < nir_op_infos[alu->op].num_inputs); + + /* Our component must be written */ + assert(s.comp < s.def->num_components); + assert(alu->dest.write_mask & (1u << s.comp)); + + assert(alu->src[alu_src_idx].src.is_ssa); + out.def = alu->src[alu_src_idx].src.ssa; + + if (nir_op_infos[alu->op].input_sizes[alu_src_idx] == 0) { + /* The ALU src is unsized so the source component follows the + * destination component. + */ + out.comp = alu->src[alu_src_idx].swizzle[s.comp]; + } else { + /* This is a sized source so all source components work together to + * produce all the destination components. Since we need to return a + * scalar, this only works if the source is a scalar. + */ + assert(nir_op_infos[alu->op].input_sizes[alu_src_idx] == 1); + out.comp = alu->src[alu_src_idx].swizzle[0]; + } + assert(out.comp < out.def->num_components); + + return out; +} + + /* * Control flow *