summaryrefslogtreecommitdiff
path: root/src/freedreno/ir3/ir3_lower_parallelcopy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/freedreno/ir3/ir3_lower_parallelcopy.c')
-rw-r--r--src/freedreno/ir3/ir3_lower_parallelcopy.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/src/freedreno/ir3/ir3_lower_parallelcopy.c b/src/freedreno/ir3/ir3_lower_parallelcopy.c
index b927e031a17..fbcd6ff62a6 100644
--- a/src/freedreno/ir3/ir3_lower_parallelcopy.c
+++ b/src/freedreno/ir3/ir3_lower_parallelcopy.c
@@ -109,11 +109,18 @@ do_swap(struct ir3_compiler *compiler, struct ir3_instruction *instr,
.flags = entry->flags & ~IR3_REG_HALF,
});
+ /* If src and dst are within the same full register, then swapping src
+ * with tmp above will also move dst to tmp. Account for that here.
+ */
+ unsigned dst =
+ (entry->src.reg & ~1u) == (entry->dst & ~1u) ?
+ tmp + (entry->dst & 1u) : entry->dst;
+
/* Do the original swap with src replaced with tmp */
do_swap(compiler, instr,
&(struct copy_entry){
.src = {.reg = tmp + (entry->src.reg & 1)},
- .dst = entry->dst,
+ .dst = dst,
.flags = entry->flags,
});
@@ -192,9 +199,16 @@ do_copy(struct ir3_compiler *compiler, struct ir3_instruction *instr,
.flags = entry->flags & ~IR3_REG_HALF,
});
+ /* Similar to in do_swap(), account for src being swapped with tmp if
+ * src and dst are in the same register.
+ */
+ struct copy_src src = entry->src;
+ if (!src.flags && (src.reg & ~1u) == (entry->dst & ~1u))
+ src.reg = tmp + (src.reg & 1u);
+
do_copy(compiler, instr,
&(struct copy_entry){
- .src = entry->src,
+ .src = src,
.dst = tmp + (entry->dst & 1),
.flags = entry->flags,
});