Chromium Code Reviews| 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..7753408efd1acbbf18be4f2ca3889eddf3c24af8 |
| --- /dev/null |
| +++ b/pkg/compiler/lib/src/cps_ir/redundant_refinement.dart |
| @@ -0,0 +1,40 @@ |
| +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. Ideally, this pass |
|
sra1
2015/11/17 05:41:15
Which are still missed?
asgerf
2015/11/17 12:43:43
Added example.
|
| +/// 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)) { |
| + value.substituteFor(refinement); |
| + refinement.destroy(); |
| + node.remove(); |
| + return next; |
| + } |
| + } |
| + return next; |
| + } |
| +} |