33

I am sure there is a term for the following bit of refactoring, but I can't remember it and my Google-fu is failing me!

The refactor moves if statements to where they are going to have most impact, for example changing this

$test = someFunctionThatReturnsABool();
for($x = 0; $x < 10000; $x++) {
    if ($test) { 
        echo $x; 
    }
}

To this

$test = someFunctionThatReturnsABool();
if ($test) {
    for($x = 0; $x < 10000; $x++) {
        echo $x; 
    }
}

4 Answers 4

56

This is loop-invariant code motion. A good compiler should do it on its own.

...loop-invariant code consists of statements or expressions (in an imperative programming language) which can be moved outside the body of a loop without affecting the semantics of the program. Loop-invariant code motion (also called hoisting or scalar promotion) is a compiler optimization which performs this movement automatically...

If we consider the following code sample, two optimizations can be easily applied.

for (int i = 0; i < n; i++) {
    x = y + z;
    a[i] = 6 * i + x * x;
}

The calculation x = y + z and x * x can be moved outside the loop since within they are loop invariant — they do not change over the iterations of the loop— so the optimized code will be something like this:

x = y + z;
t1 = x * x;
for (int i = 0; i < n; i++) {
    a[i] = 6 * i + t1;
}

This code can be optimized further...

12
  • 55
    a good programmer should do it on it's own as well, I guess
    – stijn
    Commented Jul 26, 2012 at 10:37
  • 8
    I agree @stijn - there are some things that it is reasonable to let the compiler worry about, but this isn't one of them!
    – Toby
    Commented Jul 26, 2012 at 10:48
  • @Toby: While this is true for new code (after all, the loop-invariant move makes for an easier-understood inner loop), anything that is already done by the compiler doesn't need to be done by hand. I'd just let old code such as the above example stand; the quality improvement of LICM is small and probably not worth your time.
    – thiton
    Commented Jul 26, 2012 at 12:33
  • 12
    @thiton I disagree. Leaving it as-is will mean all future maintainers would have to go through the same reasoning. It wastes time; just change it.
    – Izkata
    Commented Jul 26, 2012 at 12:55
  • 2
    @zzzzBov yes I know, but my point is that when the pattern is hidden, it probably isn't exactly the pattern anymore. Or something like that. (sorry, long day)
    – stijn
    Commented Jul 26, 2012 at 15:13
10

This is also called hoisting or scalar promotion. See here:

Hoisting means that you have pulled some operation out of a loop because the loop itself does not affect the result of the operation. In your case, you are hoisting the conditional test out of the while loop.

Re-ordering means changing the sequence of instructions in a way that does not affect the result. Typically this would be adjacent instructions with no data dependencies, e.g. it does not matter which order you perform the following two statements:

int a = x;
int b = y;
0
4

Looks like a variant of Remove Control Flag (pp 245 of Fowler's Refactoring)

A PHP example can be found on DZone.

0

I don't think such a refactoring exists.

So, it would be hard to find it amongst ''lists of refactorings''.

I'd class that example as an optimisation not a refactoring.

Refactoring, to me, is changing the code to improve its understandability without affecting its behaviour.

Optimisation, to me, is changing the code to improve performance.

Since optimised code tends to be less easy to understand. The two practices tend to work against each other.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.