[Bug tree-optimization/81330] New: missing strlen optimization with intervening memcpy
msebor at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Wed Jul 5 21:50:00 GMT 2017
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81330
Bug ID: 81330
Summary: missing strlen optimization with intervening memcpy
Product: gcc
Version: 8.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: msebor at gcc dot gnu.org
Target Milestone: ---
GCC eliminates redundant calls to strlen() with intervening calls to strcpy but
it misses an opportunity to do the same when the intervening call is to memcpy
instead. In the test case below, since both strcpy and memcpy require that the
copies do not overlap, it's safe to assume that neither call modifies any part
of the source string, including the terminating nul, and so the second strlen
call can be replaced with the result of the first in both functions, not just
in f(). The strlen dump shows that GCC doesn't take advantage of this
guarantee in the memcpy case.
(The second strlen call in g is replaced with the result of the first in g when
memcpy is passed n0 + 1 as the size but I don't see why that should make a
difference.)
$ cat a.c && gcc -O2 -S -Wall -fdump-tree-strlen=/dev/stdout a.c
void f (char* d, const char* s)
{
__SIZE_TYPE__ n0 = __builtin_strlen (s);
__builtin_strcpy (d, s);
__SIZE_TYPE__ n1 = __builtin_strlen (s);
if (n0 != n1)
__builtin_abort (); // optimized
}
void g (char* d, const char* s)
{
__SIZE_TYPE__ n0 = __builtin_strlen (s);
__builtin_memcpy (d, s, n0);
__SIZE_TYPE__ n1 = __builtin_strlen (s);
if (n0 != n1)
__builtin_abort (); // not optimized
}
;; Function f (f, funcdef_no=0, decl_uid=1816, cgraph_uid=0, symbol_order=0)
f (char * d, const char * s)
{
long unsigned int n1;
long unsigned int n0;
long unsigned int _8;
<bb 2> [100.00%] [count: INV]:
n0_3 = __builtin_strlen (s_2(D));
_8 = n0_3 + 1;
__builtin_memcpy (d_4(D), s_2(D), _8);
n1_6 = n0_3;
if (n0_3 != n1_6)
goto <bb 3>; [0.04%] [count: 0]
else
goto <bb 4>; [99.96%] [count: INV]
<bb 3> [0.04%] [count: 0]:
__builtin_abort ();
<bb 4> [99.96%] [count: INV]:
return;
}
;; Function g (g, funcdef_no=1, decl_uid=1822, cgraph_uid=1, symbol_order=1)
g (char * d, const char * s)
{
long unsigned int n1;
long unsigned int n0;
<bb 2> [100.00%] [count: INV]:
n0_3 = __builtin_strlen (s_2(D));
__builtin_memcpy (d_4(D), s_2(D), n0_3);
n1_6 = __builtin_strlen (s_2(D));
if (n0_3 != n1_6)
goto <bb 3>; [0.04%] [count: 0]
else
goto <bb 4>; [99.96%] [count: INV]
<bb 3> [0.04%] [count: 0]:
__builtin_abort ();
<bb 4> [99.96%] [count: INV]:
return;
}
More information about the Gcc-bugs
mailing list