* Find/group instruction neighbors:
*/
-/* stop condition for iteration: */
-static bool check_stop(struct ir3_instruction *instr)
-{
- if (ir3_instr_check_mark(instr))
- return true;
-
- /* stay within the block.. don't try to operate across
- * basic block boundaries or we'll have problems when
- * dealing with multiple basic blocks:
- */
- if (is_meta(instr) && (instr->opc == OPC_META_INPUT))
- return true;
-
- return false;
-}
-
/* bleh.. we need to do the same group_n() thing for both inputs/outputs
* (where we have a simple instr[] array), and fanin nodes (where we have
* an extra indirection via reg->instr).
debug_assert(instr->regs_count == 1);
- in = ir3_instr_create(instr->block, -1, OPC_META_INPUT);
+ in = ir3_instr_create(instr->block, OPC_META_INPUT);
in->inout.block = instr->block;
ir3_reg_create(in, instr->regs[0]->num, 0);
/* create src reg for meta:in and fixup to now be a mov: */
ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = in;
- instr->category = 1;
- instr->opc = 0;
+ instr->opc = OPC_MOV;
instr->cat1.src_type = TYPE_F32;
instr->cat1.dst_type = TYPE_F32;
{
return ssa(((struct ir3_instruction *)arr)->regs[idx+1]);
}
-static void instr_insert_mov(void *arr, int idx, struct ir3_instruction *instr)
+static void
+instr_insert_mov(void *arr, int idx, struct ir3_instruction *instr)
{
((struct ir3_instruction *)arr)->regs[idx+1]->instr =
ir3_MOV(instr->block, instr, TYPE_F32);
}
static struct group_ops instr_ops = { instr_get, instr_insert_mov };
+/* verify that cur != instr, but cur is also not in instr's neighbor-list: */
+static bool
+in_neighbor_list(struct ir3_instruction *instr, struct ir3_instruction *cur, int pos)
+{
+ int idx = 0;
+
+ if (!instr)
+ return false;
-static void group_n(struct group_ops *ops, void *arr, unsigned n)
+ if (instr == cur)
+ return true;
+
+ for (instr = ir3_neighbor_first(instr); instr; instr = instr->cp.right)
+ if ((idx++ != pos) && (instr == cur))
+ return true;
+
+ return false;
+}
+
+static void
+group_n(struct group_ops *ops, void *arr, unsigned n)
{
unsigned i, j;
conflict = conflicts(instr->cp.left, left) ||
conflicts(instr->cp.right, right);
+ /* Mixing array elements and higher register classes
+ * (ie. groups) doesn't really work out in RA. See:
+ *
+ * https://trello.com/c/DqeDkeVf/156-bug-with-stk-70frag
+ */
+ if (instr->regs[0]->flags & IR3_REG_ARRAY)
+ conflict = true;
+
/* we also can't have an instr twice in the group: */
for (j = i + 1; (j < n) && !conflict; j++)
- if (ops->get(arr, j) == instr)
+ if (in_neighbor_list(ops->get(arr, j), instr, i))
conflict = true;
if (conflict) {
}
}
-static void instr_find_neighbors(struct ir3_instruction *instr)
+static void
+instr_find_neighbors(struct ir3_instruction *instr)
{
struct ir3_instruction *src;
- if (check_stop(instr))
+ if (ir3_instr_check_mark(instr))
return;
- if (is_meta(instr) && (instr->opc == OPC_META_FI))
+ if (instr->opc == OPC_META_FI)
group_n(&instr_ops, instr, instr->regs_count - 1);
foreach_ssa_src(src, instr)
* we need to insert dummy/padding instruction for grouping, and
* then take it back out again before anyone notices.
*/
-static void pad_and_group_input(struct ir3_instruction **input, unsigned n)
+static void
+pad_and_group_input(struct ir3_instruction **input, unsigned n)
{
int i, mask = 0;
struct ir3_block *block = NULL;
}
}
-static void block_find_neighbors(struct ir3_block *block)
+static void
+find_neighbors(struct ir3 *ir)
{
unsigned i;
* This logic won't quite cut it if we don't align smaller
* on vec4 boundaries
*/
- for (i = 0; i < block->ninputs; i += 4)
- pad_and_group_input(&block->inputs[i], 4);
- for (i = 0; i < block->noutputs; i += 4)
- group_n(&arr_ops_out, &block->outputs[i], 4);
-
+ for (i = 0; i < ir->ninputs; i += 4)
+ pad_and_group_input(&ir->inputs[i], 4);
+ for (i = 0; i < ir->noutputs; i += 4)
+ group_n(&arr_ops_out, &ir->outputs[i], 4);
+
+ for (i = 0; i < ir->noutputs; i++) {
+ if (ir->outputs[i]) {
+ struct ir3_instruction *instr = ir->outputs[i];
+ instr_find_neighbors(instr);
+ }
+ }
- for (i = 0; i < block->noutputs; i++) {
- if (block->outputs[i]) {
- struct ir3_instruction *instr = block->outputs[i];
+ list_for_each_entry (struct ir3_block, block, &ir->block_list, node) {
+ for (i = 0; i < block->keeps_count; i++) {
+ struct ir3_instruction *instr = block->keeps[i];
instr_find_neighbors(instr);
}
}
}
-void ir3_block_group(struct ir3_block *block)
+void
+ir3_group(struct ir3 *ir)
{
- ir3_clear_mark(block->shader);
- block_find_neighbors(block);
+ ir3_clear_mark(ir);
+ find_neighbors(ir);
}