unsigned baryfs_count, baryfs_sz;
struct ir3_instruction **baryfs;
+ /* Track all indirect instructions (read and write). To avoid
+ * deadlock scenario where an address register gets scheduled,
+ * but other dependent src instructions cannot be scheduled due
+ * to dependency on a *different* address register value, the
+ * scheduler needs to ensure that all dependencies other than
+ * the instruction other than the address register are scheduled
+ * before the one that writes the address register. Having a
+ * convenient list of instructions that reference some address
+ * register simplifies this.
+ */
+ unsigned indirects_count, indirects_sz;
+ struct ir3_instruction **indirects;
+
struct ir3_block *block;
unsigned heap_idx;
struct ir3_heap_chunk *chunk;
compile_assert(ctx, ctx->block->address == instr->address);
instr->address = ctx->block->address;
+ array_insert(ctx->ir->indirects, instr);
}
reg = ir3_reg_create(instr, regid(num, chan), flags);
compile_assert(ctx, ctx->block->address == instr->address);
instr->address = ctx->block->address;
+ array_insert(ctx->ir->indirects, instr);
}
reg = ir3_reg_create(instr, regid(num, chan), flags);
}
}
+ /* if instruction writes address register, we need to ensure
+ * that the instructions which use the address register value
+ * have all their other dependencies scheduled.
+ * TODO we may possibly need to do the same thing with predicate
+ * register usage, but for now we get by without since the
+ * predicate usage patterns are more simple
+ */
+ if (writes_addr(instr)) {
+ struct ir3 *ir = instr->block->shader;
+ unsigned i;
+
+ for (i = 0; i < ir->indirects_count; i++) {
+ struct ir3_instruction *indirect = ir->indirects[i];
+ if (indirect->depth == DEPTH_UNUSED)
+ continue;
+ if (indirect->address != instr)
+ continue;
+ /* NOTE: avoid recursively scheduling the dependency
+ * on ourself (ie. avoid infinite recursion):
+ */
+ foreach_ssa_src(src, indirect) {
+ if (src == instr)
+ continue;
+ delay = trysched(ctx, src);
+ if (delay)
+ return delay;
+ }
+ }
+ }
+
/* if this is a write to address/predicate register, and that
* register is currently in use, we need to defer until it is
* free: