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

            Bug ID: 86061
           Summary: dead memset followed by strncpy and assignment not
                    eliminated
           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: ---

This is similar to bug 86010 except the optimization is absent from all
versions of GCC all the way back to 4.1.  In the test case below the memset
call zeroes out the entire destination array, only to have its contents
overwritten by the subsequent call to strncpy followed by the write to its last
element.  Rather than eliminating the memset call and keeping the
single-character store GCC does the opposite, which is obviously suboptimal.

This code is reduced from code that's idiomatic in the Linux kernel when
copying between kernel data (that's not necessarily nul-terminated) and
user-space strings (which are expected to be nul-terminated).

$ cat c.c && gcc -O2 -S -Wall -Wextra -fdump-tree-optimized=/dev/stdout c.c

struct S { int i; char n[256]; int j; };

void f (char*);

void g (struct S *p)
{
  char a[sizeof p->n + 1];

  __builtin_memset (a, 0, sizeof a);   // dead store, can be eliminated

  __builtin_strncpy (a, p->n, sizeof a - 1);
  a[sizeof a - 1] = '\0';

  f (a);
}


;; Function g (g, funcdef_no=0, decl_uid=1964, cgraph_uid=0, symbol_order=0)

g (struct S * p)
{
  char a[257];
  char[256] * _1;

  <bb 2> [local count: 1073741825]:
  __builtin_memset (&a, 0, 257);
  _1 = &p_4(D)->n;
  __builtin_strncpy (&a, _1, 256);
  f (&a);
  a ={v} {CLOBBER};
  return;

}

Reply via email to