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 <tarceri@itsqueeze.com>
This commit is contained in:
Jason Ekstrand
2019-06-20 11:12:54 -05:00
parent 9a3cb6f5fe
commit 8f7405ed9d

View File

@@ -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
*