constprop.mli 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. (** Rudimentary constant propagation, constant folding and arithmetic
  2. simplification on generated variables. *)
  3. (** The compiler sometimes generates variables of the form [_foo_1_],
  4. indicating that the variable is assigned exactly once (it is in SSA form).
  5. In many cases, generated variables leads to over-complex constructions with
  6. more variable definitions then necessary, for example when converting
  7. for-loops to while-loops. We use the knowledge of these variables being in
  8. SSA form, by propagating the constant values to their uses, and then apply
  9. arithmetic simplification to operators to reduce the size and complexity of
  10. the generated code. Note that this can only be applied when the assigned
  11. expression is a constant or an SSA variable, since these have no side
  12. effects and will not change in between the assignment and their uses. For
  13. optimisation regular of variables, some form of liveness analysis would be
  14. required.
  15. Constant propagation is supplemented with constand folding and some
  16. arithmetic simplification, the latter specifically targeting optimisation
  17. oppertunities created by earlier constant propagation. For example, in and
  18. array index calculation when constant array dimensions are propagated, the
  19. index calculation can often be simplified.
  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 = 3;
  26. \} v}
  27. After desugaring and array dimension reduction this becomes:
  28. {v void foo() \{
  29. int _i_4;
  30. int _stop_5_;
  31. int _step_6_;
  32. int _i_7;
  33. int _stop_8_;
  34. int _step_9_;
  35. int _arr_0_;
  36. int _arr_1_;
  37. int _scalar_1_;
  38. int[] arr;
  39. _arr_0_ = 2;
  40. _arr_1_ = 2;
  41. _scalar_1_ = 3;
  42. arr := <allocate>((_arr_0_ * _arr_1_));
  43. _i_4 = 0;
  44. _stop_5_ = _arr_0_;
  45. _step_6_ = 1;
  46. while (((_step_6_ > 0) ? (_i_4 < _stop_5_) : (_i_4 > _stop_5_))) \{
  47. _i_7 = 0;
  48. _stop_8_ = _arr_1_;
  49. _step_9_ = 1;
  50. while (((_step_9_ > 0) ? (_i_7 < _stop_8_) : (_i_7 > _stop_8_))) \{
  51. arr[((_i_4 * _arr_1_) + _i_7)] = _scalar_1_;
  52. _i_7 = (_i_7 + _step_9_);
  53. \}
  54. _i_4 = (_i_4 + _step_6_);
  55. \}
  56. \} v}
  57. Constant propagation reduces this to:
  58. {v void foo() \{
  59. int _i_4;
  60. int _i_7;
  61. int[] arr;
  62. arr := <allocate>(4);
  63. _i_4 = 0;
  64. while ((_i_4 < 2)) \{
  65. _i_7 = 0;
  66. while ((_i_7 < 2)) \{
  67. arr[((_i_4 * 2) + _i_7)] = 3;
  68. _i_7 = (_i_7 + 1);
  69. \}
  70. _i_4 = (_i_4 + 1);
  71. \}
  72. \} v}
  73. *)
  74. (** Constant propagation traversal. Exported for use in {!Unroll}. *)
  75. val propagate_consts : Types.node -> Types.node
  76. (** Main phase function, called by {!Main}. Calls {!propagate_consts}. *)
  77. val phase : Main.phase_func