This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug tree-optimization/86075] New: dead store elimination defeats strlen optimization after memset zero followed by strcpy
- From: "msebor at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Thu, 07 Jun 2018 00:06:25 +0000
- Subject: [Bug tree-optimization/86075] New: dead store elimination defeats strlen optimization after memset zero followed by strcpy
- Auto-submitted: auto-generated
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86075
Bug ID: 86075
Summary: dead store elimination defeats strlen optimization
after memset zero followed by strcpy
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 emits optimally efficient code for the first of the two equivalent
functions below but generates very inefficient code for the latter. First, it
zeroes out the entire array even though only a small part of it is used.
Worse, (and ironically) because it eliminates the store to a[3] as dead early
on (in fre1) and before the strlen pass runs, the strlen optimization isn't
performed, and so the entire dead body of the function isn't eliminated.
Since unnecessarily zeroing-out storage just before storing strings in it is
common practice, detecting and handling it could lead to significant
improvements. The solution for the missing strlen optimization in this case
could be as simple as enhancing the strlen pass to track not just string
lengths but also sizes of zeroed-out blocks of storage used for strings.
$ cat c.c && gcc -O2 -S -Wall -Wextra -fdump-tree-optimized=/dev/stdout c.c
void f (void)
{
char a[4096];
__builtin_memcpy (a, "123", 3);
a[3] = 0;
if (__builtin_strlen (a) != 3) // folded
__builtin_abort ();
}
void g (void)
{
char a[4096] = ""; // all bytes zeroed out
__builtin_memcpy (a, "123", 3);
a[3] = 0; // eliminated
if (__builtin_strlen (a) != 3) // not folded
__builtin_abort ();
}
;; Function f (f, funcdef_no=0, decl_uid=1956, cgraph_uid=0, symbol_order=0)
f ()
{
<bb 2> [local count: 1073741825]:
return;
}
;; Function g (g, funcdef_no=1, decl_uid=1960, cgraph_uid=1, symbol_order=1)
g ()
{
char a[4096];
long unsigned int _1;
<bb 2> [local count: 1073741825]:
a = "";
__builtin_memcpy (&a, "123", 3);
_1 = __builtin_strlen (&a);
if (_1 != 3)
goto <bb 3>; [0.00%]
else
goto <bb 4>; [99.96%]
<bb 3> [count: 0]:
__builtin_abort ();
<bb 4> [local count: 1073312327]:
a ={v} {CLOBBER};
return;
}