nir: Add b2b opcodes
authorJason Ekstrand <jason@jlekstrand.net>
Fri, 27 Mar 2020 05:18:43 +0000 (00:18 -0500)
committerMarge Bot <eric+marge@anholt.net>
Mon, 30 Mar 2020 15:46:19 +0000 (15:46 +0000)
These exist to convert between different types of boolean values.  In
particular, we want to use these for uniform and shared memory
operations where we need to convert to a reasonably sized boolean but we
don't care what its format is so we don't want to make the back-end
insert an actual i2b/b2i.  In the case of uniforms, Mesa can tweak the
format of the uniform boolean to whatever the driver wants.  In the case
of shared, every value in a shared variable comes from the shader so
it's already in the right boolean format.

The new boolean conversion opcodes get replaced with mov in
lower_bool_to_int/float32 so the back-end will hopefully never see them.
However, while we're in the middle of optimizing our NIR, they let us
have sensible load_uniform/ubo intrinsics and also have the bit size
conversion.

Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4338>

src/compiler/nir/nir_lower_bool_to_bitsize.c
src/compiler/nir/nir_lower_bool_to_float.c
src/compiler/nir/nir_lower_bool_to_int32.c
src/compiler/nir/nir_opcodes.py
src/compiler/nir/nir_opt_algebraic.py

index 5561ffa14a41c23cddaf0aacbc88e5533198656a..f45013ba1b150f9b86ce002622972ca858d0a8c2 100644 (file)
@@ -167,6 +167,16 @@ lower_alu_instr(nir_builder *b, nir_alu_instr *alu)
                                bit_size == 16 ? nir_op_i2b16 : nir_op_i2b32;
       break;
 
                                bit_size == 16 ? nir_op_i2b16 : nir_op_i2b32;
       break;
 
+   case nir_op_b2b1:
+      /* Since the canonical bit size is the size of the src, it's a no-op */
+      opcode = nir_op_mov;
+      break;
+
+   case nir_op_b2b32:
+      /* For up-converting booleans, sign-extend */
+      opcode = nir_op_i2i32;
+      break;
+
    case nir_op_flt:
       opcode = bit_size == 8 ? nir_op_flt8 :
                                bit_size == 16 ? nir_op_flt16 : nir_op_flt32;
    case nir_op_flt:
       opcode = bit_size == 8 ? nir_op_flt8 :
                                bit_size == 16 ? nir_op_flt16 : nir_op_flt32;
index d552b0575903108231799f151c0f358aa1ed276e..a94e4371375566ea20db6a838a597c41776b9a4d 100644 (file)
@@ -68,6 +68,7 @@ lower_alu_instr(nir_builder *b, nir_alu_instr *alu)
       rep = nir_sne(b, nir_ssa_for_alu_src(b, alu, 0),
                        nir_imm_float(b, 0));
       break;
       rep = nir_sne(b, nir_ssa_for_alu_src(b, alu, 0),
                        nir_imm_float(b, 0));
       break;
+   case nir_op_b2b1: alu->op = nir_op_mov; break;
 
    case nir_op_flt: alu->op = nir_op_slt; break;
    case nir_op_fge: alu->op = nir_op_sge; break;
 
    case nir_op_flt: alu->op = nir_op_slt; break;
    case nir_op_fge: alu->op = nir_op_sge; break;
index 0978207e72d2a44ef6aab3576f197d0cab4f57b0..f3c343c444af4d59aff4640dadd2acc7684c909a 100644 (file)
@@ -65,6 +65,15 @@ lower_alu_instr(nir_alu_instr *alu)
    case nir_op_f2b1: alu->op = nir_op_f2b32; break;
    case nir_op_i2b1: alu->op = nir_op_i2b32; break;
 
    case nir_op_f2b1: alu->op = nir_op_f2b32; break;
    case nir_op_i2b1: alu->op = nir_op_i2b32; break;
 
+   case nir_op_b2b32:
+   case nir_op_b2b1:
+      /* We're mutating instructions in a dominance-preserving order so our
+       * source boolean should be 32-bit by now.
+       */
+      assert(nir_src_bit_size(alu->src[0].src) == 32);
+      alu->op = nir_op_mov;
+      break;
+
    case nir_op_flt: alu->op = nir_op_flt32; break;
    case nir_op_fge: alu->op = nir_op_fge32; break;
    case nir_op_feq: alu->op = nir_op_feq32; break;
    case nir_op_flt: alu->op = nir_op_flt32; break;
    case nir_op_fge: alu->op = nir_op_fge32; break;
    case nir_op_feq: alu->op = nir_op_feq32; break;
index d116578d1c0563dba9cc03d23f8532e9cf236a03..f34c1ff20f1143b8bac77eba36acd7eaee001f90 100644 (file)
@@ -211,7 +211,7 @@ unop("flog2", tfloat, "log2f(src0)")
 # Generate all of the numeric conversion opcodes
 for src_t in [tint, tuint, tfloat, tbool]:
    if src_t == tbool:
 # Generate all of the numeric conversion opcodes
 for src_t in [tint, tuint, tfloat, tbool]:
    if src_t == tbool:
-      dst_types = [tfloat, tint]
+      dst_types = [tfloat, tint, tbool]
    elif src_t == tint:
       dst_types = [tfloat, tint, tbool]
    elif src_t == tuint:
    elif src_t == tint:
       dst_types = [tfloat, tint, tbool]
    elif src_t == tuint:
index 1625d6703e28aea01b62999ab04f05a965f1e6f4..dbfd4917503321cfb441d2655127e4b564bd4459 100644 (file)
@@ -1359,7 +1359,7 @@ for x, y in itertools.product(['f', 'u', 'i'], ['f', 'u', 'i']):
    optimizations.append(((x2yN, (b2x, a)), (b2y, a)))
 
 # Optimize away x2xN(a@N)
    optimizations.append(((x2yN, (b2x, a)), (b2y, a)))
 
 # Optimize away x2xN(a@N)
-for t in ['int', 'uint', 'float']:
+for t in ['int', 'uint', 'float', 'bool']:
    for N in type_sizes(t):
       x2xN = '{0}2{0}{1}'.format(t[0], N)
       aN = 'a@{0}'.format(N)
    for N in type_sizes(t):
       x2xN = '{0}2{0}{1}'.format(t[0], N)
       aN = 'a@{0}'.format(N)