NoodleCollie
NoodleCollie

Reputation: 1087

C/C++ compiler optimisations: should I prefer creating new variables, re-using existing ones, or avoiding variables altogether?

This is something I've always wondered: is it easier for the compiler to optimise functions where existing variables are re-used, where new (ideally const) intermediate variables are created, or where creating variables is avoided in favour of directly using expressions?

For example, consider the functions below:

// 1. Use expression as and when needed, no new variables
void MyFunction1(int a, int b)
{
    SubFunction1(a + b);
    SubFunction2(a + b);
    SubFunction3(a + b);
}

// 2. Re-use existing function parameter variable to compute
// result once, and use result multiple times.
// (I've seen this approach most in old-school C code)
void MyFunction2(int a, int b)
{
    a += b;
    
    SubFunction1(a);
    SubFunction2(a);
    SubFunction3(a);
}

// 3. Use a new variable to compute result once,
// and use result multiple times.
void MyFunction3(int a, int b)
{
    int sum = a + b;
    
    SubFunction1(sum);
    SubFunction2(sum);
    SubFunction3(sum);
}

// 4. Use a new const variable to compute result once,
// and use result multiple times.
void MyFunction4(int a, int b)
{
    const int sum = a + b;
    
    SubFunction1(sum);
    SubFunction2(sum);
    SubFunction3(sum);
}

My intuition is that:

Are my assumptions here correct? Are there more factors to take into account?

EDIT: A couple of clarifications in response to comments:

Upvotes: 1

Views: 171

Answers (1)

Eric Postpischil
Eric Postpischil

Reputation: 222908

Good modern compilers generally do not “care” about the names you use to store values. They perform lifetime analyses of the values and generate code based on that. For example, given:

int x = complicated expression 0;
... code using x
x = complicated expression 1;
... code using x

the compiler will see that complicated expression 0 is used in the first section of code and complicated expression 1 is used in the second section of code, and the name x is irrelevant. The result will be the same as if the code used different names:

int x0 = complicated expression 0;
... code using x0
int x1 = complicated expression 1;
... code using x1

So there is no point in reusing a variable for a different purpose; it will not help the compiler save memory or otherwise optimize.

Even if the code were in a loop, such as:

int x;
while (some condition)
{
    x = complicated expression;
    ... code using x
}

the compiler will see that complicated expression is born at the beginning of the loop body and ends by the end of the loop body.

What this means is you do not have to worry about what the compiler will do with the code. Instead, your decisions should be guided mostly by what is clearer to write and more likely to avoid bugs:

  • Avoid reusing a variable for more than one purpose. For example, if somebody is later updating your function to add a new feature, they might miss the fact you have changed the function parameter with a += b; and use a later in the code as if it still contained the original parameter.
  • Do freely create new variables to hold repeated expressions. int sum = a + b; is fine; it expresses the intent and makes it clearer to readers when the same expression is used in multiple places.
  • Limit the scope of variables (and identifiers generally). Declare them only in the innermost scope where they are needed, such as inside a loop rather than outside. The avoids a variable being used accidentally where it is no longer appropriate.

Upvotes: 5

Related Questions