diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2024-01-25 12:03:18 +0000 |
---|---|---|
committer | Richard Sandiford <richard.sandiford@arm.com> | 2024-01-25 12:03:18 +0000 |
commit | 8eead1148cd0ac086b39a7abccea404041c85cb5 (patch) | |
tree | 580fde4f0f6ff136e42dab6cd98113958b37e674 /gcc | |
parent | f251bbfec9174169510b2dec14b9bf763e7b77af (diff) | |
download | gcc-8eead1148cd0ac086b39a7abccea404041c85cb5.zip gcc-8eead1148cd0ac086b39a7abccea404041c85cb5.tar.gz gcc-8eead1148cd0ac086b39a7abccea404041c85cb5.tar.bz2 |
aarch64: Handle overlapping registers in movv8di [PR113550]
The LS64 movv8di pattern didn't handle loads that overlapped with
the address register (unless the overlap happened to be in the
last subload).
gcc/
PR target/113550
* config/aarch64/aarch64-simd.md: In the movv8di splitter, check
whether each split instruction is a load that clobbers the source
address. Emit that instruction last if so.
gcc/testsuite/
PR target/113550
* gcc.target/aarch64/pr113550.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/aarch64/aarch64-simd.md | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/pr113550.c | 48 |
2 files changed, 62 insertions, 4 deletions
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index 48f0741..f036f6c 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -8221,11 +8221,21 @@ || (memory_operand (operands[0], V8DImode) && register_operand (operands[1], V8DImode))) { + std::pair<rtx, rtx> last_pair = {}; for (int offset = 0; offset < 64; offset += 16) - emit_move_insn (simplify_gen_subreg (TImode, operands[0], - V8DImode, offset), - simplify_gen_subreg (TImode, operands[1], - V8DImode, offset)); + { + std::pair<rtx, rtx> pair = { + simplify_gen_subreg (TImode, operands[0], V8DImode, offset), + simplify_gen_subreg (TImode, operands[1], V8DImode, offset) + }; + if (register_operand (pair.first, TImode) + && reg_overlap_mentioned_p (pair.first, pair.second)) + last_pair = pair; + else + emit_move_insn (pair.first, pair.second); + } + if (last_pair.first) + emit_move_insn (last_pair.first, last_pair.second); DONE; } else diff --git a/gcc/testsuite/gcc.target/aarch64/pr113550.c b/gcc/testsuite/gcc.target/aarch64/pr113550.c new file mode 100644 index 0000000..0ff3c7b --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr113550.c @@ -0,0 +1,48 @@ +/* { dg-options "-O" } */ +/* { dg-do run } */ + +#pragma GCC push_options +#pragma GCC target "+ls64" +#pragma GCC aarch64 "arm_acle.h" +#pragma GCC pop_options + +#define DEF_FUNCTION(NAME, ARGS) \ + __attribute__((noipa)) \ + __arm_data512_t \ + NAME ARGS \ + { \ + return *ptr; \ + } + +DEF_FUNCTION (f0, (__arm_data512_t *ptr)) +DEF_FUNCTION (f1, (int x0, __arm_data512_t *ptr)) +DEF_FUNCTION (f2, (int x0, int x1, __arm_data512_t *ptr)) +DEF_FUNCTION (f3, (int x0, int x1, int x2, __arm_data512_t *ptr)) +DEF_FUNCTION (f4, (int x0, int x1, int x2, int x3, __arm_data512_t *ptr)) +DEF_FUNCTION (f5, (int x0, int x1, int x2, int x3, int x4, + __arm_data512_t *ptr)) +DEF_FUNCTION (f6, (int x0, int x1, int x2, int x3, int x4, int x5, + __arm_data512_t *ptr)) +DEF_FUNCTION (f7, (int x0, int x1, int x2, int x3, int x4, int x5, int x6, + __arm_data512_t *ptr)) + +int +main (void) +{ + __arm_data512_t x = { 0, 10, 20, 30, 40, 50, 60, 70 }; + __arm_data512_t res[8] = + { + f0 (&x), + f1 (0, &x), + f2 (0, 1, &x), + f3 (0, 1, 2, &x), + f4 (0, 1, 2, 3, &x), + f5 (0, 1, 2, 3, 4, &x), + f6 (0, 1, 2, 3, 4, 5, &x), + f7 (0, 1, 2, 3, 4, 5, 6, &x) + }; + for (int i = 0; i < 8; ++i) + if (__builtin_memcmp (&x, &res[i], sizeof (x)) != 0) + __builtin_abort (); + return 0; +} |