diff options
author | Tamar Christina <tamar.christina@arm.com> | 2018-08-30 10:40:07 +0000 |
---|---|---|
committer | Tamar Christina <tnfchris@gcc.gnu.org> | 2018-08-30 10:40:07 +0000 |
commit | f7e1d19d58660dee3fb0bd41496610a343f93e45 (patch) | |
tree | 9260b896db0bc13a11c812bd438f016bc728b63c /gcc | |
parent | c729951e9c51dabfc3ab7ef864ab2ab8b07b5934 (diff) | |
download | gcc-f7e1d19d58660dee3fb0bd41496610a343f93e45.zip gcc-f7e1d19d58660dee3fb0bd41496610a343f93e45.tar.gz gcc-f7e1d19d58660dee3fb0bd41496610a343f93e45.tar.bz2 |
Limit movmem copies to TImode on AArch64
On AArch64 we have integer modes larger than TImode, and while we can generate
moves for these they're not as efficient.
So instead make sure we limit the maximum we can copy to TImode. This means
copying a 16 byte struct will issue 1 TImode copy, which will be done using a
single STP as we expect but an CImode sized copy won't issue CImode operations.
I am also moving the residual code inside the if since smallest_mode_for_int may
trap if the mode doesn't exist. And the only time we know the mode to exist for
sure is when the condition of the if is true. This also saves repeated calls to
the iterator.
gcc/
2018-08-30 Tamar Christina <tamar.christina@arm.com>
* config/aarch64/aarch64.c (aarch64_expand_movmem): Set TImode max.
gcc/testsuite/
2018-08-30 Tamar Christina <tamar.christina@arm.com>
* gcc.target/aarch64/large_struct_copy_2.c: New.
From-SVN: r263974
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.c | 12 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/large_struct_copy_2.c | 26 |
4 files changed, 42 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e57a592..f7fb162 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2018-08-30 Tamar Christina <tamar.christina@arm.com> + + * config/aarch64/aarch64.c (aarch64_expand_movmem): Set TImode max. + 2018-08-30 Vlad Lazar <vlad.lazar@arm.com> PR middle-end/86995 diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 0d7ca99..1de76e0 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -15938,13 +15938,17 @@ aarch64_expand_movmem (rtx *operands) /* Convert n to bits to make the rest of the code simpler. */ n = n * BITS_PER_UNIT; + /* Maximum amount to copy in one go. The AArch64 back-end has integer modes + larger than TImode, but we should not use them for loads/stores here. */ + const int copy_limit = GET_MODE_BITSIZE (TImode); + while (n > 0) { /* Find the largest mode in which to do the copy in without over reading or writing. */ opt_scalar_int_mode mode_iter; FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_INT) - if (GET_MODE_BITSIZE (mode_iter.require ()) <= n) + if (GET_MODE_BITSIZE (mode_iter.require ()) <= MIN (n, copy_limit)) cur_mode = mode_iter.require (); gcc_assert (cur_mode != BLKmode); @@ -15958,10 +15962,10 @@ aarch64_expand_movmem (rtx *operands) cheaper. i.e. less instructions to do so. For instance doing a 15 byte copy it's more efficient to do two overlapping 8 byte copies than 8 + 6 + 1. */ - next_mode = smallest_mode_for_size (n, MODE_INT); - int n_bits = GET_MODE_BITSIZE (next_mode).to_constant (); - if (n > 0 && n_bits > n && n_bits <= 8 * BITS_PER_UNIT) + if (n > 0 && n <= 8 * BITS_PER_UNIT) { + next_mode = smallest_mode_for_size (n, MODE_INT); + int n_bits = GET_MODE_BITSIZE (next_mode).to_constant (); src = aarch64_move_pointer (src, (n - n_bits) / BITS_PER_UNIT); dst = aarch64_move_pointer (dst, (n - n_bits) / BITS_PER_UNIT); n = n_bits; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 317cb47..fd78dcf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2018-08-30 Tamar Christina <tamar.christina@arm.com> + + * gcc.target/aarch64/large_struct_copy_2.c: New. + 2018-08-29 Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/87053 diff --git a/gcc/testsuite/gcc.target/aarch64/large_struct_copy_2.c b/gcc/testsuite/gcc.target/aarch64/large_struct_copy_2.c new file mode 100644 index 0000000..5654342 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/large_struct_copy_2.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +typedef unsigned __attribute__((mode(DI))) uint64_t; + +struct S0 { + uint64_t f1; + uint64_t f2; + uint64_t f3; + uint64_t f4; + uint64_t f5; +} a; +struct S2 { + uint64_t f0; + uint64_t f2; + struct S0 f3; +}; + +void fn1 () { + struct S2 b = {0, 1, 7, 4073709551611, 4, 8, 7}; + a = b.f3; +} + +/* { dg-final { scan-assembler-times {ldp\s+x[0-9]+} 2 } } */ +/* { dg-final { scan-assembler-times {stp\s+x[0-9]+} 2 } } */ +/* { dg-final { scan-assembler-not {ld[1-3]} } } */ |