| Index: pkg/compiler/lib/src/ssa/optimize.dart
|
| diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
|
| index 998ab1879131517cd2120afd67414d5e065b467d..3be36870803db668e86480d381adb49ff5a65cdf 100644
|
| --- a/pkg/compiler/lib/src/ssa/optimize.dart
|
| +++ b/pkg/compiler/lib/src/ssa/optimize.dart
|
| @@ -55,6 +55,7 @@ class SsaOptimizerTask extends CompilerTask {
|
| new SsaTypePropagator(compiler),
|
| new SsaCodeMotion(),
|
| new SsaLoadElimination(compiler),
|
| + new SsaRedundantPhiEliminator(),
|
| new SsaDeadPhiEliminator(),
|
| new SsaTypePropagator(compiler),
|
| new SsaValueRangeAnalyzer(compiler, constantSystem, this, work),
|
| @@ -197,6 +198,14 @@ class SsaInstructionSimplifier extends HBaseVisitor
|
| assert(inputs.length == 1);
|
| HInstruction input = inputs[0];
|
| if (input.isBoolean(compiler)) return input;
|
| +
|
| + // If the code is unreachable, remove the HBoolify. This can happen when
|
| + // there is a throw expression in a short-circuit conditional. Removing the
|
| + // unreachable HBoolify makes it easier to reconstruct the short-circuit
|
| + // operation.
|
| + if (input.instructionType.isEmpty && !input.instructionType.isNullable)
|
| + return input;
|
| +
|
| // All values that cannot be 'true' are boolified to false.
|
| TypeMask mask = input.instructionType;
|
| if (!mask.contains(backend.jsBoolClass, compiler.world)) {
|
| @@ -513,35 +522,46 @@ class SsaInstructionSimplifier extends HBaseVisitor
|
| TypeMask leftType = left.instructionType;
|
| TypeMask rightType = right.instructionType;
|
|
|
| + HInstruction makeTrue() => graph.addConstantBool(true, compiler);
|
| + HInstruction makeFalse() => graph.addConstantBool(false, compiler);
|
| +
|
| // Intersection of int and double return conflicting, so
|
| // we don't optimize on numbers to preserve the runtime semantics.
|
| if (!(left.isNumberOrNull(compiler) && right.isNumberOrNull(compiler))) {
|
| TypeMask intersection = leftType.intersection(rightType, compiler.world);
|
| if (intersection.isEmpty && !intersection.isNullable) {
|
| - return graph.addConstantBool(false, compiler);
|
| + return makeFalse();
|
| }
|
| }
|
|
|
| if (left.isNull() && right.isNull()) {
|
| - return graph.addConstantBool(true, compiler);
|
| + return makeTrue();
|
| }
|
|
|
| - if (left.isConstantBoolean() && right.isBoolean(compiler)) {
|
| - HConstant constant = left;
|
| + HInstruction compareConstant(HConstant constant, HInstruction input) {
|
| if (constant.constant.isTrue) {
|
| - return right;
|
| + return input;
|
| } else {
|
| - return new HNot(right, backend.boolType);
|
| + return new HNot(input, backend.boolType);
|
| }
|
| }
|
|
|
| + if (left.isConstantBoolean() && right.isBoolean(compiler)) {
|
| + return compareConstant(left, right);
|
| + }
|
| +
|
| if (right.isConstantBoolean() && left.isBoolean(compiler)) {
|
| - HConstant constant = right;
|
| - if (constant.constant.isTrue) {
|
| - return left;
|
| - } else {
|
| - return new HNot(left, backend.boolType);
|
| - }
|
| + return compareConstant(right, left);
|
| + }
|
| +
|
| +
|
| + if (identical(left.nonCheck(), right.nonCheck())) {
|
| + // Avoid constant-folding `identical(x, x)` when `x` might be double. The
|
| + // dart2js runtime has not always been consistent with the Dart
|
| + // specification (section 16.0.1), which makes distinctions on NaNs and
|
| + // -0.0 that are hard to implement efficiently.
|
| + if (left.isIntegerOrNull(compiler)) return makeTrue();
|
| + if (!left.canBePrimitiveNumber(compiler)) return makeTrue();
|
| }
|
|
|
| return null;
|
| @@ -822,6 +842,19 @@ class SsaInstructionSimplifier extends HBaseVisitor
|
| return new HFieldSet(field, receiver, value);
|
| }
|
|
|
| + HInstruction visitInvokeStatic(HInvokeStatic node) {
|
| + if (node.element == backend.getCheckConcurrentModificationError()) {
|
| + if (node.inputs.length == 2) {
|
| + HInstruction firstArgument = node.inputs[0];
|
| + if (firstArgument is HConstant) {
|
| + HConstant constant = firstArgument;
|
| + if (constant.constant.isTrue) return constant;
|
| + }
|
| + }
|
| + }
|
| + return node;
|
| + }
|
| +
|
| HInstruction visitStringConcat(HStringConcat node) {
|
| // Simplify string concat:
|
| //
|
|
|