In this case also, I make use of the solution to the reaching definitions problem using the generic data flow solver. First I detect whether an instruction is invariant for a given loop, and then for each invariant instruction I check if it is safe to be moved outside the loop. Loops might be nested in other loops. In such cases, I start by processing the innermost loop first and work outwards from it. In each case, the movable code is added to the loop pre-header, which gets executed only once per loop.