diff options
-rw-r--r-- | .pick_status.json | 2 | ||||
-rw-r--r-- | src/freedreno/ir3/ir3_lower_parallelcopy.c | 18 |
2 files changed, 17 insertions, 3 deletions
diff --git a/.pick_status.json b/.pick_status.json index 326f0768d3e..603e0a56b49 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -2029,7 +2029,7 @@ "description": "ir3/lower_pcopy: Fix bug with \"illegal\" copies and swaps", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "0ffcb19b9d9fbe902224542047c389a661fbf816" }, 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, }); |