ir3: Support any/all/getone branches

This plumbs through the support in the IR.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6752>
This commit is contained in:
Connor Abbott 2020-09-11 13:17:40 +02:00 committed by Marge Bot
parent 7a8e0b15e2
commit 232ec710fd
3 changed files with 80 additions and 15 deletions

View file

@ -514,6 +514,13 @@ struct ir3_array {
struct ir3_array * ir3_lookup_array(struct ir3 *ir, unsigned id);
enum ir3_branch_type {
IR3_BRANCH_COND, /* condition */
IR3_BRANCH_ANY, /* subgroupAny(condition) */
IR3_BRANCH_ALL, /* subgroupAll(condition) */
IR3_BRANCH_GETONE, /* subgroupElect() */
};
struct ir3_block {
struct list_head node;
struct ir3 *shader;
@ -522,6 +529,9 @@ struct ir3_block {
struct list_head instr_list; /* list of ir3_instruction */
/* The actual branch condition, if there are two successors */
enum ir3_branch_type brtype;
/* each block has either one or two successors.. in case of two
* successors, 'condition' decides which one to follow. A block preceding
* an if/else has two successors.
@ -1840,6 +1850,7 @@ INSTR0(CHMASK)
INSTR1NODST(PREDT)
INSTR0(PREDF)
INSTR0(PREDE)
INSTR0(GETONE)
/* cat2 instructions, most 2 src but some 1 src: */
INSTR2(ADD_F)

View file

@ -643,23 +643,51 @@ block_sched(struct ir3 *ir)
foreach_block (block, &ir->block_list) {
if (block->successors[1]) {
/* if/else, conditional branches to "then" or "else": */
struct ir3_instruction *br;
struct ir3_instruction *br1, *br2;
debug_assert(block->condition);
if (block->brtype == IR3_BRANCH_GETONE) {
/* getone can't be inverted, and it wouldn't even make sense
* to follow it with an inverted branch, so follow it by an
* unconditional branch.
*/
debug_assert(!block->condition);
br1 = ir3_GETONE(block);
br1->cat0.target = block->successors[1];
/* create "else" branch first (since "then" block should
* frequently/always end up being a fall-thru):
*/
br = ir3_instr_create(block, OPC_B, 0, 1);
ir3_src_create(br, regid(REG_P0, 0), 0)->def = block->condition->dsts[0];
br->cat0.inv1 = true;
br->cat0.target = block->successors[1];
br2 = ir3_JUMP(block);
br2->cat0.target = block->successors[0];
} else {
debug_assert(block->condition);
/* "then" branch: */
br = ir3_instr_create(block, OPC_B, 0, 1);
ir3_src_create(br, regid(REG_P0, 0), 0)->def = block->condition->dsts[0];
br->cat0.target = block->successors[0];
/* create "else" branch first (since "then" block should
* frequently/always end up being a fall-thru):
*/
br1 = ir3_instr_create(block, OPC_B, 0, 1);
ir3_src_create(br1, regid(REG_P0, 0), 0)->def = block->condition->dsts[0];
br1->cat0.inv1 = true;
br1->cat0.target = block->successors[1];
/* "then" branch: */
br2 = ir3_instr_create(block, OPC_B, 0, 1);
ir3_src_create(br2, regid(REG_P0, 0), 0)->def = block->condition->dsts[0];
br2->cat0.target = block->successors[0];
switch (block->brtype) {
case IR3_BRANCH_COND:
br1->cat0.brtype = br2->cat0.brtype = BRANCH_PLAIN;
break;
case IR3_BRANCH_ALL:
br1->cat0.brtype = BRANCH_ANY;
br2->cat0.brtype = BRANCH_ALL;
break;
case IR3_BRANCH_ANY:
br1->cat0.brtype = BRANCH_ALL;
br2->cat0.brtype = BRANCH_ANY;
break;
case IR3_BRANCH_GETONE:
unreachable("can't get here");
}
}
} else if (block->successors[0]) {
/* otherwise unconditional jump to next block: */
struct ir3_instruction *jmp;

View file

@ -123,6 +123,17 @@ static void print_instr_name(struct log_stream *stream, struct ir3_instruction *
mesa_log_stream_printf(stream, ".%s%s", type_name(instr->cat1.src_type),
type_name(instr->cat1.dst_type));
}
} else if (instr->opc == OPC_B) {
const char *name[8] = {
[BRANCH_PLAIN] = "br",
[BRANCH_OR] = "brao",
[BRANCH_AND] = "braa",
[BRANCH_CONST] = "brac",
[BRANCH_ANY] = "bany",
[BRANCH_ALL] = "ball",
[BRANCH_X] = "brax",
};
mesa_log_stream_printf(stream, "%s", name[instr->cat0.brtype]);
} else {
mesa_log_stream_printf(stream, "%s", disasm_a3xx_instr_name(instr->opc));
if (instr->flags & IR3_INSTR_3D)
@ -411,8 +422,23 @@ print_block(struct ir3_block *block, int lvl)
if (block->successors[1]) {
/* leading into if/else: */
tab(stream, lvl+1);
mesa_log_stream_printf(stream, "/* succs: if "SYN_SSA("ssa_%u")" block%u; else block%u */\n",
block->condition->serialno,
mesa_log_stream_printf(stream, "/* succs: if ");
switch (block->brtype) {
case IR3_BRANCH_COND:
break;
case IR3_BRANCH_ANY:
printf("any ");
break;
case IR3_BRANCH_ALL:
printf("all ");
break;
case IR3_BRANCH_GETONE:
printf("getone ");
break;
}
if (block->condition)
mesa_log_stream_printf(stream, SYN_SSA("ssa_%u")" ", block->condition->serialno);
mesa_log_stream_printf(stream, "block%u; else block%u; */\n",
block_id(block->successors[0]),
block_id(block->successors[1]));
} else if (block->successors[0]) {