| Index: pkg/compiler/lib/src/cps_ir/redundant_refinement.dart
|
| diff --git a/pkg/compiler/lib/src/cps_ir/redundant_refinement.dart b/pkg/compiler/lib/src/cps_ir/redundant_refinement.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..cff47d64fa4b757bb1014327bec6827408541cc6
|
| --- /dev/null
|
| +++ b/pkg/compiler/lib/src/cps_ir/redundant_refinement.dart
|
| @@ -0,0 +1,55 @@
|
| +// Copyright (c) 2015, 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.
|
| +
|
| +library dart2js.cps_ir.redundant_refinement;
|
| +
|
| +import 'cps_ir_nodes.dart';
|
| +import 'optimizers.dart' show Pass;
|
| +import 'type_mask_system.dart';
|
| +
|
| +/// Removes [Refinement] nodes where the input value is already known to
|
| +/// satisfy the refinement type.
|
| +///
|
| +/// Note: This pass improves loop-invariant code motion in the GVN pass because
|
| +/// GVN will currently not hoist a primitive across a refinement guard.
|
| +/// But some opportunities for hoisting are still missed. A field access can
|
| +/// safely be hoisted across a non-redundant refinement as long as the less
|
| +/// refined value is still known to have the field. For example:
|
| +///
|
| +/// class A { var field; }
|
| +/// class B extends A {}
|
| +///
|
| +/// var x = getA(); // Return type is subclass of A.
|
| +/// while (x is B) { // Refinement to B is not redundant.
|
| +/// x.field.baz++; // x.field is safe for hoisting,
|
| +/// } // but blocked by the refinement node.
|
| +///
|
| +/// Ideally, this pass should go away and GVN should handle refinements
|
| +/// directly.
|
| +class RedundantRefinementEliminator extends TrampolineRecursiveVisitor
|
| + implements Pass {
|
| + String get passName => 'Redundant refinement elimination';
|
| +
|
| + TypeMaskSystem typeSystem;
|
| +
|
| + RedundantRefinementEliminator(this.typeSystem);
|
| +
|
| + void rewrite(FunctionDefinition node) {
|
| + visit(node);
|
| + }
|
| +
|
| + Expression traverseLetPrim(LetPrim node) {
|
| + Expression next = node.body;
|
| + if (node.primitive is Refinement) {
|
| + Refinement refinement = node.primitive;
|
| + Primitive value = refinement.value.definition;
|
| + if (typeSystem.isMorePreciseOrEqual(value.type, refinement.refineType)) {
|
| + refinement..replaceUsesWith(value)..destroy();
|
| + node.remove();
|
| + return next;
|
| + }
|
| + }
|
| + return next;
|
| + }
|
| +}
|
|
|