nir: add nir_type_conversion_op()
authorSamuel Iglesias Gonsálvez <siglesias@igalia.com>
Wed, 7 Dec 2016 07:34:42 +0000 (08:34 +0100)
committerSamuel Iglesias Gonsálvez <siglesias@igalia.com>
Mon, 9 Jan 2017 08:10:13 +0000 (09:10 +0100)
This function returns the nir_op corresponding to the conversion between
the given nir_alu_type arguments.

This function lacks support for integer-based types with bit_size != 32
and for float16 conversion ops.

v2:
- Improve readiness of the code and delete cases that don't happen now (Jason)

Signed-off-by: Samuel Iglesias Gonsálvez <siglesias@igalia.com>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
src/compiler/nir/nir.c
src/compiler/nir/nir.h

index 1f6837a88dd21c9afbc9a2254794b6328847aafa..a2af3909464c5e825ac47cd27730825e00bf34fa 100644 (file)
@@ -1956,3 +1956,84 @@ nir_system_value_from_intrinsic(nir_intrinsic_op intrin)
       unreachable("intrinsic doesn't produce a system value");
    }
 }
+
+nir_op
+nir_type_conversion_op(nir_alu_type src, nir_alu_type dst)
+{
+   nir_alu_type src_base_type = (nir_alu_type) nir_alu_type_get_base_type(src);
+   nir_alu_type dst_base_type = (nir_alu_type) nir_alu_type_get_base_type(dst);
+   unsigned src_bitsize = nir_alu_type_get_type_size(src);
+   unsigned dst_bitsize = nir_alu_type_get_type_size(dst);
+
+   if (src_base_type == dst_base_type) {
+      if (src_bitsize == dst_bitsize)
+         return (src_base_type == nir_type_float) ? nir_op_fmov : nir_op_imov;
+
+      assert (src_base_type == nir_type_float);
+      /* TODO: implement support for float16 */
+      assert(src_bitsize == 64 || dst_bitsize == 64);
+      return (src_bitsize == 64) ? nir_op_d2f : nir_op_f2d;
+   }
+
+   /* Different base type but same bit_size */
+   if (src_bitsize == dst_bitsize) {
+      /* TODO: This does not include specific conversions between
+       * signed or unsigned integer types of bit size different than 32 yet.
+       */
+      assert(src_bitsize == 32);
+      switch (src_base_type) {
+      case nir_type_uint:
+         return (dst_base_type == nir_type_float) ? nir_op_u2f : nir_op_imov;
+      case nir_type_int:
+         return (dst_base_type == nir_type_float) ? nir_op_i2f : nir_op_imov;
+      case nir_type_bool:
+         return (dst_base_type == nir_type_float) ? nir_op_b2f : nir_op_b2i;
+      case nir_type_float:
+         switch (dst_base_type) {
+         case nir_type_uint:
+            return nir_op_f2u;
+         case nir_type_bool:
+            return nir_op_f2b;
+         default:
+            return nir_op_f2i;
+         };
+      default:
+         assert(!"Invalid conversion");
+      };
+   }
+
+   /* Different bit_size and different base type */
+   /* TODO: Implement integer support for types with bit_size != 32 */
+   switch (src_base_type) {
+   case nir_type_uint:
+      assert(dst == nir_type_float64);
+      return nir_op_u2d;
+   case nir_type_int:
+      assert(dst == nir_type_float64);
+      return nir_op_i2d;
+   case nir_type_bool:
+      assert(dst == nir_type_float64);
+      return nir_op_u2d;
+   case nir_type_float:
+      assert(src_bitsize == 32 || src_bitsize == 64);
+      if (src_bitsize != 64) {
+         assert(dst == nir_type_float64);
+         return nir_op_f2d;
+      }
+      assert(dst_bitsize == 32);
+      switch (dst_base_type) {
+      case nir_type_uint:
+         return nir_op_d2u;
+      case nir_type_int:
+         return nir_op_d2i;
+      case nir_type_bool:
+         return nir_op_d2b;
+      case nir_type_float:
+         return nir_op_d2f;
+      default:
+         assert(!"Invalid conversion");
+      };
+   default:
+      assert(!"Invalid conversion");
+   };
+}
index 654a26728ac741555409c5741b6abc76893fdb83..c9226e94dd217631a21801418b7d5bd7c10746a2 100644 (file)
@@ -699,6 +699,8 @@ nir_get_nir_type_for_glsl_type(const struct glsl_type *type)
    }
 }
 
+nir_op nir_type_conversion_op(nir_alu_type src, nir_alu_type dst);
+
 typedef enum {
    NIR_OP_IS_COMMUTATIVE = (1 << 0),
    NIR_OP_IS_ASSOCIATIVE = (1 << 1),