/* PR tree-optimization/91996 - fold non-constant strlen relational expressions { dg-do run } { dg-options "-O2 -Wall -Wno-unused-local-typedefs" } */ typedef __SIZE_TYPE__ size_t; #define NOIPA __attribute__ ((noipa)) #define CONCAT(a, b) a ## b #define CAT(a, b) CONCAT (a, b) /* Used in tests where EXPR is expected to be folded to false. */ #define ELIM(expr) \ if (expr) { \ extern void \ CAT (CAT (test_on_line_, __LINE__), _not_eliminated)(void); \ CAT (CAT (test_on_line_, __LINE__), _not_eliminated)(); \ } typedef void dummy_type /* Set the alignment for targets that depend on it in order to optimize away the ELIM calls. See pr92128. */ __attribute__ ((aligned(4))) char a[32], b[32]; void init (void) { __builtin_strncpy (a, "abcdefgh", sizeof a); __builtin_strncpy (b, "0123456789", sizeof b); } NOIPA void fail (const char *func) { __builtin_printf ("failure in %s\n", func); __builtin_abort (); } NOIPA void test_global_cpy_4 (void) { size_t blen = __builtin_strlen (b); if (blen < 9) return; char *d = a; __builtin_memcpy (d, b, 4); size_t dlen = __builtin_strlen (d); if (dlen != 8) // cannot be eliminated fail ("test_global"); } NOIPA void test_global_cpy_10 (void) { size_t blen = __builtin_strlen (b); if (blen < 9) return; char *d = a; __builtin_memcpy (d, b, 10); size_t dlen = __builtin_strlen (d); if (dlen != 10) // cannot be eliminated fail ("test_global_cpy_10"); } NOIPA void test_global_cpy_11 (void) { size_t blen = __builtin_strlen (b); if (blen < 9) return; char *d = a; __builtin_memcpy (d, b, 11); size_t dlen = __builtin_strlen (d); if (dlen != 10) // cannot be eliminated fail ("test_global_cpy_11"); } NOIPA void test_global_cpy_20 (void) { size_t blen = __builtin_strlen (b); if (blen < 9) return; char *d = a; __builtin_memcpy (d, b, 20); size_t dlen = __builtin_strlen (d); if (dlen != 10) // cannot be eliminated fail ("test_global_cpy_20"); } NOIPA void test_local_cpy_4 (void) { size_t blen = __builtin_strlen (b); if (blen < 9) return; /* Set the alignment for targets that depend on it in order to optimize away the ELIM calls. See pr92128. */ __attribute__ ((aligned(4))) char a[10] = "abcdefgh"; char *d = a; __builtin_memcpy (d, b, 4); size_t dlen = __builtin_strlen (d); ELIM (dlen != 8); } NOIPA void test_local_cpy_10 (void) { size_t blen = __builtin_strlen (b); if (blen < 9) return; char a[32] = "abcdefgh"; char *d = a; __builtin_memcpy (d, b, 10); /* B can be longer than 9 and A can initially be longer than 10 so the test below cannot be eliminated. */ size_t dlen = __builtin_strlen (d); if (dlen != 10) fail ("test_local_cpy_10"); } NOIPA void test_local_cpy_11 (void) { size_t blen = __builtin_strlen (b); if (blen < 9) return; char a[32] = "abcdefgh"; char *d = a; __builtin_memcpy (d, b, 11); size_t dlen = __builtin_strlen (d); if (dlen != 10) fail ("test_global_cpy_20"); } NOIPA void test_local_cpy_20 (void) { size_t blen = __builtin_strlen (b); if (blen < 9) return; char a[32] = "abcdefgh"; char *d = a; __builtin_memcpy (d, b, 20); size_t dlen = __builtin_strlen (d); if (dlen != 10) fail ("test_global_cpy_20"); } NOIPA void test_global_length_eq (void) { size_t blen = __builtin_strlen (b); if (blen != 10) return; size_t alen = __builtin_strlen (a); if (alen != 8) return; char *d = a; __builtin_memcpy (d, b, 4); size_t dlen = __builtin_strlen (d); ELIM (dlen != 8); } NOIPA void test_global_length_gt (void) { size_t blen = __builtin_strlen (b); if (blen < 9) return; size_t alen = __builtin_strlen (a); if (alen < 8) return; char *d = a; __builtin_memcpy (d, b, 4); size_t dlen = __builtin_strlen (d); ELIM (dlen < 8); } #define TEST(name) do { init (); test_ ## name (); } while (0) int main (void) { TEST (local_cpy_4); TEST (local_cpy_10); TEST (local_cpy_11); TEST (local_cpy_20); TEST (global_cpy_4); TEST (global_cpy_10); TEST (global_cpy_11); TEST (global_cpy_20); TEST (global_length_eq); TEST (global_length_gt); }