Learning is a mess
Learning is a mess

Reputation: 8277

Evaluation of constants in for loop condition

for(int i = 0; i < my_function(MY_CONSTANT); ++i){
    //code using i
}

In this example, will my_function(MY_CONSTANT) be evaluated at each iteration, or will it be stored automatically? Would this depend on the optimization flags used?

Upvotes: 2

Views: 1177

Answers (4)

Shafik Yaghmour
Shafik Yaghmour

Reputation: 158469

A modern optimizing compiler under the as-if rule may be able to optimize away the function call in the case that you outlined in your comment here. The as-if rule says that conforming compiler only has the emulate the observable behavior, we can see this by going to the draft C++ standard section 1.9 Program execution which says:

[...]Rather, conforming implementations are required to emulate (only) the observable behavior of the abstract machine as explained below.5

So if you are using a constant expression and my_function does not have observable side effects it could be optimized out. We can put together a simple test (see it live on godbolt):

#include <stdio.h>

#define blah 10

int func( int x )
{
  return x + 20 ;
}

void withConstant( int y )
{
  for(int i = 0; i < func(blah); i++)
  {
    printf("%d ", i ) ;
  }
}

void withoutConstant(int y)
{
  for(int i = 0; i < func(i+y); i++)
  {
    printf("%d ", i ) ;
  }
}

In the case of withConstant we can see it optimizes the computation:

cmpl    $30, %ebx   #, i

and even in the case of withoutConstant it inlines the calculation instead of performing a function call:

leal    0(%rbp,%rbx), %eax  #, D.2605

Upvotes: 2

Surt
Surt

Reputation: 16099

If my_function is declared constexpr and the argument is really a constant, the value is calculated at compile time and thereby fulfilling the "as-if" and "sequential-consistency with no data-race" rule.

constexpr my_function(const int c);

If your function has side effects it would prevent the compiler from moving it out of the for-loop as it would not fulfil the "as-if" rule, unless the compiler can reason its way out of it.

The compiler might inline my_function, reduce on it as if it was part of the loop and with constant reduction find out that its really only a constant, de-facto removing the call and replacing it with a constant.

int my_function(const int c) {
    return 17+c; // inline and constant reduced to the value.
}

So the answer to your question is ... maybe!

Upvotes: 1

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145279

It has to work as if the function is called each time.

However, if the compiler can prove that the function result will be the same each time, it can optimize under the “as if” rule.

E.g. this usually happens with calls to .end() for standard containers.


General advice: when in doubt about whether to micro-optimize a piece of code,

  1. Don't do it.
  2. If you're still thinking of doing it, measure.
  3. Well there was a third point but I've forgetting, maybe it was, still wait.

In other words, decide whether to use a variable based on how clear the code then is, not on imagined performance.

Upvotes: 10

Cory Kramer
Cory Kramer

Reputation: 117876

It will be evaluated each iteration. You can save the extra computation time by doing something like

const int stop = my_function(MY_CONSTANT);
for(int i = 0; i < stop; ++i){
    //code using i
}

Upvotes: 3

Related Questions