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
This commit is contained in:
parent
57534689d7
commit
204a913bda
|
@ -1,5 +1,15 @@
|
||||||
2015-01-08 Jakub Jelinek <jakub@redhat.com>
|
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 target/55023
|
||||||
PR middle-end/64388
|
PR middle-end/64388
|
||||||
* dse.c (struct insn_info): Mention frame_read set also
|
* dse.c (struct insn_info): Mention frame_read set also
|
||||||
|
|
|
@ -1078,7 +1078,7 @@ DEFPARAM (PARAM_MAX_TRACKED_STRLENS,
|
||||||
"max-tracked-strlens",
|
"max-tracked-strlens",
|
||||||
"Maximum number of strings for which strlen optimization pass will "
|
"Maximum number of strings for which strlen optimization pass will "
|
||||||
"track string lengths",
|
"track string lengths",
|
||||||
1000, 0, 0)
|
10000, 0, 0)
|
||||||
|
|
||||||
/* Keep this in sync with the sched_pressure_algorithm enum. */
|
/* Keep this in sync with the sched_pressure_algorithm enum. */
|
||||||
DEFPARAM (PARAM_SCHED_PRESSURE_ALGORITHM,
|
DEFPARAM (PARAM_SCHED_PRESSURE_ALGORITHM,
|
||||||
|
|
|
@ -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>
|
2015-01-08 David Malcolm <dmalcolm@redhat.com>
|
||||||
|
|
||||||
* jit.dg/harness.h (set_up_logging): New function.
|
* jit.dg/harness.h (set_up_logging): New function.
|
||||||
|
|
|
@ -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" } } */
|
|
@ -181,6 +181,18 @@ struct laststmt_struct
|
||||||
int stridx;
|
int stridx;
|
||||||
} laststmt;
|
} 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. */
|
/* Helper function for get_stridx. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -219,7 +231,43 @@ get_stridx (tree exp)
|
||||||
tree s, o;
|
tree s, o;
|
||||||
|
|
||||||
if (TREE_CODE (exp) == SSA_NAME)
|
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)
|
if (TREE_CODE (exp) == ADDR_EXPR)
|
||||||
{
|
{
|
||||||
|
@ -388,16 +436,6 @@ free_strinfo (strinfo si)
|
||||||
pool_free (strinfo_pool, 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. */
|
/* Set strinfo in the vector entry IDX to SI. */
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -555,7 +593,7 @@ maybe_invalidate (gimple stmt)
|
||||||
return nonempty;
|
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
|
if stridx_to_strinfo vector is shared with some other
|
||||||
bbs. */
|
bbs. */
|
||||||
|
|
||||||
|
@ -605,6 +643,82 @@ verify_related_strinfos (strinfo origsi)
|
||||||
return si;
|
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
|
/* 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
|
to a zero-length string and if possible chain it to a related strinfo
|
||||||
chain whose part is or might be CHAINSI. */
|
chain whose part is or might be CHAINSI. */
|
||||||
|
@ -614,8 +728,10 @@ zero_length_string (tree ptr, strinfo chainsi)
|
||||||
{
|
{
|
||||||
strinfo si;
|
strinfo si;
|
||||||
int idx;
|
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
|
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))
|
if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
Loading…
Reference in New Issue