Chromium Code Reviews

Side by Side Diff: lib/compiler/implementation/ssa/codegen_helpers.dart

Issue 10539042: Recognize nested logical operations. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 /** 5 /**
6 * Instead of emitting each SSA instruction with a temporary variable 6 * Instead of emitting each SSA instruction with a temporary variable
7 * mark instructions that can be emitted at their use-site. 7 * mark instructions that can be emitted at their use-site.
8 * For example, in: 8 * For example, in:
9 * t0 = 4; 9 * t0 = 4;
10 * t1 = 3; 10 * t1 = 3;
(...skipping 133 matching lines...)
144 /** 144 /**
145 * Check if a block has at least one statement other than 145 * Check if a block has at least one statement other than
146 * [instruction]. 146 * [instruction].
147 */ 147 */
148 bool hasStatement(HBasicBlock block, HInstruction instruction) { 148 bool hasStatement(HBasicBlock block, HInstruction instruction) {
149 // If [instruction] is not in [block], then if the block is not 149 // If [instruction] is not in [block], then if the block is not
150 // empty, we know there will be a statement to emit. 150 // empty, we know there will be a statement to emit.
151 if (instruction.block !== block) return block.last !== block.first; 151 if (instruction.block !== block) return block.last !== block.first;
152 152
153 // If [instruction] is not the last instruction of the block 153 // If [instruction] is not the last instruction of the block
154 // before the control flow instruction, then we will have to emit 154 // before the control flow instruction, or the last instruction,
155 // a statement for that last instruction. 155 // then we will have to emit a statement for that last instruction.
156 if (instruction !== block.last.previous) return true; 156 if (instruction != block.last
157 && instruction !== block.last.previous) return true;
Lasse Reichstein Nielsen 2012/06/07 12:02:47 Putting "&&" at the end of the previous line seems
157 158
158 // If one of the instructions in the block until [instruction] is 159 // If one of the instructions in the block until [instruction] is
159 // not generated at use site, then we will have to emit a 160 // not generated at use site, then we will have to emit a
160 // statement for it. 161 // statement for it.
161 // TODO(ngeoffray): we could generate a comma separated 162 // TODO(ngeoffray): we could generate a comma separated
162 // list of expressions. 163 // list of expressions.
163 for (HInstruction temp = block.first; 164 for (HInstruction temp = block.first;
164 temp !== instruction; 165 temp !== instruction;
165 temp = temp.next) { 166 temp = temp.next) {
166 if (!generateAtUseSite.contains(temp)) return true; 167 if (!generateAtUseSite.contains(temp)) return true;
(...skipping 12 matching lines...)
179 // / \ 180 // / \
180 // / \ 181 // / \
181 // 1 expr goto 182 // 1 expr goto
182 // goto / 183 // goto /
183 // \ / 184 // \ /
184 // \ / 185 // \ /
185 // phi(expr, true|false) 186 // phi(expr, true|false)
186 if (end == null) return; 187 if (end == null) return;
187 if (end.phis.isEmpty()) return; 188 if (end.phis.isEmpty()) return;
188 if (end.phis.first !== end.phis.last) return; 189 if (end.phis.first !== end.phis.last) return;
189 HBasicBlock thenBlock = startIf.thenBlock;
190 HBasicBlock elseBlock = startIf.elseBlock; 190 HBasicBlock elseBlock = startIf.elseBlock;
191 if (end.predecessors[0] !== thenBlock) return; 191
192 if (end.predecessors[1] !== elseBlock) return; 192 if (end.predecessors[1] !== elseBlock) return;
193 HPhi phi = end.phis.first; 193 HPhi phi = end.phis.first;
194 if (!phi.inputs[1].isConstantBoolean()) return; 194 if (!phi.inputs[1].isConstantBoolean()) return;
195 if (elseBlock.first !== elseBlock.last) return;
Lasse Reichstein Nielsen 2012/06/07 12:02:47 Or "if (elseBlock.first is! HGoto) return;"?
ngeoffray 2012/06/07 12:39:18 Done.
196
197 HBasicBlock thenBlock = startIf.thenBlock;
198 // Skip trivial goto blocks.
199 while (thenBlock.successors[0] != end
200 && thenBlock.first == thenBlock.last
Lasse Reichstein Nielsen 2012/06/07 12:02:47 You could just check that thenBlock.first is HGoto
ngeoffray 2012/06/07 12:39:18 Done.
201 && thenBlock.last is HGoto) {
202 thenBlock = thenBlock.successors[0];
203 }
195 204
196 HInstruction thenInput = phi.inputs[0]; 205 HInstruction thenInput = phi.inputs[0];
197 if (hasStatement(thenBlock, thenInput)) return; 206
198 if (elseBlock.first !== elseBlock.last) return; 207 // If the [thenBlock] is already a logical operation, and does not
199 208 // have statements, we can emit a sequence of logical operation.
Lasse Reichstein Nielsen 2012/06/07 12:02:47 "have a statement" to match the call to "hasStatem
ngeoffray 2012/06/07 12:39:18 Done.
209 if (logicalOperations.contains(thenBlock.last)) {
210 if (hasStatement(thenBlock, thenBlock.last)) return;
211 assert(thenInput.usedBy.length == 1);
212 generateAtUseSite.add(thenInput);
213 } else {
214 if (end.predecessors[0] !== thenBlock) return;
215 if (hasStatement(thenBlock, thenInput)) return;
216 // If [thenInput] is defined in [thenBlock], then it is only used
217 // by [phi] and can be generated at use site.
218 if (thenInput.block === thenBlock) {
219 assert(thenInput.usedBy.length == 1);
Lasse Reichstein Nielsen 2012/06/07 12:02:47 Can't it also be used internally in the block?
ngeoffray 2012/06/07 12:39:18 No, because otherwise there would be an instructio
220 generateAtUseSite.add(thenInput);
221 }
222 }
223
200 // From now on, we have recognized a logical operation built from 224 // From now on, we have recognized a logical operation built from
201 // the builder. We don't expect the builder and the optimizers to 225 // the builder. We don't expect the builder and the optimizers to
202 // generate the then and else branches with multiple successors, 226 // generate the then and else branches with multiple successors,
203 // and the join branch to have more than two predecessors. 227 // and the join branch to have more than two predecessors.
Lasse Reichstein Nielsen 2012/06/07 12:02:47 Then check if that's the case and return if it isn
ngeoffray 2012/06/07 12:39:18 Added asserts instead.
204 228
205 // Mark the if instruction as a logical operation. 229 // Mark the if instruction as a logical operation.
206 logicalOperations.add(startIf); 230 logicalOperations.add(startIf);
207 231
208 // If the logical operation is only used by the first instruction 232 // If the logical operation is only used by the first instruction
209 // of its block, it can be generated at use site. 233 // of its block, it can be generated at use site.
210 if (phi.usedBy.length == 1 && phi.usedBy[0] === phi.block.first) { 234 if (phi.usedBy.length == 1 && phi.usedBy[0] === phi.block.first) {
211 generateAtUseSite.add(phi); 235 generateAtUseSite.add(phi);
212 } 236 }
213
214 // If [thenInput] is defined in [thenBlock], then it is only used
215 // by [phi] and can be generated at use site.
216 if (thenInput.block === thenBlock) {
217 assert(thenInput.usedBy.length == 1);
218 generateAtUseSite.add(thenInput);
219 }
220 } 237 }
221 } 238 }
222 239
223 // Precedence information for JavaScript operators. 240 // Precedence information for JavaScript operators.
224 class JSPrecedence { 241 class JSPrecedence {
225 // Used as precedence for something that's not even an expression. 242 // Used as precedence for something that's not even an expression.
226 static final int STATEMENT_PRECEDENCE = 0; 243 static final int STATEMENT_PRECEDENCE = 0;
227 // Precedences of JS operators. 244 // Precedences of JS operators.
228 static final int EXPRESSION_PRECEDENCE = 1; 245 static final int EXPRESSION_PRECEDENCE = 1;
229 static final int ASSIGNMENT_PRECEDENCE = 2; 246 static final int ASSIGNMENT_PRECEDENCE = 2;
(...skipping 63 matching lines...)
293 }; 310 };
294 } 311 }
295 312
296 class JSBinaryOperatorPrecedence { 313 class JSBinaryOperatorPrecedence {
297 final int left; 314 final int left;
298 final int right; 315 final int right;
299 const JSBinaryOperatorPrecedence(this.left, this.right); 316 const JSBinaryOperatorPrecedence(this.left, this.right);
300 // All binary operators (excluding assignment) are left associative. 317 // All binary operators (excluding assignment) are left associative.
301 int get precedence() => left; 318 int get precedence() => left;
302 } 319 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/ssa/codegen.dart ('k') | lib/compiler/implementation/ssa/tracer.dart » ('j') | no next file with comments »

Powered by Google App Engine