diff options
author | Jason Ekstrand <[email protected]> | 2019-06-20 11:12:54 -0500 |
---|---|---|
committer | Juan A. Suarez Romero <[email protected]> | 2019-07-18 08:22:26 +0000 |
commit | b685e303f7488d10b37736af3ff0011afb4e649b (patch) | |
tree | 496f8f066a89a0ebfc5f988fece829af9f560100 /src/compiler | |
parent | b9b376b8215f2ee17fb33f9dacad2ccf434e4507 (diff) |
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 <[email protected]>
(cherry picked from commit 8f7405ed9d473c1729d48c5add4f0d9fe147c75a)
[Juan A. Suarez: resolve trivial conflicts]
Signed-off-by: Juan A. Suarez Romero <[email protected]>
Conflicts:
src/compiler/nir/nir.h
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/nir/nir.h | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 1bca07c0a8e..88981398c8d 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -1925,6 +1925,85 @@ NIR_DEFINE_CAST(nir_instr_as_parallel_copy, nir_instr, nir_parallel_copy_instr, instr, type, nir_instr_type_parallel_copy) +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 * |