aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2018-06-25 20:46:45 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2018-06-25 14:46:45 -0600
commitb36bc89e32a52ac41b6b68d834c7692b890741e6 (patch)
tree5b89ff8ce0de4a470d9653841c70fa1d0d32d042
parent03cd7d3fa2d756cb4fb7d62d4aba277893932ace (diff)
downloadgcc-b36bc89e32a52ac41b6b68d834c7692b890741e6.zip
gcc-b36bc89e32a52ac41b6b68d834c7692b890741e6.tar.gz
gcc-b36bc89e32a52ac41b6b68d834c7692b890741e6.tar.bz2
PR tree-optimization/86204 - wrong strlen result after prior strnlen
gcc/ChangeLog: PR tree-optimization/86204 * tree-ssa-strlen.c (handle_builtin_strlen): Avoid storing a strnlen result if it's less than the length of the string. gcc/testsuite/ChangeLog: PR tree-optimization/86204 * gcc.dg/strlenopt-46.c: New test. From-SVN: r262114
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-46.c131
-rw-r--r--gcc/tree-ssa-strlen.c34
4 files changed, 171 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5334c36..dedbffd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,11 @@
2018-06-25 Martin Sebor <msebor@redhat.com>
+ PR tree-optimization/86204
+ * tree-ssa-strlen.c (handle_builtin_strlen): Avoid storing
+ a strnlen result if it's less than the length of the string.
+
+2018-06-25 Martin Sebor <msebor@redhat.com>
+
PR tree-optimization/85700
* gimple-fold.c (gimple_fold_builtin_strncat): Adjust comment.
* tree-ssa-strlen.c (is_strlen_related_p): Handle integer subtraction.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4606474..4a90a33 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
2018-06-25 Martin Sebor <msebor@redhat.com>
+ PR tree-optimization/86204
+ * gcc.dg/strlenopt-46.c: New test.
+
+2018-06-25 Martin Sebor <msebor@redhat.com>
+
PR tree-optimization/85700
* gcc.dg/Wstringop-truncation-4.c: New test.
diff --git a/gcc/testsuite/gcc.dg/strlenopt-46.c b/gcc/testsuite/gcc.dg/strlenopt-46.c
new file mode 100644
index 0000000..dc6eef7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-46.c
@@ -0,0 +1,131 @@
+/* PR tree-optimization/86204 - wrong strlen result after prior strnlen
+ { dg-do run }
+ { dg-options "-O2 -Wall" } */
+
+#include "strlenopt.h"
+
+#define NOIPA __attribute__ ((noipa))
+
+char a[] = "12345";
+
+NOIPA void f0 (void)
+{
+ unsigned n0 = strnlen (a, 0);
+ unsigned n1 = strlen (a);
+
+ if (n0 != 0 || n1 != 5)
+ abort ();
+}
+
+NOIPA void f1 (void)
+{
+ unsigned n0 = strnlen (a, 1);
+ unsigned n1 = strlen (a);
+
+ if (n0 != 1 || n1 != 5)
+ abort ();
+}
+
+NOIPA void f2 (void)
+{
+ unsigned n0 = strnlen (a, 2);
+ unsigned n1 = strlen (a);
+
+ if (n0 != 2 || n1 != 5)
+ abort ();
+}
+
+NOIPA void f3 (void)
+{
+ unsigned n0 = strnlen (a, 3);
+ unsigned n1 = strlen (a);
+
+ if (n0 != 3 || n1 != 5)
+ abort ();
+}
+
+NOIPA void f4 (void)
+{
+ unsigned n0 = strnlen (a, 4);
+ unsigned n1 = strlen (a);
+
+ if (n0 != 4 || n1 != 5)
+ abort ();
+}
+
+NOIPA void f5 (void)
+{
+ unsigned n0 = strnlen (a, 5);
+ unsigned n1 = strlen (a);
+
+ if (n0 != 5 || n1 != 5)
+ abort ();
+}
+
+NOIPA void f6 (void)
+{
+ unsigned n0 = strnlen (a, 6);
+ unsigned n1 = strlen (a);
+
+ if (n0 != 5 || n1 != 5)
+ abort ();
+}
+
+NOIPA void fx (unsigned n)
+{
+ unsigned n0 = strnlen (a, n);
+ unsigned n1 = strlen (a);
+
+ unsigned min = n < 5 ? n : 5;
+ if (n0 != min || n1 != 5)
+ abort ();
+}
+
+NOIPA void g2 (void)
+{
+ strcpy (a, "123");
+ unsigned n0 = strnlen (a, 2);
+ unsigned n1 = strlen (a);
+
+ if (n0 != 2 || n1 != 3)
+ abort ();
+}
+
+NOIPA void g7 (void)
+{
+ strcpy (a, "123");
+ unsigned n0 = strnlen (a, 7);
+ unsigned n1 = strlen (a);
+
+ if (n0 != 3 || n1 != 3)
+ abort ();
+}
+
+NOIPA void gx (unsigned n)
+{
+ strcpy (a, "123");
+ unsigned n0 = strnlen (a, n);
+ unsigned n1 = strlen (a);
+
+ unsigned min = n < 3 ? n : 3;
+ if (n0 != min || n1 != 3)
+ abort ();
+}
+
+int main (void)
+{
+ f0 ();
+ f1 ();
+ f2 ();
+ f3 ();
+ f4 ();
+ f5 ();
+ f6 ();
+ fx (2);
+ fx (7);
+
+ g2 ();
+ g7 ();
+ gx (2);
+ gx (7);
+}
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 2da82a8..5807c79 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -1270,8 +1270,20 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
rhs = unshare_expr (rhs);
if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
+
+ /* Set for strnlen() calls with a non-constant bound. */
+ bool noncst_bound = false;
if (bound)
- rhs = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (rhs), rhs, bound);
+ {
+ tree new_rhs
+ = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (rhs), rhs, bound);
+
+ noncst_bound = (TREE_CODE (new_rhs) != INTEGER_CST
+ || tree_int_cst_lt (new_rhs, rhs));
+
+ rhs = new_rhs;
+ }
+
if (!update_call_from_tree (gsi, rhs))
gimplify_and_update_call_from_tree (gsi, rhs);
stmt = gsi_stmt (*gsi);
@@ -1281,6 +1293,12 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
fprintf (dump_file, "into: ");
print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
}
+
+ /* Avoid storing the length for calls to strnlen() with
+ a non-constant bound. */
+ if (noncst_bound)
+ return;
+
if (si != NULL
&& TREE_CODE (si->nonzero_chars) != SSA_NAME
&& TREE_CODE (si->nonzero_chars) != INTEGER_CST
@@ -1299,6 +1317,7 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
}
if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
return;
+
if (idx == 0)
idx = new_stridx (src);
else
@@ -1333,9 +1352,14 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
}
if (idx)
{
- strinfo *si = new_strinfo (src, idx, lhs, true);
- set_strinfo (idx, si);
- find_equal_ptrs (src, idx);
+ if (!bound)
+ {
+ /* Only store the new length information for calls to strlen(),
+ not for those to strnlen(). */
+ strinfo *si = new_strinfo (src, idx, lhs, true);
+ set_strinfo (idx, si);
+ find_equal_ptrs (src, idx);
+ }
/* For SRC that is an array of N elements, set LHS's range
to [0, min (N, BOUND)]. A constant return value means
@@ -1362,7 +1386,7 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
}
}
- if (strlen_to_stridx)
+ if (strlen_to_stridx && !bound)
strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
}
}