Index: pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart |
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart |
index 0bb70ed14ee9d9695136c159c23ebb4e491f5126..49a6c22c480866179db5a7889c649803ee20d9eb 100644 |
--- a/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart |
+++ b/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart |
@@ -306,6 +306,17 @@ class LogicalRewriter extends RecursiveTransformer |
node.elseExpression = tmp; |
} |
+ // x ? y : x ==> x && y |
+ if (isSameVariable(node.condition, node.elseExpression)) { |
+ destroyVariableUse(node.elseExpression); |
+ return new LogicalOperator.and(node.condition, node.thenExpression); |
+ } |
+ // x ? x : y ==> x || y |
+ if (isSameVariable(node.condition, node.thenExpression)) { |
+ destroyVariableUse(node.thenExpression); |
+ return new LogicalOperator.or(node.condition, node.elseExpression); |
+ } |
+ |
return node; |
} |
@@ -468,6 +479,18 @@ class LogicalRewriter extends RecursiveTransformer |
e.elseExpression = (e.elseExpression as Not).operand; |
return new Not(e); |
} |
+ |
+ // x ? y : x ==> x && y |
+ if (isSameVariable(e.condition, e.elseExpression)) { |
+ destroyVariableUse(e.elseExpression); |
+ return new LogicalOperator.and(e.condition, e.thenExpression); |
+ } |
+ // x ? x : y ==> x || y |
+ if (isSameVariable(e.condition, e.thenExpression)) { |
+ destroyVariableUse(e.thenExpression); |
+ return new LogicalOperator.or(e.condition, e.elseExpression); |
+ } |
+ |
return e; |
} |
if (e is Constant && e.value.isBool) { |
@@ -509,5 +532,23 @@ class LogicalRewriter extends RecursiveTransformer |
return new LogicalOperator.or(e1, e2); |
} |
} |
+ |
+ /// True if [e2] is known to return the same value as [e1] |
+ /// (with no additional side effects) if evaluated immediately after [e1]. |
+ /// |
+ /// Concretely, this is true if [e1] and [e2] are uses of the same variable, |
+ /// or if [e2] is a use of a variable assigned by [e1]. |
+ bool isSameVariable(Expression e1, Expression e2) { |
+ if (e1 is VariableUse) { |
+ return e2 is VariableUse && e1.variable == e2.variable; |
+ } else if (e1 is Assign) { |
+ return e2 is VariableUse && e1.variable == e2.variable; |
+ } |
+ return false; |
+ } |
+ |
+ void destroyVariableUse(VariableUse node) { |
+ --node.variable.readCount; |
+ } |
} |