[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