pvr: Add basic support for manual instruction grouping

Signed-off-by: Simon Perretta <simon.perretta@imgtec.com>
Acked-by: Frank Binns <frank.binns@imgtec.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21474>
This commit is contained in:
Simon Perretta
2023-02-17 14:59:47 +00:00
committed by Marge Bot
parent b642e77cdd
commit c38c119617
6 changed files with 74 additions and 29 deletions

View File

@@ -840,6 +840,8 @@ bool rogue_schedule_instr_groups(rogue_shader *shader, bool multi_instr_groups)
rogue_lower_regs(shader); rogue_lower_regs(shader);
rogue_instr_group *group;
bool grouping = false;
unsigned g = 0; unsigned g = 0;
rogue_foreach_block (block, shader) { rogue_foreach_block (block, shader) {
struct list_head instr_groups; 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."); unreachable("Unsupported instruction type.");
} }
rogue_instr_group *group = rogue_instr_group_create(block, group_alu); if (!grouping) {
group->index = g++; 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_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); list_replace(&instr_groups, &block->instrs);

View File

@@ -450,10 +450,17 @@ typedef struct rogue_instr {
rogue_block *block; /** Basic block containing this instruction. */ rogue_block *block; /** Basic block containing this instruction. */
bool group_next; /** Group next instruction with this one. */
unsigned index; /** Instruction index. */ unsigned index; /** Instruction index. */
char *comment; /** Comment string. */ char *comment; /** Comment string. */
} rogue_instr; } 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) \ #define rogue_foreach_instr_in_block(instr, block) \
list_for_each_entry (rogue_instr, instr, &(block)->instrs, link) list_for_each_entry (rogue_instr, instr, &(block)->instrs, link)

View File

@@ -70,6 +70,52 @@ static unsigned rogue_calc_da(const rogue_instr_group *group)
return da; 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, static void rogue_encode_instr_group_header(rogue_instr_group *group,
struct util_dynarray *binary) struct util_dynarray *binary)
{ {
@@ -116,31 +162,12 @@ static void rogue_encode_instr_group_header(rogue_instr_group *group,
switch (group->header.alu) { switch (group->header.alu) {
case ROGUE_ALU_MAIN: case ROGUE_ALU_MAIN:
h.alutype = ALUTYPE_MAIN; h.alutype = ALUTYPE_MAIN;
/* TODO: Support multiple phase instructions. */ h.oporg = rogue_calc_oporg(group->header.phases);
#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
break; break;
case ROGUE_ALU_BITWISE: case ROGUE_ALU_BITWISE:
h.alutype = ALUTYPE_BITWISE; h.alutype = ALUTYPE_BITWISE;
#define P(type) BITFIELD64_BIT(ROGUE_INSTR_PHASE_##type) h.opcnt = rogue_calc_opcnt(group->header.phases);
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
break; break;
case ROGUE_ALU_CONTROL: 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) { if (group->header.alu != ROGUE_ALU_CONTROL) {
h.end = group->header.end; h.end = group->header.end;
/* h.crel = ; */ /* Unused for now */
/* h.atom = ; */ /* Unused for now */ /* h.atom = ; */ /* Unused for now */
h.rpt = group->header.repeat - 1; h.rpt = group->header.repeat - 1;
} }
util_dynarray_append_mem(binary, group->size.header, &h); util_dynarray_append_mem(binary, group->size.header, &h);
} }
#undef P
typedef union rogue_instr_encoding { typedef union rogue_instr_encoding {
rogue_alu_instr_encoding alu; rogue_alu_instr_encoding alu;

View File

@@ -574,7 +574,7 @@ const rogue_alu_op_info rogue_alu_op_infos[ROGUE_ALU_OP_COUNT] = {
.supported_src_mods = { .supported_src_mods = {
[0] = SM(ABS) | SM(NEG), [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 = { .supported_src_types = {
[0] = T(REG), [0] = T(REG),
}, },

View File

@@ -1346,7 +1346,7 @@ typedef struct rogue_instr_group_header_encoding {
unsigned ccext : 1; unsigned ccext : 1;
unsigned rpt : 2; unsigned rpt : 2;
unsigned atom : 1; unsigned atom : 1;
unsigned crel : 1; unsigned : 1;
unsigned alutype : 2; unsigned alutype : 2;
unsigned end : 1; unsigned end : 1;
} PACKED; } PACKED;

View File

@@ -592,7 +592,7 @@ static inline void rogue_print_instr_group(FILE *fp,
fputs("{ ", fp); fputs("{ ", fp);
CYAN(fp); CYAN(fp);
fprintf(fp, "%s ", rogue_alu_str[group->header.alu]); fprintf(fp, "%s", rogue_alu_str[group->header.alu]);
RESET(fp); RESET(fp);
/* Print each instruction. */ /* Print each instruction. */
@@ -600,6 +600,7 @@ static inline void rogue_print_instr_group(FILE *fp,
const rogue_instr *instr = group->instrs[p]; const rogue_instr *instr = group->instrs[p];
assert(instr); assert(instr);
fputs(" ", fp);
rogue_print_instr_phase(fp, group->header.alu, p); rogue_print_instr_phase(fp, group->header.alu, p);
fputs(": ", fp); fputs(": ", fp);
rogue_print_instr(fp, instr); rogue_print_instr(fp, instr);