https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63880
Bug ID: 63880 Summary: GCC overoptimization on local arrays of size 1 Product: gcc Version: 4.8.2 Status: UNCONFIRMED Severity: major Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: petzke at teltarif dot de Created attachment 33979 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=33979&action=edit Overoptimized C code: The loop is unrolled to a single iteration, which the compiler should not rely on, at least not in C. In general, C code may rely on the fact, that structs are allocated sequentially, even, if this is considered a somewhat bad coding practice. So, if one has the following structures in C: typedef struct { int nargs; char * data[1]; } arglist; struct { arglist args; char * moredata[1000]; } par; it is actually safe to access par.args.data[2] through par.args.data[1000], as they get basically mapped onto par.moredata[0] through par.moredata[999]. However, GCC version 4.8.2 seems to believe, that this access is "off limits", and actually optimizes a simple loop: for(i = args->nargs; --i >= 0; ) { if(args->data[i][0]) { cnt++; } } to run at most once, when optimizing option -O3 is used. An example of a thus over-optimized code snippet (compile with "-m64 -Wall -O3 -S" on Intel x86_64 - cannot compile into an executable though) is attached as "overoptimized.c". It suffices to introduce a pointer to "arglist" to turn off that overoptimization and actually get working code again. An exmpale is added as "works.c". I assume, that this array size optimization is not applied on pointers to structs, as these may be malloc()ed with the well-known trick of requesting extra space to increase the array size of the last element. However, that trick is not reserved to malloc(), it is also available to local vars via the combined struct shown for "par" above. Of course, this is only true for *C*. C++ may rip structs apart, but C may not. Having said that: * The loop optimization based on array size should still be applied, if the above example "arglist" is *directly* defined as a local var. * But if that "arglist" is part of another struct, that defines extra data items at the end, the compiler should not assume, that the array won't be accessed out of bounds. I know, that this out-of-bounds access is a somewhat "bad" coding style, but there is code, that still relies on these "dirty old C tricks".