unroll.mli 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. (** Unroll for-loops with constant boundaries. *)
  2. (** When initializing arrays with scalar values, the desugaring phase creates
  3. for-loops, that are later transformed into while-loops. This has an effect
  4. on the stack size, which grows because of the increase in variables. The
  5. readability of generated code is also affected, since while-loops are very
  6. verbose. Constant propagation helps somewhat, but the loops still exist.
  7. This loop unrolling phase recognizes while-loops that are generated from
  8. for-loops. If the upper bound, lower bound, and step variable of the loop
  9. are constant integers, the loop is replaced with occurrences of its body for
  10. each iteration value. Afterwards, the constant propagation traversal is
  11. executed again to utilise new possibilities for constant folding, which are
  12. generated by replacing the loop counter variable with a constant value. An
  13. example follows:
  14. {v void foo() \{
  15. int[2, 3] arr = 1;
  16. \} v}
  17. After desugaring and constant propagation, this has been transformed into:
  18. {v void foo() \{
  19. int _i_6;
  20. int _i_9;
  21. int[] arr;
  22. arr := <allocate>(6);
  23. _i_6 = 0;
  24. while ((_i_6 < 2)) \{
  25. _i_9 = 0;
  26. while ((_i_9 < 3)) \{
  27. arr[((_i_6 * 3) + _i_9)] = 1;
  28. _i_9 = (_i_9 + 1);
  29. \}
  30. _i_6 = (_i_6 + 1);
  31. \}
  32. \} v}
  33. Now, the loops are unrolled (first the inner loop, then the outer loop) and
  34. constant folding is applied to [arr[((_i_6 * 3) + _i_9)]] in each
  35. iteration:
  36. {v void foo() \{
  37. int[] arr;
  38. arr := <allocate>(6);
  39. arr[0] = 1;
  40. arr[1] = 1;
  41. arr[2] = 1;
  42. arr[3] = 1;
  43. arr[4] = 1;
  44. arr[5] = 1;
  45. \} v}
  46. A simple heuristic is applied to decide whether a recognised for-loop will
  47. be unrolled: the resulting number of statements must not be larger than 25.
  48. Note that since programmer-defined for-loops are also transformed into
  49. while-loops, these are recognized by the compiler as well (as long as the
  50. loop has constant boundaries). For example:
  51. {v extern void printInt(int val);
  52. export int main() \{
  53. for (int i = 0, 10, 2) \{
  54. printInt(i);
  55. \}
  56. return 0;
  57. \} v}
  58. which is transformed into:
  59. {v extern void printInt(int val);
  60. export int main() \{
  61. printInt(0);
  62. printInt(2);
  63. printInt(4);
  64. printInt(6);
  65. printInt(8);
  66. return 0;
  67. \} v}
  68. *)
  69. (** Main phase function, called by {!Main}. *)
  70. val phase : Main.phase_func