Hi,
this is an update on my strlen range patch (V6). Again re-based and retested to current trunk. It finally removes the -ffassume-zero-terminated-char-arrays flag. And is more careful to preserve existing strlen optimization tests. I did not see the need to change the interface of get_range_string yet, as this would make the patch much larger, and might as well be done in a follow-up patch. I might suggest to rename one of the two get_range_strlen functions at the same time as it is rather confusing to have to count the parameters in order to tell which function is meant. This hunk in tree-ssa-strlen.c really needs some explanations: @@ -3192,7 +3156,13 @@ get_min_string_length (tree rhs, bool *f && TREE_READONLY (rhs)) rhs = DECL_INITIAL (rhs); - if (rhs && TREE_CODE (rhs) == STRING_CST) + if (rhs && TREE_CODE (rhs) == STRING_CST + && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (rhs))) + && compare_tree_int (TYPE_SIZE_UNIT (TREE_TYPE (rhs)), + TREE_STRING_LENGTH (rhs)) >= 0 + && tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (rhs)))) == 1 + && TREE_STRING_LENGTH (rhs) > 0 + && TREE_STRING_POINTER (rhs) [TREE_STRING_LENGTH (rhs) - 1] == '\0') { *full_string_p = true; return strlen (TREE_STRING_POINTER (rhs)); This is responsible for the removed xfail on c-c++-common/attr-nonstring-3.c and is tested in gcc.dg/strlenopt-57.c where an invalid call to strlen is not folded, while in gcc.dg/strlenopt-58.c a valid call to strlen is folded and finally completely removed. This hunk depends a lot on the STRING_CST semantics. In the V1 of the proposed STRING_CST semantics, this part is tautological, and could be removed, or changed to an assertion: + && TREE_STRING_LENGTH (rhs) > 0 + && TREE_STRING_POINTER (rhs) [TREE_STRING_LENGTH (rhs) - 1] == '\0') In the V2 of the proposed STRING_CST semantics, this part is tautlological: + && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (rhs))) + && compare_tree_int (TYPE_SIZE_UNIT (TREE_TYPE (rhs)), + TREE_STRING_LENGTH (rhs)) >= 0 Currently due the the way the braced initializer to string folding works, there are now initializer strings that are not zero-terminated and some that are. What is interesting to note, is that this is another path where the initializer STRING_CST and literal STRING_CST seem to mix with their different semantics. And the change in string_constant to return initializer elements seems not to be responsible for this confusion here. Bootstrapped and reg-tested on x86_64-pc-linux-gnu. Is it OK for trunk? Thanks Bernd.
gcc: 2018-08-26 Bernd Edlinger <bernd.edlin...@hotmail.de> * gimple-fold.c (looks_like_a_char_array_without_typecast_p): New helper function for strlen range estimations. (get_range_strlen): Use looks_like_a_char_array_without_typecast_p for warnings, but use GIMPLE semantics otherwise. * tree-ssa-strlen.c (maybe_set_strlen_range): Use GIMPLE semantics. (get_min_string_length): Avoid not NUL terminated string literals. testsuite: 2018-08-26 Bernd Edlinger <bernd.edlin...@hotmail.de> * c-c++-common/attr-nonstring-3.c: Remove xfail. * gcc.dg/pr83373.c: Add xfail. * gcc.dg/strlenopt-36.c: Add xfail. * gcc.dg/strlenopt-40.c: Adjust test expectations. * gcc.dg/strlenopt-45.c: Adjust test expectations. * gcc.dg/strlenopt-48.c: Add xfail. * gcc.dg/strlenopt-51.c: Adjust test expectations. * gcc.dg/strlenopt-57.c: New test. * gcc.dg/strlenopt-58.c: New test.
diff -Npur gcc/gimple-fold.c gcc/gimple-fold.c --- gcc/gimple-fold.c 2018-08-23 12:35:17.000000000 +0200 +++ gcc/gimple-fold.c 2018-08-25 21:50:18.354332301 +0200 @@ -1257,6 +1257,40 @@ gimple_fold_builtin_memset (gimple_stmt_ return true; } +/* Determine if a char array is suitable for strlen range estimations. + Return false if ARG is not a char array, or if the inner reference + chain appears to go through a type cast, otherwise return true. + Note that the gimple type informations are not 100% guaranteed + to be accurate, therefore this function shall only be used for + warnings. */ + +static bool +looks_like_a_char_array_without_typecast_p (tree arg) +{ + /* We handle arrays of integer types. */ + if (TREE_CODE (TREE_TYPE (arg)) != ARRAY_TYPE + || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != INTEGER_TYPE + || TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))) != TYPE_MODE (char_type_node) + || TYPE_PRECISION (TREE_TYPE (TREE_TYPE (arg))) + != TYPE_PRECISION (char_type_node)) + return false; + + tree base = arg; + while (TREE_CODE (base) == ARRAY_REF + || TREE_CODE (base) == ARRAY_RANGE_REF + || TREE_CODE (base) == COMPONENT_REF) + base = TREE_OPERAND (base, 0); + + /* If this looks like a type cast don't assume anything. */ + if ((TREE_CODE (base) == MEM_REF + && (! integer_zerop (TREE_OPERAND (base, 1)) + || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (TREE_OPERAND (base, 0)))) + != TYPE_MAIN_VARIANT (TREE_TYPE (base)))) + || handled_component_p (base)) + return false; + + return true; +} /* Obtain the minimum and maximum string length or minimum and maximum value of ARG in LENGTH[0] and LENGTH[1], respectively. @@ -1272,6 +1306,7 @@ gimple_fold_builtin_memset (gimple_stmt_ PHIs and COND_EXPRs optimistically, if we can determine string length minimum and maximum, it will use the minimum from the ones where it can be determined. + TYPE == 2 and FUZZY != 0 cannot be used together. Set *FLEXP to true if the range of the string lengths has been obtained from the upper bound of an array at the end of a struct. Such an array may hold a string that's longer than its upper bound @@ -1312,8 +1347,8 @@ get_range_strlen (tree arg, tree length[ member. */ tree idx = TREE_OPERAND (op, 1); - arg = TREE_OPERAND (op, 0); - tree optype = TREE_TYPE (arg); + op = TREE_OPERAND (op, 0); + tree optype = TREE_TYPE (op); if (tree dom = TYPE_DOMAIN (optype)) if (tree bound = TYPE_MAX_VALUE (dom)) if (TREE_CODE (bound) == INTEGER_CST @@ -1339,23 +1374,21 @@ get_range_strlen (tree arg, tree length[ return get_range_strlen (TREE_OPERAND (arg, 0), length, visited, type, fuzzy, flexp, eltsize); + if (eltsize != 1 || fuzzy != 2) + return false; + if (TREE_CODE (arg) == ARRAY_REF) { - tree type = TREE_TYPE (TREE_OPERAND (arg, 0)); - - /* Determine the "innermost" array type. */ - while (TREE_CODE (type) == ARRAY_TYPE - && TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE) - type = TREE_TYPE (type); - - /* Avoid arrays of pointers. */ - tree eltype = TREE_TYPE (type); - if (TREE_CODE (type) != ARRAY_TYPE - || !INTEGRAL_TYPE_P (eltype)) + if (!looks_like_a_char_array_without_typecast_p (arg)) return false; + tree type = TREE_TYPE (arg); + + /* Fail when the array bound is unknown or zero. */ val = TYPE_SIZE_UNIT (type); - if (!val || integer_zerop (val)) + if (!val + || TREE_CODE (val) != INTEGER_CST + || integer_zerop (val)) return false; val = fold_build2 (MINUS_EXPR, TREE_TYPE (val), val, @@ -1364,15 +1397,16 @@ get_range_strlen (tree arg, tree length[ the array could have zero length. */ *minlen = ssize_int (0); - if (TREE_CODE (TREE_OPERAND (arg, 0)) == COMPONENT_REF - && type == TREE_TYPE (TREE_OPERAND (arg, 0)) - && array_at_struct_end_p (TREE_OPERAND (arg, 0))) + if (TREE_CODE (arg) == COMPONENT_REF + && type == TREE_TYPE (arg) + && array_at_struct_end_p (arg)) *flexp = true; } - else if (TREE_CODE (arg) == COMPONENT_REF - && (TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 1))) - == ARRAY_TYPE)) + else if (TREE_CODE (arg) == COMPONENT_REF) { + if (!looks_like_a_char_array_without_typecast_p (arg)) + return false; + /* Use the type of the member array to determine the upper bound on the length of the array. This may be overly optimistic if the array itself isn't NUL-terminated and @@ -1388,22 +1422,20 @@ get_range_strlen (tree arg, tree length[ tree type = TREE_TYPE (arg); - while (TREE_CODE (type) == ARRAY_TYPE - && TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE) - type = TREE_TYPE (type); - /* Fail when the array bound is unknown or zero. */ val = TYPE_SIZE_UNIT (type); - if (!val || integer_zerop (val)) + if (!val + || TREE_CODE (val) != INTEGER_CST + || integer_zerop (val)) return false; + val = fold_build2 (MINUS_EXPR, TREE_TYPE (val), val, integer_one_node); /* Set the minimum size to zero since the string in the array could have zero length. */ *minlen = ssize_int (0); } - - if (VAR_P (arg)) + else if (VAR_P (arg)) { tree type = TREE_TYPE (arg); if (POINTER_TYPE_P (type)) @@ -1411,13 +1443,23 @@ get_range_strlen (tree arg, tree length[ if (TREE_CODE (type) == ARRAY_TYPE) { + /* We handle arrays of integer types. */ + if (TREE_CODE (TREE_TYPE (type)) != INTEGER_TYPE + || TYPE_MODE (TREE_TYPE (type)) + != TYPE_MODE (char_type_node) + || TYPE_PRECISION (TREE_TYPE (type)) + != TYPE_PRECISION (char_type_node)) + return false; + + /* Fail when the array bound is unknown or zero. */ val = TYPE_SIZE_UNIT (type); if (!val || TREE_CODE (val) != INTEGER_CST || integer_zerop (val)) return false; - val = wide_int_to_tree (TREE_TYPE (val), - wi::sub (wi::to_wide (val), 1)); + + val = fold_build2 (MINUS_EXPR, TREE_TYPE (val), val, + integer_one_node); /* Set the minimum size to zero since the string in the array could have zero length. */ *minlen = ssize_int (0); @@ -1550,6 +1592,7 @@ get_range_strlen (tree arg, tree length[ if we can determine string length minimum and maximum; it will use the minimum from the ones where it can be determined. STRICT false should be only used for warning code. + STRICT is by default false. ELTSIZE is 1 for normal single byte character strings, and 2 or 4 for wide characer strings. ELTSIZE is by default 1. */ diff -Npur gcc/tree-ssa-strlen.c gcc/tree-ssa-strlen.c --- gcc/tree-ssa-strlen.c 2018-08-23 12:35:14.000000000 +0200 +++ gcc/tree-ssa-strlen.c 2018-08-25 21:00:29.659409820 +0200 @@ -1154,42 +1154,6 @@ maybe_set_strlen_range (tree lhs, tree s wide_int max = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node)); wide_int min = wi::zero (max.get_precision ()); - if (TREE_CODE (src) == ADDR_EXPR) - { - /* The last array member of a struct can be bigger than its size - suggests if it's treated as a poor-man's flexible array member. */ - src = TREE_OPERAND (src, 0); - bool src_is_array = TREE_CODE (TREE_TYPE (src)) == ARRAY_TYPE; - if (src_is_array && !array_at_struct_end_p (src)) - { - tree type = TREE_TYPE (src); - if (tree size = TYPE_SIZE_UNIT (type)) - if (size && TREE_CODE (size) == INTEGER_CST) - max = wi::to_wide (size); - - /* For strlen() the upper bound above is equal to - the longest string that can be stored in the array - (i.e., it accounts for the terminating nul. For - strnlen() bump up the maximum by one since the array - need not be nul-terminated. */ - if (!bound && max != 0) - --max; - } - else - { - if (TREE_CODE (src) == COMPONENT_REF && !src_is_array) - src = TREE_OPERAND (src, 1); - if (DECL_P (src)) - { - /* Handle the unlikely case of strlen (&c) where c is some - variable. */ - if (tree size = DECL_SIZE_UNIT (src)) - if (TREE_CODE (size) == INTEGER_CST) - max = wi::to_wide (size); - } - } - } - if (bound) { /* For strnlen, adjust MIN and MAX as necessary. If the bound @@ -3192,7 +3156,13 @@ get_min_string_length (tree rhs, bool *f && TREE_READONLY (rhs)) rhs = DECL_INITIAL (rhs); - if (rhs && TREE_CODE (rhs) == STRING_CST) + if (rhs && TREE_CODE (rhs) == STRING_CST + && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (rhs))) + && compare_tree_int (TYPE_SIZE_UNIT (TREE_TYPE (rhs)), + TREE_STRING_LENGTH (rhs)) >= 0 + && tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (rhs)))) == 1 + && TREE_STRING_LENGTH (rhs) > 0 + && TREE_STRING_POINTER (rhs) [TREE_STRING_LENGTH (rhs) - 1] == '\0') { *full_string_p = true; return strlen (TREE_STRING_POINTER (rhs)); diff -Npur gcc/testsuite/c-c++-common/attr-nonstring-3.c gcc/testsuite/c-c++-common/attr-nonstring-3.c --- gcc/testsuite/c-c++-common/attr-nonstring-3.c 2018-08-23 12:35:15.000000000 +0200 +++ gcc/testsuite/c-c++-common/attr-nonstring-3.c 2018-08-25 20:45:51.835677067 +0200 @@ -406,7 +406,7 @@ void test_strlen (struct MemArrays *p, c { char a[] __attribute__ ((nonstring)) = { 1, 2, 3 }; - T (strlen (a)); /* { dg-warning "argument 1 declared attribute .nonstring." "pr86688" { xfail *-*-* } } */ + T (strlen (a)); /* { dg-warning "argument 1 declared attribute .nonstring." } */ } { diff -Npur gcc/testsuite/gcc.dg/pr83373.c gcc/testsuite/gcc.dg/pr83373.c --- gcc/testsuite/gcc.dg/pr83373.c 2018-08-22 22:34:01.000000000 +0200 +++ gcc/testsuite/gcc.dg/pr83373.c 2018-08-25 14:41:59.649419917 +0200 @@ -16,7 +16,7 @@ inline char* my_strcpy (char* dst, const __builtin_memcpy (dst, src, len + 1); else { - __builtin_memcpy (dst, src, size - 1); /* { dg-bogus "\\\[-Wstringop-oveflow]" } */ + __builtin_memcpy (dst, src, size - 1); /* { dg-bogus "\\\[-Wstringop-overflow=]" "" { xfail *-*-* } } */ dst[size - 1] = '\0'; } diff -Npur gcc/testsuite/gcc.dg/strlenopt-36.c gcc/testsuite/gcc.dg/strlenopt-36.c --- gcc/testsuite/gcc.dg/strlenopt-36.c 2018-08-22 22:34:01.000000000 +0200 +++ gcc/testsuite/gcc.dg/strlenopt-36.c 2018-08-25 18:10:54.475978390 +0200 @@ -83,4 +83,4 @@ void test_nested_memarray (struct Nested T (strlen (ma->ma1.a1) == 0); */ } -/* { dg-final { scan-tree-dump-not "failure_on_line" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "failure_on_line" "optimized" { xfail *-*-* } } } */ diff -Npur gcc/testsuite/gcc.dg/strlenopt-40.c gcc/testsuite/gcc.dg/strlenopt-40.c --- gcc/testsuite/gcc.dg/strlenopt-40.c 2018-08-22 22:34:01.000000000 +0200 +++ gcc/testsuite/gcc.dg/strlenopt-40.c 2018-08-25 18:27:38.573627934 +0200 @@ -105,135 +105,20 @@ void elim_global_arrays (int i) /* Verify that the expression involving the strlen call as well as whatever depends on it is eliminated from the test output. All these expressions must be trivially true. */ - ELIM_TRUE (strlen (a7_3[0]) < sizeof a7_3[0]); - ELIM_TRUE (strlen (a7_3[1]) < sizeof a7_3[1]); - ELIM_TRUE (strlen (a7_3[6]) < sizeof a7_3[6]); - ELIM_TRUE (strlen (a7_3[i]) < sizeof a7_3[i]); - - ELIM_TRUE (strlen (a5_7[0]) < sizeof a5_7[0]); - ELIM_TRUE (strlen (a5_7[1]) < sizeof a5_7[1]); - ELIM_TRUE (strlen (a5_7[4]) < sizeof a5_7[4]); - ELIM_TRUE (strlen (a5_7[i]) < sizeof a5_7[0]); - - ELIM_TRUE (strlen (ax_3[0]) < sizeof ax_3[0]); - ELIM_TRUE (strlen (ax_3[1]) < sizeof ax_3[1]); - ELIM_TRUE (strlen (ax_3[9]) < sizeof ax_3[9]); - ELIM_TRUE (strlen (ax_3[i]) < sizeof ax_3[i]); - - ELIM_TRUE (strlen (a3) < sizeof a3); - ELIM_TRUE (strlen (a7) < sizeof a7); - ELIM_TRUE (strlen (ax) != DIFF_MAX); ELIM_TRUE (strlen (ax) != DIFF_MAX - 1); ELIM_TRUE (strlen (ax) < DIFF_MAX - 1); } -void elim_pointer_to_arrays (void) -{ - ELIM_TRUE (strlen (*pa7) < 7); - ELIM_TRUE (strlen (*pa5) < 5); - ELIM_TRUE (strlen (*pa3) < 3); - - ELIM_TRUE (strlen ((*pa7_3)[0]) < 3); - ELIM_TRUE (strlen ((*pa7_3)[1]) < 3); - ELIM_TRUE (strlen ((*pa7_3)[6]) < 3); - - ELIM_TRUE (strlen ((*pax_3)[0]) < 3); - ELIM_TRUE (strlen ((*pax_3)[1]) < 3); - ELIM_TRUE (strlen ((*pax_3)[9]) < 3); - - ELIM_TRUE (strlen ((*pa5_7)[0]) < 7); - ELIM_TRUE (strlen ((*pa5_7)[1]) < 7); - ELIM_TRUE (strlen ((*pa5_7)[4]) < 7); -} - -void elim_global_arrays_and_strings (int i) -{ - ELIM_TRUE (strlen (i < 0 ? a3 : "") < 3); - ELIM_TRUE (strlen (i < 0 ? a3 : "1") < 3); - ELIM_TRUE (strlen (i < 0 ? a3 : "12") < 3); - ELIM_TRUE (strlen (i < 0 ? a3 : "123") < 4); - - ELIM_FALSE (strlen (i < 0 ? a3 : "") > 3); - ELIM_FALSE (strlen (i < 0 ? a3 : "1") > 3); - ELIM_FALSE (strlen (i < 0 ? a3 : "12") > 3); - ELIM_FALSE (strlen (i < 0 ? a3 : "123") > 4); - - ELIM_TRUE (strlen (i < 0 ? a7 : "") < 7); - ELIM_TRUE (strlen (i < 0 ? a7 : "1") < 7); - ELIM_TRUE (strlen (i < 0 ? a7 : "12") < 7); - ELIM_TRUE (strlen (i < 0 ? a7 : "123") < 7); - ELIM_TRUE (strlen (i < 0 ? a7 : "123456") < 7); - ELIM_TRUE (strlen (i < 0 ? a7 : "1234567") < 8); - - ELIM_FALSE (strlen (i < 0 ? a7 : "") > 6); - ELIM_FALSE (strlen (i < 0 ? a7 : "1") > 6); - ELIM_FALSE (strlen (i < 0 ? a7 : "12") > 6); - ELIM_FALSE (strlen (i < 0 ? a7 : "123") > 6); - ELIM_FALSE (strlen (i < 0 ? a7 : "123456") > 7); - ELIM_FALSE (strlen (i < 0 ? a7 : "1234567") > 8); -} - -void elim_member_arrays_obj (int i) -{ - ELIM_TRUE (strlen (ma0_3_5_7[0][0][0].a3) < 3); - ELIM_TRUE (strlen (ma0_3_5_7[0][0][1].a3) < 3); - ELIM_TRUE (strlen (ma0_3_5_7[0][0][2].a3) < 3); - ELIM_TRUE (strlen (ma0_3_5_7[0][0][6].a3) < 3); - - ELIM_TRUE (strlen (ma0_3_5_7[1][0][0].a3) < 3); - ELIM_TRUE (strlen (ma0_3_5_7[2][0][1].a3) < 3); - - ELIM_TRUE (strlen (ma0_3_5_7[1][1][0].a3) < 3); - ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a3) < 3); - - ELIM_TRUE (strlen (ma0_3_5_7[0][0][0].a5) < 5); - ELIM_TRUE (strlen (ma0_3_5_7[0][0][1].a5) < 5); - ELIM_TRUE (strlen (ma0_3_5_7[0][0][2].a5) < 5); - ELIM_TRUE (strlen (ma0_3_5_7[0][0][6].a5) < 5); - - ELIM_TRUE (strlen (ma0_3_5_7[1][0][0].a5) < 5); - ELIM_TRUE (strlen (ma0_3_5_7[2][0][1].a5) < 5); - - ELIM_TRUE (strlen (ma0_3_5_7[1][1][0].a5) < 5); - ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a5) < 5); - - ELIM_TRUE (strlen (ma0_3_5_7[0][0][0].a7_3[0]) < 3); - ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a7_3[2]) < 3); - - ELIM_TRUE (strlen (ma0_3_5_7[0][0][0].a5_7[0]) < 7); - ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a5_7[4]) < 7); -} - void elim_member_arrays_ptr (struct MemArrays0 *ma0, struct MemArraysX *max, struct MemArrays7 *ma7, int i) { - ELIM_TRUE (strlen (ma0->a7_3[0]) < 3); - ELIM_TRUE (strlen (ma0->a7_3[1]) < 3); - ELIM_TRUE (strlen (ma0->a7_3[6]) < 3); - ELIM_TRUE (strlen (ma0->a7_3[6]) < 3); - ELIM_TRUE (strlen (ma0->a7_3[i]) < 3); - ELIM_TRUE (strlen (ma0->a7_3[i]) < 3); - - ELIM_TRUE (strlen (ma0->a5_7[0]) < 7); - ELIM_TRUE (strlen (ma0[0].a5_7[0]) < 7); - ELIM_TRUE (strlen (ma0[1].a5_7[0]) < 7); - ELIM_TRUE (strlen (ma0[1].a5_7[4]) < 7); - ELIM_TRUE (strlen (ma0[9].a5_7[0]) < 7); - ELIM_TRUE (strlen (ma0[9].a5_7[4]) < 7); - - ELIM_TRUE (strlen (ma0->a3) < sizeof ma0->a3); - ELIM_TRUE (strlen (ma0->a5) < sizeof ma0->a5); ELIM_TRUE (strlen (ma0->a0) < DIFF_MAX - 1); - ELIM_TRUE (strlen (max->a3) < sizeof max->a3); - ELIM_TRUE (strlen (max->a5) < sizeof max->a5); ELIM_TRUE (strlen (max->ax) < DIFF_MAX - 1); - ELIM_TRUE (strlen (ma7->a3) < sizeof max->a3); - ELIM_TRUE (strlen (ma7->a5) < sizeof max->a5); ELIM_TRUE (strlen (ma7->a7) < DIFF_MAX - 1); } diff -Npur gcc/testsuite/gcc.dg/strlenopt-45.c gcc/testsuite/gcc.dg/strlenopt-45.c --- gcc/testsuite/gcc.dg/strlenopt-45.c 2018-08-22 22:34:01.000000000 +0200 +++ gcc/testsuite/gcc.dg/strlenopt-45.c 2018-08-25 18:46:19.901932755 +0200 @@ -58,46 +58,24 @@ void elim_strnlen_arr_cst (void) be one). */ ELIM (strnlen (&c, 0) == 0); ELIM (strnlen (&c, 1) < 2); - ELIM (strnlen (&c, 2) == 0); - ELIM (strnlen (&c, 9) == 0); - ELIM (strnlen (&c, PTRDIFF_MAX) == 0); - ELIM (strnlen (&c, SIZE_MAX) == 0); - ELIM (strnlen (&c, -1) == 0); ELIM (strnlen (a1, 0) == 0); ELIM (strnlen (a1, 1) < 2); - ELIM (strnlen (a1, 2) == 0); - ELIM (strnlen (a1, 9) == 0); - ELIM (strnlen (a1, PTRDIFF_MAX) == 0); - ELIM (strnlen (a1, SIZE_MAX) == 0); - ELIM (strnlen (a1, -1) == 0); ELIM (strnlen (a3, 0) == 0); ELIM (strnlen (a3, 1) < 2); ELIM (strnlen (a3, 2) < 3); ELIM (strnlen (a3, 3) < 4); - ELIM (strnlen (a3, 9) < 4); - ELIM (strnlen (a3, PTRDIFF_MAX) < 4); - ELIM (strnlen (a3, SIZE_MAX) < 4); - ELIM (strnlen (a3, -1) < 4); ELIM (strnlen (a3_7[0], 0) == 0); ELIM (strnlen (a3_7[0], 1) < 2); ELIM (strnlen (a3_7[0], 2) < 3); ELIM (strnlen (a3_7[0], 3) < 4); - ELIM (strnlen (a3_7[0], 9) < 8); - ELIM (strnlen (a3_7[0], PTRDIFF_MAX) < 8); - ELIM (strnlen (a3_7[0], SIZE_MAX) < 8); - ELIM (strnlen (a3_7[0], -1) < 8); ELIM (strnlen (a3_7[2], 0) == 0); ELIM (strnlen (a3_7[2], 1) < 2); ELIM (strnlen (a3_7[2], 2) < 3); ELIM (strnlen (a3_7[2], 3) < 4); - ELIM (strnlen (a3_7[2], 9) < 8); - ELIM (strnlen (a3_7[2], PTRDIFF_MAX) < 8); - ELIM (strnlen (a3_7[2], SIZE_MAX) < 8); - ELIM (strnlen (a3_7[2], -1) < 8); ELIM (strnlen ((char*)a3_7, 0) == 0); ELIM (strnlen ((char*)a3_7, 1) < 2); @@ -106,10 +84,6 @@ void elim_strnlen_arr_cst (void) ELIM (strnlen ((char*)a3_7, 9) < 10); ELIM (strnlen ((char*)a3_7, 19) < 20); ELIM (strnlen ((char*)a3_7, 21) < 22); - ELIM (strnlen ((char*)a3_7, 23) < 22); - ELIM (strnlen ((char*)a3_7, PTRDIFF_MAX) < 22); - ELIM (strnlen ((char*)a3_7, SIZE_MAX) < 22); - ELIM (strnlen ((char*)a3_7, -1) < 22); ELIM (strnlen (ax, 0) == 0); ELIM (strnlen (ax, 1) < 2); @@ -135,56 +109,32 @@ void elim_strnlen_memarr_cst (struct Mem { ELIM (strnlen (&p->c, 0) == 0); ELIM (strnlen (&p->c, 1) < 2); - ELIM (strnlen (&p->c, 9) == 0); - ELIM (strnlen (&p->c, PTRDIFF_MAX) == 0); - ELIM (strnlen (&p->c, SIZE_MAX) == 0); - ELIM (strnlen (&p->c, -1) == 0); /* Other accesses to internal zero-length arrays are undefined. */ ELIM (strnlen (p->a0, 0) == 0); ELIM (strnlen (p->a1, 0) == 0); ELIM (strnlen (p->a1, 1) < 2); - ELIM (strnlen (p->a1, 9) == 0); - ELIM (strnlen (p->a1, PTRDIFF_MAX) == 0); - ELIM (strnlen (p->a1, SIZE_MAX) == 0); - ELIM (strnlen (p->a1, -1) == 0); ELIM (strnlen (p->a3, 0) == 0); ELIM (strnlen (p->a3, 1) < 2); ELIM (strnlen (p->a3, 2) < 3); ELIM (strnlen (p->a3, 3) < 4); - ELIM (strnlen (p->a3, 9) < 4); - ELIM (strnlen (p->a3, PTRDIFF_MAX) < 4); - ELIM (strnlen (p->a3, SIZE_MAX) < 4); - ELIM (strnlen (p->a3, -1) < 4); ELIM (strnlen (p[i].a3, 0) == 0); ELIM (strnlen (p[i].a3, 1) < 2); ELIM (strnlen (p[i].a3, 2) < 3); ELIM (strnlen (p[i].a3, 3) < 4); - ELIM (strnlen (p[i].a3, 9) < 4); - ELIM (strnlen (p[i].a3, PTRDIFF_MAX) < 4); - ELIM (strnlen (p[i].a3, SIZE_MAX) < 4); - ELIM (strnlen (p[i].a3, -1) < 4); ELIM (strnlen (p->a3_7[0], 0) == 0); ELIM (strnlen (p->a3_7[0], 1) < 2); ELIM (strnlen (p->a3_7[0], 2) < 3); ELIM (strnlen (p->a3_7[0], 3) < 4); - ELIM (strnlen (p->a3_7[0], 9) < 8); - ELIM (strnlen (p->a3_7[0], PTRDIFF_MAX) < 8); - ELIM (strnlen (p->a3_7[0], SIZE_MAX) < 8); - ELIM (strnlen (p->a3_7[0], -1) < 8); ELIM (strnlen (p->a3_7[2], 0) == 0); ELIM (strnlen (p->a3_7[2], 1) < 2); ELIM (strnlen (p->a3_7[2], 2) < 3); ELIM (strnlen (p->a3_7[2], 3) < 4); - ELIM (strnlen (p->a3_7[2], 9) < 8); - ELIM (strnlen (p->a3_7[2], PTRDIFF_MAX) < 8); - ELIM (strnlen (p->a3_7[2], SIZE_MAX) < 8); - ELIM (strnlen (p->a3_7[2], -1) < 8); ELIM (strnlen (p->a3_7[i], 0) == 0); ELIM (strnlen (p->a3_7[i], 1) < 2); @@ -210,10 +160,6 @@ void elim_strnlen_memarr_cst (struct Mem ELIM (strnlen ((char*)p->a3_7, 9) < 10); ELIM (strnlen ((char*)p->a3_7, 19) < 20); ELIM (strnlen ((char*)p->a3_7, 21) < 22); - ELIM (strnlen ((char*)p->a3_7, 23) < 22); - ELIM (strnlen ((char*)p->a3_7, PTRDIFF_MAX) < 22); - ELIM (strnlen ((char*)p->a3_7, SIZE_MAX) < 22); - ELIM (strnlen ((char*)p->a3_7, -1) < 22); ELIM (strnlen (p->ax, 0) == 0); ELIM (strnlen (p->ax, 1) < 2); diff -Npur gcc/testsuite/gcc.dg/strlenopt-48.c gcc/testsuite/gcc.dg/strlenopt-48.c --- gcc/testsuite/gcc.dg/strlenopt-48.c 2018-08-22 22:34:01.000000000 +0200 +++ gcc/testsuite/gcc.dg/strlenopt-48.c 2018-08-25 18:50:25.483526060 +0200 @@ -31,5 +31,5 @@ void h (void) abort(); } -/* { dg-final { scan-tree-dump-times "strlen" 0 "optimized" } } - { dg-final { scan-tree-dump-times "abort" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "strlen" 0 "optimized" { xfail *-*-* } } } + { dg-final { scan-tree-dump-times "abort" 0 "optimized" { xfail *-*-* } } } */ diff -Npur gcc/testsuite/gcc.dg/strlenopt-51.c gcc/testsuite/gcc.dg/strlenopt-51.c --- gcc/testsuite/gcc.dg/strlenopt-51.c 2018-08-22 22:34:01.000000000 +0200 +++ gcc/testsuite/gcc.dg/strlenopt-51.c 2018-08-25 14:41:59.649419917 +0200 @@ -101,7 +101,7 @@ void test_keep_a9_9 (int i) { #undef T #define T(I) \ - KEEP (strlen (&a9_9[i][I][0]) > (1 + I) % 9); \ + KEEP (strlen (&a9_9[i][I][0]) > (0 + I) % 9); \ KEEP (strlen (&a9_9[i][I][1]) > (1 + I) % 9); \ KEEP (strlen (&a9_9[i][I][2]) > (2 + I) % 9); \ KEEP (strlen (&a9_9[i][I][3]) > (3 + I) % 9); \ @@ -115,7 +115,7 @@ void test_keep_a9_9 (int i) } /* { dg-final { scan-tree-dump-times "strlen" 72 "gimple" } } - { dg-final { scan-tree-dump-times "strlen" 63 "optimized" } } + { dg-final { scan-tree-dump-times "strlen" 72 "optimized" } } - { dg-final { scan-tree-dump-times "call_made_in_true_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 72 "optimized" } } + { dg-final { scan-tree-dump-times "call_made_in_true_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 81 "optimized" } } { dg-final { scan-tree-dump-times "call_made_in_false_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 81 "optimized" } } */ diff -Npur gcc/testsuite/gcc.dg/strlenopt-57.c gcc/testsuite/gcc.dg/strlenopt-57.c --- gcc/testsuite/gcc.dg/strlenopt-57.c 1970-01-01 01:00:00.000000000 +0100 +++ gcc/testsuite/gcc.dg/strlenopt-57.c 2018-08-25 14:41:59.649419917 +0200 @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fdump-tree-optimized" } */ + +#define assert(x) do { if (!(x)) __builtin_abort (); } while (0) +extern int system (const char *); +static int fun (char *p) +{ + char buf[16]; + + assert (__builtin_strlen (p) < 4); + + __builtin_sprintf (buf, "echo %s - %s", p, p); + return system (buf); +} + +void test (void) +{ + char b[2] = "ab"; + fun (b); +} + +/* { dg-final { scan-tree-dump-times "__builtin_strlen" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_abort" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_sprintf" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "system" 1 "optimized" } } */ diff -Npur gcc/testsuite/gcc.dg/strlenopt-58.c gcc/testsuite/gcc.dg/strlenopt-58.c --- gcc/testsuite/gcc.dg/strlenopt-58.c 1970-01-01 01:00:00.000000000 +0100 +++ gcc/testsuite/gcc.dg/strlenopt-58.c 2018-08-25 15:26:13.653767630 +0200 @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fdump-tree-optimized" } */ + +#define assert(x) do { if (!(x)) __builtin_abort (); } while (0) +extern int system (const char *); +static int fun (char *p) +{ + char buf[16]; + + assert (__builtin_strlen (p) < 4); + + __builtin_sprintf (buf, "echo %s - %s", p, p); + return system (buf); +} + +void test (void) +{ + char b[3] = "ab"; + fun (b); +} + +/* { dg-final { scan-tree-dump-times "__builtin_strlen" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_abort" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_sprintf" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "system" 1 "optimized" } } */