[Mesa-dev] [PATCH v2 09/11] nir: Make boolean conversions sized just like the others

Jason Ekstrand jason at jlekstrand.net
Thu Nov 29 23:37:21 UTC 2018


Instead of a single i2b and b2i, we now have i2b32 and b2iN where N is
one if 8, 16, 32, or 64.  This leads to having a few more opcodes but
now everything is consistent and booleans aren't a weird special case
anymore.
---
 src/compiler/nir/nir.h             |  4 ++--
 src/compiler/nir/nir_algebraic.py  |  4 ++++
 src/compiler/nir/nir_lower_idiv.c  |  2 +-
 src/compiler/nir/nir_lower_int64.c |  2 +-
 src/compiler/nir/nir_opcodes.py    | 25 +++++++++++++------------
 src/compiler/nir/nir_opcodes_c.py  | 30 ++++++++++++------------------
 src/compiler/nir/nir_opt_if.c      |  2 +-
 src/compiler/nir/nir_search.c      | 19 +++++++++++++++++++
 src/compiler/nir/nir_search.h      |  4 ++++
 9 files changed, 57 insertions(+), 35 deletions(-)

diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index db935c8496b..cb8122def8a 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -1568,8 +1568,8 @@ nir_alu_instr_is_comparison(const nir_alu_instr *instr)
    case nir_op_uge:
    case nir_op_ieq:
    case nir_op_ine:
-   case nir_op_i2b:
-   case nir_op_f2b:
+   case nir_op_i2b32:
+   case nir_op_f2b32:
    case nir_op_inot:
    case nir_op_fnot:
       return true;
diff --git a/src/compiler/nir/nir_algebraic.py b/src/compiler/nir/nir_algebraic.py
index def0f94da48..ce77db80a40 100644
--- a/src/compiler/nir/nir_algebraic.py
+++ b/src/compiler/nir/nir_algebraic.py
@@ -45,6 +45,10 @@ conv_opcode_types = {
     'f2i' : 'int',
     'u2u' : 'uint',
     'i2i' : 'int',
+    'b2f' : 'float',
+    'b2i' : 'int',
+    'i2b' : 'bool',
+    'f2b' : 'bool',
 }
 
 if sys.version_info < (3, 0):
diff --git a/src/compiler/nir/nir_lower_idiv.c b/src/compiler/nir/nir_lower_idiv.c
index 194ca5a75a8..b2a0a3c1899 100644
--- a/src/compiler/nir/nir_lower_idiv.c
+++ b/src/compiler/nir/nir_lower_idiv.c
@@ -95,7 +95,7 @@ convert_instr(nir_builder *bld, nir_alu_instr *alu)
    r = nir_isub(bld, a, r);
 
    r = nir_uge(bld, r, b);
-   r = nir_b2i(bld, r);
+   r = nir_b2i32(bld, r);
 
    q = nir_iadd(bld, q, r);
    if (is_signed)  {
diff --git a/src/compiler/nir/nir_lower_int64.c b/src/compiler/nir/nir_lower_int64.c
index 50acc858605..81669c02cc6 100644
--- a/src/compiler/nir/nir_lower_int64.c
+++ b/src/compiler/nir/nir_lower_int64.c
@@ -48,7 +48,7 @@ lower_isign64(nir_builder *b, nir_ssa_def *x)
 
    nir_ssa_def *is_non_zero = nir_i2b(b, nir_ior(b, x_lo, x_hi));
    nir_ssa_def *res_hi = nir_ishr(b, x_hi, nir_imm_int(b, 31));
-   nir_ssa_def *res_lo = nir_ior(b, res_hi, nir_b2i(b, is_non_zero));
+   nir_ssa_def *res_lo = nir_ior(b, res_hi, nir_b2i32(b, is_non_zero));
 
    return nir_pack_64_2x32_split(b, res_lo, res_hi);
 }
diff --git a/src/compiler/nir/nir_opcodes.py b/src/compiler/nir/nir_opcodes.py
index 00720708305..55b2ff0f678 100644
--- a/src/compiler/nir/nir_opcodes.py
+++ b/src/compiler/nir/nir_opcodes.py
@@ -90,6 +90,7 @@ class Opcode(object):
 # helper variables for strings
 tfloat = "float"
 tint = "int"
+tbool = "bool"
 tbool32 = "bool32"
 tuint = "uint"
 tuint16 = "uint16"
@@ -117,6 +118,8 @@ def type_size(type_):
 def type_sizes(type_):
     if type_has_size(type_):
         return [type_size(type_)]
+    elif type_ == 'bool':
+        return [32]
     elif type_ == 'float':
         return [16, 32, 64]
     else:
@@ -196,11 +199,15 @@ unop("fexp2", tfloat, "exp2f(src0)")
 unop("flog2", tfloat, "log2f(src0)")
 
 # Generate all of the numeric conversion opcodes
-for src_t in [tint, tuint, tfloat]:
-   if src_t in (tint, tuint):
-      dst_types = [tfloat, src_t]
+for src_t in [tint, tuint, tfloat, tbool]:
+   if src_t == tbool:
+      dst_types = [tfloat, tint]
+   elif src_t == tint:
+      dst_types = [tfloat, tint, tbool]
+   elif src_t == tuint:
+      dst_types = [tfloat, tuint]
    elif src_t == tfloat:
-      dst_types = [tint, tuint, tfloat]
+      dst_types = [tint, tuint, tfloat, tbool]
 
    for dst_t in dst_types:
       for bit_size in type_sizes(dst_t):
@@ -211,15 +218,9 @@ for src_t in [tint, tuint, tfloat]:
                                                        bit_size, rnd_mode),
                                dst_t + str(bit_size), src_t, "src0")
           else:
+              conv_expr = "src0 != 0" if dst_t == tbool else "src0"
               unop_convert("{0}2{1}{2}".format(src_t[0], dst_t[0], bit_size),
-                           dst_t + str(bit_size), src_t, "src0")
-
-# We'll hand-code the to/from bool conversion opcodes.  Because bool doesn't
-# have multiple bit-sizes, we can always infer the size from the other type.
-unop_convert("f2b", tbool32, tfloat, "src0 != 0.0")
-unop_convert("i2b", tbool32, tint, "src0 != 0")
-unop_convert("b2f", tfloat, tbool32, "src0 ? 1.0 : 0.0")
-unop_convert("b2i", tint, tbool32, "src0 ? 1 : 0")
+                           dst_t + str(bit_size), src_t, conv_expr)
 
 
 # Unary floating-point rounding operations.
diff --git a/src/compiler/nir/nir_opcodes_c.py b/src/compiler/nir/nir_opcodes_c.py
index 9e3c06b8634..017c8b7ea9a 100644
--- a/src/compiler/nir/nir_opcodes_c.py
+++ b/src/compiler/nir/nir_opcodes_c.py
@@ -41,6 +41,8 @@ nir_type_conversion_op(nir_alu_type src, nir_alu_type dst, nir_rounding_mode rnd
 
    if (src == dst && src_base == nir_type_float) {
       return nir_op_fmov;
+   } else if (src == dst && src_base == nir_type_bool) {
+      return nir_op_imov;
    } else if ((src_base == nir_type_int || src_base == nir_type_uint) &&
               (dst_base == nir_type_int || dst_base == nir_type_uint) &&
               src_bit_size == dst_bit_size) {
@@ -51,10 +53,10 @@ nir_type_conversion_op(nir_alu_type src, nir_alu_type dst, nir_rounding_mode rnd
    }
 
    switch (src_base) {
-%     for src_t in ['int', 'uint', 'float']:
+%     for src_t in ['int', 'uint', 'float', 'bool']:
       case nir_type_${src_t}:
          switch (dst_base) {
-%           for dst_t in ['int', 'uint', 'float']:
+%           for dst_t in ['int', 'uint', 'float', 'bool']:
             case nir_type_${dst_t}:
 %              if src_t in ['int', 'uint'] and dst_t in ['int', 'uint']:
 %                 if dst_t == 'int':
@@ -62,6 +64,14 @@ nir_type_conversion_op(nir_alu_type src, nir_alu_type dst, nir_rounding_mode rnd
 %                 else:
 <%                   dst_t = src_t %>
 %                 endif
+%              elif src_t == 'bool' and dst_t in ['int', 'uint', 'bool']:
+%                 if dst_t == 'int':
+<%                   continue %>
+%                 else:
+<%                   dst_t = 'int' %>
+%                 endif
+%              elif src_t == 'uint' and dst_t == 'bool':
+<%                src_t = 'int' %>
 %              endif
                switch (dst_bit_size) {
 %                 for dst_bits in type_sizes(dst_t):
@@ -85,26 +95,10 @@ nir_type_conversion_op(nir_alu_type src, nir_alu_type dst, nir_rounding_mode rnd
                      unreachable("Invalid nir alu bit size");
                }
 %           endfor
-            case nir_type_bool:
-%              if src_t == 'float':
-                  return nir_op_f2b;
-%              else:
-                  return nir_op_i2b;
-%              endif
             default:
                unreachable("Invalid nir alu base type");
          }
 %     endfor
-      case nir_type_bool:
-         switch (dst_base) {
-            case nir_type_int:
-            case nir_type_uint:
-               return nir_op_b2i;
-            case nir_type_float:
-               return nir_op_b2f;
-            default:
-               unreachable("Invalid nir alu base type");
-         }
       default:
          unreachable("Invalid nir alu base type");
    }
diff --git a/src/compiler/nir/nir_opt_if.c b/src/compiler/nir/nir_opt_if.c
index 8a971c43f24..ab00f447097 100644
--- a/src/compiler/nir/nir_opt_if.c
+++ b/src/compiler/nir/nir_opt_if.c
@@ -509,7 +509,7 @@ can_propagate_through_alu(nir_src *src)
       case nir_op_ior:
       case nir_op_iand:
       case nir_op_inot:
-      case nir_op_b2i:
+      case nir_op_b2i32:
          return true;
       case nir_op_bcsel:
          return src == &alu->src[0].src;
diff --git a/src/compiler/nir/nir_search.c b/src/compiler/nir/nir_search.c
index f5fc92ec33c..c7954b39415 100644
--- a/src/compiler/nir/nir_search.c
+++ b/src/compiler/nir/nir_search.c
@@ -108,6 +108,10 @@ nir_op_matches_search_op(nir_op nop, uint16_t sop)
              nop == nir_op_##op##32 || \
              nop == nir_op_##op##64;
 
+#define MATCH_BCONV_CASE(op) \
+   case nir_search_op_##op: \
+      return nop == nir_op_##op##32;
+
    switch (sop) {
    MATCH_FCONV_CASE(i2f)
    MATCH_FCONV_CASE(u2f)
@@ -116,6 +120,10 @@ nir_op_matches_search_op(nir_op nop, uint16_t sop)
    MATCH_ICONV_CASE(f2i)
    MATCH_ICONV_CASE(u2u)
    MATCH_ICONV_CASE(i2i)
+   MATCH_FCONV_CASE(b2f)
+   MATCH_ICONV_CASE(b2i)
+   MATCH_BCONV_CASE(i2b)
+   MATCH_BCONV_CASE(f2b)
    default:
       unreachable("Invalid nir_search_op");
    }
@@ -149,6 +157,13 @@ nir_op_for_search_op(uint16_t sop, unsigned bit_size)
       default: unreachable("Invalid bit size"); \
       }
 
+#define RET_BCONV_CASE(op) \
+   case nir_search_op_##op: \
+      switch (bit_size) { \
+      case 32: return nir_op_##op##32; \
+      default: unreachable("Invalid bit size"); \
+      }
+
    switch (sop) {
    RET_FCONV_CASE(i2f)
    RET_FCONV_CASE(u2f)
@@ -157,6 +172,10 @@ nir_op_for_search_op(uint16_t sop, unsigned bit_size)
    RET_ICONV_CASE(f2i)
    RET_ICONV_CASE(u2u)
    RET_ICONV_CASE(i2i)
+   RET_FCONV_CASE(b2f)
+   RET_ICONV_CASE(b2i)
+   RET_BCONV_CASE(i2b)
+   RET_BCONV_CASE(f2b)
    default:
       unreachable("Invalid nir_search_op");
    }
diff --git a/src/compiler/nir/nir_search.h b/src/compiler/nir/nir_search.h
index 47a539fdcd9..b442d48dd4f 100644
--- a/src/compiler/nir/nir_search.h
+++ b/src/compiler/nir/nir_search.h
@@ -102,6 +102,10 @@ enum nir_search_op {
    nir_search_op_f2i,
    nir_search_op_u2u,
    nir_search_op_i2i,
+   nir_search_op_b2f,
+   nir_search_op_b2i,
+   nir_search_op_i2b,
+   nir_search_op_f2b,
 };
 
 typedef struct {
-- 
2.19.1



More information about the mesa-dev mailing list