freedreno/ir3: rework size/type conversion instructions
authorRob Clark <robdclark@gmail.com>
Thu, 26 Apr 2018 18:54:24 +0000 (14:54 -0400)
committerRob Clark <robdclark@gmail.com>
Mon, 11 Jun 2018 13:06:03 +0000 (09:06 -0400)
With 8b and 16b, there are a lot more to handle.

Signed-off-by: Rob Clark <robdclark@gmail.com>
src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c

index 186171960e71e1dde43e47b2edce0e4a0e25e523..206a3f0f772ca6d013b2a00695a0a9c3faa1ec85 100644 (file)
@@ -919,11 +919,138 @@ ir3_n2b(struct ir3_block *block, struct ir3_instruction *instr)
  * alu/sfu instructions:
  */
 
+static struct ir3_instruction *
+create_cov(struct ir3_context *ctx, struct ir3_instruction *src,
+               unsigned src_bitsize, nir_op op)
+{
+       type_t src_type, dst_type;
+
+       switch (op) {
+       case nir_op_f2f32:
+       case nir_op_f2f16_rtne:
+       case nir_op_f2f16_rtz:
+       case nir_op_f2f16_undef:
+       case nir_op_f2i32:
+       case nir_op_f2i16:
+       case nir_op_f2i8:
+       case nir_op_f2u32:
+       case nir_op_f2u16:
+       case nir_op_f2u8:
+               switch (src_bitsize) {
+               case 32:
+                       src_type = TYPE_F32;
+                       break;
+               case 16:
+                       src_type = TYPE_F16;
+                       break;
+               default:
+                       compile_error(ctx, "invalid src bit size: %u", src_bitsize);
+               }
+               break;
+
+       case nir_op_i2f32:
+       case nir_op_i2f16:
+       case nir_op_i2i32:
+       case nir_op_i2i16:
+       case nir_op_i2i8:
+               switch (src_bitsize) {
+               case 32:
+                       src_type = TYPE_S32;
+                       break;
+               case 16:
+                       src_type = TYPE_S16;
+                       break;
+               case 8:
+                       src_type = TYPE_S8;
+                       break;
+               default:
+                       compile_error(ctx, "invalid src bit size: %u", src_bitsize);
+               }
+               break;
+
+       case nir_op_u2f32:
+       case nir_op_u2f16:
+       case nir_op_u2u32:
+       case nir_op_u2u16:
+       case nir_op_u2u8:
+               switch (src_bitsize) {
+               case 32:
+                       src_type = TYPE_U32;
+                       break;
+               case 16:
+                       src_type = TYPE_U16;
+                       break;
+               case 8:
+                       src_type = TYPE_U8;
+                       break;
+               default:
+                       compile_error(ctx, "invalid src bit size: %u", src_bitsize);
+               }
+               break;
+
+       default:
+               compile_error(ctx, "invalid conversion op: %u", op);
+       }
+
+       switch (op) {
+       case nir_op_f2f32:
+       case nir_op_i2f32:
+       case nir_op_u2f32:
+               dst_type = TYPE_F32;
+               break;
+
+       case nir_op_f2f16_rtne:
+       case nir_op_f2f16_rtz:
+       case nir_op_f2f16_undef:
+               /* TODO how to handle rounding mode? */
+       case nir_op_i2f16:
+       case nir_op_u2f16:
+               dst_type = TYPE_F16;
+               break;
+
+       case nir_op_f2i32:
+       case nir_op_i2i32:
+               dst_type = TYPE_S32;
+               break;
+
+       case nir_op_f2i16:
+       case nir_op_i2i16:
+               dst_type = TYPE_S16;
+               break;
+
+       case nir_op_f2i8:
+       case nir_op_i2i8:
+               dst_type = TYPE_S8;
+               break;
+
+       case nir_op_f2u32:
+       case nir_op_u2u32:
+               dst_type = TYPE_U32;
+               break;
+
+       case nir_op_f2u16:
+       case nir_op_u2u16:
+               dst_type = TYPE_U16;
+               break;
+
+       case nir_op_f2u8:
+       case nir_op_u2u8:
+               dst_type = TYPE_U8;
+               break;
+
+       default:
+               compile_error(ctx, "invalid conversion op: %u", op);
+       }
+
+       return ir3_COV(ctx->block, src, src_type, dst_type);
+}
+
 static void
 emit_alu(struct ir3_context *ctx, nir_alu_instr *alu)
 {
        const nir_op_info *info = &nir_op_infos[alu->op];
        struct ir3_instruction **dst, *src[info->num_inputs];
+       unsigned bs[info->num_inputs];     /* bit size */
        struct ir3_block *b = ctx->block;
        unsigned dst_sz, wrmask;
 
@@ -990,22 +1117,33 @@ emit_alu(struct ir3_context *ctx, nir_alu_instr *alu)
                compile_assert(ctx, !asrc->negate);
 
                src[i] = get_src(ctx, &asrc->src)[asrc->swizzle[chan]];
+               bs[i] = nir_src_bit_size(asrc->src);
 
                compile_assert(ctx, src[i]);
        }
 
        switch (alu->op) {
+       case nir_op_f2f32:
+       case nir_op_f2f16_rtne:
+       case nir_op_f2f16_rtz:
+       case nir_op_f2f16_undef:
        case nir_op_f2i32:
-               dst[0] = ir3_COV(b, src[0], TYPE_F32, TYPE_S32);
-               break;
+       case nir_op_f2i16:
+       case nir_op_f2i8:
        case nir_op_f2u32:
-               dst[0] = ir3_COV(b, src[0], TYPE_F32, TYPE_U32);
-               break;
+       case nir_op_f2u16:
+       case nir_op_f2u8:
        case nir_op_i2f32:
-               dst[0] = ir3_COV(b, src[0], TYPE_S32, TYPE_F32);
-               break;
+       case nir_op_i2f16:
+       case nir_op_i2i32:
+       case nir_op_i2i16:
+       case nir_op_i2i8:
        case nir_op_u2f32:
-               dst[0] = ir3_COV(b, src[0], TYPE_U32, TYPE_F32);
+       case nir_op_u2f16:
+       case nir_op_u2u32:
+       case nir_op_u2u16:
+       case nir_op_u2u8:
+               dst[0] = create_cov(ctx, src[0], bs[0], alu->op);
                break;
        case nir_op_f2b:
                dst[0] = ir3_CMPS_F(b, src[0], 0, create_immed(b, fui(0.0)), 0);
@@ -1237,10 +1375,18 @@ emit_alu(struct ir3_context *ctx, nir_alu_instr *alu)
                dst[0] = ir3_n2b(b, dst[0]);
                break;
 
-       case nir_op_bcsel:
-               dst[0] = ir3_SEL_B32(b, src[1], 0, ir3_b2n(b, src[0]), 0, src[2], 0);
+       case nir_op_bcsel: {
+               struct ir3_instruction *cond = ir3_b2n(b, src[0]);
+               compile_assert(ctx, bs[1] == bs[2]);
+               /* the boolean condition is 32b even if src[1] and src[2] are
+                * half-precision, but sel.b16 wants all three src's to be the
+                * same type.
+                */
+               if (bs[1] < 32)
+                       cond = ir3_COV(b, cond, TYPE_U32, TYPE_U16);
+               dst[0] = ir3_SEL_B32(b, src[1], 0, cond, 0, src[2], 0);
                break;
-
+       }
        case nir_op_bit_count:
                dst[0] = ir3_CBITS_B(b, src[0], 0);
                break;