ir3: Make ir3_instruction::address a normal register

This fixes an annoying mismatch in the indices between foreach_ssa_src_n
and ir3_delayslots(), and lets us remove a bunch of other special cases.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11469>
This commit is contained in:
Connor Abbott 2021-06-18 12:01:18 +02:00 committed by Marge Bot
parent 2522f387a3
commit 9af795d9b9
10 changed files with 44 additions and 69 deletions

View File

@ -390,9 +390,9 @@ unsigned ir3_block_get_pred_index(struct ir3_block *block, struct ir3_block *pre
static struct ir3_instruction *instr_create(struct ir3_block *block,
opc_t opc, int nreg)
{
/* Add an extra source for array destinations */
/* Add extra sources for array destinations and the address reg */
if (1 <= opc_cat(opc))
nreg++;
nreg += 2;
struct ir3_instruction *instr;
unsigned sz = sizeof(*instr) + (nreg * sizeof(instr->regs[0]));
char *ptr = ir3_alloc(block->shader, sz);
@ -494,13 +494,14 @@ void
ir3_instr_set_address(struct ir3_instruction *instr,
struct ir3_instruction *addr)
{
if (instr->address != addr) {
if (!instr->address) {
struct ir3 *ir = instr->block->shader;
debug_assert(!instr->address);
debug_assert(instr->block == addr->block);
instr->address = addr;
instr->address = ir3_reg_create(instr, addr->regs[0]->num,
addr->regs[0]->flags & ~IR3_REG_DEST);
instr->address->def = addr->regs[0];
debug_assert(reg_num(addr->regs[0]) == REG_A0);
unsigned comp = reg_comp(addr->regs[0]);
if (comp == 0) {
@ -509,6 +510,8 @@ ir3_instr_set_address(struct ir3_instruction *instr,
debug_assert(comp == 1);
array_insert(ir, ir->a1_users, instr);
}
} else {
debug_assert(instr->address->def->instr == addr);
}
}
@ -707,7 +710,7 @@ ir3_valid_flags(struct ir3_instruction *instr, unsigned n,
*/
if (instr->regs[n+1]->flags & IR3_REG_SSA) {
struct ir3_instruction *src = ssa(instr->regs[n+1]);
if (src->address->block != instr->block)
if (src->address->def->instr->block != instr->block)
return false;
}
}

View File

@ -390,7 +390,7 @@ struct ir3_instruction {
*
* NOTE: do not write this directly, use ir3_instr_set_address()
*/
struct ir3_instruction *address;
struct ir3_register *address;
/* Tracking for additional dependent instructions. Used to handle
* barriers, WAR hazards for arrays/SSBOs/etc.
@ -1026,10 +1026,10 @@ static inline struct ir3_instruction *ssa(struct ir3_register *reg)
return NULL;
}
static inline bool conflicts(struct ir3_instruction *a,
struct ir3_instruction *b)
static inline bool conflicts(struct ir3_register *a,
struct ir3_register *b)
{
return (a && b) && (a != b);
return (a && b) && (a->def != b->def);
}
static inline bool reg_gpr(struct ir3_register *r)
@ -1352,33 +1352,26 @@ ir3_try_swap_signedness(opc_t opc, bool *can_swap)
static inline unsigned __ssa_src_cnt(struct ir3_instruction *instr)
{
unsigned cnt = instr->regs_count + instr->deps_count;
if (instr->address)
cnt++;
return cnt;
return instr->regs_count + instr->deps_count;
}
static inline bool __is_false_dep(struct ir3_instruction *instr, unsigned n)
{
if (n >= instr->regs_count)
return true;
return false;
}
static inline struct ir3_instruction **
__ssa_srcp_n(struct ir3_instruction *instr, unsigned n)
{
if (n == (instr->regs_count + instr->deps_count))
return &instr->address;
if (n >= instr->regs_count)
if (__is_false_dep(instr, n))
return &instr->deps[n - instr->regs_count];
if (ssa(instr->regs[n]))
return &instr->regs[n]->def->instr;
return NULL;
}
static inline bool __is_false_dep(struct ir3_instruction *instr, unsigned n)
{
if (n == (instr->regs_count + instr->deps_count))
return false;
if (n >= instr->regs_count)
return true;
return false;
}
#define foreach_ssa_srcp_n(__srcp, __n, __instr) \
for (struct ir3_instruction **__srcp = (void *)~0; __srcp; __srcp = NULL) \
for (unsigned __cnt = __ssa_src_cnt(__instr), __n = 0; __n < __cnt; __n++) \

View File

@ -447,7 +447,6 @@ create_addr0(struct ir3_block *block, struct ir3_instruction *src, int align)
instr = ir3_MOV(block, instr, TYPE_S16);
instr->regs[0]->num = regid(REG_A0, 0);
instr->regs[0]->flags &= ~IR3_REG_SSA;
return instr;
}
@ -458,7 +457,6 @@ create_addr1(struct ir3_block *block, unsigned const_val)
struct ir3_instruction *immed = create_immed_typed(block, const_val, TYPE_U16);
struct ir3_instruction *instr = ir3_MOV(block, immed, TYPE_U16);
instr->regs[0]->num = regid(REG_A0, 1);
instr->regs[0]->flags &= ~IR3_REG_SSA;
return instr;
}

View File

@ -99,7 +99,7 @@ static bool is_foldable_double_cmp(struct ir3_instruction *cmp)
(cmp->regs[2]->flags & IR3_REG_IMMED) &&
(cmp->regs[2]->iim_val == 0) &&
(cmp->cat2.condition == IR3_COND_NE) &&
(!cond->address || (cmp->block == cond->address->block));
(!cond->address || cond->address->def->instr->block == cmp->block);
}
/* propagate register flags from src to dst.. negates need special
@ -419,7 +419,7 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr,
instr->regs[n+1] = src_reg;
if (src_reg->flags & IR3_REG_RELATIV)
ir3_instr_set_address(instr, reg->def->instr->address);
ir3_instr_set_address(instr, reg->def->instr->address->def->instr);
return true;
}
@ -526,16 +526,15 @@ instr_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr)
if (is_meta(instr) && (src->opc != OPC_MOV))
continue;
/* Don't CP mova and mova1 into their users */
if (writes_addr0(src) || writes_addr1(src))
continue;
progress |= reg_cp(ctx, instr, reg, n);
ctx->progress |= progress;
}
} while (progress);
if (instr->address) {
instr_cp(ctx, instr->address);
ir3_instr_set_address(instr, eliminate_output_mov(ctx, instr->address));
}
/* After folding a mov's source we may wind up with a type-converting mov
* of an immediate. This happens e.g. with texture descriptors, since we
* narrow the descriptor (which may be a constant) to a half-reg in ir3.
@ -574,7 +573,8 @@ instr_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr)
instr->opc = cond->opc;
instr->flags = cond->flags;
instr->cat2 = cond->cat2;
ir3_instr_set_address(instr, cond->address);
if (cond->address)
ir3_instr_set_address(instr, cond->address->def->instr);
instr->regs[1] = ir3_reg_clone(ctx->shader, cond->regs[1]);
instr->regs[2] = ir3_reg_clone(ctx->shader, cond->regs[2]);
instr->barrier_class |= cond->barrier_class;

View File

@ -188,7 +188,7 @@ instr_cp_postsched(struct ir3_instruction *mov)
*/
if (removed) {
if (src->flags & IR3_REG_RELATIV)
ir3_instr_set_address(use, mov->address);
ir3_instr_set_address(use, mov->address->def->instr);
util_dynarray_append(&newdeps, struct ir3_instruction *, use);

View File

@ -194,11 +194,6 @@ ir3_delay_calc_prera(struct ir3_block *block, struct ir3_instruction *instr)
delay = MAX2(delay, d);
}
if (instr->address) {
unsigned d = delay_calc_srcn_prera(block, instr->address, instr, 0);
delay = MAX2(delay, d);
}
return delay;
}
@ -231,7 +226,11 @@ delay_calc_srcn_postra(struct ir3_instruction *assigner, struct ir3_instruction
bool mismatched_half =
(src->flags & IR3_REG_HALF) != (dst->flags & IR3_REG_HALF);
if (!mergedregs && mismatched_half)
/* In the mergedregs case or when the register is a special register,
* half-registers do not alias with full registers.
*/
if ((!mergedregs || is_reg_special(src) || is_reg_special(dst)) &&
mismatched_half)
return 0;
unsigned src_start = post_ra_reg_num(src) * reg_elem_size(src);
@ -318,11 +317,6 @@ delay_calc_postra(struct ir3_block *block,
unsigned new_delay = 0;
if (consumer->address == assigner) {
unsigned addr_delay = ir3_delayslots(assigner, consumer, 0, soft);
new_delay = MAX2(new_delay, addr_delay);
}
if (dest_regs(assigner) != 0) {
foreach_src_n (src, n, consumer) {
if (src->flags & (IR3_REG_IMMED | IR3_REG_CONST))

View File

@ -408,9 +408,8 @@ add_single_reg_dep(struct ir3_postsched_deps_state *state,
*
* If non-negative, then this adds a dependency on a source register, and
* src_n is the index passed into ir3_delayslots() for calculating the delay:
* 0 means this is for an address source, non-0 corresponds to
* node->instr->regs[src_n]. If negative, then this is for a destination
* register.
* If positive, corresponds to node->instr->regs[src_n]. If negative, then
* this is for a destination register.
*/
static void
add_reg_dep(struct ir3_postsched_deps_state *state,
@ -461,11 +460,6 @@ calculate_deps(struct ir3_postsched_deps_state *state,
}
}
if (node->instr->address) {
add_reg_dep(state, node, node->instr->address->regs[0],
node->instr->address->regs[0]->num, 0);
}
if (dest_regs(node->instr) == 0)
return;

View File

@ -297,13 +297,6 @@ print_instr(struct log_stream *stream, struct ir3_instruction *instr, int lvl)
}
}
if (instr->address) {
mesa_log_stream_printf(stream, ", address=_");
mesa_log_stream_printf(stream, "[");
print_instr_name(stream, instr->address, false);
mesa_log_stream_printf(stream, "]");
}
if (instr->opc == OPC_META_SPLIT) {
mesa_log_stream_printf(stream, ", off=%d", instr->split.off);
} else if (instr->opc == OPC_META_TEX_PREFETCH) {

View File

@ -381,7 +381,7 @@ check_instr(struct ir3_sched_ctx *ctx, struct ir3_sched_notes *notes,
struct ir3_instruction *indirect = ir->a0_users[i];
if (!indirect)
continue;
if (indirect->address != instr)
if (indirect->address->def != instr->regs[0])
continue;
ready = could_sched(indirect, instr);
}
@ -398,7 +398,7 @@ check_instr(struct ir3_sched_ctx *ctx, struct ir3_sched_notes *notes,
struct ir3_instruction *indirect = ir->a1_users[i];
if (!indirect)
continue;
if (indirect->address != instr)
if (indirect->address->def != instr->regs[0])
continue;
ready = could_sched(indirect, instr);
}
@ -870,13 +870,13 @@ split_addr(struct ir3_sched_ctx *ctx, struct ir3_instruction **addr,
/* remap remaining instructions using current addr
* to new addr:
*/
if (indirect->address == *addr) {
if (indirect->address->def == (*addr)->regs[0]) {
if (!new_addr) {
new_addr = split_instr(ctx, *addr);
/* original addr is scheduled, but new one isn't: */
new_addr->flags &= ~IR3_INSTR_MARK;
}
indirect->address = new_addr;
indirect->address->def = new_addr->regs[0];
/* don't need to remove old dag edge since old addr is
* already scheduled:
*/
@ -984,8 +984,6 @@ sched_node_add_dep(struct ir3_instruction *instr, struct ir3_instruction *src, i
unsigned d = 0;
if (i < instr->regs_count)
d = ir3_delayslots(src, instr, i + 1, true);
else if (src == instr->address)
d = ir3_delayslots(src, instr, 0, true);
n->delay = MAX2(n->delay, d);
}

View File

@ -157,6 +157,8 @@ validate_instr(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr)
/* must have the same size as the destination, handled in
* validate_reg().
*/
} else if (reg == instr->address) {
validate_assert(ctx, reg->flags & IR3_REG_HALF);
} else if ((instr->flags & IR3_INSTR_S2EN) && (n < 2)) {
if (n == 0) {
if (instr->flags & IR3_INSTR_B)