This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug tree-optimization/81703] New: memcpy folding defeats strlen optimization
- 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, 03 Aug 2017 18:10:02 +0000
- Subject: [Bug tree-optimization/81703] New: memcpy folding defeats strlen optimization
- Auto-submitted: auto-generated
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81703
Bug ID: 81703
Summary: memcpy folding defeats strlen optimization
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: ---
When a call to memcpy() copies a string of known length the
gimple_fold_builtin_memcpy function transforms the call to a direct memory
access. This transformation then prevents a subsequent strlen optimization
that would otherwise readily take place. As a result, even simple examples
like the one in the test case below are not optimized into optimal code. (In
addition, the folding fails to consider the size of the destination and allows
buffer overflow to go unnoticed -- this is the subject of bug 79220).
I think this could be dealt in one of at least two ways: a) by enhancing the
tree-ssa-strlen pass to recognize direct memory references (this alone won't
help with bug 79220), or b) by deferring the folding until after the
tree-ssa-strlen pass has had a chance to perform its sophisticate analysis and
transformations. Between the two alternatives, I would expect b) to be the
simpler solution and yield better results (it could also better handle bug
79220).
$ cat a.c && gcc -O2 -S -Wall -Wextra -Wpedantic
-fdump-tree-optimized=/dev/stdout a.c
unsigned f (void)
{
char d[8];
const char s[] = "0123";
__builtin_strcpy (d, s);
return __builtin_strlen (d);
}
unsigned g (void) // can be optimized the same as f()
{
char d[8];
const char s[] = "0123";
__builtin_memcpy (d, s, sizeof s);
return __builtin_strlen (d);
}
;; Function f (f, funcdef_no=0, decl_uid=1815, cgraph_uid=0, symbol_order=0)
f ()
{
<bb 2> [100.00%] [count: INV]:
return 4;
}
;; Function g (g, funcdef_no=1, decl_uid=1820, cgraph_uid=1, symbol_order=1)
g ()
{
const char s[5];
char d[8];
long unsigned int _1;
unsigned int _5;
<bb 2> [100.00%] [count: INV]:
s = "0123";
MEM[(char * {ref-all})&d] = MEM[(char * {ref-all})&s];
_1 = __builtin_strlen (&d);
_5 = (unsigned int) _1;
d ={v} {CLOBBER};
s ={v} {CLOBBER};
return _5;
}