The r160529 introduced alternative way of removing globals to appease leak detectors (e.g valgrind). However this commit made nearly impossible removing global if it is of structure or array type and contains element of pointer type. Consider following example:
static int bar() { return 42; } static struct S { int (*F)(); int A; } Obj = { bar, 0 }; int main() { Obj.A = 42; return 0; }
In the example above global variable Obj will not be eliminated by globalopt, because it contains a pointer, although that pointer is a pointer to function and is never really accessed. The more serious problem is that function bar is not being DCE'd, although it's obviously dead. This could be especially problematic for LTO builds - I'm observing significant amount of dead stuff left in the image, which would otherwise have been eliminated.
Another issues with r160529 are:
- Very poor test coverage. The only test case cleanup-pointer-root-users.ll covers tiny part of added functionality
- While preventing optimizations in many cases it strangely allows some of global stores to be eliminated. For instance this one will be optimized out:
static void *p; int main() { p = malloc(100); return 0; }
And this one not:
static void *p; __attribute__((noinline)) int set(void *_p) { p = _p; } int main() { set(malloc(100)); return 0; }
An alternative to removal of r160529 could probably be converting global to private with zero initializer.