pan/bi: Rewrite conversion packing
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Mon, 13 Apr 2020 19:56:06 +0000 (15:56 -0400)
committerMarge Bot <eric+marge@anholt.net>
Mon, 13 Apr 2020 22:32:40 +0000 (22:32 +0000)
To support roundmodes and other goodies.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4539>

src/panfrost/bifrost/bi_pack.c
src/panfrost/bifrost/bifrost.h

index 7c2f11ab82198c856a2a72d2f702fa76545efdd4..dc304f3d7d90e683203029a8d17e312366b45110 100644 (file)
@@ -749,49 +749,80 @@ bi_pack_fma_convert(bi_instruction *ins, struct bi_registers *regs)
         nir_alu_type to_base = nir_alu_type_get_base_type(ins->dest_type);
         unsigned to_size = nir_alu_type_get_type_size(ins->dest_type);
         bool to_unsigned = to_base == nir_type_uint;
+        bool to_float = to_base == nir_type_float;
 
         /* Sanity check */
         assert((from_base != to_base) || (from_size != to_size));
         assert((MAX2(from_size, to_size) / MIN2(from_size, to_size)) <= 2);
 
-        if (from_size == 16 && to_size == 16) {
-                /* f2i_i2f16 */
-                unreachable("i16 not yet implemented");
-        } else if (from_size == 32 && to_size == 32) {
-                unsigned op = 0;
+        /* f32 to f16 is special */
+        if (from_size == 32 && to_size == 16 && from_base == nir_type_float && to_base == from_base) {
+                /* TODO: second vectorized source? */
+                struct bifrost_fma_2src pack = {
+                        .src0 = bi_get_src(ins, regs, 0, true),
+                        .src1 = BIFROST_SRC_STAGE, /* 0 */
+                        .op = BIFROST_FMA_FLOAT32_TO_16
+                };
 
-                if (from_base == nir_type_float) {
-                        op = BIFROST_FMA_FLOAT32_TO_INT(to_unsigned);
-                } else {
-                        op = BIFROST_FMA_INT_TO_FLOAT32(from_unsigned);
-                }
+                RETURN_PACKED(pack);
+        }
 
-                return bi_pack_fma_1src(ins, regs, op);
-        } else if (from_size == 16 && to_size == 32) {
-                bool from_y = ins->swizzle[0][0];
+        /* Otherwise, figure out the mode */
+        unsigned op = 0;
+
+        if (from_size == 16 && to_size == 32) {
+                unsigned component = ins->swizzle[0][0];
+                assert(component <= 1);
+
+                if (from_base == nir_type_float)
+                        op = BIFROST_CONVERT_5(component);
+                else
+                        op = BIFROST_CONVERT_4(from_unsigned, component, to_float);
+        } else {
+                unsigned mode = 0;
+                unsigned swizzle = (from_size == 16) ? bi_swiz16(ins, 0) : 0;
+                bool is_unsigned = from_unsigned;
 
                 if (from_base == nir_type_float) {
-                        return bi_pack_fma_1src(ins, regs,
-                                        BIFROST_FMA_FLOAT16_TO_32(from_y));
-                } else {
-                        unreachable("i16 not yet implemented");
-                }
-        } else if (from_size == 32 && to_size == 16) {
-                if (from_base == nir_type_float) {
-                        /* TODO: second vectorized source? */
-                        struct bifrost_fma_2src pack = {
-                                .src0 = bi_get_src(ins, regs, 0, true),
-                                .src1 = BIFROST_SRC_STAGE, /* 0 */
-                                .op = BIFROST_FMA_FLOAT32_TO_16
-                        };
-
-                        RETURN_PACKED(pack);
+                        assert(to_base != nir_type_float);
+                        is_unsigned = to_unsigned;
+
+                        if (from_size == 32 && to_size == 32)
+                                mode = BIFROST_CONV_F32_TO_I32;
+                        else if (from_size == 16 && to_size == 16)
+                                mode = BIFROST_CONV_F16_TO_I16;
+                        else
+                                unreachable("Invalid float conversion");
                 } else {
-                        unreachable("i16 not yet implemented");
+                        assert(to_base == nir_type_float);
+                        assert(from_size == to_size);
+
+                        if (to_size == 32)
+                                mode = BIFROST_CONV_I32_TO_F32;
+                        else if (to_size == 16)
+                                mode = BIFROST_CONV_I16_TO_F16;
+                        else
+                                unreachable("Invalid int conversion");
                 }
+
+                /* Fixup swizzle for 32-bit only modes */
+
+                if (mode == BIFROST_CONV_I32_TO_F32)
+                        swizzle = 0b11;
+                else if (mode == BIFROST_CONV_F32_TO_I32)
+                        swizzle = 0b10;
+
+                op = BIFROST_CONVERT(is_unsigned, ins->roundmode, swizzle, mode);
+
+                /* Unclear what the top bit is for... maybe 16-bit related */
+                bool mode2 = mode == BIFROST_CONV_F16_TO_I16;
+                bool mode6 = mode == BIFROST_CONV_I16_TO_F16;
+
+                if (!(mode2 || mode6))
+                        op |= 0x100;
         }
 
-        unreachable("Unknown convert");
+        return bi_pack_fma_1src(ins, regs, BIFROST_FMA_CONVERT | op);
 }
 
 static unsigned
index 88ed61601b2be1cedd7ffb60ff03d57b71e5d639..8700b18d436b5265ea0ef3b22a8274ca1fb22ff9 100644 (file)
@@ -333,39 +333,34 @@ struct bifrost_shift_add {
         unsigned op : 7;
 } __attribute__((packed));
 
-#define BIFROST_FMA_INT16_TO_32 (0xe0198 >> 3)
-
-struct bifrost_fma_int16_to_32 {
-        unsigned src0 : 3;
-        unsigned is_unsigned : 1;
-        unsigned swizzle : 1;
-        unsigned to_float : 1;
-        unsigned op : 17;
-} __attribute__((packed));
-
-/* We could combine but it's easier to just use FMA_ONE_SRC */
-#define BIFROST_FMA_FLOAT16_TO_32(y) (0xe01a2 | ((y) ? 1 : 0))
-
 /* Two sources for vectorization */
 #define BIFROST_FMA_FLOAT32_TO_16 (0xdd000 >> 3)
 
-/* Again we could combine but easier to just ONE_SRC with an
- * argumnt for unsignedness */
-#define BIFROST_FMA_FLOAT32_TO_INT(u) (0xe0136 | ((u) ? 1 : 0))
-#define BIFROST_FMA_INT_TO_FLOAT32(u) (0xe0178 | ((u) ? 1 : 0))
+enum bifrost_convert_mode {
+        BIFROST_CONV_UNK0 = 0,
+        BIFROST_CONV_F32_TO_I32 = 1,
+        BIFROST_CONV_F16_TO_I16 = 2,
+        BIFROST_CONV_I32_TO_F32 = 3,
+        BIFROST_CONV_I16_TO_X32 = 4,
+        BIFROST_CONV_F16_TO_F32 = 5,
+        BIFROST_CONV_I16_TO_F16 = 6,
+        BIFROST_CONV_UNK7 = 7
+};
 
-/* Used for f2i16 and i2f16 */
-#define BIFROST_FMA_F2I16 (0xe00)
+/* i16 to x32 */
+#define BIFROST_CONVERT_4(is_unsigned, component, to_float) \
+        ((is_unsigned & 1) | ((component & 1) << 1) | ((to_float & 1) << 2) | \
+         ((0x3) << 3) | ((4) << 5) | 0x100)
 
-struct bifrost_fma_f2i_i2f16 {
-        unsigned src0 : 3;
-        unsigned is_unsigned : 1;
-        unsigned direction : 2; /* 00 for i2f, 11 for f2i */
-        unsigned swizzle : 2;
-        unsigned unk : 2; /* always 10 */
-        unsigned direction_2 : 1; /* 0 for f2i, 1 for i2f */
-        unsigned op : 12;
-} __attribute__((packed));
+/* f16 to f32 */
+#define BIFROST_CONVERT_5(component) \
+        ((component & 1) | ((1) << 1) | ((5) << 5) | 0x100)
+
+/* Other conversions */
+#define BIFROST_CONVERT(is_unsigned, roundmode, swizzle, mode) \
+        ((is_unsigned & 1) | ((roundmode & 3) << 1) | ((swizzle & 3) << 3) | ((mode & 7) << 5))
+
+#define BIFROST_FMA_CONVERT (0xe0000)
 
 enum bifrost_ldst_type {
         BIFROST_LDST_F16 = 0,