ir3: Moves with shared destination are always legal

I got this wrong before because I missed the need for (ss), once that
was fixed then a move from anything to a shared register is legal,
include non-shared registers, as long as all active channels have the
same value.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22075>
This commit is contained in:
Connor Abbott 2022-05-19 16:33:39 +02:00 committed by Marge Bot
parent 4ee0f6d1fb
commit ae2db62aab
6 changed files with 5 additions and 39 deletions

View file

@ -196,7 +196,6 @@ static const struct opc_info {
OPC(1, OPC_ELECT_MACRO, elect.macro),
OPC(1, OPC_READ_COND_MACRO, read_cond.macro),
OPC(1, OPC_READ_FIRST_MACRO, read_first.macro),
OPC(1, OPC_SWZ_SHARED_MACRO, swz_shared.macro),
OPC(1, OPC_SCAN_MACRO, scan.macro),
OPC(1, OPC_SCAN_CLUSTERS_MACRO, scan_clusters.macro),
OPC(1, OPC_SHPS_MACRO, shps.macro),

View file

@ -124,8 +124,7 @@ typedef enum {
OPC_ELECT_MACRO = _OPC(1, 53),
OPC_READ_COND_MACRO = _OPC(1, 54),
OPC_READ_FIRST_MACRO = _OPC(1, 55),
OPC_SWZ_SHARED_MACRO = _OPC(1, 56),
OPC_SHPS_MACRO = _OPC(1, 57),
OPC_SHPS_MACRO = _OPC(1, 56),
/* Macros that expand to a loop */
OPC_SCAN_MACRO = _OPC(1, 58),

View file

@ -998,7 +998,6 @@ is_subgroup_cond_mov_macro(struct ir3_instruction *instr)
case OPC_ELECT_MACRO:
case OPC_READ_COND_MACRO:
case OPC_READ_FIRST_MACRO:
case OPC_SWZ_SHARED_MACRO:
case OPC_SCAN_MACRO:
case OPC_SCAN_CLUSTERS_MACRO:
return true;

View file

@ -162,14 +162,7 @@ do_swap(struct ir3_compiler *compiler, struct ir3_instruction *instr,
do_xor(instr, src_num, src_num, dst_num, entry->flags);
do_xor(instr, dst_num, dst_num, src_num, entry->flags);
} else {
/* Use a macro for shared regs because any shared reg writes need to
* be wrapped in a getone block to work correctly. Writing shared regs
* with multiple threads active does not work, even if they all return
* the same value.
*/
unsigned opc =
(entry->flags & IR3_REG_SHARED) ? OPC_SWZ_SHARED_MACRO : OPC_SWZ;
struct ir3_instruction *swz = ir3_instr_create(instr->block, opc, 2, 2);
struct ir3_instruction *swz = ir3_instr_create(instr->block, OPC_SWZ, 2, 2);
ir3_dst_create(swz, dst_num, entry->flags);
ir3_dst_create(swz, src_num, entry->flags);
ir3_src_create(swz, src_num, entry->flags);
@ -253,10 +246,7 @@ do_copy(struct ir3_compiler *compiler, struct ir3_instruction *instr,
unsigned src_num = ra_physreg_to_num(entry->src.reg, entry->flags);
unsigned dst_num = ra_physreg_to_num(entry->dst, entry->flags);
/* Similar to the swap case, we have to use a macro for shared regs. */
unsigned opc =
(entry->flags & IR3_REG_SHARED) ? OPC_READ_FIRST_MACRO : OPC_MOV;
struct ir3_instruction *mov = ir3_instr_create(instr->block, opc, 1, 1);
struct ir3_instruction *mov = ir3_instr_create(instr->block, OPC_MOV, 1, 1);
ir3_dst_create(mov, dst_num, entry->flags);
if (entry->src.flags & (IR3_REG_IMMED | IR3_REG_CONST))
ir3_src_create(mov, INVALID_REG, (entry->flags & IR3_REG_HALF) | entry->src.flags);

View file

@ -263,7 +263,6 @@ lower_instr(struct ir3 *ir, struct ir3_block **block, struct ir3_instruction *in
case OPC_ALL_MACRO:
case OPC_ELECT_MACRO:
case OPC_READ_COND_MACRO:
case OPC_SWZ_SHARED_MACRO:
case OPC_SCAN_MACRO:
case OPC_SCAN_CLUSTERS_MACRO:
break;
@ -411,16 +410,10 @@ lower_instr(struct ir3 *ir, struct ir3_block **block, struct ir3_instruction *in
} else {
/* For ballot, the destination must be initialized to 0 before we do
* the movmsk because the condition may be 0 and then the movmsk will
* be skipped. Because it's a shared register we have to wrap the
* initialization in a getone block.
* be skipped.
*/
if (instr->opc == OPC_BALLOT_MACRO) {
struct ir3_block *then_block =
create_if(ir, before_block, after_block, OPC_GETONE, NULL);
mov_immed(instr->dsts[0], then_block, 0);
after_block->reconvergence_point = true;
before_block = after_block;
after_block = split_block(ir, before_block, instr);
mov_immed(instr->dsts[0], before_block, 0);
}
struct ir3_instruction *condition = NULL;
@ -450,7 +443,6 @@ lower_instr(struct ir3 *ir, struct ir3_block **block, struct ir3_instruction *in
branch_opc = OPC_BALL;
break;
case OPC_ELECT_MACRO:
case OPC_SWZ_SHARED_MACRO:
after_block->reconvergence_point = true;
branch_opc = OPC_GETONE;
break;
@ -490,18 +482,6 @@ lower_instr(struct ir3 *ir, struct ir3_block **block, struct ir3_instruction *in
break;
}
case OPC_SWZ_SHARED_MACRO: {
struct ir3_instruction *swz =
ir3_instr_create(then_block, OPC_SWZ, 2, 2);
ir3_dst_create(swz, instr->dsts[0]->num, instr->dsts[0]->flags);
ir3_dst_create(swz, instr->dsts[1]->num, instr->dsts[1]->flags);
ir3_src_create(swz, instr->srcs[0]->num, instr->srcs[0]->flags);
ir3_src_create(swz, instr->srcs[1]->num, instr->srcs[1]->flags);
swz->cat1.dst_type = swz->cat1.src_type = TYPE_U32;
swz->repeat = 1;
break;
}
default:
unreachable("bad opcode");
}

View file

@ -303,7 +303,6 @@ ir3_calc_reconvergence(struct ir3_shader_variant *so)
case OPC_READ_COND_MACRO:
case OPC_ELECT_MACRO:
case OPC_READ_FIRST_MACRO:
case OPC_SWZ_SHARED_MACRO:
so->branchstack = MAX2(so->branchstack, rc_level + 1);
break;
default: