| Index: sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
|
| index b5757726f6a670514de7a9b3c6baa4368aafa454..0be8910a2af8cac275e84fd21738eedd20ba6efe 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
|
| @@ -1243,7 +1243,7 @@ class SsaGlobalValueNumberer implements OptimizationPhase {
|
| && loopHeader.successors[0] == block);
|
| while (instruction != null) {
|
| HInstruction next = instruction.next;
|
| - if (instruction.useGvn()
|
| + if (instruction.useGvn() && instruction.isMovable
|
| && (!instruction.canThrow() || firstInstructionInLoop)
|
| && !instruction.sideEffects.dependsOn(dependsFlags)) {
|
| bool loopInvariantInputs = true;
|
| @@ -1465,11 +1465,7 @@ class SsaCodeMotion extends HBaseVisitor implements OptimizationPhase {
|
|
|
| HInstruction current = instruction;
|
| instruction = instruction.next;
|
| -
|
| - // TODO(ngeoffray): this check is needed because we currently do
|
| - // not have flags to express 'Gvn'able', but not movable.
|
| - if (current is HCheck) continue;
|
| - if (!current.useGvn()) continue;
|
| + if (!current.useGvn() || !current.isMovable) continue;
|
| if (current.sideEffects.dependsOn(dependsFlags)) continue;
|
|
|
| bool canBeMoved = true;
|
| @@ -1504,14 +1500,16 @@ class SsaTypeConversionInserter extends HBaseVisitor
|
| }
|
|
|
| // Update users of [input] that are dominated by [:dominator.first:]
|
| - // to use [newInput] instead.
|
| - void changeUsesDominatedBy(HBasicBlock dominator,
|
| - HInstruction input,
|
| - TypeMask convertedType) {
|
| + // to use [TypeKnown] of [input] instead. As the type information depends
|
| + // on the control flow, we mark the inserted [HTypeKnown] nodes as
|
| + // non-movable.
|
| + void insertTypePropagationForDominatedUsers(HBasicBlock dominator,
|
| + HInstruction input,
|
| + TypeMask convertedType) {
|
| Setlet<HInstruction> dominatedUsers = input.dominatedUsers(dominator.first);
|
| if (dominatedUsers.isEmpty) return;
|
|
|
| - HTypeKnown newInput = new HTypeKnown(convertedType, input);
|
| + HTypeKnown newInput = new HTypeKnown.pinned(convertedType, input);
|
| dominator.addBefore(dominator.first, newInput);
|
| dominatedUsers.forEach((HInstruction user) {
|
| user.changeUse(input, newInput);
|
| @@ -1538,12 +1536,14 @@ class SsaTypeConversionInserter extends HBaseVisitor
|
| HInstruction input = instruction.expression;
|
|
|
| for (HIf ifUser in ifUsers) {
|
| - changeUsesDominatedBy(ifUser.thenBlock, input, convertedType);
|
| + insertTypePropagationForDominatedUsers(ifUser.thenBlock, input,
|
| + convertedType);
|
| // TODO(ngeoffray): Also change uses for the else block on a type
|
| // that knows it is not of a specific type.
|
| }
|
| for (HIf ifUser in notIfUsers) {
|
| - changeUsesDominatedBy(ifUser.elseBlock, input, convertedType);
|
| + insertTypePropagationForDominatedUsers(ifUser.elseBlock, input,
|
| + convertedType);
|
| // TODO(ngeoffray): Also change uses for the then block on a type
|
| // that knows it is not of a specific type.
|
| }
|
| @@ -1575,11 +1575,13 @@ class SsaTypeConversionInserter extends HBaseVisitor
|
| TypeMask nonNullType = input.instructionType.nonNullable();
|
|
|
| for (HIf ifUser in ifUsers) {
|
| - changeUsesDominatedBy(ifUser.elseBlock, input, nonNullType);
|
| + insertTypePropagationForDominatedUsers(ifUser.elseBlock, input,
|
| + nonNullType);
|
| // Uses in thenBlock are `null`, but probably not common.
|
| }
|
| for (HIf ifUser in notIfUsers) {
|
| - changeUsesDominatedBy(ifUser.thenBlock, input, nonNullType);
|
| + insertTypePropagationForDominatedUsers(ifUser.thenBlock, input,
|
| + nonNullType);
|
| // Uses in elseBlock are `null`, but probably not common.
|
| }
|
| }
|
|
|