[PATCH 0/1] forwprop: Extend memcmp forwprop inlining to the general case

Tudor-Stefan Magirescu <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
This patch addresses an optimization opportunity already performed by Clang:
inlining small constant-length memcmp calls beyond the cases where the result
is only used in an equality comparison with zero.

memcmp inlining in GCC happens in two places: once in forwprop for small
powers-of-two lengths, and once during RTL lowering.  This patch addresses
the forwprop case, with non-power-of-two lengths being left as future work.

A call like memcmp(a, b, 8) is inlined as two loads, a byte-swap on
little-endian targets, and a (cmp_gt - cmp_lt) expression representing the
sign of the difference.  When the result is subsequently used in a comparison
with zero, this expression can be further simplified to a single comparison.
I have submitted a separate patch for that simplification:
https://gcc.gnu.org/pipermail/gcc-patches/2026-July/725363.html.

Since the byte-swap is only profitable on targets with an efficient bswap
instruction, I introduced a new target hook TARGET_MEMCMP_INLINE_USING_BSWAP_P
that defaults to false.  x86 and AArch64 override it to enable the
optimization.  On big-endian targets no byte-swap is needed and the
optimization fires unconditionally.

This patch also exposes a pre-existing issue introduced by
bfa70ddb650ec91c2511d351b2b3c3f78dfad6d4: when forwprop inlines a memcmp
call, the subsequent pass_warn_access passes no longer see the original call
and cannot emit -Wstringop-overread diagnostics.  For example, the following
currently produces no warning:

  _Bool foo(const char *a) {
    return memcmp(a, "12", 4) == 0;
  }

The root cause is that pass_warn_access intentionally skips check_read_access
during its early invocation (m_early_checks_p), but by the time the later
invocations run, forwprop has already replaced the call.  This patch extends
the scope of the issue to all inlined memcmp calls, not just the equality
case.  Should I open a Bugzilla report for this?

As a consequence of this issue, the existing test gcc.dg/builtin-stringop-chk-8.c
had to be adjusted: the memcmp bound was changed from 2 to 3 (a non-power-of-two)
to prevent forwprop from inlining the call before pass_warn_access has a chance
to check it.

Tudor-Stefan Magirescu (1):
  forwprop: Extend memcmp forwprop inlining to the general case

 gcc/config/aarch64/aarch64.cc                 | 19 +++++
 gcc/config/i386/i386.cc                       | 22 +++++
 gcc/doc/tm.texi                               |  7 ++
 gcc/doc/tm.texi.in                            |  2 +
 gcc/target.def                                |  9 ++
 gcc/testsuite/gcc.dg/builtin-stringop-chk-8.c |  2 +-
 .../gcc.target/aarch64/memcmp-rev-1.c         | 26 ++++++
 .../gcc.target/i386/memcmp-bswap-1.c          | 14 ++++
 .../gcc.target/i386/memcmp-bswap-2.c          | 13 +++
 .../gcc.target/powerpc/memcmp-inline-1.c      | 24 ++++++
 gcc/tree-ssa-forwprop.cc                      | 84 +++++++++++++++++--
 11 files changed, 213 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/memcmp-rev-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/memcmp-bswap-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/memcmp-bswap-2.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/memcmp-inline-1.c

-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.