mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-24 17:30:12 +01:00
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:
parent
3561d34fff
commit
f484d63617
4 changed files with 122 additions and 8 deletions
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue