aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2016-06-29 10:47:46 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2016-06-29 10:47:46 +0200
commit5f3cd7c3f31373789dbc8360fa3d46fcaf473f99 (patch)
treeaa9612115c416b5ff9f86c284f36e28909c53190
parent36d0d9be5585ccc0ea8a44e6d4e93d8d0f7f53a0 (diff)
downloadgcc-5f3cd7c3f31373789dbc8360fa3d46fcaf473f99.zip
gcc-5f3cd7c3f31373789dbc8360fa3d46fcaf473f99.tar.gz
gcc-5f3cd7c3f31373789dbc8360fa3d46fcaf473f99.tar.bz2
re PR tree-optimization/71625 (missing strlen optimization on different array initialization style)
PR tree-optimization/71625 * tree-ssa-strlen.c (get_addr_stridx): Add PTR argument. Assume list is sorted by ascending list->offset. If PTR is non-NULL and there is previous strinfo, call get_stridx_plus_constant. (get_stridx): Pass exp as second argument to get_addr_stridx. (addr_stridxptr): Add missing list = list->next, so that there can be more than one entries in the list. Bump limit from 16 to 32. Ensure the list is sorted by ascending list->offset. (get_stridx_plus_constant): Adjust so that it can be also called with ADDR_EXPR instead of SSA_NAME as PTR. (handle_char_store): Pass NULL_TREE as second argument to get_addr_stridx. * gcc.dg/strlenopt-28.c: New test. From-SVN: r237841
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-28.c59
-rw-r--r--gcc/tree-ssa-strlen.c47
4 files changed, 116 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7f6dcb3..2d4f9b3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+2016-06-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/71625
+ * tree-ssa-strlen.c (get_addr_stridx): Add PTR argument. Assume list
+ is sorted by ascending list->offset. If PTR is non-NULL and there is
+ previous strinfo, call get_stridx_plus_constant.
+ (get_stridx): Pass exp as second argument to get_addr_stridx.
+ (addr_stridxptr): Add missing list = list->next, so that there can be
+ more than one entries in the list. Bump limit from 16 to 32. Ensure
+ the list is sorted by ascending list->offset.
+ (get_stridx_plus_constant): Adjust so that it can be also called with
+ ADDR_EXPR instead of SSA_NAME as PTR.
+ (handle_char_store): Pass NULL_TREE as second argument to
+ get_addr_stridx.
+
2016-06-29 Richard Biener <rguenther@suse.de>
PR rtl-optimization/68961
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 70e9048..c1c9a31 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-06-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/71625
+ * gcc.dg/strlenopt-28.c: New test.
+
2016-06-29 Richard Biener <rguenther@suse.de>
PR middle-end/71002
diff --git a/gcc/testsuite/gcc.dg/strlenopt-28.c b/gcc/testsuite/gcc.dg/strlenopt-28.c
new file mode 100644
index 0000000..03fb017
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-28.c
@@ -0,0 +1,59 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-strlen" } */
+
+#include "strlenopt.h"
+
+volatile int v;
+
+size_t
+f1 (void)
+{
+ char a[30];
+ v += 1;
+ memcpy (a, "1234567", 8);
+ memcpy (a + 7, "89abcdefg", 10);
+ memcpy (a + 16, "h", 2);
+ return strlen (a); // This strlen should be optimized into 17.
+}
+
+size_t
+f2 (void)
+{
+ char a[30];
+ v += 2;
+ strcpy (a, "1234567");
+ strcpy (a + 7, "89abcdefg");
+ strcpy (a + 16, "h");
+ return strlen (a); // This strlen should be optimized into 17.
+}
+
+size_t
+f3 (char *a)
+{
+ v += 3;
+ memcpy (a, "1234567", 8);
+ memcpy (a + 7, "89abcdefg", 10);
+ memcpy (a + 16, "h", 2);
+ return strlen (a); // This strlen should be optimized into 17.
+}
+
+size_t
+f4 (char *a)
+{
+ v += 4;
+ strcpy (a, "1234567");
+ strcpy (a + 7, "89abcdefg");
+ strcpy (a + 16, "h");
+ return strlen (a); // This strlen should be optimized into 17.
+}
+
+int
+main ()
+{
+ char a[30];
+ if (f1 () != 17 || f2 () != 17 || f3 (a) != 17 || f4 (a) != 17)
+ abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index f306a9c..232594b 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -159,10 +159,10 @@ get_strinfo (int idx)
/* Helper function for get_stridx. */
static int
-get_addr_stridx (tree exp)
+get_addr_stridx (tree exp, tree ptr)
{
HOST_WIDE_INT off;
- struct stridxlist *list;
+ struct stridxlist *list, *last = NULL;
tree base;
if (!decl_to_stridxlist_htab)
@@ -180,9 +180,22 @@ get_addr_stridx (tree exp)
{
if (list->offset == off)
return list->idx;
+ if (list->offset > off)
+ return 0;
+ last = list;
list = list->next;
}
while (list);
+
+ if (ptr && last && last->idx > 0)
+ {
+ strinfo *si = get_strinfo (last->idx);
+ if (si
+ && si->length
+ && TREE_CODE (si->length) == INTEGER_CST
+ && compare_tree_int (si->length, off - last->offset) != -1)
+ return get_stridx_plus_constant (si, off - last->offset, ptr);
+ }
return 0;
}
@@ -234,7 +247,7 @@ get_stridx (tree exp)
if (TREE_CODE (exp) == ADDR_EXPR)
{
- int idx = get_addr_stridx (TREE_OPERAND (exp, 0));
+ int idx = get_addr_stridx (TREE_OPERAND (exp, 0), exp);
if (idx != 0)
return idx;
}
@@ -304,15 +317,29 @@ addr_stridxptr (tree exp)
if (existed)
{
int i;
- for (i = 0; i < 16; i++)
+ stridxlist *before = NULL;
+ for (i = 0; i < 32; i++)
{
if (list->offset == off)
return &list->idx;
+ if (list->offset > off && before == NULL)
+ before = list;
if (list->next == NULL)
break;
+ list = list->next;
}
- if (i == 16)
+ if (i == 32)
return NULL;
+ if (before)
+ {
+ list = before;
+ before = XOBNEW (&stridx_obstack, struct stridxlist);
+ *before = *list;
+ list->next = before;
+ list->offset = off;
+ list->idx = 0;
+ return &list->idx;
+ }
list->next = XOBNEW (&stridx_obstack, struct stridxlist);
list = list->next;
}
@@ -613,9 +640,7 @@ verify_related_strinfos (strinfo *origsi)
static int
get_stridx_plus_constant (strinfo *basesi, HOST_WIDE_INT off, tree ptr)
{
- gcc_checking_assert (TREE_CODE (ptr) == SSA_NAME);
-
- if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
+ if (TREE_CODE (ptr) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
return 0;
if (basesi->length == NULL_TREE
@@ -633,7 +658,8 @@ get_stridx_plus_constant (strinfo *basesi, HOST_WIDE_INT off, tree ptr)
|| TREE_CODE (si->length) != INTEGER_CST)
return 0;
- if (ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
+ if (TREE_CODE (ptr) == SSA_NAME
+ && ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
gcc_checking_assert (compare_tree_int (si->length, off) != -1);
@@ -651,6 +677,7 @@ get_stridx_plus_constant (strinfo *basesi, HOST_WIDE_INT off, tree ptr)
{
if (r == 0)
{
+ gcc_assert (TREE_CODE (ptr) == SSA_NAME);
ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = si->idx;
return si->idx;
}
@@ -2063,7 +2090,7 @@ handle_char_store (gimple_stmt_iterator *gsi)
}
}
else
- idx = get_addr_stridx (lhs);
+ idx = get_addr_stridx (lhs, NULL_TREE);
if (idx > 0)
{