[Bug tree-optimization/82946] New: member pointer defeats strlen optimization involving a string literal

msebor at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Sat Nov 11 00:57:00 GMT 2017


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

            Bug ID: 82946
           Summary: member pointer defeats strlen optimization involving a
                    string literal
           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: ---

In the program below, while GCC optimizes the strlen call in f() to a constant
it doesn't do the same for the equivalent function g().

I suspect this is caused by the same underlying assumptions as pr80944: i.e.,
that the strcpy (a->d, "123") call could change a->d if a->d pointed at or into
itself.  While that might be true in other circumstances, it's not possible
here.  Since the array at a->d is subsequently accessed by the call to strlen,
the strcpy call cannot change a->d in a valid program because "123" (or any
other string literal) cannot be a valid representation of a pointer.  (The only
way for a conforming program to obtain a valid pointer is by assigning to it
the value of another valid pointer.  Even if the bit pattern of the literal
"123" happened to match a valid address in a program, copying the literal into
a pointer and then using that pointer is undefined.)

So a->d can be assumed not to change in either function and the strlen
optimization below is safe in both.

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

char* strcpy (char*, const char*);
__SIZE_TYPE__ strlen (const char*);

struct A { char *d; };

unsigned f (struct A *a)
{
  char *d = a->d;
  strcpy (d, "123");
  return strlen (d);   // folded into 3
}

unsigned g (struct A *a)
{
  strcpy (a->d, "123");
  return strlen (a->d);   // not folded but can be
}


;; Function f (f, funcdef_no=0, decl_uid=1898, cgraph_uid=0, symbol_order=0)

f (struct A * a)
{
  char * d;

  <bb 2> [local count: 10000]:
  d_4 = a_3(D)->d;
  __builtin_memcpy (d_4, "123", 4);
  return 3;

}



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

g (struct A * a)
{
  char * _1;
  char * _2;
  long unsigned int _3;
  unsigned int _7;

  <bb 2> [local count: 10000]:
  _1 = a_5(D)->d;
  __builtin_memcpy (_1, "123", 4);
  _2 = a_5(D)->d; 
  _3 = strlen (_2);
  _7 = (unsigned int) _3;
  return _7;

}


More information about the Gcc-bugs mailing list