aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2015-01-08 22:30:56 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2015-01-08 22:30:56 +0100
commit204a913bda3c3228723ea13e41c9dd831c362b33 (patch)
tree769905ce0ea2dd0ec84a6ed340016c2adba5f3d1 /gcc
parent57534689d75b6164dae4ac7f5c6f23d543f63583 (diff)
downloadgcc-204a913bda3c3228723ea13e41c9dd831c362b33.zip
gcc-204a913bda3c3228723ea13e41c9dd831c362b33.tar.gz
gcc-204a913bda3c3228723ea13e41c9dd831c362b33.tar.bz2
re PR tree-optimization/63989 (tree-ssa-strlen.c doesn't handle constant pointer plus and array refs if constant offset is smaller than known constant string length)
PR tree-optimization/63989 * params.def (PARAM_MAX_TRACKED_STRLENS): Increment default from 1000 to 10000. * tree-ssa-strlen.c (get_strinfo): Moved earlier. (get_stridx): If we don't have a record for certain SSA_NAME, but it is POINTER_PLUS_EXPR of some SSA_NAME we do with constant offset, call get_stridx_plus_constant. (get_stridx_plus_constant): New function. (zero_length_string): Don't use get_stridx here. * gcc.dg/strlenopt-27.c: New test. From-SVN: r219362
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/params.def2
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-27.c23
-rw-r--r--gcc/tree-ssa-strlen.c142
5 files changed, 168 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 53eb2f2..33ba9da 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,15 @@
2015-01-08 Jakub Jelinek <jakub@redhat.com>
+ PR tree-optimization/63989
+ * params.def (PARAM_MAX_TRACKED_STRLENS): Increment default
+ from 1000 to 10000.
+ * tree-ssa-strlen.c (get_strinfo): Moved earlier.
+ (get_stridx): If we don't have a record for certain SSA_NAME,
+ but it is POINTER_PLUS_EXPR of some SSA_NAME we do with
+ constant offset, call get_stridx_plus_constant.
+ (get_stridx_plus_constant): New function.
+ (zero_length_string): Don't use get_stridx here.
+
PR target/55023
PR middle-end/64388
* dse.c (struct insn_info): Mention frame_read set also
diff --git a/gcc/params.def b/gcc/params.def
index 4e68273..cbdc477 100644
--- a/gcc/params.def
+++ b/gcc/params.def
@@ -1078,7 +1078,7 @@ DEFPARAM (PARAM_MAX_TRACKED_STRLENS,
"max-tracked-strlens",
"Maximum number of strings for which strlen optimization pass will "
"track string lengths",
- 1000, 0, 0)
+ 10000, 0, 0)
/* Keep this in sync with the sched_pressure_algorithm enum. */
DEFPARAM (PARAM_SCHED_PRESSURE_ALGORITHM,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6ec4ba2..c3ab418 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2015-01-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/63989
+ * gcc.dg/strlenopt-27.c: New test.
+
2015-01-08 David Malcolm <dmalcolm@redhat.com>
* jit.dg/harness.h (set_up_logging): New function.
diff --git a/gcc/testsuite/gcc.dg/strlenopt-27.c b/gcc/testsuite/gcc.dg/strlenopt-27.c
new file mode 100644
index 0000000..8d06aac
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-27.c
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-strlen" } */
+
+#include "strlenopt.h"
+
+__attribute__((noinline, noclone)) size_t
+fn1 (char *p)
+{
+ strcpy (p, "foobar");
+ return strlen (p + 2); // This strlen should be optimized into 4.
+}
+
+int
+main (void)
+{
+ char p[] = "barfoo";
+ if (fn1 (p) != 4)
+ abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
+/* { dg-final { cleanup-tree-dump "strlen" } } */
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index acf4f58..c9e8f1e 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -181,6 +181,18 @@ struct laststmt_struct
int stridx;
} laststmt;
+static int get_stridx_plus_constant (strinfo, HOST_WIDE_INT, tree);
+
+/* Return strinfo vector entry IDX. */
+
+static inline strinfo
+get_strinfo (int idx)
+{
+ if (vec_safe_length (stridx_to_strinfo) <= (unsigned int) idx)
+ return NULL;
+ return (*stridx_to_strinfo)[idx];
+}
+
/* Helper function for get_stridx. */
static int
@@ -219,7 +231,43 @@ get_stridx (tree exp)
tree s, o;
if (TREE_CODE (exp) == SSA_NAME)
- return ssa_ver_to_stridx[SSA_NAME_VERSION (exp)];
+ {
+ if (ssa_ver_to_stridx[SSA_NAME_VERSION (exp)])
+ return ssa_ver_to_stridx[SSA_NAME_VERSION (exp)];
+ int i;
+ tree e = exp;
+ HOST_WIDE_INT off = 0;
+ for (i = 0; i < 5; i++)
+ {
+ gimple def_stmt = SSA_NAME_DEF_STMT (e);
+ if (!is_gimple_assign (def_stmt)
+ || gimple_assign_rhs_code (def_stmt) != POINTER_PLUS_EXPR)
+ return 0;
+ tree rhs1 = gimple_assign_rhs1 (def_stmt);
+ tree rhs2 = gimple_assign_rhs2 (def_stmt);
+ if (TREE_CODE (rhs1) != SSA_NAME
+ || !tree_fits_shwi_p (rhs2))
+ return 0;
+ HOST_WIDE_INT this_off = tree_to_shwi (rhs2);
+ if (this_off < 0)
+ return 0;
+ off = (unsigned HOST_WIDE_INT) off + this_off;
+ if (off < 0)
+ return 0;
+ if (ssa_ver_to_stridx[SSA_NAME_VERSION (rhs1)])
+ {
+ strinfo si
+ = get_strinfo (ssa_ver_to_stridx[SSA_NAME_VERSION (rhs1)]);
+ if (si
+ && si->length
+ && TREE_CODE (si->length) == INTEGER_CST
+ && compare_tree_int (si->length, off) != -1)
+ return get_stridx_plus_constant (si, off, exp);
+ }
+ e = rhs1;
+ }
+ return 0;
+ }
if (TREE_CODE (exp) == ADDR_EXPR)
{
@@ -388,16 +436,6 @@ free_strinfo (strinfo si)
pool_free (strinfo_pool, si);
}
-/* Return strinfo vector entry IDX. */
-
-static inline strinfo
-get_strinfo (int idx)
-{
- if (vec_safe_length (stridx_to_strinfo) <= (unsigned int) idx)
- return NULL;
- return (*stridx_to_strinfo)[idx];
-}
-
/* Set strinfo in the vector entry IDX to SI. */
static inline void
@@ -555,7 +593,7 @@ maybe_invalidate (gimple stmt)
return nonempty;
}
-/* Unshare strinfo record SI, if it has recount > 1 or
+/* Unshare strinfo record SI, if it has refcount > 1 or
if stridx_to_strinfo vector is shared with some other
bbs. */
@@ -605,6 +643,82 @@ verify_related_strinfos (strinfo origsi)
return si;
}
+/* Attempt to create a new strinfo for BASESI + OFF, or find existing
+ strinfo if there is any. Return it's idx, or 0 if no strinfo has
+ been created. */
+
+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))
+ return 0;
+
+ if (basesi->length == NULL_TREE
+ || TREE_CODE (basesi->length) != INTEGER_CST
+ || compare_tree_int (basesi->length, off) == -1
+ || !tree_fits_shwi_p (basesi->length))
+ return 0;
+
+ HOST_WIDE_INT len = tree_to_shwi (basesi->length) - off;
+ strinfo si = basesi, chainsi;
+ if (si->first || si->prev || si->next)
+ si = verify_related_strinfos (basesi);
+ if (si == NULL
+ || si->length == NULL_TREE
+ || TREE_CODE (si->length) != INTEGER_CST)
+ return 0;
+
+ if (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);
+ for (chainsi = si; chainsi->next; chainsi = si)
+ {
+ si = get_strinfo (chainsi->next);
+ if (si == NULL
+ || si->first != chainsi->first
+ || si->prev != chainsi->idx
+ || si->length == NULL_TREE
+ || TREE_CODE (si->length) != INTEGER_CST)
+ break;
+ int r = compare_tree_int (si->length, len);
+ if (r != 1)
+ {
+ if (r == 0)
+ {
+ ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = si->idx;
+ return si->idx;
+ }
+ break;
+ }
+ }
+
+ int idx = new_stridx (ptr);
+ if (idx == 0)
+ return 0;
+ si = new_strinfo (ptr, idx, build_int_cst (size_type_node, len));
+ set_strinfo (idx, si);
+ if (chainsi->next)
+ {
+ strinfo nextsi = unshare_strinfo (get_strinfo (chainsi->next));
+ si->next = nextsi->idx;
+ nextsi->prev = idx;
+ }
+ chainsi = unshare_strinfo (chainsi);
+ if (chainsi->first == 0)
+ chainsi->first = chainsi->idx;
+ chainsi->next = idx;
+ if (chainsi->endptr == NULL_TREE && len == 0)
+ chainsi->endptr = ptr;
+ si->endptr = chainsi->endptr;
+ si->prev = chainsi->idx;
+ si->first = chainsi->first;
+ si->writable = chainsi->writable;
+ return si->idx;
+}
+
/* Note that PTR, a pointer SSA_NAME initialized in the current stmt, points
to a zero-length string and if possible chain it to a related strinfo
chain whose part is or might be CHAINSI. */
@@ -614,8 +728,10 @@ zero_length_string (tree ptr, strinfo chainsi)
{
strinfo si;
int idx;
+ if (ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
+ ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
gcc_checking_assert (TREE_CODE (ptr) == SSA_NAME
- && get_stridx (ptr) == 0);
+ && ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] == 0);
if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
return NULL;