summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2015-07-02 13:52:38 -0400
committerRob Clark <[email protected]>2015-07-03 08:56:09 -0400
commit6b9f5cd5f7b25e9e03104fe279df74817f69fe87 (patch)
treef73fcf483f51dcff5d4eded53718bb2147f1e27b
parent0a155538eb7e7870b99fb8b3fd8e2a268361d2c8 (diff)
freedreno/ir3: fix indirects tracking
cp would update instr->address but not update the indirects array resulting in sched getting confused when it had to 'spill' the address register. Add an ir3_instr_set_address() helper to set instr->address and also update ir->indirects, and update all places that were writing instr->address to use helper instead. Signed-off-by: Rob Clark <[email protected]>
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3.c11
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3.h5
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c9
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_cp.c6
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_sched.c2
5 files changed, 23 insertions, 10 deletions
diff --git a/src/gallium/drivers/freedreno/ir3/ir3.c b/src/gallium/drivers/freedreno/ir3/ir3.c
index 1da6cf0477e..a0cb74498ec 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3.c
@@ -707,6 +707,17 @@ struct ir3_register * ir3_reg_create(struct ir3_instruction *instr,
}
void
+ir3_instr_set_address(struct ir3_instruction *instr,
+ struct ir3_instruction *addr)
+{
+ if (instr->address != addr) {
+ struct ir3 *ir = instr->block->shader;
+ instr->address = addr;
+ array_insert(ir->indirects, instr);
+ }
+}
+
+void
ir3_block_clear_mark(struct ir3_block *block)
{
list_for_each_entry (struct ir3_instruction, instr, &block->instr_list, node)
diff --git a/src/gallium/drivers/freedreno/ir3/ir3.h b/src/gallium/drivers/freedreno/ir3/ir3.h
index bc0144568a5..f11d8eda5f2 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3.h
+++ b/src/gallium/drivers/freedreno/ir3/ir3.h
@@ -285,6 +285,8 @@ struct ir3_instruction {
/* an instruction can reference at most one address register amongst
* it's src/dst registers. Beyond that, you need to insert mov's.
+ *
+ * NOTE: do not write this directly, use ir3_instr_set_address()
*/
struct ir3_instruction *address;
@@ -420,6 +422,9 @@ const char *ir3_instr_name(struct ir3_instruction *instr);
struct ir3_register * ir3_reg_create(struct ir3_instruction *instr,
int num, int flags);
+void ir3_instr_set_address(struct ir3_instruction *instr,
+ struct ir3_instruction *addr);
+
static inline bool ir3_instr_check_mark(struct ir3_instruction *instr)
{
if (instr->flags & IR3_INSTR_MARK)
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c b/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
index fa13c4076dc..8d8d4434d9e 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
@@ -637,9 +637,8 @@ create_uniform_indirect(struct ir3_compile *ctx, unsigned n,
mov->cat1.dst_type = TYPE_U32;
ir3_reg_create(mov, 0, 0);
ir3_reg_create(mov, n, IR3_REG_CONST | IR3_REG_RELATIV);
- mov->address = address;
- array_insert(ctx->ir->indirects, mov);
+ ir3_instr_set_address(mov, address);
return mov;
}
@@ -677,9 +676,8 @@ create_indirect_load(struct ir3_compile *ctx, unsigned arrsz, unsigned n,
src->instr = collect;
src->size = arrsz;
src->offset = n;
- mov->address = address;
- array_insert(ctx->ir->indirects, mov);
+ ir3_instr_set_address(mov, address);
return mov;
}
@@ -700,10 +698,9 @@ create_indirect_store(struct ir3_compile *ctx, unsigned arrsz, unsigned n,
dst->size = arrsz;
dst->offset = n;
ir3_reg_create(mov, 0, IR3_REG_SSA)->instr = src;
- mov->address = address;
mov->fanin = collect;
- array_insert(ctx->ir->indirects, mov);
+ ir3_instr_set_address(mov, address);
return mov;
}
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_cp.c b/src/gallium/drivers/freedreno/ir3/ir3_cp.c
index 8c7c80f7aae..f4c825b2ab6 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_cp.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_cp.c
@@ -291,7 +291,7 @@ reg_cp(struct ir3_instruction *instr, struct ir3_register *reg, unsigned n)
instr->regs[n+1] = src_reg;
if (src_reg->flags & IR3_REG_RELATIV)
- instr->address = reg->instr->address;
+ ir3_instr_set_address(instr, reg->instr->address);
return;
}
@@ -300,7 +300,7 @@ reg_cp(struct ir3_instruction *instr, struct ir3_register *reg, unsigned n)
!conflicts(instr->address, reg->instr->address)) {
src_reg->flags = new_flags;
instr->regs[n+1] = src_reg;
- instr->address = reg->instr->address;
+ ir3_instr_set_address(instr, reg->instr->address);
return;
}
@@ -389,7 +389,7 @@ instr_cp(struct ir3_instruction *instr, unsigned *flags)
}
if (instr->address)
- instr->address = instr_cp(instr->address, NULL);
+ ir3_instr_set_address(instr, instr_cp(instr->address, NULL));
return instr;
}
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_sched.c b/src/gallium/drivers/freedreno/ir3/ir3_sched.c
index 49a4426d163..01d72301dcc 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_sched.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_sched.c
@@ -312,7 +312,7 @@ split_addr(struct ir3_sched_ctx *ctx)
/* original addr is scheduled, but new one isn't: */
new_addr->flags &= ~IR3_INSTR_MARK;
}
- indirect->address = new_addr;
+ ir3_instr_set_address(indirect, new_addr);
}
}