diff --git a/gcc/testsuite/gcc.dg/strcmpopt_12.c b/gcc/testsuite/gcc.dg/strcmpopt_12.c new file mode 100644 index 00000000000..d8077b62f7f --- /dev/null +++ b/gcc/testsuite/gcc.dg/strcmpopt_12.c @@ -0,0 +1,17 @@ +/* PR tree-optimization/96758 */ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +int v = 1; + +int +main () +{ + const char *s = v ? "a" : "b"; + char x[5]; + char y[5] = "a\0a"; + __builtin_memcpy (x, y, sizeof (y)); + if (__builtin_strncmp (x, s, 4) != 0) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index fbaee745f7d..96962286735 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -4485,11 +4485,19 @@ handle_builtin_string_cmp (gimple_stmt_iterator *gsi, const vr_values *rvals) ++cstlen2; /* The exact number of characters to compare. */ - HOST_WIDE_INT cmpsiz = bound < 0 ? cstlen1 < 0 ? cstlen2 : cstlen1 : bound; + HOST_WIDE_INT cmpsiz; + if (cstlen1 >= 0 && cstlen2 >= 0) + cmpsiz = MIN (cstlen1, cstlen2); + else if (cstlen1 >= 0) + cmpsiz = cstlen1; + else + cmpsiz = cstlen2; + if (bound >= 0) + cmpsiz = MIN (cmpsiz, bound); /* The size of the array in which the unknown string is stored. */ HOST_WIDE_INT varsiz = arysiz1 < 0 ? arysiz2 : arysiz1; - if (cmpsiz < varsiz && used_only_for_zero_equality (lhs)) + if ((varsiz < 0 || cmpsiz < varsiz) && used_only_for_zero_equality (lhs)) { /* If the known length is less than the size of the other array and the strcmp result is only used to test equality to zero,