PR tree-optimization/86083 - handle non-constant assignments in strlen
authorMartin Sebor <msebor@redhat.com>
Mon, 11 Jun 2018 20:01:40 +0000 (20:01 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Mon, 11 Jun 2018 20:01:40 +0000 (14:01 -0600)
gcc/ChangeLog:

PR tree-optimization/86083
* tree-ssa-strlen.c (handle_char_store): Use tree_expr_nonzero_p.

gcc/testsuite/ChangeLog:

PR tree-optimization/86083
* gcc.dg/strlenopt-44.c: New test.

From-SVN: r261452

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/strlenopt-44.c [new file with mode: 0644]
gcc/tree-ssa-strlen.c

index 96d953fd0e5c7809753d8f409f0f4a763950a93c..655a5141ac179706a650aad45bca2ab4ce4ddcb1 100644 (file)
@@ -1,3 +1,8 @@
+2018-06-11  Martin Sebor  <msebor@redhat.com>
+
+       * PR tree-optimization/86083
+       * tree-ssa-strlen.c (handle_char_store): Use tree_expr_nonzero_p.
+
 2018-06-11 Zhouyi Zhou <zhouzhouyi@gmail.com>
 
        * tree-eh.c (lower_eh_constructs_2): Add a comma to comment.
index ae6acb39deb7c279a70aa5bfae785fd9e329a2ec..3ded9ffe653fb6e4aba37d0ff629f1e492109bf7 100644 (file)
@@ -1,3 +1,8 @@
+2018-06-11  Martin Sebor  <msebor@redhat.com>
+
+       PR tree-optimization/86083
+       * gcc.dg/strlenopt-44.c: New test.
+
 2018-06-11  Janus Weil  <janus@gcc.gnu.org>
 
        PR fortran/45521
diff --git a/gcc/testsuite/gcc.dg/strlenopt-44.c b/gcc/testsuite/gcc.dg/strlenopt-44.c
new file mode 100644 (file)
index 0000000..0c01088
--- /dev/null
@@ -0,0 +1,92 @@
+/* PR tree-optimization/86083 - handle non-constant assignments in strlen
+   { dg-do compile }
+   { dg-options "-O2 -Wall -fdump-tree-optimized" } */
+
+#include "range.h"
+#include "strlenopt.h"
+
+#define CAT(x, y) x ## y
+#define CONCAT(x, y) CAT (x, y)
+#define FAILNAME(name) CONCAT (call_ ## name ##_on_line_, __LINE__)
+
+#define FAIL(name) do {                                \
+    extern void FAILNAME (name) (void);                \
+    FAILNAME (name)();                         \
+  } while (0)
+
+/* Macro to emit a call to funcation named
+     call_in_true_branch_not_eliminated_on_line_NNN()
+   for each call that's expected to be eliminated.  The dg-final
+   scan-tree-dump-time directive at the bottom of the test verifies
+   that no such call appears in output.  */
+#define ASSERT_ELIM(expr)                                              \
+  if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
+
+/* Macro to emit a call to a function named
+     call_made_in_{true,false}_branch_on_line_NNN()
+   for each call that's expected to be retained.  The dg-final
+   scan-tree-dump-time directive at the bottom of the test verifies
+   that the expected number of both kinds of calls appears in output
+   (a pair for each line with the invocation of the KEEP() macro.  */
+#define ASSERT_KEEP(expr)                      \
+  if (expr)                                    \
+    FAIL (made_in_true_branch);                        \
+  else                                         \
+    FAIL (made_in_false_branch)
+
+
+#define ELIM(init, i, c, res)                  \
+  do {                                         \
+    char a[] = init;                           \
+    a[i] = c;                                  \
+    ASSERT_ELIM (strlen (a) == res);           \
+  } while (0)
+
+#define KEEP(init, i, c, res)                  \
+  do {                                         \
+    char a[] = init;                           \
+    a[i] = c;                                  \
+    ASSERT_KEEP (strlen (a) == res);           \
+  } while (0)
+
+
+void test_elim_range (char c)
+{
+  ELIM ("1", 0, UR (1, 2), 1);
+  ELIM ("1", 0, UR (1, 127), 1);
+  ELIM ("1", 0, UR ('0', '9'), 1);
+
+  ELIM ("12", 0, UR (1, 127), 2);
+  ELIM ("12", 1, UR (1, 127), 2);
+
+  ELIM ("123", 0, UR (1, 9), 3);
+  ELIM ("123", 1, UR (10, 99), 3);
+  ELIM ("123", 2, UR (100, 127), 3);
+}
+
+void test_elim_anti_range (const char *s)
+{
+  char c = *s++;
+  ELIM ("123", 0, c ? c : 'x', 3);
+
+  c = *s++;
+  ELIM ("1234", 1, c ? c : 'y', 4);
+
+  c = *s++;
+  ELIM ("123", 2, c ? c : 'z', 3);
+}
+
+#line 1000
+
+void test_keep (void)
+{
+  size_t uchar_max = (unsigned char)-1;
+
+  KEEP ("1",     0, UR (1, uchar_max + 1), 1);
+  KEEP ("1\0\3", 1, UR (1, 2), 1);
+}
+
+/* { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated_" 0 "optimized" } }
+
+   { dg-final { scan-tree-dump-times "call_made_in_true_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 2 "optimized" } }
+   { dg-final { scan-tree-dump-times "call_made_in_false_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 2 "optimized" } } */
index 50562144078b391e72b59d368a8f19c0c1695176..cc1f5f48e3411142c30549e175c4e84638904832 100644 (file)
@@ -3073,9 +3073,7 @@ handle_char_store (gimple_stmt_iterator *gsi)
     }
 
   bool storing_zero_p = initializer_zerop (rhs);
-  bool storing_nonzero_p = (!storing_zero_p
-                           && TREE_CODE (rhs) == INTEGER_CST
-                           && integer_nonzerop (rhs));
+  bool storing_nonzero_p = !storing_zero_p && tree_expr_nonzero_p (rhs);
   /* Set to the length of the string being assigned if known.  */
   HOST_WIDE_INT rhslen;