aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2020-08-14 17:11:53 -0600
committerGiuliano Belinassi <giuliano.belinassi@usp.br>2020-08-17 15:08:14 -0300
commit8fa40c65f417914ac74fbc44243671d13d85b9f3 (patch)
treebaa7dc09c75780c601edf10e8c2f995dc4abe160 /gcc/testsuite
parent27f2a40dadae86a9b6e1d0777dc4a0d99a3aee60 (diff)
PR tree-optimization/78257 - missing memcmp optimization with constant arrays
gcc/ChangeLog: PR middle-end/78257 * builtins.c (expand_builtin_memory_copy_args): Rename called function. (expand_builtin_stpcpy_1): Remove argument from call. (expand_builtin_memcmp): Rename called function. (inline_expand_builtin_bytecmp): Same. * expr.c (convert_to_bytes): New function. (constant_byte_string): New function (formerly string_constant). (string_constant): Call constant_byte_string. (byte_representation): New function. * expr.h (byte_representation): Declare. * fold-const-call.c (fold_const_call): Rename called function. * fold-const.c (c_getstr): Remove an argument. (getbyterep): Define a new function. * fold-const.h (c_getstr): Remove an argument. (getbyterep): Declare a new function. * gimple-fold.c (gimple_fold_builtin_memory_op): Rename callee. (gimple_fold_builtin_string_compare): Same. (gimple_fold_builtin_memchr): Same. gcc/testsuite/ChangeLog: PR middle-end/78257 * gcc.dg/memchr.c: New test. * gcc.dg/memcmp-2.c: New test. * gcc.dg/memcmp-3.c: New test. * gcc.dg/memcmp-4.c: New test.
Diffstat (limited to 'gcc/testsuite')
-rw-r--r--gcc/testsuite/gcc.dg/memchr.c94
-rw-r--r--gcc/testsuite/gcc.dg/memcmp-2.c183
-rw-r--r--gcc/testsuite/gcc.dg/memcmp-3.c349
-rw-r--r--gcc/testsuite/gcc.dg/memcmp-4.c81
4 files changed, 707 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/memchr.c b/gcc/testsuite/gcc.dg/memchr.c
new file mode 100644
index 00000000000..fb21d58b476
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/memchr.c
@@ -0,0 +1,94 @@
+/* PR middle-end/78257 - missing memcmp optimization with constant arrays
+ { dg-do compile }
+ { dg-options "-O -Wall -fdump-tree-optimized" } */
+
+typedef __INT8_TYPE__ int8_t;
+typedef __INT16_TYPE__ int16_t;
+typedef __INT32_TYPE__ int32_t;
+typedef __SIZE_TYPE__ size_t;
+
+extern void* memchr (const void*, int, size_t);
+
+/* Verify that initializers for flexible array members are handled
+ correctly. */
+
+struct SX
+{
+ /* offset */
+ /* 0 */ int32_t n;
+ /* 4 */ int8_t: 1;
+ /* 6 */ int16_t a[];
+};
+
+_Static_assert (__builtin_offsetof (struct SX, a) == 6);
+
+const struct SX sx =
+ {
+ 0x11121314, { 0x2122, 0x3132, 0x4142, 0x5152 }
+ };
+
+const char sx_rep[] =
+ {
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ 0x11, 0x12, 0x13, 0x14, 0, 0, 0x21, 0x22, 0x31, 0x32, 0x41, 0x42, 0x51, 0x52
+#else
+ 0x14, 0x13, 0x12, 0x11, 0, 0, 0x22, 0x21, 0x32, 0x31, 0x42, 0x41, 0x52, 0x51
+#endif
+ };
+
+
+void test_find (void)
+{
+ int n = 0, nb = (const char*)&sx.a[4] - (const char*)&sx;
+ const char *p = (const char*)&sx, *q = sx_rep;
+
+ if (nb != sizeof sx_rep)
+ __builtin_abort ();
+
+ n += p == memchr (p, q[ 0], nb);
+ n += p + 1 == memchr (p, q[ 1], nb);
+ n += p + 2 == memchr (p, q[ 2], nb);
+ n += p + 3 == memchr (p, q[ 3], nb);
+ n += p + 4 == memchr (p, q[ 4], nb);
+ n += p + 4 == memchr (p, q[ 5], nb);
+ n += p + 6 == memchr (p, q[ 6], nb);
+ n += p + 7 == memchr (p, q[ 7], nb);
+ n += p + 8 == memchr (p, q[ 8], nb);
+ n += p + 9 == memchr (p, q[ 9], nb);
+ n += p + 10 == memchr (p, q[10], nb);
+ n += p + 11 == memchr (p, q[11], nb);
+ n += p + 12 == memchr (p, q[12], nb);
+ n += p + 13 == memchr (p, q[13], nb);
+
+ if (n != 14)
+ __builtin_abort ();
+}
+
+void test_not_find (void)
+{
+ int n = 0, nb = (const char*)&sx.a[4] - (const char*)&sx;
+ const char *p = (const char*)&sx, *q = sx_rep;
+
+ if (nb != sizeof sx_rep)
+ __builtin_abort ();
+
+ n += 0 == memchr (p, 0xff, nb);
+ n += 0 == memchr (p + 1, q[ 0], nb - 1);
+ n += 0 == memchr (p + 2, q[ 1], nb - 2);
+ n += 0 == memchr (p + 3, q[ 2], nb - 3);
+ n += 0 == memchr (p + 4, q[ 3], nb - 4);
+ n += 0 == memchr (p + 6, q[ 4], nb - 6);
+ n += 0 == memchr (p + 7, q[ 6], nb - 7);
+ n += 0 == memchr (p + 8, q[ 7], nb - 8);
+ n += 0 == memchr (p + 9, q[ 8], nb - 9);
+ n += 0 == memchr (p + 10, q[ 9], nb - 10);
+ n += 0 == memchr (p + 11, q[10], nb - 11);
+ n += 0 == memchr (p + 12, q[11], nb - 12);
+ n += 0 == memchr (p + 13, q[12], nb - 13);
+ n += 0 == memchr (p + 14, q[13], nb - 14);
+
+ if (n != 14)
+ __builtin_abort ();
+}
+
+/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/memcmp-2.c b/gcc/testsuite/gcc.dg/memcmp-2.c
new file mode 100644
index 00000000000..ff99c12b0af
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/memcmp-2.c
@@ -0,0 +1,183 @@
+/* PR middle-end/78257 - missing memcmp optimization with constant arrays
+ { dg-do compile }
+ { dg-options "-O -Wall -fdump-tree-optimized" } */
+
+#define assert(e) ((e) ? (void)0 : __builtin_abort ())
+
+typedef __INT32_TYPE__ int32_t;
+
+extern int memcmp (const void*, const void*, __SIZE_TYPE__);
+
+const int32_t i_0 = 0;
+const int32_t j_0 = 0;
+
+void eq_i0_j0 (void)
+{
+ const char *pi = (char*)&i_0, *pj = (char*)&j_0;
+ int n = 0;
+
+ n += 0 == memcmp (pi, pj, sizeof (int32_t));
+ n += 0 == memcmp (pi + 1, pj + 1, sizeof (int32_t) - 1);
+ n += 0 == memcmp (pi + 2, pj + 2, sizeof (int32_t) - 2);
+ n += 0 == memcmp (pi + 3, pj + 3, sizeof (int32_t) - 3);
+ n += 0 == memcmp (pi + 4, pj + 4, sizeof (int32_t) - 4);
+
+ assert (n == 5);
+}
+
+
+const int32_t i1234 = 1234;
+const int32_t j1234 = 1234;
+
+void eq_i1234_j1245 (void)
+{
+ const char *pi = (char*)&i1234, *pj = (char*)&j1234;
+ int n = 0;
+
+ n += 0 == memcmp (pi, pj, sizeof (int32_t));
+ n += 0 == memcmp (pi + 1, pj + 1, sizeof (int32_t) - 1);
+ n += 0 == memcmp (pi + 2, pj + 2, sizeof (int32_t) - 2);
+ n += 0 == memcmp (pi + 3, pj + 3, sizeof (int32_t) - 3);
+ n += 0 == memcmp (pi + 4, pj + 4, sizeof (int32_t) - 4);
+
+ assert (n == 5);
+}
+
+
+const int32_t a1[2] = { 1234 };
+const int32_t b1[2] = { 1234 };
+
+void eq_a1_b1 (void)
+{
+ const char *pi = (char*)&a1, *pj = (char*)&b1;
+ int n = 0, nb = sizeof a1;
+
+ n += 0 == memcmp (pi, pj, nb);
+ n += 0 == memcmp (pi + 1, pj + 1, nb - 1);
+ n += 0 == memcmp (pi + 2, pj + 2, nb - 2);
+ n += 0 == memcmp (pi + 3, pj + 3, nb - 3);
+ n += 0 == memcmp (pi + 4, pj + 4, nb - 4);
+ n += 0 == memcmp (pi + 5, pj + 5, nb - 5);
+ n += 0 == memcmp (pi + 6, pj + 6, nb - 6);
+ n += 0 == memcmp (pi + 7, pj + 7, nb - 7);
+ n += 0 == memcmp (pi + 8, pj + 8, nb - 8);
+
+ assert (n == 9);
+}
+
+const int32_t a2[2] = { 1234 };
+const int32_t b2[2] = { 1234, 0 };
+
+void eq_a2_b2 (void)
+{
+ const char *pi = (char*)&a2, *pj = (char*)&b2;
+ int n = 0, nb = sizeof a2;
+
+ n += 0 == memcmp (pi, pj, nb);
+ n += 0 == memcmp (pi + 1, pj + 1, nb - 1);
+ n += 0 == memcmp (pi + 2, pj + 2, nb - 2);
+ n += 0 == memcmp (pi + 3, pj + 3, nb - 3);
+ n += 0 == memcmp (pi + 4, pj + 4, nb - 4);
+ n += 0 == memcmp (pi + 5, pj + 5, nb - 5);
+ n += 0 == memcmp (pi + 6, pj + 6, nb - 6);
+ n += 0 == memcmp (pi + 7, pj + 7, nb - 7);
+ n += 0 == memcmp (pi + 8, pj + 8, nb - 8);
+
+ assert (n == 9);
+}
+
+
+const int32_t a5[5] = { [3] = 1234, [1] = 0 };
+const int32_t b5[5] = { 0, 0, 0, 1234 };
+
+void eq_a5_b5 (void)
+{
+ int n = 0, b = sizeof a5;
+ const char *pi = (char*)a5, *pj = (char*)b5;
+
+ n += 0 == memcmp (pi, pj, b);
+ n += 0 == memcmp (pi + 1, pj + 1, b - 1);
+ n += 0 == memcmp (pi + 2, pj + 2, b - 2);
+ n += 0 == memcmp (pi + 3, pj + 3, b - 3);
+
+ n += 0 == memcmp (pi + 4, pj + 4, b - 4);
+ n += 0 == memcmp (pi + 5, pj + 5, b - 5);
+ n += 0 == memcmp (pi + 6, pj + 6, b - 6);
+ n += 0 == memcmp (pi + 7, pj + 7, b - 7);
+
+ n += 0 == memcmp (pi + 8, pj + 8, b - 8);
+ n += 0 == memcmp (pi + 9, pj + 9, b - 9);
+ n += 0 == memcmp (pi + 10, pj + 10, b - 10);
+ n += 0 == memcmp (pi + 11, pj + 11, b - 11);
+
+ n += 0 == memcmp (pi + 12, pj + 12, b - 12);
+ n += 0 == memcmp (pi + 13, pj + 13, b - 13);
+ n += 0 == memcmp (pi + 14, pj + 14, b - 14);
+ n += 0 == memcmp (pi + 15, pj + 15, b - 15);
+
+ n += 0 == memcmp (pi + 16, pj + 16, b - 16);
+ n += 0 == memcmp (pi + 17, pj + 17, b - 17);
+ n += 0 == memcmp (pi + 18, pj + 18, b - 18);
+ n += 0 == memcmp (pi + 19, pj + 19, b - 19);
+
+ assert (n == 20);
+}
+
+
+const int32_t a19[19] = { [13] = 13, [8] = 8, [4] = 4, [1] = 1 };
+const int32_t b19[19] = { 0, 1, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 13 };
+
+void eq_a19_b19 (void)
+{
+ int n = 0, b = sizeof a19;
+ const char *pi = (char*)a19, *pj = (char*)b19;
+
+ n += 0 == memcmp (pi, pj, b);
+ n += 0 == memcmp (pi + 1, pj + 1, b - 1);
+ n += 0 == memcmp (pi + 2, pj + 2, b - 2);
+ n += 0 == memcmp (pi + 3, pj + 3, b - 3);
+
+ n += 0 == memcmp (pi + 14, pj + 14, b - 14);
+ n += 0 == memcmp (pi + 15, pj + 15, b - 15);
+ n += 0 == memcmp (pi + 16, pj + 16, b - 16);
+ n += 0 == memcmp (pi + 17, pj + 17, b - 17);
+
+ n += 0 == memcmp (pi + 28, pj + 28, b - 28);
+ n += 0 == memcmp (pi + 29, pj + 29, b - 29);
+ n += 0 == memcmp (pi + 30, pj + 30, b - 30);
+ n += 0 == memcmp (pi + 31, pj + 31, b - 31);
+
+ n += 0 == memcmp (pi + 42, pj + 42, b - 42);
+ n += 0 == memcmp (pi + 43, pj + 43, b - 43);
+ n += 0 == memcmp (pi + 44, pj + 44, b - 44);
+ n += 0 == memcmp (pi + 45, pj + 45, b - 45);
+
+ n += 0 == memcmp (pi + 56, pj + 56, b - 56);
+ n += 0 == memcmp (pi + 57, pj + 57, b - 57);
+ n += 0 == memcmp (pi + 58, pj + 58, b - 58);
+ n += 0 == memcmp (pi + 59, pj + 59, b - 59);
+
+ assert (n == 20);
+}
+
+
+const int32_t A20[20] = { [13] = 14, [8] = 8, [4] = 4, [1] = 1 };
+const int32_t b20[20] = { 0, 1, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 13 };
+
+void gt_A20_b20 (void)
+{
+ int n = memcmp (A20, b20, sizeof A20) > 0;
+ assert (n == 1);
+}
+
+const int32_t a21[21] = { [13] = 12, [8] = 8, [4] = 4, [1] = 1 };
+const int32_t B21[21] = { 0, 1, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 13 };
+
+void lt_a21_B21 (void)
+{
+ int n = memcmp (a21, B21, sizeof a21) < 0;
+ assert (n == 1);
+}
+
+
+/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/memcmp-3.c b/gcc/testsuite/gcc.dg/memcmp-3.c
new file mode 100644
index 00000000000..b5b8ac1209f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/memcmp-3.c
@@ -0,0 +1,349 @@
+/* PR middle-end/78257 - missing memcmp optimization with constant arrays
+ { dg-do compile }
+ { dg-options "-O -Wall -fdump-tree-optimized" }
+ { dg-skip-if "missing data representation" { "pdp11-*-*" } } */
+
+#define offsetof(T, m) __builtin_offsetof (T, m)
+
+typedef __INT8_TYPE__ int8_t;
+typedef __INT16_TYPE__ int16_t;
+typedef __INT32_TYPE__ int32_t;
+typedef __INT64_TYPE__ int64_t;
+typedef __SIZE_TYPE__ size_t;
+
+extern int memcmp (const void*, const void*, size_t);
+
+const int32_t ia4[4] = { 0x11121314, 0x21222324, 0x31323334, 0x41424344 };
+const int32_t ia4_des[4] =
+ { [2] = 0x31323334, [0] = 0x11121314, 0x21222324, [3] = 0x41424344 };
+const char ia4_rep[] =
+ {
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ "\x11\x12\x13\x14" "\x21\x22\x23\x24"
+ "\x31\x32\x33\x34" "\x41\x42\x43\x44"
+#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ "\x14\x13\x12\x11" "\x24\x23\x22\x21"
+ "\x34\x33\x32\x31" "\x44\x43\x42\x41"
+#endif
+ };
+
+void eq_ia4 (void)
+{
+ int n = 0, b = sizeof ia4;
+ const char *p = (const char*)ia4, *q = ia4_rep;
+
+ n += memcmp (p, q, b);
+ n += memcmp (p + 1, q + 1, b - 1);
+ n += memcmp (p + 2, q + 2, b - 2);
+ n += memcmp (p + 3, q + 3, b - 3);
+ n += memcmp (p + 4, q + 4, b - 4);
+ n += memcmp (p + 5, q + 5, b - 5);
+ n += memcmp (p + 6, q + 6, b - 6);
+ n += memcmp (p + 7, q + 7, b - 7);
+ n += memcmp (p + 8, q + 8, b - 8);
+ n += memcmp (p + 9, q + 9, b - 9);
+ n += memcmp (p + 10, q + 10, b - 10);
+ n += memcmp (p + 11, q + 11, b - 11);
+ n += memcmp (p + 12, q + 12, b - 12);
+ n += memcmp (p + 13, q + 13, b - 13);
+ n += memcmp (p + 14, q + 14, b - 14);
+ n += memcmp (p + 15, q + 15, b - 15);
+ n += memcmp (p + 16, q + 16, b - 16);
+
+ p = (const char*)ia4_des;
+
+ n += memcmp (p, q, b);
+ n += memcmp (p + 1, q + 1, b - 1);
+ n += memcmp (p + 2, q + 2, b - 2);
+ n += memcmp (p + 3, q + 3, b - 3);
+ n += memcmp (p + 4, q + 4, b - 4);
+ n += memcmp (p + 5, q + 5, b - 5);
+ n += memcmp (p + 6, q + 6, b - 6);
+ n += memcmp (p + 7, q + 7, b - 7);
+ n += memcmp (p + 8, q + 8, b - 8);
+ n += memcmp (p + 9, q + 9, b - 9);
+ n += memcmp (p + 10, q + 10, b - 10);
+ n += memcmp (p + 11, q + 11, b - 11);
+ n += memcmp (p + 12, q + 12, b - 12);
+ n += memcmp (p + 13, q + 13, b - 13);
+ n += memcmp (p + 14, q + 14, b - 14);
+ n += memcmp (p + 15, q + 15, b - 15);
+ n += memcmp (p + 16, q + 16, b - 16);
+
+ if (n != 0)
+ __builtin_abort ();
+}
+
+const float fa4[4] = { 1.0, 2.0, 3.0, 4.0 };
+const float fa4_des[4] = { [0] = fa4[0], [1] = 2.0, [2] = fa4[2], [3] = 4.0 };
+
+void eq_fa4 (void)
+{
+ int n = 0, b = sizeof fa4;
+ const char *p = (const char*)fa4, *q = (const char*)fa4_des;
+
+ n += memcmp (p, q, b);
+ n += memcmp (p + 1, q + 1, b - 1);
+ n += memcmp (p + 2, q + 2, b - 2);
+ n += memcmp (p + 3, q + 3, b - 3);
+ n += memcmp (p + 4, q + 4, b - 4);
+ n += memcmp (p + 5, q + 5, b - 5);
+ n += memcmp (p + 6, q + 6, b - 6);
+ n += memcmp (p + 7, q + 7, b - 7);
+ n += memcmp (p + 8, q + 8, b - 8);
+ n += memcmp (p + 9, q + 9, b - 9);
+ n += memcmp (p + 10, q + 10, b - 10);
+ n += memcmp (p + 11, q + 11, b - 11);
+ n += memcmp (p + 12, q + 12, b - 12);
+ n += memcmp (p + 13, q + 13, b - 13);
+ n += memcmp (p + 14, q + 14, b - 14);
+ n += memcmp (p + 15, q + 15, b - 15);
+ n += memcmp (p + 16, q + 16, b - 16);
+
+ if (n != 0)
+ __builtin_abort ();
+}
+
+/* Verify "greater than" comparison with the difference in the last byte. */
+const char ia4_xrep_16[sizeof ia4] =
+ {
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ 0x11, 0x12, 0x13, 0x14, 0x21, 0x22, 0x23, 0x24,
+ 0x31, 0x32, 0x33, 0x34, 0x41, 0x42, 0x43
+#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ 0x14, 0x13, 0x12, 0x11, 0x24, 0x23, 0x22, 0x21,
+ 0x34, 0x33, 0x32, 0x31, 0x44, 0x43, 0x42
+#endif
+ };
+
+void gt_ia4 (void)
+{
+ int n = 0, b = sizeof ia4;
+ const char *p = (const char*)ia4, *q = ia4_xrep_16;
+
+ n += 0 < memcmp (p, q, b);
+ n += 0 < memcmp (p + 1, q + 1, b - 1);
+ n += 0 < memcmp (p + 2, q + 2, b - 2);
+ n += 0 < memcmp (p + 3, q + 3, b - 3);
+ n += 0 < memcmp (p + 4, q + 4, b - 4);
+ n += 0 < memcmp (p + 5, q + 5, b - 5);
+ n += 0 < memcmp (p + 6, q + 6, b - 6);
+ n += 0 < memcmp (p + 7, q + 7, b - 7);
+ n += 0 < memcmp (p + 8, q + 8, b - 8);
+ n += 0 < memcmp (p + 9, q + 9, b - 9);
+ n += 0 < memcmp (p + 10, q + 10, b - 10);
+ n += 0 < memcmp (p + 11, q + 11, b - 11);
+ n += 0 < memcmp (p + 12, q + 12, b - 12);
+ n += 0 < memcmp (p + 13, q + 13, b - 13);
+ n += 0 < memcmp (p + 14, q + 14, b - 14);
+ n += 0 < memcmp (p + 15, q + 15, b - 15);
+
+ if (n != 16)
+ __builtin_abort ();
+}
+
+struct S8_16_32
+{
+ int8_t i8;
+ int16_t i16;
+ int32_t i32;
+};
+
+_Static_assert (sizeof (struct S8_16_32) == 8);
+
+const struct S8_16_32 s8_16_32 = { 1, 0x2122, 0x31323334 };
+const struct S8_16_32 s8_16_32_des =
+ { .i8 = 1, .i16 = 0x2122, .i32 = 0x31323334 };
+
+const char s8_16_32_rep[] =
+ {
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ 1, 0, 0x21, 0x22, 0x31, 0x32, 0x33, 0x34
+#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ 1, 0, 0x22, 0x21, 0x34, 0x33, 0x32, 0x31
+#endif
+ };
+
+void eq_s8_16_32 (void)
+{
+ int n = 0, b = sizeof s8_16_32;
+ const char *p = (char*)&s8_16_32, *q = s8_16_32_rep;
+
+ n += memcmp (p, q, b);
+ n += memcmp (p + 1, q + 1, b - 1);
+ n += memcmp (p + 2, q + 2, b - 2);
+ n += memcmp (p + 3, q + 3, b - 3);
+ n += memcmp (p + 4, q + 4, b - 4);
+ n += memcmp (p + 5, q + 5, b - 5);
+ n += memcmp (p + 6, q + 6, b - 6);
+ n += memcmp (p + 7, q + 7, b - 7);
+
+ p = (char*)&s8_16_32_des;
+
+ n += memcmp (p, q, b);
+ n += memcmp (p + 1, q + 1, b - 1);
+ n += memcmp (p + 2, q + 2, b - 2);
+ n += memcmp (p + 3, q + 3, b - 3);
+ n += memcmp (p + 4, q + 4, b - 4);
+ n += memcmp (p + 5, q + 5, b - 5);
+ n += memcmp (p + 6, q + 6, b - 6);
+ n += memcmp (p + 7, q + 7, b - 7);
+
+ if (n != 0)
+ __builtin_abort ();
+}
+
+
+struct S8_16_32_64
+{
+ /* 0 */ int8_t i8;
+ /* 1 */ int8_t: 1;
+ /* 2 */ int16_t i16;
+ /* 4 */ int32_t: 1;
+ /* 8 */ int32_t i32;
+ /* 12 */ int32_t: 1;
+ /* 16 */ int64_t i64;
+ /* 24 */ int8_t: 0;
+};
+
+_Static_assert (offsetof (struct S8_16_32_64, i16) == 2);
+_Static_assert (offsetof (struct S8_16_32_64, i32) == 8);
+_Static_assert (offsetof (struct S8_16_32_64, i64) == 16);
+_Static_assert (sizeof (struct S8_16_32_64) == 24);
+
+const struct S8_16_32_64 s8_16_32_64 =
+ { 1, 0x2122, 0x31323334, 0x4142434445464748LLU };
+
+const char s8_16_32_64_rep[sizeof s8_16_32_64] =
+ {
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ "\x01" "\x00" "\x21\x22" "\x00\x00\x00\x00" "\x31\x32\x33\x34"
+ "\x00\x00\x00\x00" "\x41\x42\x43\x44\x45\x46\x47\x48"
+#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ "\x01" "\x00" "\x22\x21" "\x00\x00\x00\x00" "\x34\x33\x32\x31"
+ "\x00\x00\x00\x00" "\x48\x47\x46\x45\x44\x43\x42\x41"
+#endif
+ };
+
+const struct S8_16_32_64 s8_16_32_64_des =
+ { .i64 = 0x4142434445464748LLU, .i16 = 0x2122, .i32 = 0x31323334, .i8 = 1 };
+
+
+void eq_8_16_32_64 (void)
+{
+ int n = 0, b = sizeof s8_16_32_64;
+ const char *p = (char*)&s8_16_32_64, *q = s8_16_32_64_rep;
+
+ n += memcmp (p, q, b);
+ n += memcmp (p + 1, q + 1, b - 1);
+ n += memcmp (p + 2, q + 2, b - 2);
+ n += memcmp (p + 3, q + 3, b - 3);
+ n += memcmp (p + 4, q + 4, b - 4);
+ n += memcmp (p + 5, q + 5, b - 5);
+ n += memcmp (p + 6, q + 6, b - 6);
+ n += memcmp (p + 7, q + 7, b - 7);
+ n += memcmp (p + 8, q + 8, b - 8);
+ n += memcmp (p + 9, q + 9, b - 9);
+ n += memcmp (p + 10, q + 10, b - 10);
+ n += memcmp (p + 11, q + 11, b - 11);
+ n += memcmp (p + 12, q + 12, b - 12);
+ n += memcmp (p + 13, q + 13, b - 13);
+ n += memcmp (p + 14, q + 14, b - 14);
+ n += memcmp (p + 15, q + 15, b - 15);
+ n += memcmp (p + 16, q + 16, b - 16);
+ n += memcmp (p + 17, q + 17, b - 17);
+ n += memcmp (p + 18, q + 18, b - 18);
+ n += memcmp (p + 19, q + 19, b - 19);
+ n += memcmp (p + 20, q + 20, b - 20);
+ n += memcmp (p + 21, q + 21, b - 21);
+ n += memcmp (p + 22, q + 22, b - 22);
+ n += memcmp (p + 23, q + 23, b - 23);
+
+ p = (char*)&s8_16_32_64_des;
+
+ n += memcmp (p, q, b);
+ n += memcmp (p + 1, q + 1, b - 1);
+ n += memcmp (p + 2, q + 2, b - 2);
+ n += memcmp (p + 3, q + 3, b - 3);
+ n += memcmp (p + 4, q + 4, b - 4);
+ n += memcmp (p + 5, q + 5, b - 5);
+ n += memcmp (p + 6, q + 6, b - 6);
+ n += memcmp (p + 7, q + 7, b - 7);
+ n += memcmp (p + 8, q + 8, b - 8);
+ n += memcmp (p + 9, q + 9, b - 9);
+ n += memcmp (p + 10, q + 10, b - 10);
+ n += memcmp (p + 11, q + 11, b - 11);
+ n += memcmp (p + 12, q + 12, b - 12);
+ n += memcmp (p + 13, q + 13, b - 13);
+ n += memcmp (p + 14, q + 14, b - 14);
+ n += memcmp (p + 15, q + 15, b - 15);
+ n += memcmp (p + 16, q + 16, b - 16);
+ n += memcmp (p + 17, q + 17, b - 17);
+ n += memcmp (p + 18, q + 18, b - 18);
+ n += memcmp (p + 19, q + 19, b - 19);
+ n += memcmp (p + 20, q + 20, b - 20);
+ n += memcmp (p + 21, q + 21, b - 21);
+ n += memcmp (p + 22, q + 22, b - 22);
+ n += memcmp (p + 23, q + 23, b - 23);
+
+ if (n != 0)
+ __builtin_abort ();
+}
+
+struct S64_x_3
+{
+ int64_t i64a[3];
+};
+
+_Static_assert (sizeof (struct S64_x_3) == 24);
+
+const struct S64_x_3 s64_x_3 =
+ { { 0x0000000021220001LLU, 0x0000000031323334LLU, 0x4142434445464748LLU } };
+
+const char s64_x_3_rep[sizeof s64_x_3] =
+ {
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ "\x00\x00\x00\x00\x21\x22\x00\x01"
+ "\x00\x00\x00\x00\x31\x32\x33\x34"
+ "\x41\x42\x43\x44\x45\x46\x47\x48"
+#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ "\x01\x00\x22\x21\x00\x00\x00\x00"
+ "\x34\x33\x32\x31\x00\x00\x00\x00"
+ "\x48\x47\x46\x45\x44\x43\x42\x41"
+#endif
+ };
+
+void eq_64_x_3 (void)
+{
+ int n = 0, b = sizeof s8_16_32_64;
+ const char *p = (char*)&s8_16_32_64, *q = s64_x_3_rep;
+ n += memcmp (p, q, b);
+ n += memcmp (p + 1, q + 1, b - 1);
+ n += memcmp (p + 2, q + 2, b - 2);
+ n += memcmp (p + 3, q + 3, b - 3);
+ n += memcmp (p + 4, q + 4, b - 4);
+ n += memcmp (p + 5, q + 5, b - 5);
+ n += memcmp (p + 6, q + 6, b - 6);
+ n += memcmp (p + 7, q + 7, b - 7);
+ n += memcmp (p + 8, q + 8, b - 8);
+ n += memcmp (p + 9, q + 9, b - 9);
+ n += memcmp (p + 10, q + 10, b - 10);
+ n += memcmp (p + 11, q + 11, b - 11);
+ n += memcmp (p + 12, q + 12, b - 12);
+ n += memcmp (p + 13, q + 13, b - 13);
+ n += memcmp (p + 14, q + 14, b - 14);
+ n += memcmp (p + 15, q + 15, b - 15);
+ n += memcmp (p + 16, q + 16, b - 16);
+ n += memcmp (p + 17, q + 17, b - 17);
+ n += memcmp (p + 18, q + 18, b - 18);
+ n += memcmp (p + 19, q + 19, b - 19);
+ n += memcmp (p + 20, q + 20, b - 20);
+ n += memcmp (p + 21, q + 21, b - 21);
+ n += memcmp (p + 22, q + 22, b - 22);
+ n += memcmp (p + 23, q + 23, b - 23);
+
+ if (n != 0)
+ __builtin_abort ();
+}
+
+/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/memcmp-4.c b/gcc/testsuite/gcc.dg/memcmp-4.c
new file mode 100644
index 00000000000..bbac7197501
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/memcmp-4.c
@@ -0,0 +1,81 @@
+/* PR middle-end/78257 - missing memcmp optimization with constant arrays
+ { dg-do compile }
+ { dg-options "-O -Wall -fdump-tree-optimized" } */
+
+typedef __INT8_TYPE__ int8_t;
+typedef __INT16_TYPE__ int16_t;
+typedef __INT32_TYPE__ int32_t;
+typedef __SIZE_TYPE__ size_t;
+
+extern int memcmp (const void*, const void*, size_t);
+
+/* Verify that initializers for flexible array members are handled
+ correctly. */
+
+struct Si16_x
+{
+ int16_t n, a[];
+};
+
+const struct Si16_x si16_4 =
+ {
+ 0x1112, { 0x2122, 0x3132, 0x4142 }
+ };
+
+const char si16_4_rep[] =
+ {
+ 0x12, 0x11, 0x22, 0x21, 0x32, 0x31, 0x42, 0x41
+ };
+
+void eq_si16_x (void)
+{
+ int n = 0, b = sizeof si16_4_rep;
+ const char *p = (const char*)&si16_4, *q = si16_4_rep;
+
+ n += memcmp (p, q, b);
+ n += memcmp (p + 1, q + 1, b - 1);
+ n += memcmp (p + 2, q + 2, b - 2);
+ n += memcmp (p + 3, q + 3, b - 3);
+ n += memcmp (p + 4, q + 4, b - 4);
+ n += memcmp (p + 5, q + 5, b - 5);
+ n += memcmp (p + 6, q + 6, b - 6);
+ n += memcmp (p + 7, q + 7, b - 7);
+ n += memcmp (p + 8, q + 8, b - 8);
+
+ p = (const char*)&si16_4.n;
+
+ n += memcmp (p, q, b);
+ n += memcmp (p + 1, q + 1, b - 1);
+ n += memcmp (p + 2, q + 2, b - 2);
+ n += memcmp (p + 3, q + 3, b - 3);
+ n += memcmp (p + 4, q + 4, b - 4);
+ n += memcmp (p + 5, q + 5, b - 5);
+ n += memcmp (p + 6, q + 6, b - 6);
+ n += memcmp (p + 7, q + 7, b - 7);
+ n += memcmp (p + 8, q + 8, b - 8);
+
+ p = (const char*)si16_4.a;
+ q = si16_4_rep + 2;
+
+ n += memcmp (p, q, b - 2);
+ n += memcmp (p + 1, q + 1, b - 3);
+ n += memcmp (p + 2, q + 2, b - 4);
+ n += memcmp (p + 3, q + 3, b - 5);
+ n += memcmp (p + 4, q + 4, b - 6);
+ n += memcmp (p + 5, q + 5, b - 7);
+ n += memcmp (p + 6, q + 6, b - 8);
+
+ p = (const char*)&si16_4.a[1];
+ q = si16_4_rep + 4;
+
+ n += memcmp (p, q, b - 4);
+ n += memcmp (p + 1, q + 1, b - 5);
+ n += memcmp (p + 2, q + 2, b - 6);
+ n += memcmp (p + 3, q + 3, b - 7);
+ n += memcmp (p + 4, q + 4, b - 8);
+
+ if (n != 0)
+ __builtin_abort ();
+}
+
+/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */