https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92155
Bug ID: 92155
Summary: strlen(a) not folded after memset(a, 0, sizeof a)
Product: gcc
Version: 9.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: ---
Now that GCC unrolls memset-like loops with small numbers of iterations
(pr91975) and transforms some of them into MEM_REF, the strlen pass can also
determine the lengths of zeroed-out arrays to be zero. This can be seen in
function f below.
But GCC doesn't yet transform memset calls into the equivalent MEM_REFs, and
the strlen pass for some reason can't figure out that the length of an array
that's been zeroed-out by memset is also zero. This missed optimization can be
seen in function g below.
$ cat z.c && gcc -O2 -S -Wall -fdump-tree-optimized=/dev/stdout z.c
extern char a4[4];
extern char b4[4];
void f (void)
{
for (int i = 0; i != sizeof a4; ++i)
a4[i] = 0;
for (int i = 0; i != sizeof b4; ++i)
b4[i] = 0;
if (__builtin_strlen (a4) != __builtin_strlen (b4))
__builtin_abort ();
}
void g (void)
{
__builtin_memset (a4, 0, sizeof a4);
__builtin_memset (b4, 0, sizeof b4);
if (__builtin_strlen (a4) != __builtin_strlen (b4))
__builtin_abort ();
}
;; Function f (f, funcdef_no=0, decl_uid=1932, cgraph_uid=1, symbol_order=0)
f ()
{
<bb 2> [local count: 214748369]:
MEM <unsigned int> [(char *)&a4] = 0;
MEM <unsigned int> [(char *)&b4] = 0;
return;
}
;; Function g (g, funcdef_no=1, decl_uid=1943, cgraph_uid=2, symbol_order=1)
g ()
{
long unsigned int _1;
long unsigned int _2;
<bb 2> [local count: 1073741824]:
__builtin_memset (&a4, 0, 4);
__builtin_memset (&b4, 0, 4);
_1 = __builtin_strlen (&a4);
_2 = __builtin_strlen (&b4);
if (_1 != _2)
goto <bb 3>; [0.00%]
else
goto <bb 4>; [100.00%]
<bb 3> [count: 0]:
__builtin_abort ();
<bb 4> [local count: 1073741824]:
return;
}