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 part of ssa; | 5 part of ssa; |
6 | 6 |
7 /** | 7 /** |
| 8 * Replaces some instructions with specialized versions to make codegen easier. |
| 9 * Caches codegen information on nodes. |
| 10 */ |
| 11 class SsaInstructionSelection extends HBaseVisitor { |
| 12 final Compiler compiler; |
| 13 |
| 14 SsaInstructionSelection(this.compiler); |
| 15 |
| 16 void visitGraph(HGraph graph) { |
| 17 visitDominatorTree(graph); |
| 18 } |
| 19 |
| 20 visitBasicBlock(HBasicBlock block) { |
| 21 HInstruction instruction = block.first; |
| 22 while (instruction != null) { |
| 23 HInstruction next = instruction.next; |
| 24 HInstruction replacement = instruction.accept(this); |
| 25 if (replacement != instruction) { |
| 26 block.rewrite(instruction, replacement); |
| 27 |
| 28 // If the replacement instruction does not know its source element, use |
| 29 // the source element of the instruction. |
| 30 if (replacement.sourceElement == null) { |
| 31 replacement.sourceElement = instruction.sourceElement; |
| 32 } |
| 33 if (replacement.sourcePosition == null) { |
| 34 replacement.sourcePosition = instruction.sourcePosition; |
| 35 } |
| 36 if (!replacement.isInBasicBlock()) { |
| 37 // The constant folding can return an instruction that is already |
| 38 // part of the graph (like an input), so we only add the replacement |
| 39 // if necessary. |
| 40 block.addAfter(instruction, replacement); |
| 41 // Visit the replacement as the next instruction in case it can also |
| 42 // be constant folded away. |
| 43 next = replacement; |
| 44 } |
| 45 block.remove(instruction); |
| 46 } |
| 47 instruction = next; |
| 48 } |
| 49 } |
| 50 |
| 51 HInstruction visitInstruction(HInstruction node) { |
| 52 return node; |
| 53 } |
| 54 |
| 55 HInstruction visitIs(HIs node) { |
| 56 if (node.kind == HIs.RAW_CHECK) { |
| 57 HInstruction interceptor = node.interceptor; |
| 58 if (interceptor != null) { |
| 59 JavaScriptBackend backend = compiler.backend; |
| 60 return new HIsViaInterceptor(node.typeExpression, interceptor, |
| 61 backend.boolType); |
| 62 } |
| 63 } |
| 64 return node; |
| 65 } |
| 66 |
| 67 HInstruction visitIdentity(HIdentity node) { |
| 68 node.singleComparisonOp = simpleOp(node.left, node.right); |
| 69 return node; |
| 70 } |
| 71 |
| 72 String simpleOp(HInstruction left, HInstruction right) { |
| 73 // Returns the single identity comparison (== or ===) or null if a more |
| 74 // complex expression is required. |
| 75 TypeMask leftType = left.instructionType; |
| 76 TypeMask rightType = right.instructionType; |
| 77 if (leftType.isNullable && rightType.isNullable) { |
| 78 if (left.isConstantNull() || |
| 79 right.isConstantNull() || |
| 80 (left.isPrimitive(compiler) && |
| 81 leftType == rightType)) { |
| 82 return '=='; |
| 83 } |
| 84 return null; |
| 85 } |
| 86 return '==='; |
| 87 } |
| 88 } |
| 89 |
| 90 /** |
8 * Remove [HTypeKnown] instructions from the graph, to make codegen | 91 * Remove [HTypeKnown] instructions from the graph, to make codegen |
9 * analysis easier. | 92 * analysis easier. |
10 */ | 93 */ |
11 class SsaTypeKnownRemover extends HBaseVisitor { | 94 class SsaTypeKnownRemover extends HBaseVisitor { |
12 | 95 |
13 void visitGraph(HGraph graph) { | 96 void visitGraph(HGraph graph) { |
14 visitDominatorTree(graph); | 97 visitDominatorTree(graph); |
15 } | 98 } |
16 | 99 |
17 void visitBasicBlock(HBasicBlock block) { | 100 void visitBasicBlock(HBasicBlock block) { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 // A bounds check method must not have its first input generated at use site, | 200 // A bounds check method must not have its first input generated at use site, |
118 // because it's using it twice. | 201 // because it's using it twice. |
119 void visitBoundsCheck(HBoundsCheck instruction) { | 202 void visitBoundsCheck(HBoundsCheck instruction) { |
120 analyzeInputs(instruction, 1); | 203 analyzeInputs(instruction, 1); |
121 } | 204 } |
122 | 205 |
123 // An identity operation must only have its inputs generated at use site if | 206 // An identity operation must only have its inputs generated at use site if |
124 // does not require an expression with multiple uses (because of null / | 207 // does not require an expression with multiple uses (because of null / |
125 // undefined). | 208 // undefined). |
126 void visitIdentity(HIdentity instruction) { | 209 void visitIdentity(HIdentity instruction) { |
127 HInstruction left = instruction.left; | 210 if (instruction.singleComparisonOp != null) { |
128 HInstruction right = instruction.right; | |
129 if (singleIdentityComparison(left, right, compiler) != null) { | |
130 super.visitIdentity(instruction); | 211 super.visitIdentity(instruction); |
131 } | 212 } |
132 // Do nothing. | 213 // Do nothing. |
133 } | 214 } |
134 | 215 |
135 void visitTypeConversion(HTypeConversion instruction) { | 216 void visitTypeConversion(HTypeConversion instruction) { |
136 if (!instruction.isArgumentTypeCheck | 217 if (!instruction.isArgumentTypeCheck |
137 && !instruction.isReceiverTypeCheck) { | 218 && !instruction.isReceiverTypeCheck) { |
138 assert(instruction.isCheckedModeCheck || instruction.isCastTypeCheck); | 219 assert(instruction.isCheckedModeCheck || instruction.isCastTypeCheck); |
139 // Checked mode checks and cast checks compile to code that | 220 // Checked mode checks and cast checks compile to code that |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 } | 484 } |
404 | 485 |
405 // If [thenInput] is defined in the first predecessor, then it is only used | 486 // If [thenInput] is defined in the first predecessor, then it is only used |
406 // by [phi] and can be generated at use site. | 487 // by [phi] and can be generated at use site. |
407 if (identical(thenInput.block, end.predecessors[0])) { | 488 if (identical(thenInput.block, end.predecessors[0])) { |
408 assert(thenInput.usedBy.length == 1); | 489 assert(thenInput.usedBy.length == 1); |
409 markAsGenerateAtUseSite(thenInput); | 490 markAsGenerateAtUseSite(thenInput); |
410 } | 491 } |
411 } | 492 } |
412 } | 493 } |
OLD | NEW |