Loop-invariant code motion: Difference between revisions

Content deleted Content added
Example: abstract interpretation would be needed to detect n>0, compilers usually don't do that; guarding by "n>0" leads to equivalent code without extra assumption; suggest to use non-K&R-code to make t1 as fresh local variable
Replaced 'for' with 'while' for easier splitting of condition and initialization. rewrote the optimized code using do {} while loop to account for possible side effects in evaluating the loop condition. See https://cs.stackexchange.com/a/108620/104558 for details and discussion
Line 7:
 
<source lang="C">
for (int i = 0; i < n; ++i) {
while (i < n) {
x = y + z;
a[i] = 6 * i + x * x;
++i;
}
</source>
 
Although the calculation <code>x = y + z</code> and <code>x * x</code> is loop-invariant, precautions must be taken before moving the code outside the loop. It is possible that the loop condition is <code>false</code> (for example, if <code>n</code> 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. It should also be noted that evaluating the loop condition can have [[Side_effect_(computer_science)|side effects]], so an additional evaluation by the <code>if</code> construct should be compensated by replacing the <code>while</code> loop with a <code>do {} while</code>. If the code used <code>do {} while</code> in the first place, the whole guarding process is not needed, as the loop body is guaranteed to execute at least once.
For n > 0, the calculation <code>x = y + z</code> and <code>x * x</code> can be moved outside the loop since within they are [[loop-invariant code]], while for n <= 0 the loop has no effect at all. Therefore the optimized code will be something like this:
 
<source lang="C">
ifint (ni >= 0) {;
if (i < n) {
x = y + z;
int const t1 = x * x;
do {
for (int i = 0; i < n; ++i) {
a[i] = 6 * i + t1;
} ++i;
} while (i < n);
}
</source>