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; }