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>
|
||||
|
||||
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
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
23
gcc/testsuite/gcc.dg/strlenopt-27.c
Normal file
23
gcc/testsuite/gcc.dg/strlenopt-27.c
Normal file
@ -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;
|
||||
} 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)
|
||||
{
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user