| 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 |