| 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 refinement | |
| 49 ..replaceUsesWith(value) | |
| 50 ..destroy(); | |
| 51 node.remove(); | |
| 52 return next; | |
| 53 } | |
| 54 } | |
| 55 return next; | |
| 56 } | |
| 57 } | |
| OLD | NEW |