Module: Mesa Branch: main Commit: e74aaa347b671587c875b00d5a5cd1e89375aaa8 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=e74aaa347b671587c875b00d5a5cd1e89375aaa8
Author: Simon Perretta <[email protected]> Date: Wed Jan 18 15:41:23 2023 +0000 pvr: Support dual-destination ALU instructions Signed-off-by: Simon Perretta <[email protected]> Acked-by: Frank Binns <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20430> --- src/imagination/rogue/passes/rogue_copy_prop.c | 20 ++-- src/imagination/rogue/passes/rogue_dce.c | 2 +- .../rogue/passes/rogue_lower_pseudo_ops.c | 14 +-- .../rogue/passes/rogue_schedule_instr_groups.c | 15 ++- src/imagination/rogue/rogue.c | 42 ++++---- src/imagination/rogue/rogue.h | 25 +++-- src/imagination/rogue/rogue_alu_instrs.def | 58 +++++----- src/imagination/rogue/rogue_builder.c | 120 +++++++++++++-------- src/imagination/rogue/rogue_builder.h | 21 ++-- src/imagination/rogue/rogue_info.c | 46 ++++---- src/imagination/rogue/rogue_print.c | 15 ++- src/imagination/rogue/rogue_validate.c | 5 +- 12 files changed, 235 insertions(+), 148 deletions(-) diff --git a/src/imagination/rogue/passes/rogue_copy_prop.c b/src/imagination/rogue/passes/rogue_copy_prop.c index a1102aeb9eb..bd58c128c3a 100644 --- a/src/imagination/rogue/passes/rogue_copy_prop.c +++ b/src/imagination/rogue/passes/rogue_copy_prop.c @@ -37,7 +37,8 @@ static bool can_back_prop(rogue_alu_instr *mov) { /* TODO: Check for src/dst modifiers when support is added for them. */ - if (!rogue_ref_is_reg(&mov->src[0].ref) || !rogue_ref_is_reg(&mov->dst.ref)) + if (!rogue_ref_is_reg(&mov->src[0].ref) || + !rogue_ref_is_reg(&mov->dst[0].ref)) return false; if (mov->src[0].ref.reg->regarray) @@ -45,7 +46,7 @@ static bool can_back_prop(rogue_alu_instr *mov) /* Vertex outputs require uvsw.write; only back-propagate if the parent * instruction is also a mov. */ - if (mov->dst.ref.reg->class == ROGUE_REG_CLASS_VTXOUT) { + if (mov->dst[0].ref.reg->class == ROGUE_REG_CLASS_VTXOUT) { rogue_reg_write *write = list_first_entry(&mov->src[0].ref.reg->writes, rogue_reg_write, link); @@ -62,7 +63,7 @@ static bool can_back_prop(rogue_alu_instr *mov) return false; /* Is this the only instruction that writes to this register? */ - if (!list_is_singular(&mov->dst.ref.reg->writes)) + if (!list_is_singular(&mov->dst[0].ref.reg->writes)) return false; return true; @@ -72,13 +73,14 @@ static bool can_forward_prop(rogue_alu_instr *mov) { /* TODO: Check for src/dst modifiers when support is added for them. */ - if (!rogue_ref_is_reg(&mov->src[0].ref) || !rogue_ref_is_reg(&mov->dst.ref)) + if (!rogue_ref_is_reg(&mov->src[0].ref) || + !rogue_ref_is_reg(&mov->dst[0].ref)) return false; - if (mov->dst.ref.reg->regarray) + if (mov->dst[0].ref.reg->regarray) return false; - if (mov->dst.ref.reg->class != ROGUE_REG_CLASS_SSA) + if (mov->dst[0].ref.reg->class != ROGUE_REG_CLASS_SSA) return false; /* Is the source register written to more than once (driver-supplied regs can @@ -87,7 +89,7 @@ static bool can_forward_prop(rogue_alu_instr *mov) return false; /* Is this the only instruction that writes to this register? */ - if (!list_is_singular(&mov->dst.ref.reg->writes)) + if (!list_is_singular(&mov->dst[0].ref.reg->writes)) return false; return true; @@ -96,7 +98,7 @@ static bool can_forward_prop(rogue_alu_instr *mov) static bool rogue_back_prop(rogue_alu_instr *mov) { rogue_reg *mov_src = mov->src[0].ref.reg; - rogue_reg *mov_dst = mov->dst.ref.reg; + rogue_reg *mov_dst = mov->dst[0].ref.reg; rogue_reg_write *write = list_first_entry(&mov_src->writes, rogue_reg_write, link); @@ -114,7 +116,7 @@ static bool rogue_forward_prop(rogue_alu_instr *mov) bool success = true; rogue_reg *mov_src = mov->src[0].ref.reg; - rogue_reg *mov_dst = mov->dst.ref.reg; + rogue_reg *mov_dst = mov->dst[0].ref.reg; rogue_foreach_reg_use_safe (use, mov_dst) if (rogue_can_replace_reg_use(use, mov_src)) diff --git a/src/imagination/rogue/passes/rogue_dce.c b/src/imagination/rogue/passes/rogue_dce.c index 6acbdd20fcb..75c0b7d03a2 100644 --- a/src/imagination/rogue/passes/rogue_dce.c +++ b/src/imagination/rogue/passes/rogue_dce.c @@ -47,7 +47,7 @@ static bool rogue_dce_alu_instr(rogue_alu_instr *alu) switch (alu->op) { case ROGUE_ALU_OP_MOV: case ROGUE_ALU_OP_MBYP: - if (!alu->mod && rogue_alu_dst_src_equal(&alu->dst, &alu->src[0])) { + if (!alu->mod && rogue_alu_dst_src_equal(&alu->dst[0], &alu->src[0])) { rogue_instr_delete(&alu->instr); progress = true; } diff --git a/src/imagination/rogue/passes/rogue_lower_pseudo_ops.c b/src/imagination/rogue/passes/rogue_lower_pseudo_ops.c index 26a1ed26619..b89905d2c87 100644 --- a/src/imagination/rogue/passes/rogue_lower_pseudo_ops.c +++ b/src/imagination/rogue/passes/rogue_lower_pseudo_ops.c @@ -35,7 +35,7 @@ static inline bool rogue_lower_FABS(rogue_builder *b, rogue_alu_instr *fabs) { - rogue_alu_instr *mbyp = rogue_MBYP(b, fabs->dst.ref, fabs->src[0].ref); + rogue_alu_instr *mbyp = rogue_MBYP(b, fabs->dst[0].ref, fabs->src[0].ref); rogue_merge_instr_comment(&mbyp->instr, &fabs->instr, "fabs"); rogue_set_alu_src_mod(mbyp, 0, ROGUE_ALU_SRC_MOD_ABS); rogue_instr_delete(&fabs->instr); @@ -45,7 +45,7 @@ static inline bool rogue_lower_FABS(rogue_builder *b, rogue_alu_instr *fabs) static inline bool rogue_lower_FNEG(rogue_builder *b, rogue_alu_instr *fneg) { - rogue_alu_instr *mbyp = rogue_MBYP(b, fneg->dst.ref, fneg->src[0].ref); + rogue_alu_instr *mbyp = rogue_MBYP(b, fneg->dst[0].ref, fneg->src[0].ref); rogue_merge_instr_comment(&mbyp->instr, &fneg->instr, "fneg"); rogue_set_alu_src_mod(mbyp, 0, ROGUE_ALU_SRC_MOD_NEG); rogue_instr_delete(&fneg->instr); @@ -55,7 +55,7 @@ static inline bool rogue_lower_FNEG(rogue_builder *b, rogue_alu_instr *fneg) static inline bool rogue_lower_FNABS(rogue_builder *b, rogue_alu_instr *fnabs) { - rogue_alu_instr *mbyp = rogue_MBYP(b, fnabs->dst.ref, fnabs->src[0].ref); + rogue_alu_instr *mbyp = rogue_MBYP(b, fnabs->dst[0].ref, fnabs->src[0].ref); rogue_merge_instr_comment(&mbyp->instr, &fnabs->instr, "fnabs"); rogue_set_alu_src_mod(mbyp, 0, ROGUE_ALU_SRC_MOD_ABS); rogue_set_alu_src_mod(mbyp, 0, ROGUE_ALU_SRC_MOD_NEG); @@ -70,11 +70,11 @@ static inline bool rogue_lower_MOV(rogue_builder *b, rogue_alu_instr *mov) /* If we're writing to a vertex output register, we need to use uvsw.write. */ - if (rogue_ref_is_reg(&mov->dst.ref) && - mov->dst.ref.reg->class == ROGUE_REG_CLASS_VTXOUT) { - instr = &rogue_UVSW_WRITE(b, mov->dst.ref, mov->src[0].ref)->instr; + if (rogue_ref_is_reg(&mov->dst[0].ref) && + mov->dst[0].ref.reg->class == ROGUE_REG_CLASS_VTXOUT) { + instr = &rogue_UVSW_WRITE(b, mov->dst[0].ref, mov->src[0].ref)->instr; } else { - instr = &rogue_MBYP(b, mov->dst.ref, mov->src[0].ref)->instr; + instr = &rogue_MBYP(b, mov->dst[0].ref, mov->src[0].ref)->instr; } rogue_merge_instr_comment(instr, &mov->instr, "mov"); diff --git a/src/imagination/rogue/passes/rogue_schedule_instr_groups.c b/src/imagination/rogue/passes/rogue_schedule_instr_groups.c index 271ba8b83a6..cb288fefa5b 100644 --- a/src/imagination/rogue/passes/rogue_schedule_instr_groups.c +++ b/src/imagination/rogue/passes/rogue_schedule_instr_groups.c @@ -72,11 +72,16 @@ static void rogue_lower_alu_io(rogue_alu_instr *alu, rogue_instr_group *group) const rogue_alu_op_info *info = &rogue_alu_op_infos[alu->op]; enum rogue_instr_phase phase = alu->instr.index; - rogue_set_io_sel(&group->io_sel, - info->phase_io[phase].dst, - &alu->dst.ref, - true); - alu->dst.ref = rogue_ref_io(info->phase_io[phase].dst); + for (unsigned u = 0; u < info->num_dsts; ++u) { + if (info->phase_io[phase].dst[u] == ROGUE_IO_INVALID) + continue; + + rogue_set_io_sel(&group->io_sel, + info->phase_io[phase].dst[u], + &alu->dst[u].ref, + true); + alu->dst[u].ref = rogue_ref_io(info->phase_io[phase].dst[u]); + } for (unsigned u = 0; u < info->num_srcs; ++u) { if (info->phase_io[phase].src[u] == ROGUE_IO_INVALID) diff --git a/src/imagination/rogue/rogue.c b/src/imagination/rogue/rogue.c index 8bd10225534..3ba5aec62ae 100644 --- a/src/imagination/rogue/rogue.c +++ b/src/imagination/rogue/rogue.c @@ -646,17 +646,20 @@ void rogue_link_instr_write(rogue_instr *instr) switch (instr->type) { case ROGUE_INSTR_TYPE_ALU: { rogue_alu_instr *alu = rogue_instr_as_alu(instr); + const unsigned num_dsts = rogue_alu_op_infos[alu->op].num_dsts; - if (rogue_ref_is_reg(&alu->dst.ref)) { - rogue_reg_write *write = &alu->dst_write.reg; - rogue_reg *reg = alu->dst.ref.reg; - rogue_link_instr_write_reg(instr, write, reg, 0); - } else if (rogue_ref_is_regarray(&alu->dst.ref)) { - struct util_dynarray **writearray = &alu->dst_write.regarray; - rogue_regarray *regarray = alu->dst.ref.regarray; - rogue_link_instr_write_regarray(instr, writearray, regarray, 0); - } else { - unreachable("Invalid destination reference type."); + for (unsigned i = 0; i < num_dsts; ++i) { + if (rogue_ref_is_reg(&alu->dst[i].ref)) { + rogue_reg_write *write = &alu->dst_write[i].reg; + rogue_reg *reg = alu->dst[i].ref.reg; + rogue_link_instr_write_reg(instr, write, reg, 0); + } else if (rogue_ref_is_regarray(&alu->dst[i].ref)) { + struct util_dynarray **writearray = &alu->dst_write[i].regarray; + rogue_regarray *regarray = alu->dst[i].ref.regarray; + rogue_link_instr_write_regarray(instr, writearray, regarray, 0); + } else { + unreachable("Invalid destination reference type."); + } } break; @@ -815,15 +818,18 @@ void rogue_unlink_instr_write(rogue_instr *instr) switch (instr->type) { case ROGUE_INSTR_TYPE_ALU: { rogue_alu_instr *alu = rogue_instr_as_alu(instr); + const unsigned num_dsts = rogue_alu_op_infos[alu->op].num_dsts; - if (rogue_ref_is_reg(&alu->dst.ref)) { - rogue_reg_write *write = &alu->dst_write.reg; - rogue_unlink_instr_write_reg(instr, write); - } else if (rogue_ref_is_regarray(&alu->dst.ref)) { - struct util_dynarray **writearray = &alu->dst_write.regarray; - rogue_unlink_instr_write_regarray(instr, writearray); - } else { - unreachable("Invalid destination reference type."); + for (unsigned i = 0; i < num_dsts; ++i) { + if (rogue_ref_is_reg(&alu->dst[i].ref)) { + rogue_reg_write *write = &alu->dst_write[i].reg; + rogue_unlink_instr_write_reg(instr, write); + } else if (rogue_ref_is_regarray(&alu->dst[i].ref)) { + struct util_dynarray **writearray = &alu->dst_write[i].regarray; + rogue_unlink_instr_write_regarray(instr, writearray); + } else { + unreachable("Invalid destination reference type."); + } } break; diff --git a/src/imagination/rogue/rogue.h b/src/imagination/rogue/rogue.h index cd78bacde8e..f331a3814ca 100644 --- a/src/imagination/rogue/rogue.h +++ b/src/imagination/rogue/rogue.h @@ -864,6 +864,7 @@ static inline bool rogue_refs_equal(rogue_ref *a, rogue_ref *b) typedef struct rogue_alu_dst { rogue_ref ref; uint64_t mod; + unsigned index; } rogue_alu_dst; typedef struct rogue_alu_src { @@ -1066,9 +1067,10 @@ static inline bool rogue_ctrl_op_has_dsts(enum rogue_ctrl_op op) /* ALU instructions have at most 3 sources. */ #define ROGUE_ALU_OP_MAX_SRCS 3 +#define ROGUE_ALU_OP_MAX_DSTS 2 typedef struct rogue_alu_io_info { - enum rogue_io dst; + enum rogue_io dst[ROGUE_ALU_OP_MAX_DSTS]; enum rogue_io src[ROGUE_ALU_OP_MAX_SRCS]; } rogue_alu_io_info; @@ -1076,17 +1078,18 @@ typedef struct rogue_alu_io_info { typedef struct rogue_alu_op_info { const char *str; + unsigned num_dsts; unsigned num_srcs; uint64_t supported_phases; rogue_alu_io_info phase_io[ROGUE_INSTR_PHASE_COUNT]; uint64_t supported_op_mods; - uint64_t supported_dst_mods; + uint64_t supported_dst_mods[ROGUE_ALU_OP_MAX_DSTS]; uint64_t supported_src_mods[ROGUE_ALU_OP_MAX_SRCS]; /* TODO NEXT: Do the same for other instruction types. */ - uint64_t supported_dst_types; + uint64_t supported_dst_types[ROGUE_ALU_OP_MAX_DSTS]; uint64_t supported_src_types[ROGUE_ALU_OP_MAX_SRCS]; } rogue_alu_op_info; @@ -1143,12 +1146,12 @@ typedef struct rogue_alu_instr { uint64_t mod; - rogue_alu_dst dst; + rogue_alu_dst dst[ROGUE_ALU_OP_MAX_DSTS]; union { rogue_reg_write reg; struct util_dynarray *regarray; - } dst_write; + } dst_write[ROGUE_ALU_OP_MAX_DSTS]; rogue_alu_src src[ROGUE_ALU_OP_MAX_SRCS]; @@ -1171,9 +1174,17 @@ static inline bool rogue_alu_op_mod_is_set(const rogue_alu_instr *alu, } static inline void rogue_set_alu_dst_mod(rogue_alu_instr *alu, + unsigned dst_index, enum rogue_alu_dst_mod mod) { - alu->dst.mod |= BITFIELD64_BIT(mod); + alu->dst[dst_index].mod |= BITFIELD64_BIT(mod); +} + +static inline bool rogue_alu_dst_mod_is_set(const rogue_alu_instr *alu, + unsigned dst_index, + enum rogue_alu_dst_mod mod) +{ + return !!(alu->dst[dst_index].mod & BITFIELD64_BIT(mod)); } static inline void rogue_set_alu_src_mod(rogue_alu_instr *alu, @@ -2082,7 +2093,7 @@ static inline bool rogue_dst_reg_replace(rogue_reg_write *write, switch (instr->type) { case ROGUE_INSTR_TYPE_ALU: - ref = &rogue_instr_as_alu(instr)->dst.ref; + ref = &rogue_instr_as_alu(instr)->dst[dst_index].ref; break; case ROGUE_INSTR_TYPE_BACKEND: diff --git a/src/imagination/rogue/rogue_alu_instrs.def b/src/imagination/rogue/rogue_alu_instrs.def index 371017c9e52..6f903865eea 100644 --- a/src/imagination/rogue/rogue_alu_instrs.def +++ b/src/imagination/rogue/rogue_alu_instrs.def @@ -28,40 +28,48 @@ */ /* - * ROGUE_BUILDER_DEFINE_ALUs + * ROGUE_BUILDER_DEFINE_ALUds + * d: Number of destinations. * s: Number of sources. */ -#ifndef ROGUE_BUILDER_DEFINE_ALU1 -#define ROGUE_BUILDER_DEFINE_ALU1(...) -#endif /* ROGUE_BUILDER_DEFINE_ALU1 */ +#ifndef ROGUE_BUILDER_DEFINE_ALU11 +#define ROGUE_BUILDER_DEFINE_ALU11(...) +#endif /* ROGUE_BUILDER_DEFINE_ALU11 */ -#ifndef ROGUE_BUILDER_DEFINE_ALU2 -#define ROGUE_BUILDER_DEFINE_ALU2(...) -#endif /* ROGUE_BUILDER_DEFINE_ALU2 */ +#ifndef ROGUE_BUILDER_DEFINE_ALU12 +#define ROGUE_BUILDER_DEFINE_ALU12(...) +#endif /* ROGUE_BUILDER_DEFINE_ALU12 */ -#ifndef ROGUE_BUILDER_DEFINE_ALU3 -#define ROGUE_BUILDER_DEFINE_ALU3(...) -#endif /* ROGUE_BUILDER_DEFINE_ALU3 */ +#ifndef ROGUE_BUILDER_DEFINE_ALU13 +#define ROGUE_BUILDER_DEFINE_ALU13(...) +#endif /* ROGUE_BUILDER_DEFINE_ALU13 */ -ROGUE_BUILDER_DEFINE_ALU1(MOV) -ROGUE_BUILDER_DEFINE_ALU1(MBYP) +#ifndef ROGUE_BUILDER_DEFINE_ALU22 +#define ROGUE_BUILDER_DEFINE_ALU22(...) +#endif /* ROGUE_BUILDER_DEFINE_ALU22 */ -ROGUE_BUILDER_DEFINE_ALU1(FABS) -ROGUE_BUILDER_DEFINE_ALU1(FNEG) -ROGUE_BUILDER_DEFINE_ALU1(FNABS) +ROGUE_BUILDER_DEFINE_ALU11(MOV) +ROGUE_BUILDER_DEFINE_ALU11(MBYP) -ROGUE_BUILDER_DEFINE_ALU1(PCK_U8888) +ROGUE_BUILDER_DEFINE_ALU11(FABS) +ROGUE_BUILDER_DEFINE_ALU11(FNEG) +ROGUE_BUILDER_DEFINE_ALU11(FNABS) -ROGUE_BUILDER_DEFINE_ALU2(FADD) -ROGUE_BUILDER_DEFINE_ALU2(FMUL) +ROGUE_BUILDER_DEFINE_ALU11(PCK_U8888) -ROGUE_BUILDER_DEFINE_ALU2(FMAX) -ROGUE_BUILDER_DEFINE_ALU2(FMIN) +ROGUE_BUILDER_DEFINE_ALU12(FADD) +ROGUE_BUILDER_DEFINE_ALU12(FMUL) -ROGUE_BUILDER_DEFINE_ALU3(SEL) -ROGUE_BUILDER_DEFINE_ALU3(FMAD) +ROGUE_BUILDER_DEFINE_ALU12(FMAX) +ROGUE_BUILDER_DEFINE_ALU12(FMIN) -#undef ROGUE_BUILDER_DEFINE_ALU3 -#undef ROGUE_BUILDER_DEFINE_ALU2 -#undef ROGUE_BUILDER_DEFINE_ALU1 +ROGUE_BUILDER_DEFINE_ALU13(FMAD) +ROGUE_BUILDER_DEFINE_ALU13(SEL) + +ROGUE_BUILDER_DEFINE_ALU22(TST) + +#undef ROGUE_BUILDER_DEFINE_ALU22 +#undef ROGUE_BUILDER_DEFINE_ALU13 +#undef ROGUE_BUILDER_DEFINE_ALU12 +#undef ROGUE_BUILDER_DEFINE_ALU11 diff --git a/src/imagination/rogue/rogue_builder.c b/src/imagination/rogue/rogue_builder.c index 87d9ae8809e..8454c78d542 100644 --- a/src/imagination/rogue/rogue_builder.c +++ b/src/imagination/rogue/rogue_builder.c @@ -48,14 +48,19 @@ static inline void rogue_builder_insert_instr(rogue_builder *b, static inline rogue_alu_instr *rogue_build_alu(rogue_builder *b, enum rogue_alu_op op, - rogue_ref dst, + unsigned num_dsts, + rogue_ref dsts[num_dsts], unsigned num_srcs, rogue_ref srcs[num_srcs]) { rogue_alu_instr *alu = rogue_alu_instr_create(rogue_cursor_block(b->cursor), op); - alu->dst.ref = dst; + for (unsigned i = 0; i < num_dsts; ++i) { + alu->dst[i].ref = dsts[i]; + alu->dst[i].index = i; + } + for (unsigned i = 0; i < num_srcs; ++i) { alu->src[i].ref = srcs[i]; alu->src[i].index = i; @@ -65,68 +70,99 @@ static inline rogue_alu_instr *rogue_build_alu(rogue_builder *b, return alu; } -static inline rogue_alu_instr *rogue_build_alu1(rogue_builder *b, - enum rogue_alu_op op, - rogue_ref dst, - rogue_ref src0) +static inline rogue_alu_instr *rogue_build_alu11(rogue_builder *b, + enum rogue_alu_op op, + rogue_ref dst0, + rogue_ref src0) { + rogue_ref dsts[] = { dst0 }; rogue_ref srcs[] = { src0 }; - return rogue_build_alu(b, op, dst, 1, srcs); + return rogue_build_alu(b, op, 1, dsts, 1, srcs); } -static inline rogue_alu_instr *rogue_build_alu2(rogue_builder *b, - enum rogue_alu_op op, - rogue_ref dst, - rogue_ref src0, - rogue_ref src1) +static inline rogue_alu_instr *rogue_build_alu12(rogue_builder *b, + enum rogue_alu_op op, + rogue_ref dst0, + rogue_ref src0, + rogue_ref src1) { + rogue_ref dsts[] = { dst0 }; rogue_ref srcs[] = { src0, src1 }; - return rogue_build_alu(b, op, dst, 2, srcs); + return rogue_build_alu(b, op, 1, dsts, 2, srcs); } -static inline rogue_alu_instr *rogue_build_alu3(rogue_builder *b, - enum rogue_alu_op op, - rogue_ref dst, - rogue_ref src0, - rogue_ref src1, - rogue_ref src2) +static inline rogue_alu_instr *rogue_build_alu13(rogue_builder *b, + enum rogue_alu_op op, + rogue_ref dst0, + rogue_ref src0, + rogue_ref src1, + rogue_ref src2) { + rogue_ref dsts[] = { dst0 }; rogue_ref srcs[] = { src0, src1, src2 }; - return rogue_build_alu(b, op, dst, 3, srcs); + return rogue_build_alu(b, op, 1, dsts, 3, srcs); +} + +static inline rogue_alu_instr *rogue_build_alu22(rogue_builder *b, + enum rogue_alu_op op, + rogue_ref dst0, + rogue_ref dst1, + rogue_ref src0, + rogue_ref src1) +{ + rogue_ref dsts[] = { dst0, dst1 }; + rogue_ref srcs[] = { src0, src1 }; + return rogue_build_alu(b, op, 2, dsts, 2, srcs); } /* TODO: Static inline in rogue.h? */ -#define ROGUE_BUILDER_DEFINE_ALU1(op) \ +#define ROGUE_BUILDER_DEFINE_ALU11(op) \ PUBLIC \ rogue_alu_instr *rogue_##op(rogue_builder *b, \ - rogue_ref dst, \ + rogue_ref dst0, \ rogue_ref src0) \ { \ + assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 1); \ assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 1); \ - return rogue_build_alu1(b, ROGUE_ALU_OP_##op, dst, src0); \ + return rogue_build_alu11(b, ROGUE_ALU_OP_##op, dst0, src0); \ } -#define ROGUE_BUILDER_DEFINE_ALU2(op) \ - PUBLIC \ - rogue_alu_instr *rogue_##op(rogue_builder *b, \ - rogue_ref dst, \ - rogue_ref src0, \ - rogue_ref src1) \ - { \ - assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 2); \ - return rogue_build_alu2(b, ROGUE_ALU_OP_##op, dst, src0, src1); \ +#define ROGUE_BUILDER_DEFINE_ALU12(op) \ + PUBLIC \ + rogue_alu_instr *rogue_##op(rogue_builder *b, \ + rogue_ref dst0, \ + rogue_ref src0, \ + rogue_ref src1) \ + { \ + assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 1); \ + assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 2); \ + return rogue_build_alu12(b, ROGUE_ALU_OP_##op, dst0, src0, src1); \ + } + +#define ROGUE_BUILDER_DEFINE_ALU13(op) \ + PUBLIC \ + rogue_alu_instr *rogue_##op(rogue_builder *b, \ + rogue_ref dst0, \ + rogue_ref src0, \ + rogue_ref src1, \ + rogue_ref src2) \ + { \ + assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 1); \ + assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 3); \ + return rogue_build_alu13(b, ROGUE_ALU_OP_##op, dst0, src0, src1, src2); \ } -#define ROGUE_BUILDER_DEFINE_ALU3(op) \ - PUBLIC \ - rogue_alu_instr *rogue_##op(rogue_builder *b, \ - rogue_ref dst, \ - rogue_ref src0, \ - rogue_ref src1, \ - rogue_ref src2) \ - { \ - assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 3); \ - return rogue_build_alu3(b, ROGUE_ALU_OP_##op, dst, src0, src1, src2); \ +#define ROGUE_BUILDER_DEFINE_ALU22(op) \ + PUBLIC \ + rogue_alu_instr *rogue_##op(rogue_builder *b, \ + rogue_ref dst0, \ + rogue_ref dst1, \ + rogue_ref src0, \ + rogue_ref src1) \ + { \ + assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 2); \ + assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 2); \ + return rogue_build_alu22(b, ROGUE_ALU_OP_##op, dst0, dst1, src0, src1); \ } #include "rogue_alu_instrs.def" diff --git a/src/imagination/rogue/rogue_builder.h b/src/imagination/rogue/rogue_builder.h index b3061541d3d..02540bed25d 100644 --- a/src/imagination/rogue/rogue_builder.h +++ b/src/imagination/rogue/rogue_builder.h @@ -91,22 +91,31 @@ static inline rogue_block *rogue_push_block(rogue_builder *b) } /* ALU instructions. */ -#define ROGUE_BUILDER_DEFINE_ALU1(op) \ - rogue_alu_instr *rogue_##op(rogue_builder *b, rogue_ref dst, rogue_ref src0); +#define ROGUE_BUILDER_DEFINE_ALU11(op) \ + rogue_alu_instr *rogue_##op(rogue_builder *b, \ + rogue_ref dst0, \ + rogue_ref src0); -#define ROGUE_BUILDER_DEFINE_ALU2(op) \ +#define ROGUE_BUILDER_DEFINE_ALU12(op) \ rogue_alu_instr *rogue_##op(rogue_builder *b, \ - rogue_ref dst, \ + rogue_ref dst0, \ rogue_ref src0, \ rogue_ref src1); -#define ROGUE_BUILDER_DEFINE_ALU3(op) \ +#define ROGUE_BUILDER_DEFINE_ALU13(op) \ rogue_alu_instr *rogue_##op(rogue_builder *b, \ - rogue_ref dst, \ + rogue_ref dst0, \ rogue_ref src0, \ rogue_ref src1, \ rogue_ref src2); +#define ROGUE_BUILDER_DEFINE_ALU22(op) \ + rogue_alu_instr *rogue_##op(rogue_builder *b, \ + rogue_ref dst0, \ + rogue_ref dst1, \ + rogue_ref src0, \ + rogue_ref src1); + #include "rogue_alu_instrs.def" /* Backend instructions. */ diff --git a/src/imagination/rogue/rogue_info.c b/src/imagination/rogue/rogue_info.c index 8ee93d9a4c2..55ed81e99a5 100644 --- a/src/imagination/rogue/rogue_info.c +++ b/src/imagination/rogue/rogue_info.c @@ -300,50 +300,50 @@ const rogue_io_info rogue_io_infos[ROGUE_IO_COUNT] = { #define T(type) BITFIELD64_BIT(ROGUE_REF_TYPE_##type - 1) const rogue_alu_op_info rogue_alu_op_infos[ROGUE_ALU_OP_COUNT] = { [ROGUE_ALU_OP_INVALID] = { .str = "!INVALID!", }, - [ROGUE_ALU_OP_MBYP] = { .str = "mbyp", .num_srcs = 1, + [ROGUE_ALU_OP_MBYP] = { .str = "mbyp", .num_dsts = 1, .num_srcs = 1, .supported_phases = P(0), - .phase_io[PH(0)] = { .dst = IO(FT0), .src[0] = IO(S0), }, + .phase_io[PH(0)] = { .dst[0] = IO(FT0), .src[0] = IO(S0), }, .supported_src_mods = { [0] = SM(ABS) | SM(NEG), }, - .supported_dst_types = T(REG), + .supported_dst_types = { [0] = T(REG), }, .supported_src_types = { [0] = T(REG), }, }, - [ROGUE_ALU_OP_FADD] = { .str = "fadd", .num_srcs = 2, + [ROGUE_ALU_OP_FADD] = { .str = "fadd", .num_dsts = 1, .num_srcs = 2, .supported_phases = P(0), - .phase_io[PH(0)] = { .dst = IO(FT0), .src[0] = IO(S0), .src[1] = IO(S1), }, + .phase_io[PH(0)] = { .dst[0] = IO(FT0), .src[0] = IO(S0), .src[1] = IO(S1), }, .supported_op_mods = OM(LP) | OM(SAT), .supported_src_mods = { [0] = SM(FLR) | SM(ABS) | SM(NEG), [1] = SM(ABS), }, }, - [ROGUE_ALU_OP_FMUL] = { .str = "fmul", .num_srcs = 2, + [ROGUE_ALU_OP_FMUL] = { .str = "fmul", .num_dsts = 1, .num_srcs = 2, .supported_phases = P(0), - .phase_io[PH(0)] = { .dst = IO(FT0), .src[0] = IO(S0), .src[1] = IO(S1), }, + .phase_io[PH(0)] = { .dst[0] = IO(FT0), .src[0] = IO(S0), .src[1] = IO(S1), }, .supported_op_mods = OM(LP) | OM(SAT), .supported_src_mods = { [0] = SM(FLR) | SM(ABS) | SM(NEG), [1] = SM(ABS), }, - .supported_dst_types = T(REG), + .supported_dst_types = { [0] = T(REG), }, .supported_src_types = { [0] = T(REG), [1] = T(REG), }, }, - [ROGUE_ALU_OP_FMAD] = { .str = "fmad", .num_srcs = 3, + [ROGUE_ALU_OP_FMAD] = { .str = "fmad", .num_dsts = 1, .num_srcs = 3, .supported_phases = P(0), - .phase_io[PH(0)] = { .dst = IO(FT0), .src[0] = IO(S0), .src[1] = IO(S1), .src[2] = IO(S2), }, + .phase_io[PH(0)] = { .dst[0] = IO(FT0), .src[0] = IO(S0), .src[1] = IO(S1), .src[2] = IO(S2), }, .supported_op_mods = OM(LP) | OM(SAT), .supported_src_mods = { [0] = SM(ABS) | SM(NEG), [1] = SM(ABS) | SM(NEG), [2] = SM(FLR) | SM(ABS) | SM(NEG), }, - .supported_dst_types = T(REG), + .supported_dst_types = { [0] = T(REG), }, .supported_src_types = { [0] = T(REG), [1] = T(REG), @@ -351,30 +351,30 @@ const rogue_alu_op_info rogue_alu_op_infos[ROGUE_ALU_OP_COUNT] = { }, }, /* TODO: Implement */ - [ROGUE_ALU_OP_TST] = { .str = "tst", .num_srcs = 2, }, - [ROGUE_ALU_OP_PCK_U8888] = { .str = "pck.u8888", .num_srcs = 1, + [ROGUE_ALU_OP_TST] = { .str = "tst", .num_dsts = 2, .num_srcs = 2, }, + [ROGUE_ALU_OP_PCK_U8888] = { .str = "pck.u8888", .num_dsts = 1, .num_srcs = 1, .supported_phases = P(2_PCK), - .phase_io[PH(2_PCK)] = { .dst = IO(FT2), .src[0] = IO(IS3), }, + .phase_io[PH(2_PCK)] = { .dst[0] = IO(FT2), .src[0] = IO(IS3), }, .supported_op_mods = OM(SCALE) | OM(ROUNDZERO), - .supported_dst_types = T(REG), + .supported_dst_types = { [0] = T(REG), }, .supported_src_types = { [0] = T(REGARRAY), }, }, /* This mov is "fake" since it can be lowered to a MBYP, make a new instruction for real mov (call it MOVD?). */ - [ROGUE_ALU_OP_MOV] = { .str = "mov", .num_srcs = 1, - .supported_dst_types = T(REG), + [ROGUE_ALU_OP_MOV] = { .str = "mov", .num_dsts = 1, .num_srcs = 1, + .supported_dst_types = { [0] = T(REG), }, .supported_src_types = { [0] = T(REG) | T(IMM), }, }, - [ROGUE_ALU_OP_FABS] = { .str = "fabs", .num_srcs = 1, }, - [ROGUE_ALU_OP_FNEG] = { .str = "fneg", .num_srcs = 1, }, - [ROGUE_ALU_OP_FNABS] = { .str = "fnabs", .num_srcs = 1, }, + [ROGUE_ALU_OP_FABS] = { .str = "fabs", .num_dsts = 1, .num_srcs = 1, }, + [ROGUE_ALU_OP_FNEG] = { .str = "fneg", .num_dsts = 1, .num_srcs = 1, }, + [ROGUE_ALU_OP_FNABS] = { .str = "fnabs", .num_dsts = 1, .num_srcs = 1, }, - [ROGUE_ALU_OP_FMAX] = { .str = "fmax", .num_srcs = 2, }, /* TODO */ - [ROGUE_ALU_OP_FMIN] = { .str = "fmin", .num_srcs = 2, }, /* TODO */ - [ROGUE_ALU_OP_SEL] = { .str = "sel", .num_srcs = 3, }, /* TODO */ + [ROGUE_ALU_OP_FMAX] = { .str = "fmax", .num_dsts = 1, .num_srcs = 2, }, /* TODO */ + [ROGUE_ALU_OP_FMIN] = { .str = "fmin", .num_dsts = 1, .num_srcs = 2, }, /* TODO */ + [ROGUE_ALU_OP_SEL] = { .str = "sel", .num_dsts = 1, .num_srcs = 3, }, /* TODO */ }; #undef T #undef IO diff --git a/src/imagination/rogue/rogue_print.c b/src/imagination/rogue/rogue_print.c index b185869668b..94442170843 100644 --- a/src/imagination/rogue/rogue_print.c +++ b/src/imagination/rogue/rogue_print.c @@ -256,12 +256,21 @@ static inline void rogue_print_alu_instr(FILE *fp, const rogue_alu_instr *alu) rogue_print_alu_mods(fp, alu); - fputs(" ", fp); + for (unsigned i = 0; i < info->num_dsts; ++i) { + if (i > 0) + fputs(",", fp); + + fputs(" ", fp); - rogue_print_alu_dst(fp, &alu->dst); + rogue_print_alu_dst(fp, &alu->dst[i]); + } for (unsigned i = 0; i < info->num_srcs; ++i) { - fputs(", ", fp); + if (i == 0 && !info->num_dsts) + fputs(" ", fp); + else + fputs(", ", fp); + rogue_print_alu_src(fp, &alu->src[i]); } } diff --git a/src/imagination/rogue/rogue_validate.c b/src/imagination/rogue/rogue_validate.c index 76ce80640ec..c4f4110015d 100644 --- a/src/imagination/rogue/rogue_validate.c +++ b/src/imagination/rogue/rogue_validate.c @@ -194,8 +194,9 @@ static void validate_alu_instr(rogue_validation_state *state, if (!rogue_mods_supported(alu->mod, info->supported_op_mods)) validate_log(state, "Unsupported ALU op modifiers."); - /* Validate destination and sources. */ - validate_alu_dst(state, &alu->dst, info->supported_dst_types); + /* Validate destinations and sources. */ + for (unsigned i = 0; i < info->num_dsts; ++i) + validate_alu_dst(state, &alu->dst[i], info->supported_dst_types[i]); for (unsigned i = 0; i < info->num_srcs; ++i) validate_alu_src(state, &alu->src[i], info->supported_src_types[i]);
