diff options
-rw-r--r-- | src/freedreno/ir3/ir3.h | 16 | ||||
-rw-r--r-- | src/freedreno/ir3/ir3_ra.c | 59 | ||||
-rw-r--r-- | src/freedreno/ir3/ir3_validate.c | 44 |
3 files changed, 60 insertions, 59 deletions
diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h index d6ff469b26e..218fc04ab5a 100644 --- a/src/freedreno/ir3/ir3.h +++ b/src/freedreno/ir3/ir3.h @@ -976,6 +976,22 @@ static inline type_t half_type(type_t type) } } +static inline type_t full_type(type_t type) +{ + switch (type) { + case TYPE_F16: return TYPE_F32; + case TYPE_U16: return TYPE_U32; + case TYPE_S16: return TYPE_S32; + case TYPE_F32: + case TYPE_U32: + case TYPE_S32: + return type; + default: + assert(0); + return ~0; + } +} + /* some cat2 instructions (ie. those which are not float) can embed an * immediate: */ diff --git a/src/freedreno/ir3/ir3_ra.c b/src/freedreno/ir3/ir3_ra.c index 8196203848e..44dc6f1b8e4 100644 --- a/src/freedreno/ir3/ir3_ra.c +++ b/src/freedreno/ir3/ir3_ra.c @@ -1105,60 +1105,6 @@ ra_add_interference(struct ir3_ra_ctx *ctx) } } -/* some instructions need fix-up if dst register is half precision: */ -static void fixup_half_instr_dst(struct ir3_instruction *instr) -{ - switch (opc_cat(instr->opc)) { - case 1: /* move instructions */ - instr->cat1.dst_type = half_type(instr->cat1.dst_type); - break; - case 4: - switch (instr->opc) { - case OPC_RSQ: - instr->opc = OPC_HRSQ; - break; - case OPC_LOG2: - instr->opc = OPC_HLOG2; - break; - case OPC_EXP2: - instr->opc = OPC_HEXP2; - break; - default: - break; - } - break; - case 5: - instr->cat5.type = half_type(instr->cat5.type); - break; - } -} -/* some instructions need fix-up if src register is half precision: */ -static void fixup_half_instr_src(struct ir3_instruction *instr) -{ - switch (instr->opc) { - case OPC_MOV: - instr->cat1.src_type = half_type(instr->cat1.src_type); - break; - case OPC_MAD_F32: - instr->opc = OPC_MAD_F16; - break; - case OPC_SEL_B32: - instr->opc = OPC_SEL_B16; - break; - case OPC_SEL_S32: - instr->opc = OPC_SEL_S16; - break; - case OPC_SEL_F32: - instr->opc = OPC_SEL_F16; - break; - case OPC_SAD_S32: - instr->opc = OPC_SAD_S16; - break; - default: - break; - } -} - /* NOTE: instr could be NULL for IR3_REG_ARRAY case, for the first * array access(es) which do not have any previous access to depend * on from scheduling point of view @@ -1241,8 +1187,6 @@ ra_block_alloc(struct ir3_ra_ctx *ctx, struct ir3_block *block) if (writes_gpr(instr)) { if (should_assign(ctx, instr)) { reg_assign(ctx, instr->regs[0], instr); - if (instr->regs[0]->flags & IR3_REG_HALF) - fixup_half_instr_dst(instr); } } @@ -1258,9 +1202,6 @@ ra_block_alloc(struct ir3_ra_ctx *ctx, struct ir3_block *block) /* Note: reg->instr could be null for IR3_REG_ARRAY */ if (src || (reg->flags & IR3_REG_ARRAY)) reg_assign(ctx, instr->regs[n+1], src); - - if (instr->regs[n+1]->flags & IR3_REG_HALF) - fixup_half_instr_src(instr); } } diff --git a/src/freedreno/ir3/ir3_validate.c b/src/freedreno/ir3/ir3_validate.c index 422c9f49f6f..ec8bb937da8 100644 --- a/src/freedreno/ir3/ir3_validate.c +++ b/src/freedreno/ir3/ir3_validate.c @@ -99,6 +99,50 @@ validate_instr(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr) } _mesa_set_add(ctx->defs, instr); + + /* Check that src/dst types match the register types, and for + * instructions that have different opcodes depending on type, + * that the opcodes are correct. + */ + switch (opc_cat(instr->opc)) { + case 1: /* move instructions */ + if (instr->regs[0]->flags & IR3_REG_HALF) { + validate_assert(ctx, instr->cat1.dst_type == half_type(instr->cat1.dst_type)); + } else { + validate_assert(ctx, instr->cat1.dst_type == full_type(instr->cat1.dst_type)); + } + if (instr->regs[1]->flags & IR3_REG_HALF) { + validate_assert(ctx, instr->cat1.src_type == half_type(instr->cat1.src_type)); + } else { + validate_assert(ctx, instr->cat1.src_type == full_type(instr->cat1.src_type)); + } + break; + case 3: + /* Validate that cat3 opc matches the src type. We've already checked that all + * the src regs are same type + */ + if (instr->regs[1]->flags & IR3_REG_HALF) { + validate_assert(ctx, instr->opc == cat3_half_opc(instr->opc)); + } else { + validate_assert(ctx, instr->opc == cat3_full_opc(instr->opc)); + } + break; + case 4: + /* Validate that cat4 opc matches the dst type: */ + if (instr->regs[0]->flags & IR3_REG_HALF) { + validate_assert(ctx, instr->opc == cat4_half_opc(instr->opc)); + } else { + validate_assert(ctx, instr->opc == cat4_full_opc(instr->opc)); + } + break; + case 5: + if (instr->regs[0]->flags & IR3_REG_HALF) { + validate_assert(ctx, instr->cat5.type == half_type(instr->cat5.type)); + } else { + validate_assert(ctx, instr->cat5.type == full_type(instr->cat5.type)); + } + break; + } } void |