开发者

c/c++ optimize for constant variable in calling functions

开发者 https://www.devze.com 2023-02-07 10:00 出处:网络
C/C++ compilers optimize single layer functions with constant parameters (known at compile time) only when using -Os, -O1 and -O2. They do not optimize all the layers. Only -O3 can do that. gcc is Win

C/C++ compilers optimize single layer functions with constant parameters (known at compile time) only when using -Os, -O1 and -O2. They do not optimize all the layers. Only -O3 can do that. gcc is WinAVR 4.3.3 which does not support attribute "optimize".

void inner(double value)
{
    //operations using value
    //...
}

void outer(double value)
{
    //few operations using value
    //...
    inner(value);
}

int main()
{
    inner(1); //optimize
    outer(1); //only optimize by using -O3
}

What are the possible solutions other than the followings?

  1. -O3 hold program or file (misuse will blow up the size)
  2. attribute optimize -O3 for the functions (4.3.3 does not support)
  3. macro (error prone)

Update:

//inner function
static inline void _delay_us(double __us) __attribute__((always_inline));
//outer function
void f(double);
inl开发者_开发问答ine f1(double);
static inline f2(double);
static f3(double);

f1 is optimized but give warning '_delay_us' is static but used in inline function 'f1' which is not static due to static function problem. Others are not optimized.


Solution:

static inline void outer(double) __attribute__((always_inline));

Inline is the key. My outer function is too large for inline. The attribute always_inline forces the function to be inline. This allows the compiler to optimize the function with less compilation cost than trying to figure out the optimization. -O3 is smart enough to do the optimization but not -Os. -Os may need some compiler options. (The keyword static is required because the inner function is also static inline.)


Somewhat similar to the macro option (3), but without the disadvantages of a macro, you can make specific functions inline, which will typically result in the desired constant optimizations. Of course this only helps if you're calling the relevant functions from one place (or from a few places), otherwise code bloat becomes an issue.

Note that gcc has a provision for forcing specific inline functions to always be inlined (rather than leaving this to the compiler's discretion): __attribute__ ((always_inline)). Other compilers will typically have a similar mechanism, although it may be a command line switch or a pragma.


In GCC at least, the -O flags just turn on a whole load of other flags, see e.g. http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html. You could just enable the ones you're interested in, although that's generally discouraged.

Note that I'm not sure that the behaviour of e.g. GCC at -O2 and -O3 is necessarily any indicator of what a completely different compiler will do.


As a general point, if you increase the information that you supply to the compiler then it might be able to perform a better optimisation.

For instance, assuming those are the only calls to inner and outer then you could declare them as static to limit their scope and allow the compiler more flexibility in how it optimises them.

Depending on the actual content of the functions you could might also declare their parameters as const which lets the compiler know immediately that they cannot be changed without it having to analyse the code

static void inner(const double value)
{
    //operations using value
}

static void outer(const double value)
{
    //few operations using value
    //...
    inner(value);
}


How about introducing a function 'outerFast', defined in it's own cpp, including the definitions of inner and outer, and compiling only that file with -O3?

It has its own disadvantages, though.

0

精彩评论

暂无评论...
验证码 换一张
取 消