summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorConnor Abbott <cwabbott0@gmail.com>2021-06-18 12:01:18 +0200
committerMarge Bot <eric+marge@anholt.net>2021-06-23 17:20:29 +0000
commit9af795d9b984055042ef4ed33c6d3f2021be778a (patch)
treedba846737a1ebe6694893e035c1edf331922386d /src
parent2522f387a3d640b091b5ae2ca69a5e1d23edce99 (diff)
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>
Diffstat (limited to 'src')
-rw-r--r--src/freedreno/ir3/ir3.c15
-rw-r--r--src/freedreno/ir3/ir3.h33
-rw-r--r--src/freedreno/ir3/ir3_context.c2
-rw-r--r--src/freedreno/ir3/ir3_cp.c16
-rw-r--r--src/freedreno/ir3/ir3_cp_postsched.c2
-rw-r--r--src/freedreno/ir3/ir3_delay.c16
-rw-r--r--src/freedreno/ir3/ir3_postsched.c10
-rw-r--r--src/freedreno/ir3/ir3_print.c7
-rw-r--r--src/freedreno/ir3/ir3_sched.c10
-rw-r--r--src/freedreno/ir3/ir3_validate.c2
10 files changed, 44 insertions, 69 deletions
diff --git a/src/freedreno/ir3/ir3.c b/src/freedreno/ir3/ir3.c
index 72e58e8a727..14aa704ab75 100644
--- a/src/freedreno/ir3/ir3.c
+++ b/src/freedreno/ir3/ir3.c
@@ -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;
}
}
diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h
index f949ba32535..cb82eede37c 100644
--- a/src/freedreno/ir3/ir3.h
+++ b/src/freedreno/ir3/ir3.h
@@ -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++) \
diff --git a/src/freedreno/ir3/ir3_context.c b/src/freedreno/ir3/ir3_context.c
index 8fdaa239c4b..1a92497cdf3 100644
--- a/src/freedreno/ir3/ir3_context.c
+++ b/src/freedreno/ir3/ir3_context.c
@@ -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;
}
diff --git a/src/freedreno/ir3/ir3_cp.c b/src/freedreno/ir3/ir3_cp.c
index bed9efe082f..d5acba5c917 100644
--- a/src/freedreno/ir3/ir3_cp.c
+++ b/src/freedreno/ir3/ir3_cp.c
@@ -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;
diff --git a/src/freedreno/ir3/ir3_cp_postsched.c b/src/freedreno/ir3/ir3_cp_postsched.c
index dc0e1c588bb..b49a62a135d 100644
--- a/src/freedreno/ir3/ir3_cp_postsched.c
+++ b/src/freedreno/ir3/ir3_cp_postsched.c
@@ -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);
diff --git a/src/freedreno/ir3/ir3_delay.c b/src/freedreno/ir3/ir3_delay.c
index 7a310f236e4..3dbc0f768eb 100644
--- a/src/freedreno/ir3/ir3_delay.c
+++ b/src/freedreno/ir3/ir3_delay.c
@@ -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))
diff --git a/src/freedreno/ir3/ir3_postsched.c b/src/freedreno/ir3/ir3_postsched.c
index cf6bec512b5..3fbe97946ca 100644
--- a/src/freedreno/ir3/ir3_postsched.c
+++ b/src/freedreno/ir3/ir3_postsched.c
@@ -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;
diff --git a/src/freedreno/ir3/ir3_print.c b/src/freedreno/ir3/ir3_print.c
index 2ae241ba30f..a6d0b0d9786 100644
--- a/src/freedreno/ir3/ir3_print.c
+++ b/src/freedreno/ir3/ir3_print.c
@@ -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) {
diff --git a/src/freedreno/ir3/ir3_sched.c b/src/freedreno/ir3/ir3_sched.c
index a5509afb4e6..5a44ebe1bf8 100644
--- a/src/freedreno/ir3/ir3_sched.c
+++ b/src/freedreno/ir3/ir3_sched.c
@@ -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);
}
diff --git a/src/freedreno/ir3/ir3_validate.c b/src/freedreno/ir3/ir3_validate.c
index 7100cb392f7..06f85abf238 100644
--- a/src/freedreno/ir3/ir3_validate.c
+++ b/src/freedreno/ir3/ir3_validate.c
@@ -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)