[Bug tree-optimization/81704] New: strncpy folding defeats strlen optimization

msebor at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Thu Aug 3 18:33:00 GMT 2017


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81704

            Bug ID: 81704
           Summary: strncpy 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: ---

Similar to bug 81703, when a call to strncpy() copies an initial sequence from
a string of known length without NUL-terminating the result, the
gimple_fold_builtin_strncpy function transforms the call into a direct memory
access.  When the copy is immediately followed by setting the last element of
the destination to NUL the transformation then prevents a subsequent strlen
optimization that could otherwise take place (bug 81433 tracks the strncpy
optimization that's missing from tree-ssa-strlen).  As a result, examples like
the one in the test case below are not optimized into optimal code.

As in bug 81703, I think the way to solve this is to defer the folding until
after the tree-ssa-strlen pass has run, similarly to how bug 77671 has been
handled.

$ cat a.c && gcc -O2 -S -Wall -Wextra -Wpedantic
-fdump-tree-optimized=/dev/stdout a.c
tree-optimized=/dev/stdout a.c
unsigned f (void)
{
  char d[8];
  __builtin_strcpy (d, "0123456");
  return __builtin_strlen (d);
}

unsigned g (void)
{
  char d[8];
  __builtin_strncpy (d, "01234567", sizeof d);
  d[sizeof d - 1] = '\0';
  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 7;

}



;; Function g (g, funcdef_no=1, decl_uid=1819, cgraph_uid=1, symbol_order=1)

g ()
{
  char d[8];
  long unsigned int _1;
  unsigned int _5;

  <bb 2> [100.00%] [count: INV]:
  MEM[(char * {ref-all})&d] = MEM[(char * {ref-all})"01234567"];
  d[7] = 0;
  _1 = __builtin_strlen (&d);
  _5 = (unsigned int) _1;
  d ={v} {CLOBBER};
  return _5;

}


More information about the Gcc-bugs mailing list