(** Unroll for-loops with constant boundaries. *) (** When initializing arrays with scalar values, the desugaring phase creates for-loops, that are later transformed into while-loops. This has an effect on the stack size, which grows because of the increase in variables. The readability of generated code is also affected, since while-loops are very verbose. Constant propagation helps somewhat, but the loops still exist. This loop unrolling phase recognizes while-loops that are generated from for-loops. If the upper bound, lower bound, and step variable of the loop are constant integers, the loop is replaced with occurrences of its body for each iteration value. Afterwards, the constant propagation traversal is executed again to utilise new possibilities for constant folding, which are generated by replacing the loop counter variable with a constant value. An example follows: {v void foo() \{ int[2, 3] arr = 1; \} v} After desugaring and constant propagation, this has been transformed into: {v void foo() \{ int _i_6; int _i_9; int[] arr; arr = __allocate(6); _i_6 = 0; while ((_i_6 < 2)) \{ _i_9 = 0; while ((_i_9 < 3)) \{ arr[((_i_6 * 3) + _i_9)] = 1; _i_9 = (_i_9 + 1); \} _i_6 = (_i_6 + 1); \} \} v} Now, the loops are unrolled (first the inner loop, then the outer loop) and constant folding is applied to [arr[((_i_6 * 3) + _i_9)]] in each iteration: {v void foo() \{ int[] arr; arr = __allocate(6); arr[0] = 1; arr[1] = 1; arr[2] = 1; arr[3] = 1; arr[4] = 1; arr[5] = 1; \} v} A simple heuristic is applied to decide whether a recognised for-loop will be unrolled: the resulting number of statements must not be larger than 25. Note that since programmer-defined for-loops are also transformed into while-loops, these are recognized by the compiler as well (as long as the loop has constant boundaries). For example: {v extern void printInt(int val); export int main() \{ for (int i = 0, 10, 2) \{ printInt(i); \} return 0; \} v} which is transformed into: {v extern void printInt(int val); export int main() \{ printInt(0); printInt(2); printInt(4); printInt(6); printInt(8); return 0; \} v} *) (** Main phase function, called by {!Main}. *) val phase : Main.phase_func