When COMPARE_MAX_PIECES is UNITS_PER_WORD (no SSE2, or SSE2 tunings
without fast unaligned SSE loads/stores such as core2), every word piece
gets its own compare and branch, so memcmp is only inlined up to 32
bytes for 64-bit and 16 bytes for ia32.
Use a branch ratio of 2 for word_mode pieces and halve SIZE in the cost
estimate when optimizing for speed, so the thresholds match the SSE2
ones: 64 bytes for 64-bit, 32 bytes for ia32. Each pair of word pieces
is then compared with a sequence similar to the SSE2 double-word compare:
two loads, two subs, one or and one branch.
Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}.
Ok for trunk?
gcc/ChangeLog:
PR target/128035
* config/i386/i386.cc (ix86_use_by_pieces_infrastructure_p): Halve
SIZE for COMPARE_BY_PIECES when COMPARE_MAX_PIECES is
UNITS_PER_WORD and optimizing for speed.
(ix86_compare_by_pieces_branch_ratio): New function.
(TARGET_COMPARE_BY_PIECES_BRANCH_RATIO): Define.
gcc/testsuite/ChangeLog:
PR target/128035
* gcc.target/i386/pr128035.c: New test.
---
gcc/config/i386/i386.cc | 25 ++++++++++++++++++++++++
gcc/testsuite/gcc.target/i386/pr128035.c | 16 +++++++++++++++
2 files changed, 41 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/i386/pr128035.c
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 136c339c8ca..1db8083dbc5 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -11637,9 +11637,30 @@ ix86_use_by_pieces_infrastructure_p (unsigned
HOST_WIDE_INT size,
if (cfun->machine->by_pieces_in_use)
return true;
+ /* compare_by_pieces pairs up word-sized pieces before branching (see
+ ix86_compare_by_pieces_branch_ratio), which is the code a double-word
+ compare expands to. Halve SIZE so the word-mode estimate gives the
+ same cutoff as the double-word path. */
+ if (op == COMPARE_BY_PIECES
+ && COMPARE_MAX_PIECES == UNITS_PER_WORD
+ && speed_p)
+ size = CEIL (size, 2);
+
return default_use_by_pieces_infrastructure_p (size, align, op,
speed_p);
}
+
+/* Implement TARGET_COMPARE_BY_PIECES_BRANCH_RATIO. */
+
+static int
+ix86_compare_by_pieces_branch_ratio (machine_mode mode)
+{
+ if (mode == word_mode
+ && COMPARE_MAX_PIECES == UNITS_PER_WORD
+ && optimize_insn_for_speed_p ())
+ return 2;
+ return 1;
+}
/* Allow {LABEL | SYMBOL}_REF - SYMBOL_REF-FOR-PICBASE for Mach-O as
this is used for to form addresses to local data when -fPIC is in
@@ -28984,6 +29005,10 @@ static const scoped_attribute_specs *const
ix86_attribute_table[] =
#define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P \
ix86_use_by_pieces_infrastructure_p
+#undef TARGET_COMPARE_BY_PIECES_BRANCH_RATIO
+#define TARGET_COMPARE_BY_PIECES_BRANCH_RATIO \
+ ix86_compare_by_pieces_branch_ratio
+
#undef TARGET_OVERLAP_OP_BY_PIECES_P
#define TARGET_OVERLAP_OP_BY_PIECES_P hook_bool_void_true
diff --git a/gcc/testsuite/gcc.target/i386/pr128035.c
b/gcc/testsuite/gcc.target/i386/pr128035.c
new file mode 100644
index 00000000000..84a7c4486e6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr128035.c
@@ -0,0 +1,16 @@
+/* PR target/128035 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mno-sse" } */
+/* { dg-final { scan-assembler-not "memcmp" } } */
+
+#define BUFSIZE 40
+
+struct foo {
+ char buf[BUFSIZE];
+};
+
+int
+test (struct foo *p1, struct foo *p2)
+{
+ return __builtin_memcmp (p1, p2, sizeof (struct foo)) == 0;
+}
--
2.34.1