Home > Mobile >  Function that takes a const struct, compiler does not optimize function body?
Function that takes a const struct, compiler does not optimize function body?

Time:08-30

I have the following piece of code:

#include <stdio.h>

typedef struct {
    bool some_var;
} model_t;

const model_t model = {
    true
};

void bla(const model_t *m) {
    if (m->some_var) {
        printf("Some var is true!\n");
    }
    else {
        printf("Some var is false!\n");
    }
}

int main() {
    bla(&model);
}

I'd imagine that the compiler has all the information required to eliminate the else clause in the bla() function. The only code path that calls the function comes from main, it takes in const model_t, so it should be able to figure out that that code path is not being used. However:

Without inline

With GCC 12.2 we see that the second part is linked in.

If I inline the function this goes away though:

With inline

I'm wondering what I'm missing here, and if there's some way I can make the compiler do some smarter work? This happens in both C and C with -O3 and -Os.

CodePudding user response:

The compiler cannot optimize the else path away as the object file might be linked against any other code. This would be different if the function would be static or you use whole program optimization.

CodePudding user response:

The compiler does eliminate the else path in the inlined function in main. What you're confusing is the global function that is not called anyway and will be discarded by the linker eventually.

If you use -fwhole-program flag to let the compiler know that no other file is going to be linked, that unused segment is discarded:

enter image description here

Additionally, you use static or inline keywords to achieve something similar.

CodePudding user response:

I thought of sharing:

#include <stdlib.h>     // exit
#include <stdio.h>
typedef struct
{
        bool some_var;
}model_t;
const model_t model = { true };
void bla(const model_t*m)
{
        // HANDLE NULL POINTER EXCEPTIONS
        if ( m )
        {
                printf( "bla model_t* pointer is NULL\n");
                exit(1);
        }
        if (m->some_var)
        {
                printf("Some var is true!\n");
        }
        else
        {
                printf("Some var is false!\n");
        }
        // Better to use return. Reason: future enhancement may have changes to return types.
        return;
}
int main()
{
        bla(&model);
        return 0;
}
/*
$ # Using zero optimization
$ gcc -Wall -O0 73526838.cpp -o ./a.out
Optimization    Size of a.out
-O0             68162
-O1             68162
-O2             68242
-O3             68242   I used to use this optimization without using -g option.
...
*/

Using -O3, without using -g option used to help:

  1. security
  2. log files based on log level/error/exception based on server/client parameter.
  3. input file/output from client/server
  4. size of the binary
  5. use dependence libraries instead of using static library based on dll/.sl/.so library provider's business. This will reduce the size of the binary and the binary to call dependent library function(optimization) only when required.
  •  Tags:  
  • c c
  • Related