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_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);

View File

@@ -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)

View File

@@ -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;

View File

@@ -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),
},

View File

@@ -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;

View File

@@ -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);