Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of tree_ir.optimization; | 5 part of tree_ir.optimization; |
| 6 | 6 |
| 7 /// Eliminates moving assignments, such as w := v, by assigning directly to w | 7 /// Eliminates moving assignments, such as w := v, by assigning directly to w |
| 8 /// at the definition of v. | 8 /// at the definition of v. |
| 9 /// | 9 /// |
| 10 /// This compensates for suboptimal register allocation, and merges closure | 10 /// This compensates for suboptimal register allocation, and merges closure |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 102 | 102 |
| 103 Statement visitBasicBlock(Statement node) { | 103 Statement visitBasicBlock(Statement node) { |
| 104 node = visitStatement(node); | 104 node = visitStatement(node); |
| 105 move.clear(); | 105 move.clear(); |
| 106 inverseMove.clear(); | 106 inverseMove.clear(); |
| 107 return node; | 107 return node; |
| 108 } | 108 } |
| 109 | 109 |
| 110 void visitVariable(Variable variable) { | 110 void visitVariable(Variable variable) { |
| 111 // We have found a use of w. | 111 // We have found a use of w. |
| 112 // Remove assignments of form w := v from the move maps. | 112 // Remove assignments of form w := v from the move maps. |
|
Kevin Millikin (Google)
2015/02/26 12:43:18
It looks like we remove variable's that are read a
asgerf
2015/02/27 12:05:19
Completely agree.
| |
| 113 Assign movingAssignment = inverseMove.remove(variable); | 113 Assign movingAssignment = inverseMove.remove(variable); |
| 114 if (movingAssignment != null) { | 114 if (movingAssignment != null) { |
| 115 move.remove(movingAssignment.definition); | 115 VariableUse def = movingAssignment.definition; |
| 116 move.remove(def.variable); | |
| 116 } | 117 } |
| 117 } | 118 } |
| 118 | 119 |
| 119 /** | 120 /** |
| 120 * Called when a definition of [v] is encountered. | 121 * Called when a definition of [v] is encountered. |
| 121 * Attempts to propagate the assignment through a moving assignment. | 122 * Attempts to propagate the assignment through a moving assignment. |
| 122 * Returns the variable to be assigned into, defaulting to [v] itself if | 123 * Returns the variable to be assigned into, defaulting to [v] itself if |
| 123 * no optimization could be performed. | 124 * no optimization could be performed. |
| 124 */ | 125 */ |
| 125 Variable copyPropagateVariable(Variable v) { | 126 Variable copyPropagateVariable(Variable v) { |
| 126 Assign movingAssign = move[v]; | 127 Assign movingAssign = move[v]; |
| 127 if (movingAssign != null) { | 128 if (movingAssign != null) { |
| 128 // We found the pattern: | 129 // We found the pattern: |
| 129 // v := EXPR | 130 // v := EXPR |
| 130 // BLOCK (does not use w) | 131 // BLOCK (does not use w) |
| 131 // w := v (only use of v) | 132 // w := v (only use of v) |
| 132 // | 133 // |
| 133 // Rewrite to: | 134 // Rewrite to: |
| 134 // w := EXPR | 135 // w := EXPR |
| 135 // BLOCK | 136 // BLOCK |
| 136 // w := w (to be removed later) | 137 // w := w (to be removed later) |
| 137 Variable w = movingAssign.variable; | 138 Variable w = movingAssign.variable; |
| 138 | 139 |
| 139 // Make w := w. | 140 // Make w := w. |
| 140 // We can't remove the statement from here because we don't have | 141 // We can't remove the statement from here because we don't have |
| 141 // parent pointers. So just make it a no-op so it can be removed later. | 142 // parent pointers. So just make it a no-op so it can be removed later. |
| 142 movingAssign.definition = w; | 143 movingAssign.definition = new VariableUse(w); |
| 143 | 144 |
| 144 // The intermediate variable 'v' should now be orphaned, so don't bother | 145 // The intermediate variable 'v' should now be orphaned, so don't bother |
| 145 // updating its read/write counters. | 146 // updating its read/write counters. |
| 146 // Due to the nop trick, the variable 'w' now has one additional read | 147 // Due to the nop trick, the variable 'w' now has one additional write. |
|
Kevin Millikin (Google)
2015/02/26 12:43:18
'The nop trick' is a bit confusing. Isn't the ext
asgerf
2015/02/27 12:05:19
Yeah, that's why I moved it closer to the return.
Kevin Millikin (Google)
2015/02/27 12:17:18
I'm on the fence. It's definitely a downside of t
| |
| 147 // and write. | |
| 148 ++w.writeCount; | |
| 149 ++w.readCount; | |
| 150 | 148 |
| 151 // Make w := EXPR | 149 // Make w := EXPR |
| 150 ++w.writeCount; | |
| 152 return w; | 151 return w; |
| 153 } | 152 } |
| 154 return v; | 153 return v; |
| 155 } | 154 } |
| 156 | 155 |
| 157 Statement visitAssign(Assign node) { | 156 Statement visitAssign(Assign node) { |
| 158 node.next = visitStatement(node.next); | 157 node.next = visitStatement(node.next); |
| 159 node.variable = copyPropagateVariable(node.variable); | 158 node.variable = copyPropagateVariable(node.variable); |
| 160 visitExpression(node.definition); | 159 visitExpression(node.definition); |
| 161 visitVariable(node.variable); | 160 visitVariable(node.variable); |
| 162 | 161 |
| 163 // If this is a moving assignment w := v, with this being the only use of v, | 162 // If this is a moving assignment w := v, with this being the only use of v, |
| 164 // try to propagate it backwards. Do not propagate assignments where w | 163 // try to propagate it backwards. Do not propagate assignments where w |
| 165 // is from an outer function scope. | 164 // is from an outer function scope. |
| 166 if (node.definition is Variable) { | 165 if (node.definition is VariableUse) { |
| 167 Variable def = node.definition; | 166 VariableUse definition = node.definition; |
| 168 if (def.readCount == 1 && | 167 if (definition.variable.readCount == 1 && |
| 169 node.variable.host == currentElement) { | 168 node.variable.host == currentElement) { |
| 170 move[node.definition] = node; | 169 move[definition.variable] = node; |
| 171 inverseMove[node.variable] = node; | 170 inverseMove[node.variable] = node; |
| 172 } | 171 } |
| 173 } | 172 } |
| 174 | 173 |
| 175 return node; | 174 return node; |
| 176 } | 175 } |
| 177 | 176 |
| 178 Statement visitLabeledStatement(LabeledStatement node) { | 177 Statement visitLabeledStatement(LabeledStatement node) { |
| 179 node.next = visitBasicBlock(node.next); | 178 node.next = visitBasicBlock(node.next); |
| 180 node.body = visitStatement(node.body); | 179 node.body = visitStatement(node.body); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 233 | 232 |
| 234 void visitFunctionExpression(FunctionExpression node) { | 233 void visitFunctionExpression(FunctionExpression node) { |
| 235 new CopyPropagator().rewrite(node.definition); | 234 new CopyPropagator().rewrite(node.definition); |
| 236 } | 235 } |
| 237 | 236 |
| 238 void visitFieldInitializer(FieldInitializer node) { | 237 void visitFieldInitializer(FieldInitializer node) { |
| 239 visitStatement(node.body); | 238 visitStatement(node.body); |
| 240 } | 239 } |
| 241 | 240 |
| 242 } | 241 } |
| OLD | NEW |