[Bug c/102452] New: Structs with flexible array members are not optimized on stack
peter at peterzhu dot ca
gcc-bugzilla@gcc.gnu.org
Wed Sep 22 13:22:07 GMT 2021
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;
}
More information about the Gcc-bugs
mailing list