OLD | NEW |
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 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 // merged. If instructions occur in the expected order, they are | 125 // merged. If instructions occur in the expected order, they are |
126 // included in the expression. | 126 // included in the expression. |
127 | 127 |
128 // The expectedInputs list holds non-trivial instructions that may | 128 // The expectedInputs list holds non-trivial instructions that may |
129 // be generated at their use site, if they occur in the correct order. | 129 // be generated at their use site, if they occur in the correct order. |
130 if (expectedInputs == null) expectedInputs = new List<HInstruction>(); | 130 if (expectedInputs == null) expectedInputs = new List<HInstruction>(); |
131 | 131 |
132 // Pop instructions from expectedInputs until instruction is found. | 132 // Pop instructions from expectedInputs until instruction is found. |
133 // Return true if it is found, or false if not. | 133 // Return true if it is found, or false if not. |
134 bool findInInputsAndPopNonMatching(HInstruction instruction) { | 134 bool findInInputsAndPopNonMatching(HInstruction instruction) { |
135 while (!expectedInputs.isEmpty()) { | 135 while (!expectedInputs.isEmpty) { |
136 HInstruction nextInput = expectedInputs.removeLast(); | 136 HInstruction nextInput = expectedInputs.removeLast(); |
137 assert(!generateAtUseSite.contains(nextInput)); | 137 assert(!generateAtUseSite.contains(nextInput)); |
138 assert(nextInput.usedBy.length == 1); | 138 assert(nextInput.usedBy.length == 1); |
139 if (identical(nextInput, instruction)) { | 139 if (identical(nextInput, instruction)) { |
140 return true; | 140 return true; |
141 } | 141 } |
142 } | 142 } |
143 return false; | 143 return false; |
144 } | 144 } |
145 | 145 |
146 block.last.accept(this); | 146 block.last.accept(this); |
147 for (HInstruction instruction = block.last.previous; | 147 for (HInstruction instruction = block.last.previous; |
148 instruction != null; | 148 instruction != null; |
149 instruction = instruction.previous) { | 149 instruction = instruction.previous) { |
150 if (generateAtUseSite.contains(instruction)) { | 150 if (generateAtUseSite.contains(instruction)) { |
151 continue; | 151 continue; |
152 } | 152 } |
153 if (instruction.isCodeMotionInvariant()) { | 153 if (instruction.isCodeMotionInvariant()) { |
154 markAsGenerateAtUseSite(instruction); | 154 markAsGenerateAtUseSite(instruction); |
155 continue; | 155 continue; |
156 } | 156 } |
157 if (instruction.isJsStatement(types)) { | 157 if (instruction.isJsStatement(types)) { |
158 expectedInputs.clear(); | 158 expectedInputs.clear(); |
159 } | 159 } |
160 // See if the current instruction is the next non-trivial | 160 // See if the current instruction is the next non-trivial |
161 // expected input. | 161 // expected input. |
162 if (findInInputsAndPopNonMatching(instruction)) { | 162 if (findInInputsAndPopNonMatching(instruction)) { |
163 tryGenerateAtUseSite(instruction); | 163 tryGenerateAtUseSite(instruction); |
164 } else { | 164 } else { |
165 assert(expectedInputs.isEmpty()); | 165 assert(expectedInputs.isEmpty); |
166 } | 166 } |
167 instruction.accept(this); | 167 instruction.accept(this); |
168 } | 168 } |
169 | 169 |
170 if (block.predecessors.length == 1 | 170 if (block.predecessors.length == 1 |
171 && isBlockSinglePredecessor(block.predecessors[0])) { | 171 && isBlockSinglePredecessor(block.predecessors[0])) { |
172 assert(block.phis.isEmpty()); | 172 assert(block.phis.isEmpty); |
173 tryMergingExpressions(block.predecessors[0]); | 173 tryMergingExpressions(block.predecessors[0]); |
174 } else { | 174 } else { |
175 expectedInputs = null; | 175 expectedInputs = null; |
176 } | 176 } |
177 } | 177 } |
178 } | 178 } |
179 | 179 |
180 /** | 180 /** |
181 * Detect control flow arising from short-circuit logical and | 181 * Detect control flow arising from short-circuit logical and |
182 * conditional operators, and prepare the program to be generated | 182 * conditional operators, and prepare the program to be generated |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 // 1 expr2 | | 269 // 1 expr2 | |
270 // goto goto | | 270 // goto goto | |
271 // \ / | | 271 // \ / | |
272 // \ / | | 272 // \ / | |
273 // phi1(expr2, true|false) | 273 // phi1(expr2, true|false) |
274 // \ | | 274 // \ | |
275 // \ | | 275 // \ | |
276 // phi(phi1, true|false) | 276 // phi(phi1, true|false) |
277 | 277 |
278 if (end == null) return; | 278 if (end == null) return; |
279 if (end.phis.isEmpty()) return; | 279 if (end.phis.isEmpty) return; |
280 if (!identical(end.phis.first, end.phis.last)) return; | 280 if (!identical(end.phis.first, end.phis.last)) return; |
281 HBasicBlock elseBlock = startIf.elseBlock; | 281 HBasicBlock elseBlock = startIf.elseBlock; |
282 | 282 |
283 if (!identical(end.predecessors[1], elseBlock)) return; | 283 if (!identical(end.predecessors[1], elseBlock)) return; |
284 HPhi phi = end.phis.first; | 284 HPhi phi = end.phis.first; |
285 HInstruction thenInput = phi.inputs[0]; | 285 HInstruction thenInput = phi.inputs[0]; |
286 HInstruction elseInput = phi.inputs[1]; | 286 HInstruction elseInput = phi.inputs[1]; |
287 if (thenInput.isJsStatement(types) || | 287 if (thenInput.isJsStatement(types) || |
288 elseInput.isJsStatement(types)) return; | 288 elseInput.isJsStatement(types)) return; |
289 | 289 |
(...skipping 11 matching lines...) Expand all Loading... |
301 // have any statement and its join block is [end], we can emit a | 301 // have any statement and its join block is [end], we can emit a |
302 // sequence of control flow operation. | 302 // sequence of control flow operation. |
303 if (controlFlowOperators.contains(thenBlock.last)) { | 303 if (controlFlowOperators.contains(thenBlock.last)) { |
304 HIf otherIf = thenBlock.last; | 304 HIf otherIf = thenBlock.last; |
305 if (!identical(otherIf.joinBlock, end)) { | 305 if (!identical(otherIf.joinBlock, end)) { |
306 // This could be a join block that just feeds into our join block. | 306 // This could be a join block that just feeds into our join block. |
307 HBasicBlock otherJoin = otherIf.joinBlock; | 307 HBasicBlock otherJoin = otherIf.joinBlock; |
308 if (otherJoin.first != otherJoin.last) return; | 308 if (otherJoin.first != otherJoin.last) return; |
309 if (otherJoin.successors.length != 1) return; | 309 if (otherJoin.successors.length != 1) return; |
310 if (otherJoin.successors[0] != end) return; | 310 if (otherJoin.successors[0] != end) return; |
311 if (otherJoin.phis.isEmpty()) return; | 311 if (otherJoin.phis.isEmpty) return; |
312 if (!identical(otherJoin.phis.first, otherJoin.phis.last)) return; | 312 if (!identical(otherJoin.phis.first, otherJoin.phis.last)) return; |
313 HPhi otherPhi = otherJoin.phis.first; | 313 HPhi otherPhi = otherJoin.phis.first; |
314 if (thenInput != otherPhi) return; | 314 if (thenInput != otherPhi) return; |
315 if (elseInput != otherPhi.inputs[1]) return; | 315 if (elseInput != otherPhi.inputs[1]) return; |
316 } | 316 } |
317 if (hasAnyStatement(thenBlock, otherIf)) return; | 317 if (hasAnyStatement(thenBlock, otherIf)) return; |
318 } else { | 318 } else { |
319 if (!identical(end.predecessors[0], thenBlock)) return; | 319 if (!identical(end.predecessors[0], thenBlock)) return; |
320 if (hasAnyStatement(thenBlock, thenInput)) return; | 320 if (hasAnyStatement(thenBlock, thenInput)) return; |
321 assert(thenBlock.successors.length == 1); | 321 assert(thenBlock.successors.length == 1); |
(...skipping 18 matching lines...) Expand all Loading... |
340 } | 340 } |
341 | 341 |
342 // If [thenInput] is defined in the first predecessor, then it is only used | 342 // If [thenInput] is defined in the first predecessor, then it is only used |
343 // by [phi] and can be generated at use site. | 343 // by [phi] and can be generated at use site. |
344 if (identical(thenInput.block, end.predecessors[0])) { | 344 if (identical(thenInput.block, end.predecessors[0])) { |
345 assert(thenInput.usedBy.length == 1); | 345 assert(thenInput.usedBy.length == 1); |
346 markAsGenerateAtUseSite(thenInput); | 346 markAsGenerateAtUseSite(thenInput); |
347 } | 347 } |
348 } | 348 } |
349 } | 349 } |
OLD | NEW |