aarch64: Stop +mops clobbering variable values
authorRichard Sandiford <richard.sandiford@arm.com>
Tue, 5 Apr 2022 16:31:36 +0000 (17:31 +0100)
committerRichard Sandiford <richard.sandiford@arm.com>
Tue, 5 Apr 2022 16:31:36 +0000 (17:31 +0100)
commit65b77d0eece6020b927f2b8de0ac5315224e38b7
treea5290e793ef018edb099d2ba831908e4c0db36fe
parent14814e20161d7b6a4e9cac244c7013fa56f71f55
aarch64: Stop +mops clobbering variable values

The mops cpy* patterns take three registers: a destination address,
a source address, and a size.  The patterns clobber all three registers
as part of the operation.  The set* patterns take a destination address,
a size, and a store value, and they clobber the first two registers as
part of the operation.

However, the associated expanders would try to use existing source,
destination and size registers where possible.  Any variables in
those registers could therefore change unexpectedly.

For example:

    void
    copy1 (int *x, int *y, long z, int **res)
    {
      __builtin_memcpy (x, y, z);
      *res = x;
    }

generated:

        cpyfp   [x0]!, [x1]!, x2!
        cpyfm   [x0]!, [x1]!, x2!
        cpyfe   [x0]!, [x1]!, x2!
        str     x0, [x3]
        ret

which stores the incremented x at *res.

gcc/
* config/aarch64/aarch64.md (aarch64_cpymemdi): Turn into a
define_expand and turn operands 0 and 1 from REGs to MEMs.
(*aarch64_cpymemdi): New pattern.
(aarch64_setmemdi): Turn into a define_expand and turn operand 0
from a REG to a MEM.
(*aarch64_setmemdi): New pattern.
* config/aarch64/aarch64.cc (aarch64_expand_cpymem_mops): Use
copy_to_mode_reg on all three registers.  Replace the original
MEM addresses rather than creating wild reads and writes.
(aarch64_expand_setmem_mops): Likewise for the size and for the
destination memory and address.

gcc/testsuite/
* gcc.target/aarch64/mops_4.c: New test.
gcc/config/aarch64/aarch64.cc
gcc/config/aarch64/aarch64.md
gcc/testsuite/gcc.target/aarch64/mops_4.c [new file with mode: 0644]