| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 library dart2js.cps_ir.redundant_refinement; |
| 6 |
| 7 import 'cps_ir_nodes.dart'; |
| 8 import 'optimizers.dart' show Pass; |
| 9 import 'type_mask_system.dart'; |
| 10 |
| 11 /// Removes [Refinement] nodes where the input value is already known to |
| 12 /// satisfy the refinement type. |
| 13 /// |
| 14 /// Note: This pass improves loop-invariant code motion in the GVN pass because |
| 15 /// GVN will currently not hoist a primitive across a refinement guard. |
| 16 /// But some opportunities for hoisting are still missed. A field access can |
| 17 /// safely be hoisted across a non-redundant refinement as long as the less |
| 18 /// refined value is still known to have the field. For example: |
| 19 /// |
| 20 /// class A { var field; } |
| 21 /// class B extends A {} |
| 22 /// |
| 23 /// var x = getA(); // Return type is subclass of A. |
| 24 /// while (x is B) { // Refinement to B is not redundant. |
| 25 /// x.field.baz++; // x.field is safe for hoisting, |
| 26 /// } // but blocked by the refinement node. |
| 27 /// |
| 28 /// Ideally, this pass should go away and GVN should handle refinements |
| 29 /// directly. |
| 30 class RedundantRefinementEliminator extends TrampolineRecursiveVisitor |
| 31 implements Pass { |
| 32 String get passName => 'Redundant refinement elimination'; |
| 33 |
| 34 TypeMaskSystem typeSystem; |
| 35 |
| 36 RedundantRefinementEliminator(this.typeSystem); |
| 37 |
| 38 void rewrite(FunctionDefinition node) { |
| 39 visit(node); |
| 40 } |
| 41 |
| 42 Expression traverseLetPrim(LetPrim node) { |
| 43 Expression next = node.body; |
| 44 if (node.primitive is Refinement) { |
| 45 Refinement refinement = node.primitive; |
| 46 Primitive value = refinement.value.definition; |
| 47 if (typeSystem.isMorePreciseOrEqual(value.type, refinement.refineType)) { |
| 48 value.substituteFor(refinement); |
| 49 refinement.destroy(); |
| 50 node.remove(); |
| 51 return next; |
| 52 } |
| 53 } |
| 54 return next; |
| 55 } |
| 56 } |
| OLD | NEW |