#include "agx_nir.h"

#include "nir.h"
#include "nir_builder.h"
#include "nir_search.h"
#include "nir_search_helpers.h"

/* What follows is NIR algebraic transform code for the following 26
 * transforms:
 *    ('ishl', 'a@8', 'b') => ('ishl', 'a', ('iand', 'b', 7))
 *    ('ishr', 'a@8', 'b') => ('ishr', 'a', ('iand', 'b', 7))
 *    ('ushr', 'a@8', 'b') => ('ushr', 'a', ('iand', 'b', 7))
 *    ('ishl', 'a@16', 'b') => ('ishl', 'a', ('iand', 'b', 15))
 *    ('ishr', 'a@16', 'b') => ('ishr', 'a', ('iand', 'b', 15))
 *    ('ushr', 'a@16', 'b') => ('ushr', 'a', ('iand', 'b', 15))
 *    ('ishl', 'a@32', 'b') => ('ishl', 'a', ('iand', 'b', 31))
 *    ('ishr', 'a@32', 'b') => ('ishr', 'a', ('iand', 'b', 31))
 *    ('ushr', 'a@32', 'b') => ('ushr', 'a', ('iand', 'b', 31))
 *    ('ishl', 'a@64', 'b') => ('ishl', 'a', ('iand', 'b', 63))
 *    ('ishr', 'a@64', 'b') => ('ishr', 'a', ('iand', 'b', 63))
 *    ('ushr', 'a@64', 'b') => ('ushr', 'a', ('iand', 'b', 63))
 *    ('pack_half_2x16_split', 'a', 'b') => ('pack_32_2x16_split', ('f2f16', 'a'), ('f2f16', 'b'))
 *    ('unpack_half_2x16_split_x', 'a') => ('f2f32', ('unpack_32_2x16_split_x', 'a'))
 *    ('unpack_half_2x16_split_y', 'a') => ('f2f32', ('unpack_32_2x16_split_y', 'a'))
 *    ('extract_u16', 'a@32', 0) => ('u2u32', ('unpack_32_2x16_split_x', 'a'))
 *    ('extract_u16', 'a@32', 1) => ('u2u32', ('unpack_32_2x16_split_y', 'a'))
 *    ('extract_i16', 'a@32', 0) => ('i2i32', ('unpack_32_2x16_split_x', 'a'))
 *    ('extract_i16', 'a@32', 1) => ('i2i32', ('unpack_32_2x16_split_y', 'a'))
 *    ('u2f32', ('u2u32', 'a')) => ('u2f32', 'a')
 *    ('i2f32', ('i2i32', 'a')) => ('i2f32', 'a')
 *    ('ibitfield_extract', 'value', 'offset', 'bits(is_not_const)') => ('bcsel', ('ieq', 0, 'bits'), 0, ('ishr', ('ishl', 'value', ('isub', ('isub', 32, 'bits'), 'offset')), ('isub', 32, 'bits')))
 *    ('ubitfield_extract', 'value', 'offset', 'bits(is_not_const)') => ('iand', ('ushr', 'value', 'offset'), ('bcsel', ('ieq', 'bits', 32), 4294967295, ('isub', ('ishl', 1, 'bits'), 1)))
 *    ('ubitfield_extract', 'value', 'offset', 0) => 0
 *    ('ibitfield_extract', 'value', 'offset', 0) => 0
 *    ('ibitfield_extract', 'a', 'b', '#bits') => ('ishr', ('ishl', ('ubitfield_extract', 'a', 'b', 'bits'), ('isub', 32, 'bits')), ('isub', 32, 'bits'))
 */


static const nir_search_value_union agx_nir_lower_algebraic_late_values[] = {
   /* ('ishl', 'a@8', 'b') => ('ishl', 'a', ('iand', 'b', 7)) */
   { .variable = {
      { nir_search_value_variable, 8 },
      0, /* a */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .variable = {
      { nir_search_value_variable, 32 },
      1, /* b */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, 8 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 0, 1 },
      -1,
   } },

   /* replace0_0 -> 0 in the cache */
   /* replace0_1_0 -> 1 in the cache */
   { .constant = {
      { nir_search_value_constant, 32 },
      nir_type_int, { 0x7 /* 7 */ },
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_iand,
      0, 1,
      { 1, 3 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 8 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 1,
      { 0, 4 },
      -1,
   } },

   /* ('ishr', 'a@8', 'b') => ('ishr', 'a', ('iand', 'b', 7)) */
   /* search1_0 -> 0 in the cache */
   /* search1_1 -> 1 in the cache */
   { .expression = {
      { nir_search_value_expression, 8 },
      false,
      false,
      false,
      nir_op_ishr,
      -1, 0,
      { 0, 1 },
      -1,
   } },

   /* replace1_0 -> 0 in the cache */
   /* replace1_1_0 -> 1 in the cache */
   /* replace1_1_1 -> 3 in the cache */
   /* replace1_1 -> 4 in the cache */
   { .expression = {
      { nir_search_value_expression, 8 },
      false,
      false,
      false,
      nir_op_ishr,
      -1, 1,
      { 0, 4 },
      -1,
   } },

   /* ('ushr', 'a@8', 'b') => ('ushr', 'a', ('iand', 'b', 7)) */
   /* search2_0 -> 0 in the cache */
   /* search2_1 -> 1 in the cache */
   { .expression = {
      { nir_search_value_expression, 8 },
      false,
      false,
      false,
      nir_op_ushr,
      -1, 0,
      { 0, 1 },
      -1,
   } },

   /* replace2_0 -> 0 in the cache */
   /* replace2_1_0 -> 1 in the cache */
   /* replace2_1_1 -> 3 in the cache */
   /* replace2_1 -> 4 in the cache */
   { .expression = {
      { nir_search_value_expression, 8 },
      false,
      false,
      false,
      nir_op_ushr,
      -1, 1,
      { 0, 4 },
      -1,
   } },

   /* ('ishl', 'a@16', 'b') => ('ishl', 'a', ('iand', 'b', 15)) */
   { .variable = {
      { nir_search_value_variable, 16 },
      0, /* a */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   /* search3_1 -> 1 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 10, 1 },
      -1,
   } },

   /* replace3_0 -> 10 in the cache */
   /* replace3_1_0 -> 1 in the cache */
   { .constant = {
      { nir_search_value_constant, 32 },
      nir_type_int, { 0xf /* 15 */ },
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_iand,
      0, 1,
      { 1, 12 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 16 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 1,
      { 10, 13 },
      -1,
   } },

   /* ('ishr', 'a@16', 'b') => ('ishr', 'a', ('iand', 'b', 15)) */
   /* search4_0 -> 10 in the cache */
   /* search4_1 -> 1 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      false,
      false,
      false,
      nir_op_ishr,
      -1, 0,
      { 10, 1 },
      -1,
   } },

   /* replace4_0 -> 10 in the cache */
   /* replace4_1_0 -> 1 in the cache */
   /* replace4_1_1 -> 12 in the cache */
   /* replace4_1 -> 13 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      false,
      false,
      false,
      nir_op_ishr,
      -1, 1,
      { 10, 13 },
      -1,
   } },

   /* ('ushr', 'a@16', 'b') => ('ushr', 'a', ('iand', 'b', 15)) */
   /* search5_0 -> 10 in the cache */
   /* search5_1 -> 1 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      false,
      false,
      false,
      nir_op_ushr,
      -1, 0,
      { 10, 1 },
      -1,
   } },

   /* replace5_0 -> 10 in the cache */
   /* replace5_1_0 -> 1 in the cache */
   /* replace5_1_1 -> 12 in the cache */
   /* replace5_1 -> 13 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      false,
      false,
      false,
      nir_op_ushr,
      -1, 1,
      { 10, 13 },
      -1,
   } },

   /* ('ishl', 'a@32', 'b') => ('ishl', 'a', ('iand', 'b', 31)) */
   { .variable = {
      { nir_search_value_variable, 32 },
      0, /* a */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   /* search6_1 -> 1 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 19, 1 },
      -1,
   } },

   /* replace6_0 -> 19 in the cache */
   /* replace6_1_0 -> 1 in the cache */
   { .constant = {
      { nir_search_value_constant, 32 },
      nir_type_int, { 0x1f /* 31 */ },
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_iand,
      0, 1,
      { 1, 21 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 1,
      { 19, 22 },
      -1,
   } },

   /* ('ishr', 'a@32', 'b') => ('ishr', 'a', ('iand', 'b', 31)) */
   /* search7_0 -> 19 in the cache */
   /* search7_1 -> 1 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_ishr,
      -1, 0,
      { 19, 1 },
      -1,
   } },

   /* replace7_0 -> 19 in the cache */
   /* replace7_1_0 -> 1 in the cache */
   /* replace7_1_1 -> 21 in the cache */
   /* replace7_1 -> 22 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_ishr,
      -1, 1,
      { 19, 22 },
      -1,
   } },

   /* ('ushr', 'a@32', 'b') => ('ushr', 'a', ('iand', 'b', 31)) */
   /* search8_0 -> 19 in the cache */
   /* search8_1 -> 1 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_ushr,
      -1, 0,
      { 19, 1 },
      -1,
   } },

   /* replace8_0 -> 19 in the cache */
   /* replace8_1_0 -> 1 in the cache */
   /* replace8_1_1 -> 21 in the cache */
   /* replace8_1 -> 22 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_ushr,
      -1, 1,
      { 19, 22 },
      -1,
   } },

   /* ('ishl', 'a@64', 'b') => ('ishl', 'a', ('iand', 'b', 63)) */
   { .variable = {
      { nir_search_value_variable, 64 },
      0, /* a */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   /* search9_1 -> 1 in the cache */
   { .expression = {
      { nir_search_value_expression, 64 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 28, 1 },
      -1,
   } },

   /* replace9_0 -> 28 in the cache */
   /* replace9_1_0 -> 1 in the cache */
   { .constant = {
      { nir_search_value_constant, 32 },
      nir_type_int, { 0x3f /* 63 */ },
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_iand,
      0, 1,
      { 1, 30 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 64 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 1,
      { 28, 31 },
      -1,
   } },

   /* ('ishr', 'a@64', 'b') => ('ishr', 'a', ('iand', 'b', 63)) */
   /* search10_0 -> 28 in the cache */
   /* search10_1 -> 1 in the cache */
   { .expression = {
      { nir_search_value_expression, 64 },
      false,
      false,
      false,
      nir_op_ishr,
      -1, 0,
      { 28, 1 },
      -1,
   } },

   /* replace10_0 -> 28 in the cache */
   /* replace10_1_0 -> 1 in the cache */
   /* replace10_1_1 -> 30 in the cache */
   /* replace10_1 -> 31 in the cache */
   { .expression = {
      { nir_search_value_expression, 64 },
      false,
      false,
      false,
      nir_op_ishr,
      -1, 1,
      { 28, 31 },
      -1,
   } },

   /* ('ushr', 'a@64', 'b') => ('ushr', 'a', ('iand', 'b', 63)) */
   /* search11_0 -> 28 in the cache */
   /* search11_1 -> 1 in the cache */
   { .expression = {
      { nir_search_value_expression, 64 },
      false,
      false,
      false,
      nir_op_ushr,
      -1, 0,
      { 28, 1 },
      -1,
   } },

   /* replace11_0 -> 28 in the cache */
   /* replace11_1_0 -> 1 in the cache */
   /* replace11_1_1 -> 30 in the cache */
   /* replace11_1 -> 31 in the cache */
   { .expression = {
      { nir_search_value_expression, 64 },
      false,
      false,
      false,
      nir_op_ushr,
      -1, 1,
      { 28, 31 },
      -1,
   } },

   /* ('pack_half_2x16_split', 'a', 'b') => ('pack_32_2x16_split', ('f2f16', 'a'), ('f2f16', 'b')) */
   /* search12_0 -> 19 in the cache */
   /* search12_1 -> 1 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_pack_half_2x16_split,
      -1, 0,
      { 19, 1 },
      -1,
   } },

   /* replace12_0_0 -> 19 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      false,
      false,
      false,
      nir_op_f2f16,
      -1, 0,
      { 19 },
      -1,
   } },
   /* replace12_1_0 -> 1 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      false,
      false,
      false,
      nir_op_f2f16,
      -1, 0,
      { 1 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_pack_32_2x16_split,
      -1, 0,
      { 38, 39 },
      -1,
   } },

   /* ('unpack_half_2x16_split_x', 'a') => ('f2f32', ('unpack_32_2x16_split_x', 'a')) */
   /* search13_0 -> 19 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_unpack_half_2x16_split_x,
      -1, 0,
      { 19 },
      -1,
   } },

   /* replace13_0_0 -> 19 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      false,
      false,
      false,
      nir_op_unpack_32_2x16_split_x,
      -1, 0,
      { 19 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_f2f32,
      -1, 0,
      { 42 },
      -1,
   } },

   /* ('unpack_half_2x16_split_y', 'a') => ('f2f32', ('unpack_32_2x16_split_y', 'a')) */
   /* search14_0 -> 19 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_unpack_half_2x16_split_y,
      -1, 0,
      { 19 },
      -1,
   } },

   /* replace14_0_0 -> 19 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      false,
      false,
      false,
      nir_op_unpack_32_2x16_split_y,
      -1, 0,
      { 19 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_f2f32,
      -1, 0,
      { 45 },
      -1,
   } },

   /* ('extract_u16', 'a@32', 0) => ('u2u32', ('unpack_32_2x16_split_x', 'a')) */
   /* search15_0 -> 19 in the cache */
   { .constant = {
      { nir_search_value_constant, 32 },
      nir_type_int, { 0x0 /* 0 */ },
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_extract_u16,
      -1, 0,
      { 19, 47 },
      -1,
   } },

   /* replace15_0_0 -> 19 in the cache */
   /* replace15_0 -> 42 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_u2u32,
      -1, 0,
      { 42 },
      -1,
   } },

   /* ('extract_u16', 'a@32', 1) => ('u2u32', ('unpack_32_2x16_split_y', 'a')) */
   /* search16_0 -> 19 in the cache */
   { .constant = {
      { nir_search_value_constant, 32 },
      nir_type_int, { 0x1 /* 1 */ },
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_extract_u16,
      -1, 0,
      { 19, 50 },
      -1,
   } },

   /* replace16_0_0 -> 19 in the cache */
   /* replace16_0 -> 45 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_u2u32,
      -1, 0,
      { 45 },
      -1,
   } },

   /* ('extract_i16', 'a@32', 0) => ('i2i32', ('unpack_32_2x16_split_x', 'a')) */
   /* search17_0 -> 19 in the cache */
   /* search17_1 -> 47 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_extract_i16,
      -1, 0,
      { 19, 47 },
      -1,
   } },

   /* replace17_0_0 -> 19 in the cache */
   /* replace17_0 -> 42 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_i2i32,
      -1, 0,
      { 42 },
      -1,
   } },

   /* ('extract_i16', 'a@32', 1) => ('i2i32', ('unpack_32_2x16_split_y', 'a')) */
   /* search18_0 -> 19 in the cache */
   /* search18_1 -> 50 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_extract_i16,
      -1, 0,
      { 19, 50 },
      -1,
   } },

   /* replace18_0_0 -> 19 in the cache */
   /* replace18_0 -> 45 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_i2i32,
      -1, 0,
      { 45 },
      -1,
   } },

   /* ('u2f32', ('u2u32', 'a')) => ('u2f32', 'a') */
   { .variable = {
      { nir_search_value_variable, -1 },
      0, /* a */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_u2u32,
      -1, 0,
      { 57 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_u2f32,
      -1, 0,
      { 58 },
      -1,
   } },

   /* replace19_0 -> 57 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_u2f32,
      -1, 0,
      { 57 },
      -1,
   } },

   /* ('i2f32', ('i2i32', 'a')) => ('i2f32', 'a') */
   /* search20_0_0 -> 57 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_i2i32,
      -1, 0,
      { 57 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_i2f32,
      -1, 0,
      { 61 },
      -1,
   } },

   /* replace20_0 -> 57 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_i2f32,
      -1, 0,
      { 57 },
      -1,
   } },

   /* ('ibitfield_extract', 'value', 'offset', 'bits(is_not_const)') => ('bcsel', ('ieq', 0, 'bits'), 0, ('ishr', ('ishl', 'value', ('isub', ('isub', 32, 'bits'), 'offset')), ('isub', 32, 'bits'))) */
   { .variable = {
      { nir_search_value_variable, 32 },
      0, /* value */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .variable = {
      { nir_search_value_variable, 32 },
      1, /* offset */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .variable = {
      { nir_search_value_variable, 32 },
      2, /* bits */
      false,
      nir_type_invalid,
      0,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_ibitfield_extract,
      -1, 0,
      { 64, 65, 66 },
      -1,
   } },

   /* replace21_0_0 -> 47 in the cache */
   { .variable = {
      { nir_search_value_variable, 32 },
      2, /* bits */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, 1 },
      false,
      false,
      false,
      nir_op_ieq,
      0, 1,
      { 47, 68 },
      -1,
   } },
   /* replace21_1 -> 47 in the cache */
   /* replace21_2_0_0 -> 64 in the cache */
   { .constant = {
      { nir_search_value_constant, 32 },
      nir_type_int, { 0x20 /* 32 */ },
   } },
   /* replace21_2_0_1_0_1 -> 68 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_isub,
      -1, 0,
      { 70, 68 },
      -1,
   } },
   /* replace21_2_0_1_1 -> 65 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_isub,
      -1, 0,
      { 71, 65 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 64, 72 },
      -1,
   } },
   /* replace21_2_1_0 -> 70 in the cache */
   /* replace21_2_1_1 -> 68 in the cache */
   /* replace21_2_1 -> 71 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_ishr,
      -1, 0,
      { 73, 71 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_bcsel,
      -1, 1,
      { 69, 47, 74 },
      -1,
   } },

   /* ('ubitfield_extract', 'value', 'offset', 'bits(is_not_const)') => ('iand', ('ushr', 'value', 'offset'), ('bcsel', ('ieq', 'bits', 32), 4294967295, ('isub', ('ishl', 1, 'bits'), 1))) */
   /* search22_0 -> 64 in the cache */
   /* search22_1 -> 65 in the cache */
   /* search22_2 -> 66 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_ubitfield_extract,
      -1, 0,
      { 64, 65, 66 },
      -1,
   } },

   /* replace22_0_0 -> 64 in the cache */
   /* replace22_0_1 -> 65 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_ushr,
      -1, 0,
      { 64, 65 },
      -1,
   } },
   /* replace22_1_0_0 -> 68 in the cache */
   /* replace22_1_0_1 -> 70 in the cache */
   { .expression = {
      { nir_search_value_expression, 1 },
      false,
      false,
      false,
      nir_op_ieq,
      1, 1,
      { 68, 70 },
      -1,
   } },
   { .constant = {
      { nir_search_value_constant, 32 },
      nir_type_int, { 0xffffffff /* 4294967295 */ },
   } },
   /* replace22_1_2_0_0 -> 50 in the cache */
   /* replace22_1_2_0_1 -> 68 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 50, 68 },
      -1,
   } },
   /* replace22_1_2_1 -> 50 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_isub,
      -1, 0,
      { 80, 50 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_bcsel,
      -1, 1,
      { 78, 79, 81 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_iand,
      0, 2,
      { 77, 82 },
      -1,
   } },

   /* ('ubitfield_extract', 'value', 'offset', 0) => 0 */
   /* search23_0 -> 64 in the cache */
   /* search23_1 -> 65 in the cache */
   /* search23_2 -> 47 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_ubitfield_extract,
      -1, 0,
      { 64, 65, 47 },
      -1,
   } },

   /* replace23 -> 47 in the cache */

   /* ('ibitfield_extract', 'value', 'offset', 0) => 0 */
   /* search24_0 -> 64 in the cache */
   /* search24_1 -> 65 in the cache */
   /* search24_2 -> 47 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_ibitfield_extract,
      -1, 0,
      { 64, 65, 47 },
      -1,
   } },

   /* replace24 -> 47 in the cache */

   /* ('ibitfield_extract', 'a', 'b', '#bits') => ('ishr', ('ishl', ('ubitfield_extract', 'a', 'b', 'bits'), ('isub', 32, 'bits')), ('isub', 32, 'bits')) */
   /* search25_0 -> 19 in the cache */
   /* search25_1 -> 1 in the cache */
   { .variable = {
      { nir_search_value_variable, 32 },
      2, /* bits */
      true,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_ibitfield_extract,
      -1, 0,
      { 19, 1, 86 },
      -1,
   } },

   /* replace25_0_0_0 -> 19 in the cache */
   /* replace25_0_0_1 -> 1 in the cache */
   /* replace25_0_0_2 -> 68 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_ubitfield_extract,
      -1, 0,
      { 19, 1, 68 },
      -1,
   } },
   /* replace25_0_1_0 -> 70 in the cache */
   /* replace25_0_1_1 -> 68 in the cache */
   /* replace25_0_1 -> 71 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 88, 71 },
      -1,
   } },
   /* replace25_1_0 -> 70 in the cache */
   /* replace25_1_1 -> 68 in the cache */
   /* replace25_1 -> 71 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      false,
      false,
      false,
      nir_op_ishr,
      -1, 0,
      { 89, 71 },
      -1,
   } },

};


static const nir_search_variable_cond agx_nir_lower_algebraic_late_variable_cond[] = {
   (is_not_const),
};

static const struct transform agx_nir_lower_algebraic_late_transforms[] = {
   { ~0, ~0, ~0 }, /* Sentinel */

   { 2, 5, 0 },
   { 11, 14, 0 },
   { 20, 23, 0 },
   { 29, 32, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 6, 7, 0 },
   { 15, 16, 0 },
   { 24, 25, 0 },
   { 33, 34, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 8, 9, 0 },
   { 17, 18, 0 },
   { 26, 27, 0 },
   { 35, 36, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 37, 40, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 41, 43, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 44, 46, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 48, 49, 0 },
   { 51, 52, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 53, 54, 0 },
   { 55, 56, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 67, 75, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 67, 75, 0 },
   { 85, 47, 0 },
   { 87, 90, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 76, 83, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 76, 83, 0 },
   { 84, 47, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 59, 60, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 62, 63, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

};

static const struct per_op_table agx_nir_lower_algebraic_late_pass_op_table[nir_num_search_ops] = {
   [nir_op_ishl] = {
      .filter = NULL,
      
      .num_filtered_states = 1,
      .table = (const uint16_t []) {
      
         2,
      },
   },
   [nir_op_ishr] = {
      .filter = NULL,
      
      .num_filtered_states = 1,
      .table = (const uint16_t []) {
      
         3,
      },
   },
   [nir_op_ushr] = {
      .filter = NULL,
      
      .num_filtered_states = 1,
      .table = (const uint16_t []) {
      
         4,
      },
   },
   [nir_op_pack_half_2x16_split] = {
      .filter = NULL,
      
      .num_filtered_states = 1,
      .table = (const uint16_t []) {
      
         5,
      },
   },
   [nir_op_unpack_half_2x16_split_x] = {
      .filter = NULL,
      
      .num_filtered_states = 1,
      .table = (const uint16_t []) {
      
         6,
      },
   },
   [nir_op_unpack_half_2x16_split_y] = {
      .filter = NULL,
      
      .num_filtered_states = 1,
      .table = (const uint16_t []) {
      
         7,
      },
   },
   [nir_op_extract_u16] = {
      .filter = (const uint16_t []) {
         0,
         1,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
      },
      
      .num_filtered_states = 2,
      .table = (const uint16_t []) {
      
         0,
         8,
         0,
         8,
      },
   },
   [nir_op_extract_i16] = {
      .filter = (const uint16_t []) {
         0,
         1,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
      },
      
      .num_filtered_states = 2,
      .table = (const uint16_t []) {
      
         0,
         9,
         0,
         9,
      },
   },
   [nir_search_op_u2f] = {
      .filter = (const uint16_t []) {
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         1,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
      },
      
      .num_filtered_states = 2,
      .table = (const uint16_t []) {
      
         0,
         16,
      },
   },
   [nir_search_op_u2u] = {
      .filter = NULL,
      
      .num_filtered_states = 1,
      .table = (const uint16_t []) {
      
         10,
      },
   },
   [nir_search_op_i2f] = {
      .filter = (const uint16_t []) {
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         1,
         0,
         0,
         0,
         0,
         0,
         0,
      },
      
      .num_filtered_states = 2,
      .table = (const uint16_t []) {
      
         0,
         17,
      },
   },
   [nir_search_op_i2i] = {
      .filter = NULL,
      
      .num_filtered_states = 1,
      .table = (const uint16_t []) {
      
         11,
      },
   },
   [nir_op_ibitfield_extract] = {
      .filter = (const uint16_t []) {
         0,
         1,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
      },
      
      .num_filtered_states = 2,
      .table = (const uint16_t []) {
      
         12,
         13,
         12,
         13,
         12,
         13,
         12,
         13,
      },
   },
   [nir_op_ubitfield_extract] = {
      .filter = (const uint16_t []) {
         0,
         1,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
      },
      
      .num_filtered_states = 2,
      .table = (const uint16_t []) {
      
         14,
         15,
         14,
         15,
         14,
         15,
         14,
         15,
      },
   },
};

/* Mapping from state index to offset in transforms (0 being no transforms) */
static const uint16_t agx_nir_lower_algebraic_late_transform_offsets[] = {
   0,
   0,
   1,
   6,
   11,
   16,
   18,
   20,
   22,
   25,
   0,
   0,
   28,
   30,
   34,
   36,
   39,
   41,
};

static const nir_algebraic_table agx_nir_lower_algebraic_late_table = {
   .transforms = agx_nir_lower_algebraic_late_transforms,
   .transform_offsets = agx_nir_lower_algebraic_late_transform_offsets,
   .pass_op_table = agx_nir_lower_algebraic_late_pass_op_table,
   .values = agx_nir_lower_algebraic_late_values,
   .expression_cond = NULL,
   .variable_cond = agx_nir_lower_algebraic_late_variable_cond,
};

bool
agx_nir_lower_algebraic_late(nir_shader *shader)
{
   bool progress = false;
   bool condition_flags[1];
   const nir_shader_compiler_options *options = shader->options;
   const shader_info *info = &shader->info;
   (void) options;
   (void) info;

   /* This is not a great place for this, but it seems to be the best place
    * for it. Check that at most one kind of lowering is requested for
    * bitfield extract and bitfield insert. Otherwise the lowering can fight
    * with each other and optimizations.
    */
   assert((int)options->lower_bitfield_extract +
          (int)options->lower_bitfield_extract_to_shifts <= 1);
   assert((int)options->lower_bitfield_insert +
          (int)options->lower_bitfield_insert_to_shifts +
          (int)options->lower_bitfield_insert_to_bitfield_select <= 1);


   STATIC_ASSERT(91 == ARRAY_SIZE(agx_nir_lower_algebraic_late_values));
   condition_flags[0] = true;

   nir_foreach_function_impl(impl, shader) {
     progress |= nir_algebraic_impl(impl, condition_flags, &agx_nir_lower_algebraic_late_table);
   }

   return progress;
}


#include "nir.h"
#include "nir_builder.h"
#include "nir_search.h"
#include "nir_search_helpers.h"

/* What follows is NIR algebraic transform code for the following 39
 * transforms:
 *    ('iadd', ('iadd(is_used_once)', ('imul(is_used_once)', 'a', 'b'), ('imul(is_used_once)', 'c', 'd')), 'e') => ('imadshl_agx', 'a', 'b', ('imadshl_agx', 'c', 'd', 'e', 0), 0)
 *    ('iadd', ('imul(is_used_once)', 'a', 'b'), 'c') => ('imadshl_agx', 'a', 'b', 'c', 0)
 *    ('isub', ('imul(is_used_once)', 'a', 'b'), 'c') => ('imsubshl_agx', 'a', 'b', 'c', 0)
 *    ('iadd', 'a', ('ishl(is_used_once)', 'b', 1)) => ('imadshl_agx', 'a', 1, 'b', 1)
 *    ('isub', 'a', ('ishl(is_used_once)', 'b', 1)) => ('imsubshl_agx', 'a', 1, 'b', 1)
 *    ('ineg', ('ishl(is_used_once)', 'b', 1)) => ('imsubshl_agx', 0, 1, 'b', 1)
 *    ('imadshl_agx', 'a', 'b', ('ishl(is_used_once)', 'c', 1), 0) => ('imadshl_agx', 'a', 'b', 'c', 1)
 *    ('imsubshl_agx', 'a', 'b', ('ishl(is_used_once)', 'c', 1), 0) => ('imsubshl_agx', 'a', 'b', 'c', 1)
 *    ('imul', 'a', 3) => ('imadshl_agx', 'a', 1, 'a', 1)
 *    ('imul', 'a', -1) => ('imsubshl_agx', 'a', 1, 'a', 1)
 *    ('ineg', ('imul(is_used_once)', 'a', 1)) => ('imsubshl_agx', 'a', 1, 'a', 1)
 *    ('ishl', 'a', 1) => ('imadshl_agx', 0, 1, 'a', 1)
 *    ('iadd', 'a', ('ishl(is_used_once)', 'b', 2)) => ('imadshl_agx', 'a', 1, 'b', 2)
 *    ('isub', 'a', ('ishl(is_used_once)', 'b', 2)) => ('imsubshl_agx', 'a', 1, 'b', 2)
 *    ('ineg', ('ishl(is_used_once)', 'b', 2)) => ('imsubshl_agx', 0, 1, 'b', 2)
 *    ('imadshl_agx', 'a', 'b', ('ishl(is_used_once)', 'c', 2), 0) => ('imadshl_agx', 'a', 'b', 'c', 2)
 *    ('imsubshl_agx', 'a', 'b', ('ishl(is_used_once)', 'c', 2), 0) => ('imsubshl_agx', 'a', 'b', 'c', 2)
 *    ('imul', 'a', 5) => ('imadshl_agx', 'a', 1, 'a', 2)
 *    ('imul', 'a', -3) => ('imsubshl_agx', 'a', 1, 'a', 2)
 *    ('ineg', ('imul(is_used_once)', 'a', 3)) => ('imsubshl_agx', 'a', 1, 'a', 2)
 *    ('ishl', 'a', 2) => ('imadshl_agx', 0, 1, 'a', 2)
 *    ('iadd', 'a', ('ishl(is_used_once)', 'b', 3)) => ('imadshl_agx', 'a', 1, 'b', 3)
 *    ('isub', 'a', ('ishl(is_used_once)', 'b', 3)) => ('imsubshl_agx', 'a', 1, 'b', 3)
 *    ('ineg', ('ishl(is_used_once)', 'b', 3)) => ('imsubshl_agx', 0, 1, 'b', 3)
 *    ('imadshl_agx', 'a', 'b', ('ishl(is_used_once)', 'c', 3), 0) => ('imadshl_agx', 'a', 'b', 'c', 3)
 *    ('imsubshl_agx', 'a', 'b', ('ishl(is_used_once)', 'c', 3), 0) => ('imsubshl_agx', 'a', 'b', 'c', 3)
 *    ('imul', 'a', 9) => ('imadshl_agx', 'a', 1, 'a', 3)
 *    ('imul', 'a', -7) => ('imsubshl_agx', 'a', 1, 'a', 3)
 *    ('ineg', ('imul(is_used_once)', 'a', 7)) => ('imsubshl_agx', 'a', 1, 'a', 3)
 *    ('ishl', 'a', 3) => ('imadshl_agx', 0, 1, 'a', 3)
 *    ('iadd', 'a', ('ishl(is_used_once)', 'b', 4)) => ('imadshl_agx', 'a', 1, 'b', 4)
 *    ('isub', 'a', ('ishl(is_used_once)', 'b', 4)) => ('imsubshl_agx', 'a', 1, 'b', 4)
 *    ('ineg', ('ishl(is_used_once)', 'b', 4)) => ('imsubshl_agx', 0, 1, 'b', 4)
 *    ('imadshl_agx', 'a', 'b', ('ishl(is_used_once)', 'c', 4), 0) => ('imadshl_agx', 'a', 'b', 'c', 4)
 *    ('imsubshl_agx', 'a', 'b', ('ishl(is_used_once)', 'c', 4), 0) => ('imsubshl_agx', 'a', 'b', 'c', 4)
 *    ('imul', 'a', 17) => ('imadshl_agx', 'a', 1, 'a', 4)
 *    ('imul', 'a', -15) => ('imsubshl_agx', 'a', 1, 'a', 4)
 *    ('ineg', ('imul(is_used_once)', 'a', 15)) => ('imsubshl_agx', 'a', 1, 'a', 4)
 *    ('ishl', 'a', 4) => ('imadshl_agx', 0, 1, 'a', 4)
 */


static const nir_search_value_union agx_nir_fuse_algebraic_late_values[] = {
   /* ('iadd', ('iadd(is_used_once)', ('imul(is_used_once)', 'a', 'b'), ('imul(is_used_once)', 'c', 'd')), 'e') => ('imadshl_agx', 'a', 'b', ('imadshl_agx', 'c', 'd', 'e', 0), 0) */
   { .variable = {
      { nir_search_value_variable, -5 },
      0, /* a */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .variable = {
      { nir_search_value_variable, -5 },
      1, /* b */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, -5 },
      false,
      false,
      false,
      nir_op_imul,
      2, 1,
      { 0, 1 },
      0,
   } },
   { .variable = {
      { nir_search_value_variable, -5 },
      2, /* c */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .variable = {
      { nir_search_value_variable, -5 },
      3, /* d */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, -5 },
      false,
      false,
      false,
      nir_op_imul,
      3, 1,
      { 3, 4 },
      0,
   } },
   { .expression = {
      { nir_search_value_expression, -5 },
      false,
      false,
      false,
      nir_op_iadd,
      1, 3,
      { 2, 5 },
      0,
   } },
   { .variable = {
      { nir_search_value_variable, -5 },
      4, /* e */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, -5 },
      false,
      false,
      false,
      nir_op_iadd,
      0, 4,
      { 6, 7 },
      -1,
   } },

   /* replace26_0 -> 0 in the cache */
   /* replace26_1 -> 1 in the cache */
   /* replace26_2_0 -> 3 in the cache */
   /* replace26_2_1 -> 4 in the cache */
   /* replace26_2_2 -> 7 in the cache */
   { .constant = {
      { nir_search_value_constant, -5 },
      nir_type_int, { 0x0 /* 0 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -5 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 3, 4, 7, 9 },
      -1,
   } },
   /* replace26_3 -> 9 in the cache */
   { .expression = {
      { nir_search_value_expression, -5 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 0, 1, 10, 9 },
      -1,
   } },

   /* ('iadd', ('imul(is_used_once)', 'a', 'b'), 'c') => ('imadshl_agx', 'a', 'b', 'c', 0) */
   { .variable = {
      { nir_search_value_variable, -3 },
      0, /* a */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .variable = {
      { nir_search_value_variable, -3 },
      1, /* b */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imul,
      1, 1,
      { 12, 13 },
      0,
   } },
   { .variable = {
      { nir_search_value_variable, -3 },
      2, /* c */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_iadd,
      0, 2,
      { 14, 15 },
      -1,
   } },

   /* replace27_0 -> 12 in the cache */
   /* replace27_1 -> 13 in the cache */
   /* replace27_2 -> 15 in the cache */
   { .constant = {
      { nir_search_value_constant, -3 },
      nir_type_int, { 0x0 /* 0 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 12, 13, 15, 17 },
      -1,
   } },

   /* ('isub', ('imul(is_used_once)', 'a', 'b'), 'c') => ('imsubshl_agx', 'a', 'b', 'c', 0) */
   /* search28_0_0 -> 12 in the cache */
   /* search28_0_1 -> 13 in the cache */
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imul,
      0, 1,
      { 12, 13 },
      0,
   } },
   /* search28_1 -> 15 in the cache */
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_isub,
      -1, 1,
      { 19, 15 },
      -1,
   } },

   /* replace28_0 -> 12 in the cache */
   /* replace28_1 -> 13 in the cache */
   /* replace28_2 -> 15 in the cache */
   /* replace28_3 -> 17 in the cache */
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 12, 13, 15, 17 },
      -1,
   } },

   /* ('iadd', 'a', ('ishl(is_used_once)', 'b', 1)) => ('imadshl_agx', 'a', 1, 'b', 1) */
   { .variable = {
      { nir_search_value_variable, -2 },
      0, /* a */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .variable = {
      { nir_search_value_variable, -2 },
      1, /* b */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .constant = {
      { nir_search_value_constant, 32 },
      nir_type_int, { 0x1 /* 1 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 23, 24 },
      0,
   } },
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_iadd,
      0, 1,
      { 22, 25 },
      -1,
   } },

   /* replace29_0 -> 22 in the cache */
   { .constant = {
      { nir_search_value_constant, -2 },
      nir_type_int, { 0x1 /* 1 */ },
   } },
   /* replace29_2 -> 23 in the cache */
   /* replace29_3 -> 27 in the cache */
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 22, 27, 23, 27 },
      -1,
   } },

   /* ('isub', 'a', ('ishl(is_used_once)', 'b', 1)) => ('imsubshl_agx', 'a', 1, 'b', 1) */
   /* search30_0 -> 22 in the cache */
   /* search30_1_0 -> 23 in the cache */
   /* search30_1_1 -> 24 in the cache */
   /* search30_1 -> 25 in the cache */
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_isub,
      -1, 0,
      { 22, 25 },
      -1,
   } },

   /* replace30_0 -> 22 in the cache */
   /* replace30_1 -> 27 in the cache */
   /* replace30_2 -> 23 in the cache */
   /* replace30_3 -> 27 in the cache */
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 22, 27, 23, 27 },
      -1,
   } },

   /* ('ineg', ('ishl(is_used_once)', 'b', 1)) => ('imsubshl_agx', 0, 1, 'b', 1) */
   { .variable = {
      { nir_search_value_variable, -1 },
      0, /* b */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   /* search31_0_1 -> 24 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 31, 24 },
      0,
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_ineg,
      -1, 0,
      { 32 },
      -1,
   } },

   { .constant = {
      { nir_search_value_constant, -1 },
      nir_type_int, { 0x0 /* 0 */ },
   } },
   { .constant = {
      { nir_search_value_constant, -1 },
      nir_type_int, { 0x1 /* 1 */ },
   } },
   /* replace31_2 -> 31 in the cache */
   /* replace31_3 -> 35 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 34, 35, 31, 35 },
      -1,
   } },

   /* ('imadshl_agx', 'a', 'b', ('ishl(is_used_once)', 'c', 1), 0) => ('imadshl_agx', 'a', 'b', 'c', 1) */
   /* search32_0 -> 12 in the cache */
   /* search32_1 -> 13 in the cache */
   /* search32_2_0 -> 15 in the cache */
   /* search32_2_1 -> 24 in the cache */
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 15, 24 },
      0,
   } },
   /* search32_3 -> 17 in the cache */
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 12, 13, 37, 17 },
      -1,
   } },

   /* replace32_0 -> 12 in the cache */
   /* replace32_1 -> 13 in the cache */
   /* replace32_2 -> 15 in the cache */
   { .constant = {
      { nir_search_value_constant, -3 },
      nir_type_int, { 0x1 /* 1 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 12, 13, 15, 39 },
      -1,
   } },

   /* ('imsubshl_agx', 'a', 'b', ('ishl(is_used_once)', 'c', 1), 0) => ('imsubshl_agx', 'a', 'b', 'c', 1) */
   /* search33_0 -> 12 in the cache */
   /* search33_1 -> 13 in the cache */
   /* search33_2_0 -> 15 in the cache */
   /* search33_2_1 -> 24 in the cache */
   /* search33_2 -> 37 in the cache */
   /* search33_3 -> 17 in the cache */
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 12, 13, 37, 17 },
      -1,
   } },

   /* replace33_0 -> 12 in the cache */
   /* replace33_1 -> 13 in the cache */
   /* replace33_2 -> 15 in the cache */
   /* replace33_3 -> 39 in the cache */
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 12, 13, 15, 39 },
      -1,
   } },

   /* ('imul', 'a', 3) => ('imadshl_agx', 'a', 1, 'a', 1) */
   { .variable = {
      { nir_search_value_variable, -1 },
      0, /* a */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .constant = {
      { nir_search_value_constant, -1 },
      nir_type_int, { 0x3 /* 3 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imul,
      0, 1,
      { 43, 44 },
      -1,
   } },

   /* replace34_0 -> 43 in the cache */
   /* replace34_1 -> 35 in the cache */
   /* replace34_2 -> 43 in the cache */
   /* replace34_3 -> 35 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 43, 35, 43, 35 },
      -1,
   } },

   /* ('imul', 'a', -1) => ('imsubshl_agx', 'a', 1, 'a', 1) */
   /* search35_0 -> 43 in the cache */
   { .constant = {
      { nir_search_value_constant, -1 },
      nir_type_int, { -0x1 /* -1 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imul,
      0, 1,
      { 43, 47 },
      -1,
   } },

   /* replace35_0 -> 43 in the cache */
   /* replace35_1 -> 35 in the cache */
   /* replace35_2 -> 43 in the cache */
   /* replace35_3 -> 35 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 43, 35, 43, 35 },
      -1,
   } },

   /* ('ineg', ('imul(is_used_once)', 'a', 1)) => ('imsubshl_agx', 'a', 1, 'a', 1) */
   /* search36_0_0 -> 43 in the cache */
   /* search36_0_1 -> 35 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imul,
      0, 1,
      { 43, 35 },
      0,
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_ineg,
      -1, 1,
      { 50 },
      -1,
   } },

   /* replace36_0 -> 43 in the cache */
   /* replace36_1 -> 35 in the cache */
   /* replace36_2 -> 43 in the cache */
   /* replace36_3 -> 35 in the cache */
   /* replace36 -> 49 in the cache */

   /* ('ishl', 'a', 1) => ('imadshl_agx', 0, 1, 'a', 1) */
   /* search37_0 -> 43 in the cache */
   /* search37_1 -> 24 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 43, 24 },
      -1,
   } },

   /* replace37_0 -> 34 in the cache */
   /* replace37_1 -> 35 in the cache */
   /* replace37_2 -> 43 in the cache */
   /* replace37_3 -> 35 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 34, 35, 43, 35 },
      -1,
   } },

   /* ('iadd', 'a', ('ishl(is_used_once)', 'b', 2)) => ('imadshl_agx', 'a', 1, 'b', 2) */
   /* search38_0 -> 22 in the cache */
   /* search38_1_0 -> 23 in the cache */
   { .constant = {
      { nir_search_value_constant, 32 },
      nir_type_int, { 0x2 /* 2 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 23, 54 },
      0,
   } },
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_iadd,
      0, 1,
      { 22, 55 },
      -1,
   } },

   /* replace38_0 -> 22 in the cache */
   /* replace38_1 -> 27 in the cache */
   /* replace38_2 -> 23 in the cache */
   { .constant = {
      { nir_search_value_constant, -2 },
      nir_type_int, { 0x2 /* 2 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 22, 27, 23, 57 },
      -1,
   } },

   /* ('isub', 'a', ('ishl(is_used_once)', 'b', 2)) => ('imsubshl_agx', 'a', 1, 'b', 2) */
   /* search39_0 -> 22 in the cache */
   /* search39_1_0 -> 23 in the cache */
   /* search39_1_1 -> 54 in the cache */
   /* search39_1 -> 55 in the cache */
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_isub,
      -1, 0,
      { 22, 55 },
      -1,
   } },

   /* replace39_0 -> 22 in the cache */
   /* replace39_1 -> 27 in the cache */
   /* replace39_2 -> 23 in the cache */
   /* replace39_3 -> 57 in the cache */
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 22, 27, 23, 57 },
      -1,
   } },

   /* ('ineg', ('ishl(is_used_once)', 'b', 2)) => ('imsubshl_agx', 0, 1, 'b', 2) */
   /* search40_0_0 -> 31 in the cache */
   /* search40_0_1 -> 54 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 31, 54 },
      0,
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_ineg,
      -1, 0,
      { 61 },
      -1,
   } },

   /* replace40_0 -> 34 in the cache */
   /* replace40_1 -> 35 in the cache */
   /* replace40_2 -> 31 in the cache */
   { .constant = {
      { nir_search_value_constant, -1 },
      nir_type_int, { 0x2 /* 2 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 34, 35, 31, 63 },
      -1,
   } },

   /* ('imadshl_agx', 'a', 'b', ('ishl(is_used_once)', 'c', 2), 0) => ('imadshl_agx', 'a', 'b', 'c', 2) */
   /* search41_0 -> 12 in the cache */
   /* search41_1 -> 13 in the cache */
   /* search41_2_0 -> 15 in the cache */
   /* search41_2_1 -> 54 in the cache */
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 15, 54 },
      0,
   } },
   /* search41_3 -> 17 in the cache */
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 12, 13, 65, 17 },
      -1,
   } },

   /* replace41_0 -> 12 in the cache */
   /* replace41_1 -> 13 in the cache */
   /* replace41_2 -> 15 in the cache */
   { .constant = {
      { nir_search_value_constant, -3 },
      nir_type_int, { 0x2 /* 2 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 12, 13, 15, 67 },
      -1,
   } },

   /* ('imsubshl_agx', 'a', 'b', ('ishl(is_used_once)', 'c', 2), 0) => ('imsubshl_agx', 'a', 'b', 'c', 2) */
   /* search42_0 -> 12 in the cache */
   /* search42_1 -> 13 in the cache */
   /* search42_2_0 -> 15 in the cache */
   /* search42_2_1 -> 54 in the cache */
   /* search42_2 -> 65 in the cache */
   /* search42_3 -> 17 in the cache */
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 12, 13, 65, 17 },
      -1,
   } },

   /* replace42_0 -> 12 in the cache */
   /* replace42_1 -> 13 in the cache */
   /* replace42_2 -> 15 in the cache */
   /* replace42_3 -> 67 in the cache */
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 12, 13, 15, 67 },
      -1,
   } },

   /* ('imul', 'a', 5) => ('imadshl_agx', 'a', 1, 'a', 2) */
   /* search43_0 -> 43 in the cache */
   { .constant = {
      { nir_search_value_constant, -1 },
      nir_type_int, { 0x5 /* 5 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imul,
      0, 1,
      { 43, 71 },
      -1,
   } },

   /* replace43_0 -> 43 in the cache */
   /* replace43_1 -> 35 in the cache */
   /* replace43_2 -> 43 in the cache */
   /* replace43_3 -> 63 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 43, 35, 43, 63 },
      -1,
   } },

   /* ('imul', 'a', -3) => ('imsubshl_agx', 'a', 1, 'a', 2) */
   /* search44_0 -> 43 in the cache */
   { .constant = {
      { nir_search_value_constant, -1 },
      nir_type_int, { -0x3 /* -3 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imul,
      0, 1,
      { 43, 74 },
      -1,
   } },

   /* replace44_0 -> 43 in the cache */
   /* replace44_1 -> 35 in the cache */
   /* replace44_2 -> 43 in the cache */
   /* replace44_3 -> 63 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 43, 35, 43, 63 },
      -1,
   } },

   /* ('ineg', ('imul(is_used_once)', 'a', 3)) => ('imsubshl_agx', 'a', 1, 'a', 2) */
   /* search45_0_0 -> 43 in the cache */
   /* search45_0_1 -> 44 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imul,
      0, 1,
      { 43, 44 },
      0,
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_ineg,
      -1, 1,
      { 77 },
      -1,
   } },

   /* replace45_0 -> 43 in the cache */
   /* replace45_1 -> 35 in the cache */
   /* replace45_2 -> 43 in the cache */
   /* replace45_3 -> 63 in the cache */
   /* replace45 -> 76 in the cache */

   /* ('ishl', 'a', 2) => ('imadshl_agx', 0, 1, 'a', 2) */
   /* search46_0 -> 43 in the cache */
   /* search46_1 -> 54 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 43, 54 },
      -1,
   } },

   /* replace46_0 -> 34 in the cache */
   /* replace46_1 -> 35 in the cache */
   /* replace46_2 -> 43 in the cache */
   /* replace46_3 -> 63 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 34, 35, 43, 63 },
      -1,
   } },

   /* ('iadd', 'a', ('ishl(is_used_once)', 'b', 3)) => ('imadshl_agx', 'a', 1, 'b', 3) */
   /* search47_0 -> 22 in the cache */
   /* search47_1_0 -> 23 in the cache */
   { .constant = {
      { nir_search_value_constant, 32 },
      nir_type_int, { 0x3 /* 3 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 23, 81 },
      0,
   } },
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_iadd,
      0, 1,
      { 22, 82 },
      -1,
   } },

   /* replace47_0 -> 22 in the cache */
   /* replace47_1 -> 27 in the cache */
   /* replace47_2 -> 23 in the cache */
   { .constant = {
      { nir_search_value_constant, -2 },
      nir_type_int, { 0x3 /* 3 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 22, 27, 23, 84 },
      -1,
   } },

   /* ('isub', 'a', ('ishl(is_used_once)', 'b', 3)) => ('imsubshl_agx', 'a', 1, 'b', 3) */
   /* search48_0 -> 22 in the cache */
   /* search48_1_0 -> 23 in the cache */
   /* search48_1_1 -> 81 in the cache */
   /* search48_1 -> 82 in the cache */
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_isub,
      -1, 0,
      { 22, 82 },
      -1,
   } },

   /* replace48_0 -> 22 in the cache */
   /* replace48_1 -> 27 in the cache */
   /* replace48_2 -> 23 in the cache */
   /* replace48_3 -> 84 in the cache */
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 22, 27, 23, 84 },
      -1,
   } },

   /* ('ineg', ('ishl(is_used_once)', 'b', 3)) => ('imsubshl_agx', 0, 1, 'b', 3) */
   /* search49_0_0 -> 31 in the cache */
   /* search49_0_1 -> 81 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 31, 81 },
      0,
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_ineg,
      -1, 0,
      { 88 },
      -1,
   } },

   /* replace49_0 -> 34 in the cache */
   /* replace49_1 -> 35 in the cache */
   /* replace49_2 -> 31 in the cache */
   /* replace49_3 -> 44 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 34, 35, 31, 44 },
      -1,
   } },

   /* ('imadshl_agx', 'a', 'b', ('ishl(is_used_once)', 'c', 3), 0) => ('imadshl_agx', 'a', 'b', 'c', 3) */
   /* search50_0 -> 12 in the cache */
   /* search50_1 -> 13 in the cache */
   /* search50_2_0 -> 15 in the cache */
   /* search50_2_1 -> 81 in the cache */
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 15, 81 },
      0,
   } },
   /* search50_3 -> 17 in the cache */
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 12, 13, 91, 17 },
      -1,
   } },

   /* replace50_0 -> 12 in the cache */
   /* replace50_1 -> 13 in the cache */
   /* replace50_2 -> 15 in the cache */
   { .constant = {
      { nir_search_value_constant, -3 },
      nir_type_int, { 0x3 /* 3 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 12, 13, 15, 93 },
      -1,
   } },

   /* ('imsubshl_agx', 'a', 'b', ('ishl(is_used_once)', 'c', 3), 0) => ('imsubshl_agx', 'a', 'b', 'c', 3) */
   /* search51_0 -> 12 in the cache */
   /* search51_1 -> 13 in the cache */
   /* search51_2_0 -> 15 in the cache */
   /* search51_2_1 -> 81 in the cache */
   /* search51_2 -> 91 in the cache */
   /* search51_3 -> 17 in the cache */
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 12, 13, 91, 17 },
      -1,
   } },

   /* replace51_0 -> 12 in the cache */
   /* replace51_1 -> 13 in the cache */
   /* replace51_2 -> 15 in the cache */
   /* replace51_3 -> 93 in the cache */
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 12, 13, 15, 93 },
      -1,
   } },

   /* ('imul', 'a', 9) => ('imadshl_agx', 'a', 1, 'a', 3) */
   /* search52_0 -> 43 in the cache */
   { .constant = {
      { nir_search_value_constant, -1 },
      nir_type_int, { 0x9 /* 9 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imul,
      0, 1,
      { 43, 97 },
      -1,
   } },

   /* replace52_0 -> 43 in the cache */
   /* replace52_1 -> 35 in the cache */
   /* replace52_2 -> 43 in the cache */
   /* replace52_3 -> 44 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 43, 35, 43, 44 },
      -1,
   } },

   /* ('imul', 'a', -7) => ('imsubshl_agx', 'a', 1, 'a', 3) */
   /* search53_0 -> 43 in the cache */
   { .constant = {
      { nir_search_value_constant, -1 },
      nir_type_int, { -0x7 /* -7 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imul,
      0, 1,
      { 43, 100 },
      -1,
   } },

   /* replace53_0 -> 43 in the cache */
   /* replace53_1 -> 35 in the cache */
   /* replace53_2 -> 43 in the cache */
   /* replace53_3 -> 44 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 43, 35, 43, 44 },
      -1,
   } },

   /* ('ineg', ('imul(is_used_once)', 'a', 7)) => ('imsubshl_agx', 'a', 1, 'a', 3) */
   /* search54_0_0 -> 43 in the cache */
   { .constant = {
      { nir_search_value_constant, -1 },
      nir_type_int, { 0x7 /* 7 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imul,
      0, 1,
      { 43, 103 },
      0,
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_ineg,
      -1, 1,
      { 104 },
      -1,
   } },

   /* replace54_0 -> 43 in the cache */
   /* replace54_1 -> 35 in the cache */
   /* replace54_2 -> 43 in the cache */
   /* replace54_3 -> 44 in the cache */
   /* replace54 -> 102 in the cache */

   /* ('ishl', 'a', 3) => ('imadshl_agx', 0, 1, 'a', 3) */
   /* search55_0 -> 43 in the cache */
   /* search55_1 -> 81 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 43, 81 },
      -1,
   } },

   /* replace55_0 -> 34 in the cache */
   /* replace55_1 -> 35 in the cache */
   /* replace55_2 -> 43 in the cache */
   /* replace55_3 -> 44 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 34, 35, 43, 44 },
      -1,
   } },

   /* ('iadd', 'a', ('ishl(is_used_once)', 'b', 4)) => ('imadshl_agx', 'a', 1, 'b', 4) */
   /* search56_0 -> 22 in the cache */
   /* search56_1_0 -> 23 in the cache */
   { .constant = {
      { nir_search_value_constant, 32 },
      nir_type_int, { 0x4 /* 4 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 23, 108 },
      0,
   } },
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_iadd,
      0, 1,
      { 22, 109 },
      -1,
   } },

   /* replace56_0 -> 22 in the cache */
   /* replace56_1 -> 27 in the cache */
   /* replace56_2 -> 23 in the cache */
   { .constant = {
      { nir_search_value_constant, -2 },
      nir_type_int, { 0x4 /* 4 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 22, 27, 23, 111 },
      -1,
   } },

   /* ('isub', 'a', ('ishl(is_used_once)', 'b', 4)) => ('imsubshl_agx', 'a', 1, 'b', 4) */
   /* search57_0 -> 22 in the cache */
   /* search57_1_0 -> 23 in the cache */
   /* search57_1_1 -> 108 in the cache */
   /* search57_1 -> 109 in the cache */
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_isub,
      -1, 0,
      { 22, 109 },
      -1,
   } },

   /* replace57_0 -> 22 in the cache */
   /* replace57_1 -> 27 in the cache */
   /* replace57_2 -> 23 in the cache */
   /* replace57_3 -> 111 in the cache */
   { .expression = {
      { nir_search_value_expression, -2 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 22, 27, 23, 111 },
      -1,
   } },

   /* ('ineg', ('ishl(is_used_once)', 'b', 4)) => ('imsubshl_agx', 0, 1, 'b', 4) */
   /* search58_0_0 -> 31 in the cache */
   /* search58_0_1 -> 108 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 31, 108 },
      0,
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_ineg,
      -1, 0,
      { 115 },
      -1,
   } },

   /* replace58_0 -> 34 in the cache */
   /* replace58_1 -> 35 in the cache */
   /* replace58_2 -> 31 in the cache */
   { .constant = {
      { nir_search_value_constant, -1 },
      nir_type_int, { 0x4 /* 4 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 34, 35, 31, 117 },
      -1,
   } },

   /* ('imadshl_agx', 'a', 'b', ('ishl(is_used_once)', 'c', 4), 0) => ('imadshl_agx', 'a', 'b', 'c', 4) */
   /* search59_0 -> 12 in the cache */
   /* search59_1 -> 13 in the cache */
   /* search59_2_0 -> 15 in the cache */
   /* search59_2_1 -> 108 in the cache */
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 15, 108 },
      0,
   } },
   /* search59_3 -> 17 in the cache */
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 12, 13, 119, 17 },
      -1,
   } },

   /* replace59_0 -> 12 in the cache */
   /* replace59_1 -> 13 in the cache */
   /* replace59_2 -> 15 in the cache */
   { .constant = {
      { nir_search_value_constant, -3 },
      nir_type_int, { 0x4 /* 4 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 12, 13, 15, 121 },
      -1,
   } },

   /* ('imsubshl_agx', 'a', 'b', ('ishl(is_used_once)', 'c', 4), 0) => ('imsubshl_agx', 'a', 'b', 'c', 4) */
   /* search60_0 -> 12 in the cache */
   /* search60_1 -> 13 in the cache */
   /* search60_2_0 -> 15 in the cache */
   /* search60_2_1 -> 108 in the cache */
   /* search60_2 -> 119 in the cache */
   /* search60_3 -> 17 in the cache */
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 12, 13, 119, 17 },
      -1,
   } },

   /* replace60_0 -> 12 in the cache */
   /* replace60_1 -> 13 in the cache */
   /* replace60_2 -> 15 in the cache */
   /* replace60_3 -> 121 in the cache */
   { .expression = {
      { nir_search_value_expression, -3 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 12, 13, 15, 121 },
      -1,
   } },

   /* ('imul', 'a', 17) => ('imadshl_agx', 'a', 1, 'a', 4) */
   /* search61_0 -> 43 in the cache */
   { .constant = {
      { nir_search_value_constant, -1 },
      nir_type_int, { 0x11 /* 17 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imul,
      0, 1,
      { 43, 125 },
      -1,
   } },

   /* replace61_0 -> 43 in the cache */
   /* replace61_1 -> 35 in the cache */
   /* replace61_2 -> 43 in the cache */
   /* replace61_3 -> 117 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 43, 35, 43, 117 },
      -1,
   } },

   /* ('imul', 'a', -15) => ('imsubshl_agx', 'a', 1, 'a', 4) */
   /* search62_0 -> 43 in the cache */
   { .constant = {
      { nir_search_value_constant, -1 },
      nir_type_int, { -0xf /* -15 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imul,
      0, 1,
      { 43, 128 },
      -1,
   } },

   /* replace62_0 -> 43 in the cache */
   /* replace62_1 -> 35 in the cache */
   /* replace62_2 -> 43 in the cache */
   /* replace62_3 -> 117 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imsubshl_agx,
      -1, 0,
      { 43, 35, 43, 117 },
      -1,
   } },

   /* ('ineg', ('imul(is_used_once)', 'a', 15)) => ('imsubshl_agx', 'a', 1, 'a', 4) */
   /* search63_0_0 -> 43 in the cache */
   { .constant = {
      { nir_search_value_constant, -1 },
      nir_type_int, { 0xf /* 15 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imul,
      0, 1,
      { 43, 131 },
      0,
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_ineg,
      -1, 1,
      { 132 },
      -1,
   } },

   /* replace63_0 -> 43 in the cache */
   /* replace63_1 -> 35 in the cache */
   /* replace63_2 -> 43 in the cache */
   /* replace63_3 -> 117 in the cache */
   /* replace63 -> 130 in the cache */

   /* ('ishl', 'a', 4) => ('imadshl_agx', 0, 1, 'a', 4) */
   /* search64_0 -> 43 in the cache */
   /* search64_1 -> 108 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_ishl,
      -1, 0,
      { 43, 108 },
      -1,
   } },

   /* replace64_0 -> 34 in the cache */
   /* replace64_1 -> 35 in the cache */
   /* replace64_2 -> 43 in the cache */
   /* replace64_3 -> 117 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      false,
      false,
      false,
      nir_op_imadshl_agx,
      -1, 0,
      { 34, 35, 43, 117 },
      -1,
   } },

};

static const nir_search_expression_cond agx_nir_fuse_algebraic_late_expression_cond[] = {
   (is_used_once),
};


static const struct transform agx_nir_fuse_algebraic_late_transforms[] = {
   { ~0, ~0, ~0 }, /* Sentinel */

   { 45, 46, 0 },
   { 48, 49, 0 },
   { 72, 73, 0 },
   { 75, 76, 0 },
   { 98, 99, 0 },
   { 101, 102, 0 },
   { 126, 127, 0 },
   { 129, 130, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 52, 53, 0 },
   { 79, 80, 0 },
   { 106, 107, 0 },
   { 134, 135, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 16, 18, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 26, 28, 0 },
   { 56, 58, 0 },
   { 83, 85, 0 },
   { 110, 112, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 16, 18, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 16, 18, 0 },
   { 26, 28, 0 },
   { 56, 58, 0 },
   { 83, 85, 0 },
   { 110, 112, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 29, 30, 0 },
   { 59, 60, 0 },
   { 86, 87, 0 },
   { 113, 114, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 20, 21, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 20, 21, 0 },
   { 29, 30, 0 },
   { 59, 60, 0 },
   { 86, 87, 0 },
   { 113, 114, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 51, 49, 0 },
   { 78, 76, 0 },
   { 105, 102, 0 },
   { 133, 130, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 33, 36, 0 },
   { 62, 64, 0 },
   { 89, 90, 0 },
   { 116, 118, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 38, 40, 0 },
   { 66, 68, 0 },
   { 92, 94, 0 },
   { 120, 122, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 41, 42, 0 },
   { 69, 70, 0 },
   { 95, 96, 0 },
   { 123, 124, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 8, 11, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 8, 11, 0 },
   { 16, 18, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 8, 11, 0 },
   { 26, 28, 0 },
   { 56, 58, 0 },
   { 83, 85, 0 },
   { 110, 112, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

};

static const struct per_op_table agx_nir_fuse_algebraic_late_pass_op_table[nir_num_search_ops] = {
   [nir_op_iadd] = {
      .filter = (const uint16_t []) {
         0,
         0,
         1,
         1,
         2,
         0,
         0,
         3,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
      },
      
      .num_filtered_states = 4,
      .table = (const uint16_t []) {
      
         0,
         5,
         6,
         16,
         5,
         7,
         8,
         17,
         6,
         8,
         6,
         18,
         16,
         17,
         18,
         16,
      },
   },
   [nir_op_imul] = {
      .filter = (const uint16_t []) {
         0,
         1,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
      },
      
      .num_filtered_states = 2,
      .table = (const uint16_t []) {
      
         2,
         3,
         3,
         3,
      },
   },
   [nir_op_isub] = {
      .filter = (const uint16_t []) {
         0,
         0,
         1,
         1,
         2,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
      },
      
      .num_filtered_states = 3,
      .table = (const uint16_t []) {
      
         0,
         0,
         9,
         10,
         10,
         11,
         0,
         0,
         9,
      },
   },
   [nir_op_ishl] = {
      .filter = (const uint16_t []) {
         0,
         1,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
      },
      
      .num_filtered_states = 2,
      .table = (const uint16_t []) {
      
         0,
         4,
         0,
         4,
      },
   },
   [nir_op_ineg] = {
      .filter = (const uint16_t []) {
         0,
         0,
         0,
         1,
         2,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
      },
      
      .num_filtered_states = 3,
      .table = (const uint16_t []) {
      
         0,
         12,
         13,
      },
   },
   [nir_op_imadshl_agx] = {
      .filter = (const uint16_t []) {
         0,
         1,
         0,
         0,
         2,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
      },
      
      .num_filtered_states = 3,
      .table = (const uint16_t []) {
      
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         14,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         14,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         14,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         14,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         14,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         14,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         14,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         14,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         14,
         0,
      },
   },
   [nir_op_imsubshl_agx] = {
      .filter = (const uint16_t []) {
         0,
         1,
         0,
         0,
         2,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
      },
      
      .num_filtered_states = 3,
      .table = (const uint16_t []) {
      
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         15,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         15,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         15,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         15,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         15,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         15,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         15,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         15,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         15,
         0,
      },
   },
};

/* Mapping from state index to offset in transforms (0 being no transforms) */
static const uint16_t agx_nir_fuse_algebraic_late_transform_offsets[] = {
   0,
   0,
   0,
   1,
   10,
   15,
   17,
   22,
   24,
   30,
   35,
   37,
   43,
   48,
   53,
   58,
   63,
   65,
   68,
};

static const nir_algebraic_table agx_nir_fuse_algebraic_late_table = {
   .transforms = agx_nir_fuse_algebraic_late_transforms,
   .transform_offsets = agx_nir_fuse_algebraic_late_transform_offsets,
   .pass_op_table = agx_nir_fuse_algebraic_late_pass_op_table,
   .values = agx_nir_fuse_algebraic_late_values,
   .expression_cond = agx_nir_fuse_algebraic_late_expression_cond,
   .variable_cond = NULL,
};

bool
agx_nir_fuse_algebraic_late(nir_shader *shader)
{
   bool progress = false;
   bool condition_flags[1];
   const nir_shader_compiler_options *options = shader->options;
   const shader_info *info = &shader->info;
   (void) options;
   (void) info;

   /* This is not a great place for this, but it seems to be the best place
    * for it. Check that at most one kind of lowering is requested for
    * bitfield extract and bitfield insert. Otherwise the lowering can fight
    * with each other and optimizations.
    */
   assert((int)options->lower_bitfield_extract +
          (int)options->lower_bitfield_extract_to_shifts <= 1);
   assert((int)options->lower_bitfield_insert +
          (int)options->lower_bitfield_insert_to_shifts +
          (int)options->lower_bitfield_insert_to_bitfield_select <= 1);


   STATIC_ASSERT(136 == ARRAY_SIZE(agx_nir_fuse_algebraic_late_values));
   condition_flags[0] = true;

   nir_foreach_function_impl(impl, shader) {
     progress |= nir_algebraic_impl(impl, condition_flags, &agx_nir_fuse_algebraic_late_table);
   }

   return progress;
}


#include "nir.h"
#include "nir_builder.h"
#include "nir_search.h"
#include "nir_search_helpers.h"

/* What follows is NIR algebraic transform code for the following 1
 * transforms:
 *    ('ixor', ('bcsel', 'a', '#b', '#c'), '#d') => ('bcsel', 'a', ('ixor', 'b', 'd'), ('ixor', 'c', 'd'))
 */


static const nir_search_value_union agx_nir_opt_ixor_bcsel_values[] = {
   /* ('ixor', ('bcsel', 'a', '#b', '#c'), '#d') => ('bcsel', 'a', ('ixor', 'b', 'd'), ('ixor', 'c', 'd')) */
   { .variable = {
      { nir_search_value_variable, 1 },
      0, /* a */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .variable = {
      { nir_search_value_variable, -4 },
      1, /* b */
      true,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .variable = {
      { nir_search_value_variable, -4 },
      2, /* c */
      true,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, -4 },
      false,
      false,
      false,
      nir_op_bcsel,
      -1, 0,
      { 0, 1, 2 },
      -1,
   } },
   { .variable = {
      { nir_search_value_variable, -4 },
      3, /* d */
      true,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, -4 },
      false,
      false,
      false,
      nir_op_ixor,
      0, 1,
      { 3, 4 },
      -1,
   } },

   /* replace65_0 -> 0 in the cache */
   { .variable = {
      { nir_search_value_variable, -4 },
      1, /* b */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .variable = {
      { nir_search_value_variable, -4 },
      3, /* d */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, -4 },
      false,
      false,
      false,
      nir_op_ixor,
      0, 1,
      { 6, 7 },
      -1,
   } },
   { .variable = {
      { nir_search_value_variable, -4 },
      2, /* c */
      false,
      nir_type_invalid,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   /* replace65_2_1 -> 7 in the cache */
   { .expression = {
      { nir_search_value_expression, -4 },
      false,
      false,
      false,
      nir_op_ixor,
      1, 1,
      { 9, 7 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, -4 },
      false,
      false,
      false,
      nir_op_bcsel,
      -1, 2,
      { 0, 8, 10 },
      -1,
   } },

};



static const struct transform agx_nir_opt_ixor_bcsel_transforms[] = {
   { ~0, ~0, ~0 }, /* Sentinel */

   { 5, 11, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

};

static const struct per_op_table agx_nir_opt_ixor_bcsel_pass_op_table[nir_num_search_ops] = {
   [nir_op_ixor] = {
      .filter = (const uint16_t []) {
         0,
         1,
         2,
         0,
      },
      
      .num_filtered_states = 3,
      .table = (const uint16_t []) {
      
         0,
         0,
         0,
         0,
         0,
         3,
         0,
         3,
         0,
      },
   },
   [nir_op_bcsel] = {
      .filter = (const uint16_t []) {
         0,
         1,
         0,
         0,
      },
      
      .num_filtered_states = 2,
      .table = (const uint16_t []) {
      
         0,
         0,
         0,
         2,
         0,
         0,
         0,
         2,
      },
   },
};

/* Mapping from state index to offset in transforms (0 being no transforms) */
static const uint16_t agx_nir_opt_ixor_bcsel_transform_offsets[] = {
   0,
   0,
   0,
   1,
};

static const nir_algebraic_table agx_nir_opt_ixor_bcsel_table = {
   .transforms = agx_nir_opt_ixor_bcsel_transforms,
   .transform_offsets = agx_nir_opt_ixor_bcsel_transform_offsets,
   .pass_op_table = agx_nir_opt_ixor_bcsel_pass_op_table,
   .values = agx_nir_opt_ixor_bcsel_values,
   .expression_cond = NULL,
   .variable_cond = NULL,
};

bool
agx_nir_opt_ixor_bcsel(nir_shader *shader)
{
   bool progress = false;
   bool condition_flags[1];
   const nir_shader_compiler_options *options = shader->options;
   const shader_info *info = &shader->info;
   (void) options;
   (void) info;

   /* This is not a great place for this, but it seems to be the best place
    * for it. Check that at most one kind of lowering is requested for
    * bitfield extract and bitfield insert. Otherwise the lowering can fight
    * with each other and optimizations.
    */
   assert((int)options->lower_bitfield_extract +
          (int)options->lower_bitfield_extract_to_shifts <= 1);
   assert((int)options->lower_bitfield_insert +
          (int)options->lower_bitfield_insert_to_shifts +
          (int)options->lower_bitfield_insert_to_bitfield_select <= 1);


   STATIC_ASSERT(12 == ARRAY_SIZE(agx_nir_opt_ixor_bcsel_values));
   condition_flags[0] = true;

   nir_foreach_function_impl(impl, shader) {
     progress |= nir_algebraic_impl(impl, condition_flags, &agx_nir_opt_ixor_bcsel_table);
   }

   return progress;
}

