|
@@ -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
|
|
val phase : Main.phase_func
|