https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452
Bug ID: 102452 Summary: Structs with flexible array members are not optimized on stack Product: gcc Version: 9.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: peter at peterzhu dot ca Target Milestone: --- Created attachment 51494 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=51494&action=edit test.c Structs with flexible array members are not optimized on the stack. Testing with the test.c file shown below (which outputs the runtime in seconds), we see that the compiled program is significantly slower when the struct has a flexible array member than when it does not. This was tested on GCC 9.3.0 and 10.3.0 on Ubuntu 20.04. $ gcc -O3 test.c $ ./a.out 0.302769 $ gcc -O3 -DUSE_FLEX_ARR=1 test.c $ ./a.out 0.728760 clang does not have this issue. $ clang -O3 test.c $ ./a.out 0.312194 $ clang -O3 -DUSE_FLEX_ARR=1 test.c $ ./a.out 0.301175 This is what test.c looks like: #include <stdlib.h> #include <stdio.h> #include <time.h> #include <string.h> struct Test { long is_a; union { struct { long one; long two; long three; } a; struct { int one; int two; int three; int four; #if USE_FLEX_ARR char arr[]; #endif } b; } as; }; #define COUNT 100000000 static inline struct Test make_test_a(struct Test *test) { if (test->is_a) { return *test; } else { struct Test ret; ret.as.a.one = test->as.b.one; ret.as.a.two = test->as.b.two; ret.as.a.three = test->as.b.three; return ret; } } /* This function should be optimized to not allocate struct Test on the stack * since it only uses attribute "three". */ static inline long get_three(struct Test *test) { return make_test_a(test).as.a.three; } int main(int argc, char *argv[]) { struct timespec start, end; struct Test *mem = malloc(sizeof(struct Test) * COUNT); memset(mem, 0, sizeof(struct Test) * COUNT); clock_gettime(CLOCK_MONOTONIC, &start); { for (int i = 0; i < COUNT; i++) { long three = get_three(&mem[i]); if (three) { /* Impossible case. */ printf("what\n"); } } } clock_gettime(CLOCK_MONOTONIC, &end); double time = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1000000000.0; printf("%f\n", time); return 0; }