blob: 32299d5a7570e351b27ac2154d0e5ebf76fe1733 [file] [log] [blame]
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import '../mock_compiler.dart';
import 'sexpr_unstringifier.dart';
import 'package:async_helper/async_helper.dart';
import "package:expect/expect.dart";
import 'package:compiler/implementation/cps_ir/cps_ir_nodes_sexpr.dart';
import 'package:compiler/implementation/cps_ir/optimizers.dart';
import 'package:compiler/implementation/dart2jslib.dart' as dart2js;
// The tests in this file that ensure that sparse constant propagation on the
// CPS IR works as expected.
// CP1 represents the following incoming dart code:
//
// int main() {
// int i = 1;
// int j;
// if (i == 1) {
// j = 2;
// } else {
// j = 3;
// }
// return j;
// }
String CP1_IN = """
(FunctionDefinition main (return) (LetPrim v0 (Constant 1))
(LetPrim v1 (Constant 1))
(LetCont (k0 v2)
(LetCont (k1) (LetPrim v3 (Constant 2))
(InvokeContinuation return v3))
(LetCont (k2) (LetPrim v4 (Constant 3))
(InvokeContinuation return v4))
(Branch (IsTrue v2) k1 k2))
(InvokeMethod v0 == v1 k0))
""";
String CP1_OUT = """
(FunctionDefinition main ( return)
(LetPrim v0 (Constant 1))
(LetPrim v1 (Constant 1))
(LetCont (k0 v2)
(LetCont (k1)
(LetPrim v3 (Constant 2))
(InvokeContinuation return v3))
(LetCont (k2)
(LetPrim v4 (Constant 3))
(InvokeContinuation return v4))
(InvokeContinuation k1 ))
(LetPrim v5 (Constant true))
(InvokeContinuation k0 v5))
""";
// CP2 represents the following incoming dart code:
//
// int main() {
// int i = 1;
// while (true) {
// if (false || false) {
// return i;
// }
// if (true && i == 1) {
// return i;
// }
// }
// return 42;
// }
String CP2_IN = """
(FunctionDefinition main (return) (LetPrim v0 (Constant 1))
(LetCont* (k0)
(LetCont (k1) (LetPrim v1 (Constant 42))
(InvokeContinuation return v1))
(LetCont (k2) (LetPrim v2 (Constant false))
(LetCont (k3 v3)
(LetCont (k4) (InvokeContinuation return v0))
(LetCont (k5) (LetPrim v4 (Constant true))
(LetCont (k6 v5)
(LetCont (k7) (InvokeContinuation return v0))
(LetCont (k8) (InvokeContinuation* k0))
(Branch (IsTrue v5) k7 k8))
(LetCont (k9) (LetPrim v6 (Constant 1))
(LetCont (k10 v7)
(LetCont (k11) (LetPrim v8 (Constant true))
(InvokeContinuation k6 v8))
(LetCont (k12) (LetPrim v9 (Constant false))
(InvokeContinuation k6 v9))
(Branch (IsTrue v7) k11 k12))
(InvokeMethod v0 == v6 k10))
(LetCont (k13) (LetPrim v10 (Constant false))
(InvokeContinuation k6 v10))
(Branch (IsTrue v4) k9 k13))
(Branch (IsTrue v3) k4 k5))
(LetCont (k14) (LetPrim v11 (Constant true))
(InvokeContinuation k3 v11))
(LetCont (k15) (LetPrim v12 (Constant false))
(LetCont (k16) (LetPrim v13 (Constant true))
(InvokeContinuation k3 v13))
(LetCont (k17) (LetPrim v14 (Constant false))
(InvokeContinuation k3 v14))
(Branch (IsTrue v12) k16 k17))
(Branch (IsTrue v2) k14 k15))
(LetPrim v15 (Constant true))
(Branch (IsTrue v15) k2 k1))
(InvokeContinuation k0))
""";
String CP2_OUT = """
(FunctionDefinition main ( return)
(LetPrim v0 (Constant 1))
(LetCont* (k0)
(LetCont (k1) (LetPrim v1 (Constant 42))
(InvokeContinuation return v1))
(LetCont (k2)
(LetPrim v2 (Constant false))
(LetCont (k3 v3)
(LetCont (k4) (InvokeContinuation return v0))
(LetCont (k5)
(LetPrim v4 (Constant true))
(LetCont (k6 v5)
(LetCont (k7) (InvokeContinuation return v0))
(LetCont (k8) (InvokeContinuation* k0 ))
(InvokeContinuation k7 ))
(LetCont (k9)
(LetPrim v6 (Constant 1))
(LetCont (k10 v7)
(LetCont (k11)
(LetPrim v8 (Constant true))
(InvokeContinuation k6 v8))
(LetCont (k12) (LetPrim v9 (Constant false))
(InvokeContinuation k6 v9))
(InvokeContinuation k11 ))
(LetPrim v10 (Constant true))
(InvokeContinuation k10 v10))
(LetCont (k13) (LetPrim v11 (Constant false))
(InvokeContinuation k6 v11))
(InvokeContinuation k9 ))
(InvokeContinuation k5 ))
(LetCont (k14) (LetPrim v12 (Constant true))
(InvokeContinuation k3 v12))
(LetCont (k15)
(LetPrim v13 (Constant false))
(LetCont (k16) (LetPrim v14 (Constant true))
(InvokeContinuation k3 v14))
(LetCont (k17)
(LetPrim v15 (Constant false))
(InvokeContinuation k3 v15))
(InvokeContinuation k17 ))
(InvokeContinuation k15 ))
(LetPrim v16 (Constant true))
(InvokeContinuation k2 ))
(InvokeContinuation k0 ))
""";
// CP3 represents the following incoming dart code:
//
// int main() {
// int i = 1;
// i = f();
// if (i == 1) {
// return 42;
// }
// return i;
// }
String CP3_IN = """
(FunctionDefinition main ( return) (LetPrim v0 (Constant 1))
(LetCont (k0 v1) (LetPrim v2 (Constant 1))
(LetCont (k1 v3)
(LetCont (k2) (LetPrim v4 (Constant 42))
(InvokeContinuation return v4))
(LetCont (k3) (InvokeContinuation return v1))
(Branch (IsTrue v3) k2 k3))
(InvokeMethod v1 == v2 k1))
(InvokeStatic f k0))
""";
String CP3_OUT = CP3_IN;
// Addition.
String CP4_IN = """
(FunctionDefinition main ( return)
(LetPrim v0 (Constant 1))
(LetPrim v1 (Constant 2))
(LetCont (k0 v2)
(InvokeContinuation return v2))
(InvokeMethod v0 + v1 k0))
""";
String CP4_OUT = """
(FunctionDefinition main ( return)
(LetPrim v0 (Constant 1))
(LetPrim v1 (Constant 2))
(LetCont (k0 v2)
(InvokeContinuation return v2))
(LetPrim v3 (Constant 3))
(InvokeContinuation k0 v3))
""";
// Array access operator (no optimization).
String CP5_IN = """
(FunctionDefinition main ( return)
(LetPrim v0 (Constant 1))
(LetPrim v1 (Constant 2))
(LetCont (k0 v2)
(InvokeContinuation return v2))
(InvokeMethod v0 [] v1 k0))
""";
String CP5_OUT = CP5_IN;
// Division by 0.
String CP6_IN = """
(FunctionDefinition main ( return)
(LetPrim v0 (Constant 1))
(LetPrim v1 (Constant 0))
(LetCont (k0 v2)
(InvokeContinuation return v2))
(InvokeMethod v0 / v1 k0))
""";
String CP6_OUT = """
(FunctionDefinition main ( return)
(LetPrim v0 (Constant 1))
(LetPrim v1 (Constant 0))
(LetCont (k0 v2)
(InvokeContinuation return v2))
(LetPrim v3 (Constant Infinity))
(InvokeContinuation k0 v3))
""";
// Concatenate strings.
String CP7_IN = """
(FunctionDefinition main ( return)
(LetPrim v0 (Constant StringConstant("b")))
(LetPrim v1 (Constant StringConstant("d")))
(LetPrim v2 (Constant StringConstant("a")))
(LetPrim v3 (Constant StringConstant("c")))
(LetPrim v4 (Constant StringConstant("")))
(LetCont (k0 v5)
(LetCont (k1 v6)
(InvokeContinuation return v6))
(InvokeMethod v5 length k1))
(ConcatenateStrings v2 v0 v3 v1 v4 k0))
""";
String CP7_OUT = """
(FunctionDefinition main ( return)
(LetPrim v0 (Constant StringConstant("b")))
(LetPrim v1 (Constant StringConstant("d")))
(LetPrim v2 (Constant StringConstant("a")))
(LetPrim v3 (Constant StringConstant("c")))
(LetPrim v4 (Constant StringConstant("")))
(LetCont (k0 v5)
(LetCont (k1 v6)
(InvokeContinuation return v6))
(InvokeMethod v5 length k1))
(LetPrim v7 (Constant StringConstant("abcd")))
(InvokeContinuation k0 v7))
""";
// TODO(jgruber): We can't test is-check optimization because the unstringifier
// does not recreate accurate types for the TypeOperator node.
// Simple branch removal.
String CP8_IN = """
(FunctionDefinition main ( return)
(LetPrim v0 (Constant 1))
(LetPrim v1 (Constant 1))
(LetCont (k0 v2)
(LetCont (k1)
(LetPrim v3 (Constant 42))
(InvokeContinuation return v3))
(LetCont (k2)
(InvokeContinuation return v0))
(Branch (IsTrue v2) k1 k2))
(InvokeMethod v0 == v1 k0))
""";
String CP8_OUT = """
(FunctionDefinition main ( return)
(LetPrim v0 (Constant 1))
(LetPrim v1 (Constant 1))
(LetCont (k0 v2)
(LetCont (k1) (LetPrim v3 (Constant 42))
(InvokeContinuation return v3))
(LetCont (k2) (InvokeContinuation return v0))
(InvokeContinuation k1 ))
(LetPrim v4 (Constant true))
(InvokeContinuation k0 v4))
""";
// While loop.
String CP9_IN = """
(FunctionDefinition main ( return)
(LetPrim v0 (Constant 1))
(LetCont* (k0 v1)
(LetCont (k1)
(InvokeContinuation return v1))
(LetCont (k2)
(LetPrim v2 (Constant 1))
(LetCont (k3 v3)
(LetCont (k4 v4)
(LetCont (k5)
(LetPrim v5 (Constant 42))
(InvokeContinuation return v5))
(LetCont (k6)
(LetPrim v6 (Constant 1))
(LetCont (k7 v7)
(InvokeContinuation* k0 v7))
(InvokeMethod v1 + v6 k7))
(Branch (IsTrue v4) k5 k6))
(LetCont (k8)
(LetPrim v8 (Constant false))
(InvokeContinuation k4 v8))
(LetCont (k9)
(LetPrim v9 (Constant true))
(InvokeContinuation k4 v9))
(Branch (IsTrue v3) k8 k9))
(InvokeMethod v1 == v2 k3))
(LetPrim v10 (Constant true))
(Branch (IsTrue v10) k2 k1))
(InvokeContinuation k0 v0))
""";
String CP9_OUT = """
(FunctionDefinition main ( return)
(LetPrim v0 (Constant 1))
(LetCont* (k0 v1)
(LetCont (k1)
(InvokeContinuation return v1))
(LetCont (k2)
(LetPrim v2 (Constant 1))
(LetCont (k3 v3)
(LetCont (k4 v4)
(LetCont (k5)
(LetPrim v5 (Constant 42))
(InvokeContinuation return v5))
(LetCont (k6)
(LetPrim v6 (Constant 1))
(LetCont (k7 v7)
(InvokeContinuation* k0 v7))
(InvokeMethod v1 + v6 k7))
(Branch (IsTrue v4) k5 k6))
(LetCont (k8)
(LetPrim v8 (Constant false))
(InvokeContinuation k4 v8))
(LetCont (k9)
(LetPrim v9 (Constant true))
(InvokeContinuation k4 v9))
(Branch (IsTrue v3) k8 k9))
(InvokeMethod v1 == v2 k3))
(LetPrim v10 (Constant true))
(InvokeContinuation k2 ))
(InvokeContinuation k0 v0))
""";
// While loop, from:
//
// int main() {
// for (int i = 0; i < 2; i++) {
// print(42 + i);
// }
// }
String CP10_IN = """
(FunctionDefinition main ( return)
(LetPrim v0 (Constant 0))
(LetCont* (k0 v1)
(LetCont (k1)
(LetPrim v2 (Constant null))
(InvokeContinuation return v2))
(LetCont (k2)
(LetPrim v3 (Constant 42))
(LetCont (k3 v4)
(LetCont (k4 v5)
(LetPrim v6 (Constant 1))
(LetCont (k5 v7)
(InvokeContinuation* k0 v7))
(InvokeMethod v1 + v6 k5))
(InvokeStatic print v4 k4))
(InvokeMethod v3 + v1 k3))
(LetPrim v8 (Constant 2))
(LetCont (k6 v9)
(Branch (IsTrue v9) k2 k1))
(InvokeMethod v1 < v8 k6))
(InvokeContinuation k0 v0))
""";
String CP10_OUT = CP10_IN;
/// Normalizes whitespace by replacing all whitespace sequences by a single
/// space and trimming leading and trailing whitespace.
String normalizeSExpr(String input) {
return input.replaceAll(new RegExp(r'[ \n\t]+'), ' ').trim();
}
/// Parses the given input IR, runs an optimization pass over it, and compares
/// the stringification of the result against the expected output.
Future testConstantPropagator(String input, String expectedOutput) {
final compiler = new MockCompiler.internal(
emitJavaScript: false,
enableMinification: false);
return compiler.init().then((_) {
final unstringifier = new SExpressionUnstringifier();
final stringifier = new SExpressionStringifier();
final optimizer = new ConstantPropagator(
compiler, dart2js.DART_CONSTANT_SYSTEM);
final f = unstringifier.unstringify(input);
optimizer.rewrite(f);
String expected = normalizeSExpr(expectedOutput);
String actual = normalizeSExpr(stringifier.visit(f));
Expect.equals(expected, actual);
});
}
void main() {
asyncTest(() => testConstantPropagator(CP1_IN, CP1_OUT));
asyncTest(() => testConstantPropagator(CP2_IN, CP2_OUT));
asyncTest(() => testConstantPropagator(CP3_IN, CP3_OUT));
asyncTest(() => testConstantPropagator(CP4_IN, CP4_OUT));
asyncTest(() => testConstantPropagator(CP5_IN, CP5_OUT));
asyncTest(() => testConstantPropagator(CP6_IN, CP6_OUT));
asyncTest(() => testConstantPropagator(CP7_IN, CP7_OUT));
asyncTest(() => testConstantPropagator(CP8_IN, CP8_OUT));
asyncTest(() => testConstantPropagator(CP9_IN, CP9_OUT));
asyncTest(() => testConstantPropagator(CP10_IN, CP10_OUT));
}