lmirosevic
lmirosevic

Reputation: 16317

Is it worth precomputing the conditional in a for loop?

  1. Is there a difference between the following two code blocks in terms of the resulting machine code when using the llvm or gcc compilers?
  2. When is this optimization actually worthwhile, if ever?

Not optimized:

for (int i=0; i<array.count; i++) {
    //do some work
}

Optimized:

int count = array.count;
for (int i=0; i<count; i++) {
    //do some work
}

EDIT: I should point out that array is immutable and array.count doesn't change during the loop's execution.

Upvotes: 5

Views: 164

Answers (2)

dpc.pw
dpc.pw

Reputation: 3466

The Steve Jessop answer is a good one. I just want to add:

Personally, I always use optimized version. It's just in my set of good practices to remove every constant component out of the loop. It's not much work and it makes code cleaner. It's not "premature optimization" and it does not introduce any problems or tradeoffs. It makes debugging easier (stepping). And it could potentially make the code faster. So it's a no-brainer to me.

Upvotes: 1

Steve Jessop
Steve Jessop

Reputation: 279245

  1. You really need to check it yourself. My guess is that there is a difference in the emitted code, but it might depend on compiler and compiler options, and it certainly can depend on the definition of array.
  2. Nearly never, on the assumption that evaluating array.count is nearly always insignificant compared with "some work". The way to measure it, though, is to use a profiler (or equivalent) and observe what proportion of your program's runtime is spent at that line of code. Provided the profiler is accurate, that's the most you could hope to gain by changing it.

Suppose array.count is something really slow, that you happen to know will always return the same result but the compiler doesn't know that. Then it might be worth manually hoisting it. strlen gets used as an example. It's debateable how often strlen is actually slow in practice, but easy to manufacture examples likely to run slower than they need to:

char some_function(char a) {
    return (a * 2 + 1) & 0x3F;
}

for (int i = 0; i < strlen(ptr); ++i) {
    ptr[i] = some_function(ptr[i]); // faster than strlen for long enough strings.
}

You and I know that some_function never returns 0, and hence the length of the string never changes. The compiler might not see the definition of some_function, and even if it does see the definition might not realize that its non-zero-returningness is important.

Upvotes: 3

Related Questions