#include "brw_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 17
 * transforms:
 *    ('fmul@32(is_only_used_as_float)', ('fsign(is_used_once)', 'a(is_not_negative)'), 'b') => ('fcsel_gt', 'a', 'b', ('fmul', 'b', 0.0))
 *    ('~fmul@32(nsz,nnan)', ('fsign(is_used_once)', 'a(is_not_negative)'), 'b') => ('fcsel_gt', 'a', 'b', 0.0)
 *    ('fmul@32(is_only_used_as_float)', ('fsign(is_used_once)', 'a(is_not_positive)'), 'b') => ('fcsel_gt', ('fneg', 'a'), ('fneg', 'b'), ('fmul', 'b', 2147483648))
 *    ('~fmul@32(nsz,nnan)', ('fsign(is_used_once)', 'a(is_not_positive)'), 'b') => ('fcsel_gt', ('fneg', 'a'), ('fneg', 'b'), 2147483648)
 *    ('fmul@16(is_only_used_as_float)', ('fsign(is_used_once)', 'a(is_not_negative)'), 'b') => ('bcsel', ('!flt', 0, 'a'), 'b', ('fmul', 'b', 0.0))
 *    ('~fmul@16(nsz,nnan)', ('fsign(is_used_once)', 'a(is_not_negative)'), 'b') => ('bcsel', ('!flt', 0, 'a'), 'b', 0.0)
 *    ('fmul@16(is_only_used_as_float)', ('fsign(is_used_once)', 'a(is_not_positive)'), 'b') => ('bcsel', ('!flt', 0, ('fneg', 'a')), ('fneg', 'b'), ('fmul', 'b', 32768))
 *    ('~fmul@16(nsz,nnan)', ('fsign(is_used_once)', 'a(is_not_positive)'), 'b') => ('bcsel', ('!flt', 0, ('fneg', 'a')), ('fneg', 'b'), 32768)
 *    ('fmul@32(is_only_used_as_float,nsz)', ('fsign(is_used_once)', 'a'), 'b(is_finite)') => ('fcsel_gt', 'a', 'b', ('fcsel_gt', ('fneg', 'a'), ('fneg', 'b'), 0.0))
 *    ('fmul@32(is_only_used_as_float,nsz,nnan)', ('fsign(is_used_once)', 'a'), 'b') => ('fcsel_gt', 'a', 'b', ('fcsel_gt', ('fneg', 'a'), ('fneg', 'b'), 0.0))
 *    ('~fmul@32(nsz,nnan)', ('fsign(is_used_once)', 'a'), 'b') => ('fcsel_gt', 'a', 'b', ('fcsel_gt', ('fneg', 'a'), ('fneg', 'b'), 0.0))
 *    ('fsign@32', 'a') => ('fcsel_gt', ('fabs', 'a'), ('ior', ('iand', 'a', 2147483648), 1065353216), ('iand', 'a', 2147483648))
 *    ('fsign@16', 'a') => ('bcsel', ('!flt', 0, ('fabs', 'a')), ('ior', ('iand', 'a', 32768), 15360), ('iand', 'a', 32768))
 *    ('fmul(nsz,nnan)', 'a', 0.0) => 0.0
 *    ('fmul(nsz,nnan)', 'a', -0.0) => 0.0
 *    ('fmul(nsz)', 'a(is_finite)', 0.0) => 0.0
 *    ('fmul(nsz)', 'a(is_finite)', -0.0) => 0.0
 */


static const nir_search_value_union brw_nir_lower_fsign_values[] = {
   /* ('fmul@32(is_only_used_as_float)', ('fsign(is_used_once)', 'a(is_not_negative)'), 'b') => ('fcsel_gt', 'a', 'b', ('fmul', 'b', 0.0)) */
   { .variable = {
      { nir_search_value_variable, 32 },
      0, /* a */
      false,
      0,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fsign,
      -1, 0,
      { 0 },
      1,
   } },
   { .variable = {
      { nir_search_value_variable, 32 },
      1, /* b */
      false,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fmul,
      0, 1,
      { 1, 2 },
      0,
   } },

   { .variable = {
      { nir_search_value_variable, 32 },
      0, /* a */
      false,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   /* replace0_1 -> 2 in the cache */
   /* replace0_2_0 -> 2 in the cache */
   { .constant = {
      { nir_search_value_constant, 32 },
      nir_type_float, { 0x0ull /* 0.0 */ },
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      true,
      -1,
      nir_op_fmul,
      0, 1,
      { 2, 5 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fcsel_gt,
      -1, 1,
      { 4, 2, 6 },
      -1,
   } },

   /* ('~fmul@32(nsz,nnan)', ('fsign(is_used_once)', 'a(is_not_negative)'), 'b') => ('fcsel_gt', 'a', 'b', 0.0) */
   /* search1_0_0 -> 0 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_exact,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fsign,
      -1, 0,
      { 0 },
      1,
   } },
   /* search1_1 -> 2 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_exact | nir_fp_preserve_nan | nir_fp_preserve_signed_zero,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fmul,
      0, 1,
      { 8, 2 },
      -1,
   } },

   /* replace1_0 -> 4 in the cache */
   /* replace1_1 -> 2 in the cache */
   /* replace1_2 -> 5 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fcsel_gt,
      -1, 0,
      { 4, 2, 5 },
      -1,
   } },

   /* ('fmul@32(is_only_used_as_float)', ('fsign(is_used_once)', 'a(is_not_positive)'), 'b') => ('fcsel_gt', ('fneg', 'a'), ('fneg', 'b'), ('fmul', 'b', 2147483648)) */
   { .variable = {
      { nir_search_value_variable, 32 },
      0, /* a */
      false,
      1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fsign,
      -1, 0,
      { 11 },
      1,
   } },
   /* search2_1 -> 2 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fmul,
      0, 1,
      { 12, 2 },
      0,
   } },

   /* replace2_0_0 -> 4 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fneg,
      -1, 0,
      { 4 },
      -1,
   } },
   /* replace2_1_0 -> 2 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fneg,
      -1, 0,
      { 2 },
      -1,
   } },
   /* replace2_2_0 -> 2 in the cache */
   { .constant = {
      { nir_search_value_constant, 32 },
      nir_type_int, { 0x80000000ull /* 2147483648 */ },
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      true,
      -1,
      nir_op_fmul,
      0, 1,
      { 2, 16 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fcsel_gt,
      -1, 1,
      { 14, 15, 17 },
      -1,
   } },

   /* ('~fmul@32(nsz,nnan)', ('fsign(is_used_once)', 'a(is_not_positive)'), 'b') => ('fcsel_gt', ('fneg', 'a'), ('fneg', 'b'), 2147483648) */
   /* search3_0_0 -> 11 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_exact,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fsign,
      -1, 0,
      { 11 },
      1,
   } },
   /* search3_1 -> 2 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_exact | nir_fp_preserve_nan | nir_fp_preserve_signed_zero,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fmul,
      0, 1,
      { 19, 2 },
      -1,
   } },

   /* replace3_0_0 -> 4 in the cache */
   /* replace3_0 -> 14 in the cache */
   /* replace3_1_0 -> 2 in the cache */
   /* replace3_1 -> 15 in the cache */
   /* replace3_2 -> 16 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fcsel_gt,
      -1, 0,
      { 14, 15, 16 },
      -1,
   } },

   /* ('fmul@16(is_only_used_as_float)', ('fsign(is_used_once)', 'a(is_not_negative)'), 'b') => ('bcsel', ('!flt', 0, 'a'), 'b', ('fmul', 'b', 0.0)) */
   { .variable = {
      { nir_search_value_variable, 16 },
      0, /* a */
      false,
      0,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fsign,
      -1, 0,
      { 22 },
      1,
   } },
   { .variable = {
      { nir_search_value_variable, 16 },
      1, /* b */
      false,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fmul,
      0, 1,
      { 23, 24 },
      0,
   } },

   { .constant = {
      { nir_search_value_constant, 16 },
      nir_type_int, { 0x0ull /* 0 */ },
   } },
   { .variable = {
      { nir_search_value_variable, 16 },
      0, /* a */
      false,
      -1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, 1 },
      nir_fp_fast_math,
      nir_fp_exact,
      false,
      -1,
      nir_op_flt,
      -1, 0,
      { 26, 27 },
      -1,
   } },
   /* replace4_1 -> 24 in the cache */
   /* replace4_2_0 -> 24 in the cache */
   { .constant = {
      { nir_search_value_constant, 16 },
      nir_type_float, { 0x0ull /* 0.0 */ },
   } },
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      true,
      -1,
      nir_op_fmul,
      0, 1,
      { 24, 29 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_bcsel,
      -1, 1,
      { 28, 24, 30 },
      -1,
   } },

   /* ('~fmul@16(nsz,nnan)', ('fsign(is_used_once)', 'a(is_not_negative)'), 'b') => ('bcsel', ('!flt', 0, 'a'), 'b', 0.0) */
   /* search5_0_0 -> 22 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_exact,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fsign,
      -1, 0,
      { 22 },
      1,
   } },
   /* search5_1 -> 24 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_exact | nir_fp_preserve_nan | nir_fp_preserve_signed_zero,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fmul,
      0, 1,
      { 32, 24 },
      -1,
   } },

   /* replace5_0_0 -> 26 in the cache */
   /* replace5_0_1 -> 27 in the cache */
   /* replace5_0 -> 28 in the cache */
   /* replace5_1 -> 24 in the cache */
   /* replace5_2 -> 29 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_bcsel,
      -1, 0,
      { 28, 24, 29 },
      -1,
   } },

   /* ('fmul@16(is_only_used_as_float)', ('fsign(is_used_once)', 'a(is_not_positive)'), 'b') => ('bcsel', ('!flt', 0, ('fneg', 'a')), ('fneg', 'b'), ('fmul', 'b', 32768)) */
   { .variable = {
      { nir_search_value_variable, 16 },
      0, /* a */
      false,
      1,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fsign,
      -1, 0,
      { 35 },
      1,
   } },
   /* search6_1 -> 24 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fmul,
      0, 1,
      { 36, 24 },
      0,
   } },

   /* replace6_0_0 -> 26 in the cache */
   /* replace6_0_1_0 -> 27 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fneg,
      -1, 0,
      { 27 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 1 },
      nir_fp_fast_math,
      nir_fp_exact,
      false,
      -1,
      nir_op_flt,
      -1, 0,
      { 26, 38 },
      -1,
   } },
   /* replace6_1_0 -> 24 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fneg,
      -1, 0,
      { 24 },
      -1,
   } },
   /* replace6_2_0 -> 24 in the cache */
   { .constant = {
      { nir_search_value_constant, 16 },
      nir_type_int, { 0x8000ull /* 32768 */ },
   } },
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      true,
      -1,
      nir_op_fmul,
      0, 1,
      { 24, 41 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_bcsel,
      -1, 1,
      { 39, 40, 42 },
      -1,
   } },

   /* ('~fmul@16(nsz,nnan)', ('fsign(is_used_once)', 'a(is_not_positive)'), 'b') => ('bcsel', ('!flt', 0, ('fneg', 'a')), ('fneg', 'b'), 32768) */
   /* search7_0_0 -> 35 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_exact,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fsign,
      -1, 0,
      { 35 },
      1,
   } },
   /* search7_1 -> 24 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_exact | nir_fp_preserve_nan | nir_fp_preserve_signed_zero,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fmul,
      0, 1,
      { 44, 24 },
      -1,
   } },

   /* replace7_0_0 -> 26 in the cache */
   /* replace7_0_1_0 -> 27 in the cache */
   /* replace7_0_1 -> 38 in the cache */
   /* replace7_0 -> 39 in the cache */
   /* replace7_1_0 -> 24 in the cache */
   /* replace7_1 -> 40 in the cache */
   /* replace7_2 -> 41 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_bcsel,
      -1, 0,
      { 39, 40, 41 },
      -1,
   } },

   /* ('fmul@32(is_only_used_as_float,nsz)', ('fsign(is_used_once)', 'a'), 'b(is_finite)') => ('fcsel_gt', 'a', 'b', ('fcsel_gt', ('fneg', 'a'), ('fneg', 'b'), 0.0)) */
   /* search8_0_0 -> 4 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fsign,
      -1, 0,
      { 4 },
      1,
   } },
   { .variable = {
      { nir_search_value_variable, 32 },
      1, /* b */
      false,
      2,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_preserve_signed_zero,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fmul,
      0, 1,
      { 47, 48 },
      0,
   } },

   /* replace8_0 -> 4 in the cache */
   /* replace8_1 -> 2 in the cache */
   /* replace8_2_0_0 -> 4 in the cache */
   /* replace8_2_0 -> 14 in the cache */
   /* replace8_2_1_0 -> 2 in the cache */
   /* replace8_2_1 -> 15 in the cache */
   /* replace8_2_2 -> 5 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fcsel_gt,
      -1, 0,
      { 14, 15, 5 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fcsel_gt,
      -1, 0,
      { 4, 2, 50 },
      -1,
   } },

   /* ('fmul@32(is_only_used_as_float,nsz,nnan)', ('fsign(is_used_once)', 'a'), 'b') => ('fcsel_gt', 'a', 'b', ('fcsel_gt', ('fneg', 'a'), ('fneg', 'b'), 0.0)) */
   /* search9_0_0 -> 4 in the cache */
   /* search9_0 -> 47 in the cache */
   /* search9_1 -> 2 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_preserve_nan | nir_fp_preserve_signed_zero,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fmul,
      0, 1,
      { 47, 2 },
      0,
   } },

   /* replace9_0 -> 4 in the cache */
   /* replace9_1 -> 2 in the cache */
   /* replace9_2_0_0 -> 4 in the cache */
   /* replace9_2_0 -> 14 in the cache */
   /* replace9_2_1_0 -> 2 in the cache */
   /* replace9_2_1 -> 15 in the cache */
   /* replace9_2_2 -> 5 in the cache */
   /* replace9_2 -> 50 in the cache */
   /* replace9 -> 51 in the cache */

   /* ('~fmul@32(nsz,nnan)', ('fsign(is_used_once)', 'a'), 'b') => ('fcsel_gt', 'a', 'b', ('fcsel_gt', ('fneg', 'a'), ('fneg', 'b'), 0.0)) */
   /* search10_0_0 -> 4 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_exact,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fsign,
      -1, 0,
      { 4 },
      1,
   } },
   /* search10_1 -> 2 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_exact | nir_fp_preserve_nan | nir_fp_preserve_signed_zero,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fmul,
      0, 1,
      { 53, 2 },
      -1,
   } },

   /* replace10_0 -> 4 in the cache */
   /* replace10_1 -> 2 in the cache */
   /* replace10_2_0_0 -> 4 in the cache */
   /* replace10_2_0 -> 14 in the cache */
   /* replace10_2_1_0 -> 2 in the cache */
   /* replace10_2_1 -> 15 in the cache */
   /* replace10_2_2 -> 5 in the cache */
   /* replace10_2 -> 50 in the cache */
   /* replace10 -> 51 in the cache */

   /* ('fsign@32', 'a') => ('fcsel_gt', ('fabs', 'a'), ('ior', ('iand', 'a', 2147483648), 1065353216), ('iand', 'a', 2147483648)) */
   /* search11_0 -> 4 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fsign,
      -1, 0,
      { 4 },
      -1,
   } },

   /* replace11_0_0 -> 4 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fabs,
      -1, 0,
      { 4 },
      -1,
   } },
   /* replace11_1_0_0 -> 4 in the cache */
   /* replace11_1_0_1 -> 16 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      true,
      -1,
      nir_op_iand,
      1, 1,
      { 4, 16 },
      -1,
   } },
   { .constant = {
      { nir_search_value_constant, 32 },
      nir_type_int, { 0x3f800000ull /* 1065353216 */ },
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      true,
      -1,
      nir_op_ior,
      0, 2,
      { 57, 58 },
      -1,
   } },
   /* replace11_2_0 -> 4 in the cache */
   /* replace11_2_1 -> 16 in the cache */
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      true,
      -1,
      nir_op_iand,
      2, 1,
      { 4, 16 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 32 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fcsel_gt,
      -1, 3,
      { 56, 59, 60 },
      -1,
   } },

   /* ('fsign@16', 'a') => ('bcsel', ('!flt', 0, ('fabs', 'a')), ('ior', ('iand', 'a', 32768), 15360), ('iand', 'a', 32768)) */
   /* search12_0 -> 27 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fsign,
      -1, 0,
      { 27 },
      -1,
   } },

   /* replace12_0_0 -> 26 in the cache */
   /* replace12_0_1_0 -> 27 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_fabs,
      -1, 0,
      { 27 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 1 },
      nir_fp_fast_math,
      nir_fp_exact,
      false,
      -1,
      nir_op_flt,
      -1, 0,
      { 26, 63 },
      -1,
   } },
   /* replace12_1_0_0 -> 27 in the cache */
   /* replace12_1_0_1 -> 41 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      true,
      -1,
      nir_op_iand,
      1, 1,
      { 27, 41 },
      -1,
   } },
   { .constant = {
      { nir_search_value_constant, 16 },
      nir_type_int, { 0x3c00ull /* 15360 */ },
   } },
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      true,
      -1,
      nir_op_ior,
      0, 2,
      { 65, 66 },
      -1,
   } },
   /* replace12_2_0 -> 27 in the cache */
   /* replace12_2_1 -> 41 in the cache */
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      true,
      -1,
      nir_op_iand,
      2, 1,
      { 27, 41 },
      -1,
   } },
   { .expression = {
      { nir_search_value_expression, 16 },
      nir_fp_fast_math,
      nir_fp_fast_math,
      false,
      -1,
      nir_op_bcsel,
      -1, 3,
      { 64, 67, 68 },
      -1,
   } },

   /* ('fmul(nsz,nnan)', 'a', 0.0) => 0.0 */
   { .variable = {
      { nir_search_value_variable, -1 },
      0, /* a */
      false,
      -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_float, { 0x0ull /* 0.0 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      nir_fp_preserve_nan | nir_fp_preserve_signed_zero,
      nir_fp_fast_math,
      true,
      -1,
      nir_op_fmul,
      0, 1,
      { 70, 71 },
      -1,
   } },

   /* replace13 -> 71 in the cache */

   /* ('fmul(nsz,nnan)', 'a', -0.0) => 0.0 */
   /* search14_0 -> 70 in the cache */
   { .constant = {
      { nir_search_value_constant, -1 },
      nir_type_float, { 0x8000000000000000ull /* -0.0 */ },
   } },
   { .expression = {
      { nir_search_value_expression, -1 },
      nir_fp_preserve_nan | nir_fp_preserve_signed_zero,
      nir_fp_fast_math,
      true,
      -1,
      nir_op_fmul,
      0, 1,
      { 70, 73 },
      -1,
   } },

   /* replace14 -> 71 in the cache */

   /* ('fmul(nsz)', 'a(is_finite)', 0.0) => 0.0 */
   { .variable = {
      { nir_search_value_variable, -1 },
      0, /* a */
      false,
      2,
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   } },
   /* search15_1 -> 71 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      nir_fp_preserve_signed_zero,
      nir_fp_fast_math,
      true,
      -1,
      nir_op_fmul,
      0, 1,
      { 75, 71 },
      -1,
   } },

   /* replace15 -> 71 in the cache */

   /* ('fmul(nsz)', 'a(is_finite)', -0.0) => 0.0 */
   /* search16_0 -> 75 in the cache */
   /* search16_1 -> 73 in the cache */
   { .expression = {
      { nir_search_value_expression, -1 },
      nir_fp_preserve_signed_zero,
      nir_fp_fast_math,
      true,
      -1,
      nir_op_fmul,
      0, 1,
      { 75, 73 },
      -1,
   } },

   /* replace16 -> 71 in the cache */

};

UNUSED static const nir_search_expression_cond brw_nir_lower_fsign_expression_cond[] = {
   is_only_used_as_float,
   is_used_once,
};

static const nir_search_variable_cond brw_nir_lower_fsign_variable_cond[] = {
   (is_not_negative),
   (is_not_positive),
   (is_finite),
};

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

   { 72, 71, 0 },
   { 74, 71, 0 },
   { 76, 71, 0 },
   { 77, 71, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 55, 61, 0 },
   { 62, 69, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 3, 7, 0 },
   { 9, 10, 0 },
   { 13, 18, 0 },
   { 20, 21, 0 },
   { 25, 31, 0 },
   { 33, 34, 0 },
   { 37, 43, 0 },
   { 45, 46, 0 },
   { 49, 51, 0 },
   { 52, 51, 0 },
   { 54, 51, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

   { 3, 7, 0 },
   { 9, 10, 0 },
   { 13, 18, 0 },
   { 20, 21, 0 },
   { 25, 31, 0 },
   { 33, 34, 0 },
   { 37, 43, 0 },
   { 45, 46, 0 },
   { 49, 51, 0 },
   { 52, 51, 0 },
   { 54, 51, 0 },
   { 72, 71, 0 },
   { 74, 71, 0 },
   { 76, 71, 0 },
   { 77, 71, 0 },
   { ~0, ~0, ~0 }, /* Sentinel */

};

static const struct per_op_table brw_nir_lower_fsign_pass_op_table[nir_num_search_ops] = {
   [nir_op_fmul] = {
      .filter = (const uint16_t []) {
         0,
         1,
         0,
         2,
         0,
         0,
      },
      
      .num_filtered_states = 3,
      .table = (const uint16_t []) {
      
         0,
         2,
         4,
         2,
         2,
         5,
         4,
         5,
         4,
      },
   },
   [nir_op_fsign] = {
      .filter = NULL,
      
      .num_filtered_states = 1,
      .table = (const uint16_t []) {
      
         3,
      },
   },
};

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

static const nir_algebraic_table brw_nir_lower_fsign_table = {
   .transforms = brw_nir_lower_fsign_transforms,
   .transform_offsets = brw_nir_lower_fsign_transform_offsets,
   .pass_op_table = brw_nir_lower_fsign_pass_op_table,
   .values = brw_nir_lower_fsign_values,
   .expression_cond = brw_nir_lower_fsign_expression_cond,
   .variable_cond = brw_nir_lower_fsign_variable_cond,
};

bool
brw_nir_lower_fsign(
   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;

   STATIC_ASSERT(78 == ARRAY_SIZE(brw_nir_lower_fsign_values));
   condition_flags[0] = true;

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

   return progress;
}

