Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(340)

Unified Diff: pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart

Issue 1613853003: dart2js cps: More rewritings for compound assignments. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
index 1c96301711577753d98346431fcc4e8fb7d3cc06..63206914a1a046f15a2d4fc7dacff7b96e81cab6 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
@@ -752,16 +752,26 @@ class StatementRewriter extends Transformer implements Pass {
return node;
}
- bool sameVariable(Expression e1, Expression e2) {
- return e1 is VariableUse && e2 is VariableUse && e1.variable == e2.variable;
- }
-
bool isCompoundableBuiltin(Expression e) {
return e is ApplyBuiltinOperator &&
- e.arguments.length == 2 &&
+ e.arguments.length >= 2 &&
isCompoundableOperator(e.operator);
}
+ /// Converts a compoundable operator application into the right-hand side for
+ /// use in a compound assignment, discarding the left-hand value.
+ ///
+ /// For example, for `x + y + z` it returns `y + z`.
+ Expression contractCompoundableBuiltin(ApplyBuiltinOperator e) {
+ assert(isCompoundableBuiltin(e));
+ if (e.arguments.length > 2) {
+ assert(e.operator == BuiltinOperator.StringConcatenate);
+ return new ApplyBuiltinOperator(e.operator, e.arguments.skip(1).toList());
+ } else {
+ return e.arguments[1];
+ }
+ }
+
void destroyVariableUse(VariableUse node) {
--node.variable.readCount;
}
@@ -772,13 +782,12 @@ class StatementRewriter extends Transformer implements Pass {
if (isCompoundableBuiltin(node.value)) {
ApplyBuiltinOperator rhs = node.value;
Expression left = rhs.arguments[0];
- Expression right = rhs.arguments[1];
if (left is GetField &&
left.field == node.field &&
- sameVariable(left.object, node.object)) {
- destroyVariableUse(left.object);
+ samePrimary(left.object, node.object)) {
+ destroyPrimaryExpression(left.object);
node.compound = rhs.operator;
- node.value = right;
+ node.value = contractCompoundableBuiltin(rhs);
}
}
node.object = visitExpression(node.object);
@@ -798,6 +807,16 @@ class StatementRewriter extends Transformer implements Pass {
Expression visitSetStatic(SetStatic node) {
allowRhsPropagation.add(true);
node.value = visitExpression(node.value);
+ if (isCompoundableBuiltin(node.value)) {
+ ApplyBuiltinOperator rhs = node.value;
+ Expression left = rhs.arguments[0];
+ if (left is GetStatic &&
+ left.element == node.element &&
+ !left.useLazyGetter) {
+ node.compound = rhs.operator;
+ node.value = contractCompoundableBuiltin(rhs);
+ }
+ }
allowRhsPropagation.removeLast();
return node;
}
@@ -857,14 +876,13 @@ class StatementRewriter extends Transformer implements Pass {
if (isCompoundableBuiltin(node.value)) {
ApplyBuiltinOperator rhs = node.value;
Expression left = rhs.arguments[0];
- Expression right = rhs.arguments[1];
if (left is GetIndex &&
- sameVariable(left.object, node.object) &&
- sameVariable(left.index, node.index)) {
- destroyVariableUse(left.object);
- destroyVariableUse(left.index);
+ samePrimary(left.object, node.object) &&
+ samePrimary(left.index, node.index)) {
+ destroyPrimaryExpression(left.object);
+ destroyPrimaryExpression(left.index);
node.compound = rhs.operator;
- node.value = right;
+ node.value = contractCompoundableBuiltin(rhs);
}
}
node.index = visitExpression(node.index);
@@ -1036,9 +1054,34 @@ class StatementRewriter extends Transformer implements Pass {
Expression s,
Expression t,
Expression condition) {
- if (s is Assign && t is Assign && s.variable == t.variable) {
- Expression values = new Conditional(condition, s.value, t.value);
- return new CombinedAssigns(s, t, new CombinedExpressions(values));
+ if (s is Assign && t is Assign &&
+ s.variable == t.variable) {
+ return new CombinedAssigns(s, t,
+ combineAsConditional(s.value, t.value, condition));
+ }
+ if (s is SetStatic &&
+ t is SetStatic &&
+ s.element == t.element) {
+ return new CombinedSetStatics(s, t,
+ combineAsConditional(s.value, t.value, condition));
+ }
+ if (s is SetField &&
+ t is SetField &&
+ s.compound == null &&
+ t.compound == null &&
+ s.field == t.field &&
+ samePrimary(s.object, t.object)) {
+ return new CombinedSetFields(s, t,
+ combineAsConditional(s.value, t.value, condition));
+ }
+ if (s is SetIndex &&
+ t is SetIndex &&
+ s.compound == null &&
+ t.compound == null &&
+ samePrimary(s.object, t.object) &&
+ samePrimary(s.index, t.index)) {
+ return new CombinedSetIndexes(s, t,
+ combineAsConditional(s.value, t.value, condition));
}
return new CombinedExpressions(new Conditional(condition, s, t));
}
@@ -1281,12 +1324,12 @@ abstract class CombinedExpressions {
factory CombinedExpressions(Expression e) = GenericCombinedExpressions;
}
-/// Combines assignments of form `[variable] := E1` and `[variable] := E2` into
-/// a single assignment of form `[variable] := combine(E1, E2)`.
+/// Combines assignments of form `v := E1` and `v := E2` into
+/// a single assignment of form `v := combine(E1, E2)`.
sra1 2016/01/22 03:22:04 We probably want to avoid this where one arm is a
asgerf 2016/01/22 18:54:47 Good point. I looked at the IR generated by V8 in
class CombinedAssigns implements CombinedExpressions {
Assign assign1, assign2;
CombinedExpressions value;
- Expression combined;
+ Assign combined;
CombinedAssigns(this.assign1, this.assign2, this.value) {
assert(assign1.variable == assign2.variable);
@@ -1300,10 +1343,74 @@ class CombinedAssigns implements CombinedExpressions {
}
}
+/// Combines `static = E1` and `static = E2` into `static = combine(E1, E2)`.
+class CombinedSetStatics implements CombinedExpressions {
+ SetStatic assign1, assign2;
+ CombinedExpressions value;
+ SetStatic combined;
+
+ CombinedSetStatics(this.assign1, this.assign2, this.value) {
+ assert(assign1.element == assign2.element);
+ // TODO(asgerf): Can we combine source information from the two assignments?
+ combined = new SetStatic(assign1.element, value.combined,
+ assign1.sourceInformation);
+ }
+
+ void uncombine() {
+ value.uncombine();
+ }
+}
+
+/// Combines `v.field = E1` and `v.field = E2` into `v.field = combine(E1, E2)`.
+class CombinedSetFields implements CombinedExpressions {
+ SetField assign1, assign2;
+ CombinedExpressions value;
+ SetField combined;
+
+ CombinedSetFields(this.assign1, this.assign2, this.value) {
+ assert(samePrimary(assign1.object, assign2.object));
+ assert(assign1.field == assign2.field);
+ assert(assign1.compound == null);
+ assert(assign2.compound == null);
+ destroyPrimaryExpression(assign2.object);
+ combined = new SetField(assign1.object, assign1.field, value.combined);
+ }
+
+ void uncombine() {
+ value.uncombine();
+ restorePrimaryExpression(assign2.object);
+ }
+}
+
+/// Combines `v[index] = E1` and `v[index] = E2` into
+/// `v[index] = combine(E1, E2)`.
+class CombinedSetIndexes implements CombinedExpressions {
+ SetIndex assign1, assign2;
+ CombinedExpressions value;
+ SetIndex combined;
+
+ CombinedSetIndexes(this.assign1, this.assign2, this.value) {
+ assert(samePrimary(assign1.object, assign2.object));
+ assert(samePrimary(assign1.index, assign2.index));
+ assert(assign1.compound == null);
+ assert(assign2.compound == null);
+ destroyPrimaryExpression(assign2.object);
+ destroyPrimaryExpression(assign2.index);
+ combined = new SetIndex(assign1.object, assign1.index, value.combined,
+ compound: assign1.compound);
+ }
+
+ void uncombine() {
+ value.uncombine();
+ restorePrimaryExpression(assign2.object);
+ restorePrimaryExpression(assign2.index);
+ }
+}
+
/// Combines two variable uses into one.
class CombinedUses implements CombinedExpressions {
VariableUse use1, use2;
- Expression combined;
+ VariableUse combined;
CombinedUses(this.use1, this.use2) {
assert(use1.variable == use2.variable);
@@ -1356,3 +1463,31 @@ class VariableUseVisitor extends RecursiveVisitor {
new VariableUseVisitor(callback).visitExpression(node);
}
}
+
+bool sameVariable(Expression e1, Expression e2) {
+ return e1 is VariableUse && e2 is VariableUse && e1.variable == e2.variable;
+}
+
+/// True if [e1] and [e2] are primary expressions (expressions without
+/// subexpressions) with the same value.
+bool samePrimary(Expression e1, Expression e2) {
+ return sameVariable(e1, e2) || (e1 is This && e2 is This);
+}
+
+/// Decrement the reference count for [e] if it is a variable use.
+void destroyPrimaryExpression(Expression e) {
+ if (e is VariableUse) {
+ --e.variable.readCount;
+ } else {
+ assert(e is This);
+ }
+}
+
+/// Increment the reference count for [e] if it is a variable use.
+void restorePrimaryExpression(Expression e) {
+ if (e is VariableUse) {
+ ++e.variable.readCount;
+ } else {
+ assert(e is This);
+ }
+}
« no previous file with comments | « pkg/compiler/lib/src/js_backend/codegen/codegen.dart ('k') | pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698