diff options
author | Jason Ekstrand <[email protected]> | 2018-11-07 15:40:02 -0600 |
---|---|---|
committer | Jason Ekstrand <[email protected]> | 2018-12-05 15:02:56 -0600 |
commit | 05af952a1102b47e11b41991e7cee1e557279a96 (patch) | |
tree | f72a0aedb628dcaf3aeb16da5345a9d8811c96bb /src/compiler/nir/nir_search.c | |
parent | 4925290ab1771d075c994ac23e0c0a3c19d3a50e (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.c | 90 |
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. */ |