freedreno/ir3: add helpers to deal with src/dst types

Add some helpers to properly maintain src/dst types, and in the cases
where opcode depends on src or dst type, maintain that as well.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5048>
This commit is contained in:
Rob Clark 2020-05-16 14:24:45 -07:00 committed by Marge Bot
parent 3561d34fff
commit f484d63617
4 changed files with 122 additions and 8 deletions

View file

@ -1211,3 +1211,69 @@ ir3_find_ssa_uses(struct ir3 *ir, void *mem_ctx, bool falsedeps)
}
}
}
/**
* Set the destination type of an instruction, for example if a
* conversion is folded in, handling the special cases where the
* instruction's dest type or opcode needs to be fixed up.
*/
void
ir3_set_dst_type(struct ir3_instruction *instr, bool half)
{
if (half) {
instr->regs[0]->flags |= IR3_REG_HALF;
} else {
instr->regs[0]->flags &= ~IR3_REG_HALF;
}
switch (opc_cat(instr->opc)) {
case 1: /* move instructions */
if (half) {
instr->cat1.dst_type = half_type(instr->cat1.dst_type);
} else {
instr->cat1.dst_type = full_type(instr->cat1.dst_type);
}
break;
case 4:
if (half) {
instr->opc = cat4_half_opc(instr->opc);
} else {
instr->opc = cat4_full_opc(instr->opc);
}
break;
case 5:
if (half) {
instr->cat5.type = half_type(instr->cat5.type);
} else {
instr->cat5.type = full_type(instr->cat5.type);
}
break;
}
}
/**
* One-time fixup for instruction src-types. Other than cov's that
* are folded, an instruction's src type does not change.
*/
void
ir3_fixup_src_type(struct ir3_instruction *instr)
{
bool half = !!(instr->regs[1]->flags & IR3_REG_HALF);
switch (opc_cat(instr->opc)) {
case 1: /* move instructions */
if (half) {
instr->cat1.src_type = half_type(instr->cat1.src_type);
} else {
instr->cat1.src_type = full_type(instr->cat1.src_type);
}
break;
case 3:
if (half) {
instr->opc = cat3_half_opc(instr->opc);
} else {
instr->opc = cat3_full_opc(instr->opc);
}
break;
}
}

View file

@ -595,6 +595,9 @@ unsigned ir3_count_instructions_ra(struct ir3 *ir);
void ir3_find_ssa_uses(struct ir3 *ir, void *mem_ctx, bool falsedeps);
void ir3_set_dst_type(struct ir3_instruction *instr, bool half);
void ir3_fixup_src_type(struct ir3_instruction *instr);
#include "util/set.h"
#define foreach_ssa_use(__use, __instr) \
for (struct ir3_instruction *__use = (void *)~0; \
@ -830,6 +833,54 @@ static inline bool is_bool(struct ir3_instruction *instr)
}
}
static inline opc_t
cat3_half_opc(opc_t opc)
{
switch (opc) {
case OPC_MAD_F32: return OPC_MAD_F16;
case OPC_SEL_B32: return OPC_SEL_B16;
case OPC_SEL_S32: return OPC_SEL_S16;
case OPC_SEL_F32: return OPC_SEL_F16;
case OPC_SAD_S32: return OPC_SAD_S16;
default: return opc;
}
}
static inline opc_t
cat3_full_opc(opc_t opc)
{
switch (opc) {
case OPC_MAD_F16: return OPC_MAD_F32;
case OPC_SEL_B16: return OPC_SEL_B32;
case OPC_SEL_S16: return OPC_SEL_S32;
case OPC_SEL_F16: return OPC_SEL_F32;
case OPC_SAD_S16: return OPC_SAD_S32;
default: return opc;
}
}
static inline opc_t
cat4_half_opc(opc_t opc)
{
switch (opc) {
case OPC_RSQ: return OPC_HRSQ;
case OPC_LOG2: return OPC_HLOG2;
case OPC_EXP2: return OPC_HEXP2;
default: return opc;
}
}
static inline opc_t
cat4_full_opc(opc_t opc)
{
switch (opc) {
case OPC_HRSQ: return OPC_RSQ;
case OPC_HLOG2: return OPC_LOG2;
case OPC_HEXP2: return OPC_EXP2;
default: return opc;
}
}
static inline bool is_meta(struct ir3_instruction *instr)
{
return (opc_cat(instr->opc) == -1);

View file

@ -148,12 +148,7 @@ try_conversion_folding(struct ir3_instruction *conv)
}
}
if (is_half(conv)) {
src->regs[0]->flags |= IR3_REG_HALF;
} else {
src->regs[0]->flags &= ~IR3_REG_HALF;
}
ir3_set_dst_type(src, is_half(conv));
rewrite_src_uses(src);
return true;

View file

@ -256,9 +256,11 @@ ir3_put_dst(struct ir3_context *ctx, nir_dest *dst)
if (bit_size == 16) {
for (unsigned i = 0; i < ctx->last_dst_n; i++) {
struct ir3_instruction *dst = ctx->last_dst[i];
dst->regs[0]->flags |= IR3_REG_HALF;
ir3_set_dst_type(dst, true);
ir3_fixup_src_type(dst);
if (dst->opc == OPC_META_SPLIT) {
dst->regs[1]->instr->regs[0]->flags |= IR3_REG_HALF;
ir3_set_dst_type(ssa(dst->regs[1]), true);
ir3_fixup_src_type(ssa(dst->regs[1]));
dst->regs[1]->flags |= IR3_REG_HALF;
}
}