Selaa lähdekoodia

Documented constant propagation phase

Taddeus Kroes 12 vuotta sitten
vanhempi
sitoutus
8fb15b70f4
2 muutettua tiedostoa jossa 78 lisäystä ja 1 poistoa
  1. 1 1
      phases/constprop.ml
  2. 77 0
      phases/constprop.mli

+ 1 - 1
phases/constprop.ml

@@ -1,5 +1,5 @@
 (**
- * The compiler sometimes generates variables of the form foo$1, to make sure
+ * The compiler sometimes generates variables of the form foo$$1, to make sure
  * that expressions are only executed once. In many cases, this leads to
  * over-complex constructions, for example when converting for-loops to
  * while-loops. We use the knowledge of these variables being constant by

+ 77 - 0
phases/constprop.mli

@@ -1 +1,78 @@
+(** Rudimentary constant propagation and constant folding on generated
+    variables. *)
+
+(** The compiler sometimes generates variables of the form [foo$$1], to make
+    sure that expressions are only executed once. In many cases, this leads to
+    over-complex constructions with more variable definitions den necessary, for
+    example when converting for-loops to while-loops. We use the knowledge of
+    these variables being only assigned once, by propagating the constant values
+    to their occurrences, and then apply arithmetic simplification to operators
+    to reduce the size and complexity of the generated code. Note that this can
+    only be applied to constants. For variables in general, some form of
+    liveness analysis would be required (e.g. first convert to Static Single
+    Assignment form). Expressions can only be propagated when they have no side
+    effects, i.e. when they do not contain function calls. The current
+    implementation only propagates [Bool|Int|Float] constants and simple
+    variable uses ([VarUse]).
+
+    Constant propagation is merged with some some arithmetic simplification here,
+    specifically targeting optimization oppertunities created bij earlier
+    constant propagation. This is utilized, for example, in array index
+    calculation when array dimensions are constant.
+
+    The following example demonstrates the effectivity of this phase. An array
+    assignment is transformed into a for-loop, which is transformed into a
+    while-loop. Note that the condition of the while-loop body is also
+    simplified.
+
+{v void foo() \{
+    int[2, 2] arr = [[1, 2], 3];
+\} v}
+
+After desugaring and array dimension reduction this becomes:
+
+{v void foo() \{
+    int i$4$5;
+    int stop$$6;
+    int step$$7;
+    int arr$dim$$1;
+    int arr$dim$$2;
+    int const$$1;
+    int const$$2;
+    int const$$3;
+    int[] arr;
+    arr$dim$$1 = 2;
+    arr$dim$$2 = 2;
+    const$$1 = 1;
+    const$$2 = 2;
+    const$$3 = 3;
+    arr = __allocate((arr$dim$$1 * arr$dim$$2));
+    arr[((0 * arr$dim$$2) + 0)] = const$$1;
+    arr[((0 * arr$dim$$2) + 1)] = const$$2;
+    i$4$5 = 0;
+    stop$$6 = arr$dim$$2;
+    step$$7 = 1;
+    while (((step$$7 > 0) ? (i$4$5 < stop$$6) : (i$4$5 > stop$$6))) \{
+        arr[((1 * arr$dim$$2) + i$4$5)] = const$$3;
+        i$4$5 = (i$4$5 + step$$7);
+    \}
+\} v}
+
+Constant propagation reduces this to:
+
+{v void foo() \{
+    int i$4$5;
+    int[] arr;
+    arr = __allocate(4);
+    arr[0] = 1;
+    arr[1] = 2;
+    i$4$5 = 0;
+    while ((i$4$5 < 2)) \{
+        arr[(2 + i$4$5)] = 3;
+        i$4$5 = (i$4$5 + 1);
+    \}
+\} v}
+    *)
+
+(** Main phase function, called by {!Main}. *)
 val phase : Main.phase_func