Commit 02c4de76 by Martin Sebor Committed by Martin Sebor

PR tree-optimization/92226 - live nul char store to array eliminated

gcc/testsuite/ChangeLog:

	PR tree-optimization/92226
	* gcc.dg/strlenopt-88.c: New test.

gcc/ChangeLog:

	PR tree-optimization/92226
	* tree-ssa-strlen.c (compare_nonzero_chars): Return -1 also when
	the offset is in the open range outlined by SI's length.

From-SVN: r277545
parent ad1539d5
2019-10-28 Martin Sebor <msebor@redhat.com> 2019-10-28 Martin Sebor <msebor@redhat.com>
PR tree-optimization/92226
* tree-ssa-strlen.c (compare_nonzero_chars): Return -1 also when
the offset is in the open range outlined by SI's length.
2019-10-28 Martin Sebor <msebor@redhat.com>
PR c/66970 PR c/66970
* doc/cpp.texi (__has_builtin): Document. * doc/cpp.texi (__has_builtin): Document.
* doc/extend.texi (__builtin_frob_return_addr): Correct spelling. * doc/extend.texi (__builtin_frob_return_addr): Correct spelling.
2019-10-28 Martin Sebor <msebor@redhat.com> 2019-10-28 Martin Sebor <msebor@redhat.com>
PR tree-optimization/92226
* gcc.dg/strlenopt-88.c: New test.
2019-10-28 Martin Sebor <msebor@redhat.com>
PR c/66970 PR c/66970
* c-c++-common/cpp/has-builtin-2.c: New test. * c-c++-common/cpp/has-builtin-2.c: New test.
* c-c++-common/cpp/has-builtin-3.c: New test. * c-c++-common/cpp/has-builtin-3.c: New test.
......
/* PR tree-optimization/92226 - live nul char store to array eliminated
{ dg-do run }
{ dg-options "-O2 -Wall" } */
#include "strlenopt.h"
#define NOIPA __attribute__ ((noipa))
unsigned nfails;
char a[8];
void test (int line, const char *func, size_t expect)
{
size_t len = strlen (a);
if (len == expect)
return;
++nfails;
__builtin_printf ("assertion failed in %s on line %i: "
"strlen (\"%s\") == %zu, got %zu\n",
func, line, a, expect, len);
}
NOIPA const char* str (size_t n)
{
return "9876543210" + 10 - n;
}
#define T(name, CMPEXP, LEN, IDX, EXPECT) \
NOIPA static void name (void) \
{ \
const char *s = str (LEN); \
if (strlen (s) CMPEXP) \
{ \
strcpy (a, s); \
a[IDX] = 0; \
test (__LINE__, #name, EXPECT); \
} \
} typedef void dummy_type
T (len_eq_1_store_nul_0, == 1, 1, 0, 0);
T (len_eq_1_store_nul_1, == 1, 1, 1, 1);
T (len_eq_1_store_nul_2, == 1, 1, 2, 1);
T (len_eq_1_store_nul_3, == 1, 1, 3, 1);
T (len_eq_1_store_nul_4, == 1, 1, 4, 1);
T (len_eq_2_store_nul_0, == 2, 2, 0, 0);
T (len_eq_2_store_nul_1, == 2, 2, 1, 1);
T (len_eq_2_store_nul_2, == 2, 2, 2, 2);
T (len_eq_2_store_nul_3, == 2, 2, 3, 2);
T (len_eq_2_store_nul_4, == 2, 2, 4, 2);
T (len_eq_3_store_nul_0, == 3, 3, 0, 0);
T (len_eq_3_store_nul_1, == 3, 3, 1, 1);
T (len_eq_3_store_nul_2, == 3, 3, 2, 2);
T (len_eq_3_store_nul_3, == 3, 3, 3, 3);
T (len_eq_3_store_nul_4, == 3, 3, 4, 3);
T (len_gt_1_store_nul_0, > 2, 2, 0, 0);
T (len_gt_1_store_nul_1, > 2, 2, 1, 1);
T (len_gt_1_store_nul_2, > 2, 2, 2, 2);
T (len_gt_1_store_nul_3, > 2, 2, 3, 2);
T (len_gt_1_store_nul_4, > 2, 2, 4, 2);
T (len_gt_2_store_nul_0, > 2, 3, 0, 0);
T (len_gt_2_store_nul_1, > 2, 3, 1, 1);
T (len_gt_2_store_nul_2, > 2, 3, 2, 2);
T (len_gt_2_store_nul_3, > 2, 3, 3, 3);
T (len_gt_2_store_nul_4, > 2, 3, 4, 3);
T (len_gt_3_store_nul_0, > 2, 4, 0, 0);
T (len_gt_3_store_nul_1, > 2, 4, 1, 1);
T (len_gt_3_store_nul_2, > 2, 4, 2, 2);
T (len_gt_3_store_nul_3, > 2, 4, 3, 3);
T (len_gt_3_store_nul_4, > 2, 4, 4, 4);
T (len_1_lt_4_store_nul_0, < 4, 1, 0, 0);
T (len_1_lt_4_store_nul_1, < 4, 1, 1, 1);
T (len_1_lt_4_store_nul_2, < 4, 1, 2, 1);
T (len_1_lt_4_store_nul_3, < 4, 1, 3, 1);
T (len_1_lt_4_store_nul_4, < 4, 1, 4, 1);
T (len_1_lt_4_store_nul_5, < 4, 1, 5, 1);
T (len_1_lt_4_store_nul_6, < 4, 1, 6, 1);
T (len_1_lt_4_store_nul_7, < 4, 1, 7, 1);
T (len_2_lt_4_store_nul_0, < 4, 2, 0, 0);
T (len_2_lt_4_store_nul_1, < 4, 2, 1, 1);
T (len_2_lt_4_store_nul_2, < 4, 2, 2, 2);
T (len_2_lt_4_store_nul_3, < 4, 2, 3, 2);
T (len_2_lt_4_store_nul_4, < 4, 2, 4, 2);
T (len_2_lt_4_store_nul_5, < 4, 2, 5, 2);
T (len_2_lt_4_store_nul_6, < 4, 2, 6, 2);
T (len_2_lt_4_store_nul_7, < 4, 2, 7, 2);
T (len_3_lt_4_store_nul_0, < 4, 3, 0, 0);
T (len_3_lt_4_store_nul_1, < 4, 3, 1, 1);
T (len_3_lt_4_store_nul_2, < 4, 3, 2, 2);
T (len_3_lt_4_store_nul_3, < 4, 3, 3, 3);
T (len_3_lt_4_store_nul_4, < 4, 3, 4, 3);
T (len_3_lt_4_store_nul_5, < 4, 3, 5, 3);
T (len_3_lt_4_store_nul_6, < 4, 3, 6, 3);
T (len_3_lt_4_store_nul_7, < 4, 3, 7, 3);
T (len_7_lt_8_store_nul_0, < 8, 7, 0, 0);
T (len_7_lt_8_store_nul_1, < 8, 7, 1, 1);
T (len_7_lt_8_store_nul_2, < 8, 7, 2, 2);
T (len_7_lt_8_store_nul_3, < 8, 7, 3, 3);
T (len_7_lt_8_store_nul_4, < 8, 7, 4, 4);
T (len_7_lt_8_store_nul_5, < 8, 7, 5, 5);
T (len_7_lt_8_store_nul_6, < 8, 7, 6, 6);
T (len_7_lt_8_store_nul_7, < 8, 7, 7, 7);
int main (void)
{
len_eq_1_store_nul_0 ();
len_eq_1_store_nul_1 ();
len_eq_1_store_nul_2 ();
len_eq_1_store_nul_3 ();
len_eq_1_store_nul_4 ();
len_eq_2_store_nul_0 ();
len_eq_2_store_nul_1 ();
len_eq_2_store_nul_2 ();
len_eq_2_store_nul_3 ();
len_eq_2_store_nul_4 ();
len_eq_3_store_nul_0 ();
len_eq_3_store_nul_1 ();
len_eq_3_store_nul_2 ();
len_eq_3_store_nul_3 ();
len_eq_3_store_nul_4 ();
len_gt_1_store_nul_0 ();
len_gt_1_store_nul_1 ();
len_gt_1_store_nul_2 ();
len_gt_1_store_nul_3 ();
len_gt_1_store_nul_4 ();
len_gt_2_store_nul_0 ();
len_gt_2_store_nul_1 ();
len_gt_2_store_nul_2 ();
len_gt_2_store_nul_3 ();
len_gt_2_store_nul_4 ();
len_gt_3_store_nul_0 ();
len_gt_3_store_nul_1 ();
len_gt_3_store_nul_2 ();
len_gt_3_store_nul_3 ();
len_gt_3_store_nul_4 ();
len_1_lt_4_store_nul_0 ();
len_1_lt_4_store_nul_1 ();
len_1_lt_4_store_nul_2 ();
len_1_lt_4_store_nul_3 ();
len_1_lt_4_store_nul_4 ();
len_1_lt_4_store_nul_5 ();
len_1_lt_4_store_nul_6 ();
len_1_lt_4_store_nul_7 ();
len_2_lt_4_store_nul_0 ();
len_2_lt_4_store_nul_1 ();
len_2_lt_4_store_nul_2 ();
len_2_lt_4_store_nul_3 ();
len_2_lt_4_store_nul_4 ();
len_2_lt_4_store_nul_5 ();
len_2_lt_4_store_nul_6 ();
len_2_lt_4_store_nul_7 ();
len_3_lt_4_store_nul_0 ();
len_3_lt_4_store_nul_1 ();
len_3_lt_4_store_nul_2 ();
len_3_lt_4_store_nul_3 ();
len_3_lt_4_store_nul_4 ();
len_3_lt_4_store_nul_5 ();
len_3_lt_4_store_nul_6 ();
len_3_lt_4_store_nul_7 ();
len_7_lt_8_store_nul_0 ();
len_7_lt_8_store_nul_1 ();
len_7_lt_8_store_nul_2 ();
len_7_lt_8_store_nul_3 ();
len_7_lt_8_store_nul_4 ();
len_7_lt_8_store_nul_5 ();
len_7_lt_8_store_nul_6 ();
len_7_lt_8_store_nul_7 ();
if (nfails)
abort ();
}
...@@ -193,10 +193,11 @@ static void handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *); ...@@ -193,10 +193,11 @@ static void handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *);
* +1 if SI is known to start with more than OFF nonzero characters. * +1 if SI is known to start with more than OFF nonzero characters.
* 0 if SI is known to start with OFF nonzero characters, * 0 if SI is known to start with exactly OFF nonzero characters.
but is not known to start with more.
* -1 if SI might not start with OFF nonzero characters. */ * -1 if SI either does not start with OFF nonzero characters
or the relationship between the number of leading nonzero
characters in SI and OFF is unknown. */
static inline int static inline int
compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off) compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off)
...@@ -221,7 +222,7 @@ compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off, ...@@ -221,7 +222,7 @@ compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off,
if (TREE_CODE (si->nonzero_chars) == INTEGER_CST) if (TREE_CODE (si->nonzero_chars) == INTEGER_CST)
return compare_tree_int (si->nonzero_chars, off); return compare_tree_int (si->nonzero_chars, off);
if (TREE_CODE (si->nonzero_chars) != SSA_NAME) if (!rvals || TREE_CODE (si->nonzero_chars) != SSA_NAME)
return -1; return -1;
const value_range *vr const value_range *vr
...@@ -232,7 +233,15 @@ compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off, ...@@ -232,7 +233,15 @@ compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off,
if (rng != VR_RANGE || !range_int_cst_p (vr)) if (rng != VR_RANGE || !range_int_cst_p (vr))
return -1; return -1;
return compare_tree_int (vr->min (), off); /* If the offset is less than the minimum length or if the bounds
of the length range are equal return the result of the comparison
same as in the constant case. Otherwise return a conservative
result. */
int cmpmin = compare_tree_int (vr->min (), off);
if (cmpmin > 0 || tree_int_cst_equal (vr->min (), vr->max ()))
return cmpmin;
return -1;
} }
/* Return true if SI is known to be a zero-length string. */ /* Return true if SI is known to be a zero-length string. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment