constprop.mli 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  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$4$5;
  30. int stop$$6;
  31. int step$$7;
  32. int arr$dim$$1;
  33. int arr$dim$$2;
  34. int const$$1;
  35. int const$$2;
  36. int const$$3;
  37. int[] arr;
  38. arr$dim$$1 = 2;
  39. arr$dim$$2 = 2;
  40. const$$1 = 1;
  41. const$$2 = 2;
  42. const$$3 = 3;
  43. arr = __allocate((arr$dim$$1 * arr$dim$$2));
  44. arr[((0 * arr$dim$$2) + 0)] = const$$1;
  45. arr[((0 * arr$dim$$2) + 1)] = const$$2;
  46. i$4$5 = 0;
  47. stop$$6 = arr$dim$$2;
  48. step$$7 = 1;
  49. while (((step$$7 > 0) ? (i$4$5 < stop$$6) : (i$4$5 > stop$$6))) \{
  50. arr[((1 * arr$dim$$2) + i$4$5)] = const$$3;
  51. i$4$5 = (i$4$5 + step$$7);
  52. \}
  53. \} v}
  54. Constant propagation reduces this to:
  55. {v void foo() \{
  56. int i$4$5;
  57. int[] arr;
  58. arr = __allocate(4);
  59. arr[0] = 1;
  60. arr[1] = 2;
  61. i$4$5 = 0;
  62. while ((i$4$5 < 2)) \{
  63. arr[(2 + i$4$5)] = 3;
  64. i$4$5 = (i$4$5 + 1);
  65. \}
  66. \} v}
  67. *)
  68. (** Main phase function, called by {!Main}. *)
  69. val phase : Main.phase_func