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;

}

Reply via email to