summaryrefslogtreecommitdiffstats
path: root/src/compiler/nir/nir_search.c
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2018-11-07 15:40:02 -0600
committerJason Ekstrand <[email protected]>2018-12-05 15:02:56 -0600
commit05af952a1102b47e11b41991e7cee1e557279a96 (patch)
treef72a0aedb628dcaf3aeb16da5345a9d8811c96bb /src/compiler/nir/nir_search.c
parent4925290ab1771d075c994ac23e0c0a3c19d3a50e (diff)
nir/algebraic: Add support for unsized conversion opcodes
All conversion opcodes require a destination size but this makes constructing certain algebraic expressions rather cumbersome. This commit adds support to nir_search and nir_algebraic for writing conversion opcodes without a size. These meta-opcodes match any conversion of that type regardless of destination size and the size gets inferred from the sizes of the things being matched or from other opcodes in the expression. Reviewed-by: Connor Abbott <[email protected]>
Diffstat (limited to 'src/compiler/nir/nir_search.c')
-rw-r--r--src/compiler/nir/nir_search.c90
1 files changed, 84 insertions, 6 deletions
diff --git a/src/compiler/nir/nir_search.c b/src/compiler/nir/nir_search.c
index a41fca876d5..f5fc92ec33c 100644
--- a/src/compiler/nir/nir_search.c
+++ b/src/compiler/nir/nir_search.c
@@ -90,6 +90,82 @@ src_is_type(nir_src src, nir_alu_type type)
}
static bool
+nir_op_matches_search_op(nir_op nop, uint16_t sop)
+{
+ if (sop <= nir_last_opcode)
+ return nop == sop;
+
+#define MATCH_FCONV_CASE(op) \
+ case nir_search_op_##op: \
+ return nop == nir_op_##op##16 || \
+ nop == nir_op_##op##32 || \
+ nop == nir_op_##op##64;
+
+#define MATCH_ICONV_CASE(op) \
+ case nir_search_op_##op: \
+ return nop == nir_op_##op##8 || \
+ nop == nir_op_##op##16 || \
+ nop == nir_op_##op##32 || \
+ nop == nir_op_##op##64;
+
+ switch (sop) {
+ MATCH_FCONV_CASE(i2f)
+ MATCH_FCONV_CASE(u2f)
+ MATCH_FCONV_CASE(f2f)
+ MATCH_ICONV_CASE(f2u)
+ MATCH_ICONV_CASE(f2i)
+ MATCH_ICONV_CASE(u2u)
+ MATCH_ICONV_CASE(i2i)
+ default:
+ unreachable("Invalid nir_search_op");
+ }
+
+#undef MATCH_FCONV_CASE
+#undef MATCH_ICONV_CASE
+}
+
+static nir_op
+nir_op_for_search_op(uint16_t sop, unsigned bit_size)
+{
+ if (sop <= nir_last_opcode)
+ return sop;
+
+#define RET_FCONV_CASE(op) \
+ case nir_search_op_##op: \
+ switch (bit_size) { \
+ case 16: return nir_op_##op##16; \
+ case 32: return nir_op_##op##32; \
+ case 64: return nir_op_##op##64; \
+ default: unreachable("Invalid bit size"); \
+ }
+
+#define RET_ICONV_CASE(op) \
+ case nir_search_op_##op: \
+ switch (bit_size) { \
+ case 8: return nir_op_##op##8; \
+ case 16: return nir_op_##op##16; \
+ case 32: return nir_op_##op##32; \
+ case 64: return nir_op_##op##64; \
+ default: unreachable("Invalid bit size"); \
+ }
+
+ switch (sop) {
+ RET_FCONV_CASE(i2f)
+ RET_FCONV_CASE(u2f)
+ RET_FCONV_CASE(f2f)
+ RET_ICONV_CASE(f2u)
+ RET_ICONV_CASE(f2i)
+ RET_ICONV_CASE(u2u)
+ RET_ICONV_CASE(i2i)
+ default:
+ unreachable("Invalid nir_search_op");
+ }
+
+#undef RET_FCONV_CASE
+#undef RET_ICONV_CASE
+}
+
+static bool
match_value(const nir_search_value *value, nir_alu_instr *instr, unsigned src,
unsigned num_components, const uint8_t *swizzle,
struct match_state *state)
@@ -223,7 +299,7 @@ match_expression(const nir_search_expression *expr, nir_alu_instr *instr,
if (expr->cond && !expr->cond(instr))
return false;
- if (instr->op != expr->opcode)
+ if (!nir_op_matches_search_op(instr->op, expr->opcode))
return false;
assert(instr->dest.dest.is_ssa);
@@ -311,13 +387,15 @@ construct_value(nir_builder *build,
switch (value->type) {
case nir_search_value_expression: {
const nir_search_expression *expr = nir_search_value_as_expression(value);
+ unsigned dst_bit_size = replace_bitsize(value, search_bitsize, state);
+ nir_op op = nir_op_for_search_op(expr->opcode, dst_bit_size);
- if (nir_op_infos[expr->opcode].output_size != 0)
- num_components = nir_op_infos[expr->opcode].output_size;
+ if (nir_op_infos[op].output_size != 0)
+ num_components = nir_op_infos[op].output_size;
- nir_alu_instr *alu = nir_alu_instr_create(build->shader, expr->opcode);
+ nir_alu_instr *alu = nir_alu_instr_create(build->shader, op);
nir_ssa_dest_init(&alu->instr, &alu->dest.dest, num_components,
- replace_bitsize(value, search_bitsize, state), NULL);
+ dst_bit_size, NULL);
alu->dest.write_mask = (1 << num_components) - 1;
alu->dest.saturate = false;
@@ -328,7 +406,7 @@ construct_value(nir_builder *build,
*/
alu->exact = state->has_exact_alu;
- for (unsigned i = 0; i < nir_op_infos[expr->opcode].num_inputs; i++) {
+ for (unsigned i = 0; i < nir_op_infos[op].num_inputs; i++) {
/* If the source is an explicitly sized source, then we need to reset
* the number of components to match.
*/