diff options
author | Uros Bizjak <ubizjak@gmail.com> | 2023-10-05 17:40:37 +0200 |
---|---|---|
committer | Uros Bizjak <ubizjak@gmail.com> | 2023-10-05 17:43:10 +0200 |
commit | c6bff80d786919f2f64e8a9f3179d6d36888bdb3 (patch) | |
tree | 016ba9793c6a54805919e7085a542061a0dcf51a | |
parent | e866d08d8b02ea19f88ac149ecb41695ba626aa6 (diff) | |
download | gcc-c6bff80d786919f2f64e8a9f3179d6d36888bdb3.zip gcc-c6bff80d786919f2f64e8a9f3179d6d36888bdb3.tar.gz gcc-c6bff80d786919f2f64e8a9f3179d6d36888bdb3.tar.bz2 |
i386: Improve memory copy from named address space [PR111657]
The stringop strategy selection algorithm falls back to a libcall strategy
when it exhausts its pool of available strategies. The memory area copy
function (memcpy) is not availabe from the system library for non-default
address spaces, so the compiler emits the most trivial byte-at-a-time
copy loop instead.
The compiler should instead emit an optimized copy loop as a fallback for
non-default address spaces.
PR target/111657
gcc/ChangeLog:
* config/i386/i386-expand.cc (alg_usable_p): Reject libcall
strategy for non-default address spaces.
(decide_alg): Use loop strategy as a fallback strategy for
non-default address spaces.
gcc/testsuite/ChangeLog:
* gcc.target/i386/pr111657.c: New test.
-rw-r--r-- | gcc/config/i386/i386-expand.cc | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr111657.c | 9 |
2 files changed, 19 insertions, 1 deletions
diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc index e42ff27..9a98834 100644 --- a/gcc/config/i386/i386-expand.cc +++ b/gcc/config/i386/i386-expand.cc @@ -8320,6 +8320,11 @@ alg_usable_p (enum stringop_alg alg, bool memset, bool have_as) { if (alg == no_stringop) return false; + /* It is not possible to use a library call if we have non-default + address space. We can do better than the generic byte-at-a-time + loop, used as a fallback. */ + if (alg == libcall && have_as) + return false; if (alg == vector_loop) return TARGET_SSE || TARGET_AVX; /* Algorithms using the rep prefix want at least edi and ecx; @@ -8494,8 +8499,12 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, gcc_assert (alg != libcall); return alg; } + + /* Try to use some reasonable fallback algorithm. Note that for + non-default address spaces we default to a loop instead of + a libcall. */ return (alg_usable_p (algs->unknown_size, memset, have_as) - ? algs->unknown_size : libcall); + ? algs->unknown_size : have_as ? loop : libcall); } /* Decide on alignment. We know that the operand is already aligned to ALIGN diff --git a/gcc/testsuite/gcc.target/i386/pr111657.c b/gcc/testsuite/gcc.target/i386/pr111657.c new file mode 100644 index 0000000..fe54fca --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr111657.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-rtl-expand -mno-sse" } */ + +struct a { long arr[30]; }; + +__seg_gs struct a m; +void bar (struct a *dst) { *dst = m; } + +/* { dg-final { scan-rtl-dump-not "libcall" "expand" } } */ |