summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2016-04-18 11:32:40 -0400
committerRob Clark <[email protected]>2016-04-18 15:41:32 -0400
commit77a9107bf299faa738737ed105c1b5e5ac06d1ca (patch)
tree948a93c4fcfce1d01f4d1a90d85e28c218f2f6bf /src
parented66c75784e3a51d414a6c4e90820d908d724b80 (diff)
freedreno/ir3: fix grouping issue w/ reverse swizzles
When we have something like: MOV OUT[n], IN[m].wzyx the existing grouping code was missing a potential conflict. Due to input needing to be sequential scalar regs, we have: IN: x <-> y <-> z <-> w which would be grouped to: OUT: w <-> z2 <-> y2 <-> x (where the 2 denotes a copy/mov) but that can't actually work. We need to realize that x and w are already in the same chain, not just that they aren't both already in new chain being built. With this fixed, we probably no longer need the hack from f68f6c0. Signed-off-by: Rob Clark <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_group.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_group.c b/src/gallium/drivers/freedreno/ir3/ir3_group.c
index cd59080b0f1..f229fe6eecd 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_group.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_group.c
@@ -90,6 +90,22 @@ instr_insert_mov(void *arr, int idx, struct ir3_instruction *instr)
}
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)
+{
+ if (!instr)
+ return false;
+
+ if (instr == cur)
+ return true;
+
+ for (instr = ir3_neighbor_first(instr); instr; instr = instr->cp.right)
+ if (instr == cur)
+ return true;
+
+ return false;
+}
static void
group_n(struct group_ops *ops, void *arr, unsigned n)
@@ -121,7 +137,7 @@ restart:
/* 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))
conflict = true;
if (conflict) {