From c38c119617a83d72a34b6f8e42db78029e6e9ece Mon Sep 17 00:00:00 2001 From: Simon Perretta Date: Fri, 17 Feb 2023 14:59:47 +0000 Subject: [PATCH] pvr: Add basic support for manual instruction grouping Signed-off-by: Simon Perretta Acked-by: Frank Binns Part-of: --- .../passes/rogue_schedule_instr_groups.c | 18 +++-- src/imagination/rogue/rogue.h | 7 ++ src/imagination/rogue/rogue_encode.c | 71 +++++++++++++------ src/imagination/rogue/rogue_info.c | 2 +- src/imagination/rogue/rogue_isa.h | 2 +- src/imagination/rogue/rogue_print.c | 3 +- 6 files changed, 74 insertions(+), 29 deletions(-) diff --git a/src/imagination/rogue/passes/rogue_schedule_instr_groups.c b/src/imagination/rogue/passes/rogue_schedule_instr_groups.c index 0ed103671a0..1587ec777f7 100644 --- a/src/imagination/rogue/passes/rogue_schedule_instr_groups.c +++ b/src/imagination/rogue/passes/rogue_schedule_instr_groups.c @@ -840,6 +840,8 @@ bool rogue_schedule_instr_groups(rogue_shader *shader, bool multi_instr_groups) rogue_lower_regs(shader); + rogue_instr_group *group; + bool grouping = false; unsigned g = 0; rogue_foreach_block (block, shader) { struct list_head instr_groups; @@ -865,12 +867,20 @@ bool rogue_schedule_instr_groups(rogue_shader *shader, bool multi_instr_groups) unreachable("Unsupported instruction type."); } - rogue_instr_group *group = rogue_instr_group_create(block, group_alu); - group->index = g++; + if (!grouping) { + group = rogue_instr_group_create(block, group_alu); + group->index = g++; + } + assert(group_alu == group->header.alu); rogue_move_instr_to_group(instr, group); - rogue_finalise_instr_group(group); - list_addtail(&group->link, &instr_groups); + + grouping = instr->group_next; + + if (!grouping) { + rogue_finalise_instr_group(group); + list_addtail(&group->link, &instr_groups); + } } list_replace(&instr_groups, &block->instrs); diff --git a/src/imagination/rogue/rogue.h b/src/imagination/rogue/rogue.h index 5b5ce650876..b4b611c2243 100644 --- a/src/imagination/rogue/rogue.h +++ b/src/imagination/rogue/rogue.h @@ -450,10 +450,17 @@ typedef struct rogue_instr { rogue_block *block; /** Basic block containing this instruction. */ + bool group_next; /** Group next instruction with this one. */ unsigned index; /** Instruction index. */ char *comment; /** Comment string. */ } rogue_instr; +static inline void rogue_set_instr_group_next(rogue_instr *instr, + bool group_next) +{ + instr->group_next = group_next; +} + #define rogue_foreach_instr_in_block(instr, block) \ list_for_each_entry (rogue_instr, instr, &(block)->instrs, link) diff --git a/src/imagination/rogue/rogue_encode.c b/src/imagination/rogue/rogue_encode.c index c88839304be..cd8100d6e7b 100644 --- a/src/imagination/rogue/rogue_encode.c +++ b/src/imagination/rogue/rogue_encode.c @@ -70,6 +70,52 @@ static unsigned rogue_calc_da(const rogue_instr_group *group) return da; } +#define P(type) BITFIELD64_BIT(ROGUE_INSTR_PHASE_##type) +static enum oporg rogue_calc_oporg(uint64_t alu_phases) +{ + bool P0 = !!(alu_phases & P(0)); + bool P1 = !!(alu_phases & P(1)); + bool P2 = !!(alu_phases & (P(2_PCK) | P(2_TST) | P(2_MOV))); + bool PBE = !!(alu_phases & P(BACKEND)); + + if (P0 && P1 && P2 && PBE) + return OPORG_P0_P1_P2_BE; + else if (P0 && !P1 && P2 && PBE) + return OPORG_P0_P2_BE; + else if (P0 && P1 && P2 && !PBE) + return OPORG_P0_P1_P2; + else if (P0 && !P1 && P2 && !PBE) + return OPORG_P0_P2; + else if (P0 && P1 && !P2 && !PBE) + return OPORG_P0_P1; + else if (!P0 && !P1 && !P2 && PBE) + return OPORG_BE; + else if (!P0 && !P1 && P2 && !PBE) + return OPORG_P2; + else if (P0 && !P1 && !P2 && !PBE) + return OPORG_P0; + + unreachable("Invalid ALU phase combination."); +} + +static enum opcnt rogue_calc_opcnt(uint64_t bitwise_phases) +{ + enum opcnt opcnt = 0; + + if (bitwise_phases & P(0_BITMASK) || bitwise_phases & P(0_SHIFT1) || + bitwise_phases & P(0_COUNT)) { + opcnt |= OPCNT_P0; + } + + if (bitwise_phases & P(1_LOGICAL)) + opcnt |= OPCNT_P1; + + if (bitwise_phases & P(2_SHIFT2) || bitwise_phases & P(2_TEST)) + opcnt |= OPCNT_P2; + + return opcnt; +} + static void rogue_encode_instr_group_header(rogue_instr_group *group, struct util_dynarray *binary) { @@ -116,31 +162,12 @@ static void rogue_encode_instr_group_header(rogue_instr_group *group, switch (group->header.alu) { case ROGUE_ALU_MAIN: h.alutype = ALUTYPE_MAIN; - /* TODO: Support multiple phase instructions. */ -#define P(type) BITFIELD64_BIT(ROGUE_INSTR_PHASE_##type) - if (group->header.phases & P(0)) - h.oporg = OPORG_P0; - if (group->header.phases & P(2_PCK) || group->header.phases & P(2_TST) || - group->header.phases & P(2_MOV)) - h.oporg = OPORG_P2; - if (group->header.phases & P(BACKEND)) - h.oporg = OPORG_BE; -#undef P + h.oporg = rogue_calc_oporg(group->header.phases); break; case ROGUE_ALU_BITWISE: h.alutype = ALUTYPE_BITWISE; -#define P(type) BITFIELD64_BIT(ROGUE_INSTR_PHASE_##type) - if (group->header.phases & P(0_BITMASK) || - group->header.phases & P(0_SHIFT1) || - group->header.phases & P(0_COUNT)) - h.oporg |= OPCNT_P0; - if (group->header.phases & P(1_LOGICAL)) - h.oporg |= OPCNT_P1; - if (group->header.phases & P(2_SHIFT2) || - group->header.phases & P(2_TEST)) - h.oporg |= OPCNT_P2; -#undef P + h.opcnt = rogue_calc_opcnt(group->header.phases); break; case ROGUE_ALU_CONTROL: @@ -180,13 +207,13 @@ static void rogue_encode_instr_group_header(rogue_instr_group *group, if (group->header.alu != ROGUE_ALU_CONTROL) { h.end = group->header.end; - /* h.crel = ; */ /* Unused for now */ /* h.atom = ; */ /* Unused for now */ h.rpt = group->header.repeat - 1; } util_dynarray_append_mem(binary, group->size.header, &h); } +#undef P typedef union rogue_instr_encoding { rogue_alu_instr_encoding alu; diff --git a/src/imagination/rogue/rogue_info.c b/src/imagination/rogue/rogue_info.c index afe049c7fbb..0e1eb5b1a7c 100644 --- a/src/imagination/rogue/rogue_info.c +++ b/src/imagination/rogue/rogue_info.c @@ -574,7 +574,7 @@ const rogue_alu_op_info rogue_alu_op_infos[ROGUE_ALU_OP_COUNT] = { .supported_src_mods = { [0] = SM(ABS) | SM(NEG), }, - .supported_dst_types = { [0] = T(REG) | T(REGARRAY), }, + .supported_dst_types = { [0] = T(REG) | T(REGARRAY) | T(IO), }, .supported_src_types = { [0] = T(REG), }, diff --git a/src/imagination/rogue/rogue_isa.h b/src/imagination/rogue/rogue_isa.h index 88bfaeffe68..32c25e64289 100644 --- a/src/imagination/rogue/rogue_isa.h +++ b/src/imagination/rogue/rogue_isa.h @@ -1346,7 +1346,7 @@ typedef struct rogue_instr_group_header_encoding { unsigned ccext : 1; unsigned rpt : 2; unsigned atom : 1; - unsigned crel : 1; + unsigned : 1; unsigned alutype : 2; unsigned end : 1; } PACKED; diff --git a/src/imagination/rogue/rogue_print.c b/src/imagination/rogue/rogue_print.c index 7748385f343..49edbe3151e 100644 --- a/src/imagination/rogue/rogue_print.c +++ b/src/imagination/rogue/rogue_print.c @@ -592,7 +592,7 @@ static inline void rogue_print_instr_group(FILE *fp, fputs("{ ", fp); CYAN(fp); - fprintf(fp, "%s ", rogue_alu_str[group->header.alu]); + fprintf(fp, "%s", rogue_alu_str[group->header.alu]); RESET(fp); /* Print each instruction. */ @@ -600,6 +600,7 @@ static inline void rogue_print_instr_group(FILE *fp, const rogue_instr *instr = group->instrs[p]; assert(instr); + fputs(" ", fp); rogue_print_instr_phase(fp, group->header.alu, p); fputs(": ", fp); rogue_print_instr(fp, instr);