constprop.mli 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. (** Rudimentary constant propagation and constant folding on generated
  2. variables. *)
  3. (** The compiler sometimes generates variables of the form [__foo_1__], to make
  4. sure that expressions are only executed once. In many cases, this leads to
  5. over-complex constructions with more variable definitions den necessary, for
  6. example when converting for-loops to while-loops. We use the knowledge of
  7. these variables being only assigned once, by propagating the constant values
  8. to their occurrences, and then apply arithmetic simplification to operators
  9. to reduce the size and complexity of the generated code. Note that this can
  10. only be applied to constants. For variables in general, some form of
  11. liveness analysis would be required (e.g. first convert to Static Single
  12. Assignment form). Expressions can only be propagated when they have no side
  13. effects, i.e. when they do not contain function calls. The current
  14. implementation only propagates [Bool|Int|Float] constants and simple
  15. variable uses ([VarUse]).
  16. Constant propagation is merged with some some arithmetic simplification here,
  17. specifically targeting optimization oppertunities created bij earlier
  18. constant propagation. This is utilized, for example, in array index
  19. calculation when array dimensions are constant.
  20. The following example demonstrates the effectivity of this phase. An array
  21. assignment is transformed into a for-loop, which is transformed into a
  22. while-loop. Note that the condition of the while-loop body is also
  23. simplified.
  24. {v void foo() \{
  25. int[2, 2] arr = [[1, 2], 3];
  26. \} v}
  27. After desugaring and array dimension reduction this becomes:
  28. {v void foo() \{
  29. int ____i_6_7;
  30. int __arr_1_2__;
  31. int __arr_2_1__;
  32. int __const_3__;
  33. int __const_4__;
  34. int __const_5__;
  35. int[] arr;
  36. int __stop_8__;
  37. int __step_9__;
  38. __arr_1_2__ = 2;
  39. __arr_2_1__ = 2;
  40. __const_3__ = 1;
  41. __const_4__ = 2;
  42. __const_5__ = 3;
  43. arr := <allocate>((__arr_1_2__ * __arr_2_1__));
  44. arr[((0 * __arr_2_1__) + 0)] = __const_3__;
  45. arr[((0 * __arr_2_1__) + 1)] = __const_4__;
  46. ____i_6_7 = 0;
  47. __stop_8__ = __arr_2_1__;
  48. __step_9__ = 1;
  49. while (((__step_9__ > 0) ? (____i_6_7 < __stop_8__) : (____i_6_7 > __stop_8__))) \{
  50. arr[((1 * __arr_2_1__) + ____i_6_7)] = __const_5__;
  51. ____i_6_7 = (____i_6_7 + __step_9__);
  52. \}
  53. \} v}
  54. Constant propagation reduces this to:
  55. {v void foo() \{
  56. int ____i_6_7;
  57. int[] arr;
  58. arr := <allocate>(4);
  59. arr[0] = 1;
  60. arr[1] = 2;
  61. ____i_6_7 = 0;
  62. while ((____i_6_7 < 2)) \{
  63. arr[(2 + ____i_6_7)] = 3;
  64. ____i_6_7 = (____i_6_7 + 1);
  65. \}
  66. \} v}
  67. *)
  68. (** Constant propagation traversal. Exported for use in {!Unroll}. *)
  69. val propagate_consts : Types.node -> Types.node
  70. (** Main phase function, called by {!Main}. Calls {!propagate_consts}. *)
  71. val phase : Main.phase_func