The recent enhancement to memchr/memcmp folding introduced two bugs (that I know of). The attached patch fixes the one where a call to the string_constant function that would previously be guaranteed to succeed now fails as a result of the function only handling strings and not other types. The unexpected failure triggers an ICE down the line. I have committed the bootstrapped/regtested one-line patch in r11-2742.
Martin
PR tree-optimization/96670 - ICE on memchr with an empty initializer gcc/ChangeLog: PR tree-optimization/96670 PR middle-end/78257 * gimple-fold.c (gimple_fold_builtin_memchr): Call byte_representation to get it, not string_constant. gcc/testsuite/ChangeLog: PR tree-optimization/96670 * gcc.dg/memchr-2.c: New test. * gcc.dg/memcmp-6.c: New test. diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index db56cb6aa47..dcc1b56a273 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -2670,7 +2670,7 @@ gimple_fold_builtin_memchr (gimple_stmt_iterator *gsi) if (r == NULL) { tree mem_size, offset_node; - string_constant (arg1, &offset_node, &mem_size, NULL); + byte_representation (arg1, &offset_node, &mem_size, NULL); unsigned HOST_WIDE_INT offset = (offset_node == NULL_TREE) ? 0 : tree_to_uhwi (offset_node); /* MEM_SIZE is the size of the array the string literal diff --git a/gcc/testsuite/gcc.dg/memchr-2.c b/gcc/testsuite/gcc.dg/memchr-2.c new file mode 100644 index 00000000000..61357f96d12 --- /dev/null +++ b/gcc/testsuite/gcc.dg/memchr-2.c @@ -0,0 +1,41 @@ +/* PR tree-optimization/96670 - ICE on memchr with an empty initializer + { dg-do compile } + { dg-options "-O -Wall -fdump-tree-optimized" } */ + +struct { + int i, j; +} const s = { }; + +void memchr_success_unused (void) +{ + int n = (char *)&s.j - (char *)&s; + char *p = (char *)&s; + __builtin_memchr (p, '\0', n); +} + +void memchr_success_used (void) +{ + int n = (char *)&s.j - (char *)&s; + char *p = (char *)&s; + if (&s != __builtin_memchr (p, '\0', n)) + __builtin_abort (); +} + +void memchr_fail_unused (void) +{ + int n = (char *)&s.j - (char *)&s; + char *p = (char *)&s; + __builtin_memchr (p, '\5', n); +} + +void memchr_fail_used (void) +{ + int n = (char *)&s.j - (char *)&s; + char *p = (char *)&s; + if (__builtin_memchr (p, '\5', n)) + __builtin_abort (); +} + +/* { dg-prune-output "\\\[-Wunused-value" } + { dg-final { scan-tree-dump-not "abort" "optimized" } } + { dg-final { scan-tree-dump-not "memcmp \\(" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/memcmp-6.c b/gcc/testsuite/gcc.dg/memcmp-6.c new file mode 100644 index 00000000000..d57352616cf --- /dev/null +++ b/gcc/testsuite/gcc.dg/memcmp-6.c @@ -0,0 +1,47 @@ +/* PR tree-optimization/96670 - ICE on memchr with an empty initializer + { dg-do compile } + { dg-options "-O -Wall -fdump-tree-optimized" } */ + +struct { + int i, j; +} const s = { }; + +const char a[sizeof s] = { }; + +void memcmp_success_unused (void) +{ + int n = (char *)&s.j - (char *)&s; + char *p = (char *)&s; + __builtin_memcmp (p, a, n); + __builtin_memcmp (a, p, n); +} + +void memcmp_success_used (void) +{ + int n = (char *)&s.j - (char *)&s; + char *p = (char *)&s; + if (__builtin_memcmp (p, a, n) + || __builtin_memcmp (a, p, n)) + __builtin_abort (); +} + +void memcmp_fail_unused (void) +{ + int n = (char *)&s.j - (char *)&s; + char *p = (char *)&s; + __builtin_memcmp (p, a, n); + __builtin_memcmp (a, p, n); +} + +void memcmp_fail_used (void) +{ + int n = (char *)&s.j - (char *)&s; + char *p = (char *)&s; + if (__builtin_memcmp (p, a, n) + || __builtin_memcmp (a, p, n)) + __builtin_abort (); +} + +/* { dg-prune-output "\\\[-Wunused-value" } + { dg-final { scan-tree-dump-not "abort" "optimized" } } + { dg-final { scan-tree-dump-not "memcmp \\\(" "optimized" } } */