Loop-invariant code motion

In computer programming, 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.
Example.
In the following code sample, two optimizations can be applied.
int i = 0;
while (i < n) {
 x = y + z;
 a[i] = 6 * i + x * x;
 ++i;
Although the calculation codice_1 and codice_2 is loop-invariant, precautions must be taken before moving the code outside the loop. It is possible that the loop condition is codice_3 (for example, if codice_4 holds a negative value), and in such case, the loop body should not be executed at all. One way of guaranteeing correct behaviour is using a conditional branch outside of the loop. Evaluating the loop condition can have side effects, so an additional evaluation by the codice_5 construct should be compensated by replacing the codice_6 loop with a codice_7. If the code used codice_7 in the first place, the whole guarding process is not needed, as the loop body is guaranteed to execute at least once.
int i = 0;
if (i < n) {
 x = y + z;
 int const t1 = x * x;
 do {
 a[i] = 6 * i + t1;
 ++i;
 } while (i < n);
This code can be optimized further. For example, strength reduction could remove the two multiplications inside the loop (codice_9 and codice_10), and induction variable elimination could then elide codice_11 completely. Since codice_12 must be in lock step with codice_11 itself, there is no need to have both.
Invariant code detection.
Usually, a reaching definitions analysis is used to detect whether a statement or expression is loop invariant.
For example, if all reaching definitions for the operands of some simple expression are outside of the loop, the expression can be moved out of the loop.
Recent work using data-flow dependence analysis allows to detect not only invariant commands but larger code fragments such as an inner loop. The analysis also detects quasi-invariants of arbitrary degrees, that is commands or code fragments that become invariant after a fixed number of iterations of the loop body.
Benefits.
Loop-invariant code which has been hoisted out of a loop is executed less often, providing a speedup. Another effect of this transformation is allowing constants to be stored in registers and not having to calculate the address and access the memory (or cache line) at each iteration.
However, if too many variables are created, there will be high register pressure, especially on processors with few registers, like the 32-bit x86. If the compiler runs out of registers, some variables will be spilled. To counteract this, the inverse optimization can be performed, rematerialization.