| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 interface OptimizationPhase { | 5 interface OptimizationPhase { |
| 6 String get name(); | 6 String get name(); |
| 7 void visitGraph(HGraph graph); | 7 void visitGraph(HGraph graph); |
| 8 } | 8 } |
| 9 | 9 |
| 10 class SsaOptimizerTask extends CompilerTask { | 10 class SsaOptimizerTask extends CompilerTask { |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 HInstruction visitInstruction(HInstruction node) { | 123 HInstruction visitInstruction(HInstruction node) { |
| 124 return node; | 124 return node; |
| 125 } | 125 } |
| 126 | 126 |
| 127 HInstruction visitBoolify(HBoolify node) { | 127 HInstruction visitBoolify(HBoolify node) { |
| 128 List<HInstruction> inputs = node.inputs; | 128 List<HInstruction> inputs = node.inputs; |
| 129 assert(inputs.length == 1); | 129 assert(inputs.length == 1); |
| 130 HInstruction input = inputs[0]; | 130 HInstruction input = inputs[0]; |
| 131 if (input.isBoolean()) return input; | 131 if (input.isBoolean()) return input; |
| 132 // All values !== true are boolified to false. | 132 // All values !== true are boolified to false. |
| 133 if (input.propagatedType.isUseful()) { | 133 Type type = input.propagatedType.computeType(compiler); |
| 134 if (type !== null && type.element !== compiler.boolClass) { |
| 134 return graph.addConstantBool(false); | 135 return graph.addConstantBool(false); |
| 135 } | 136 } |
| 136 return node; | 137 return node; |
| 137 } | 138 } |
| 138 | 139 |
| 139 HInstruction visitNot(HNot node) { | 140 HInstruction visitNot(HNot node) { |
| 140 List<HInstruction> inputs = node.inputs; | 141 List<HInstruction> inputs = node.inputs; |
| 141 assert(inputs.length == 1); | 142 assert(inputs.length == 1); |
| 142 HInstruction input = inputs[0]; | 143 HInstruction input = inputs[0]; |
| 143 if (input is HConstant) { | 144 if (input is HConstant) { |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 } else if (right.isConstantNull()) { | 431 } else if (right.isConstantNull()) { |
| 431 return graph.addConstantBool(false); | 432 return graph.addConstantBool(false); |
| 432 } else { | 433 } else { |
| 433 // We can just emit an identity check because the type does | 434 // We can just emit an identity check because the type does |
| 434 // not implement operator=. | 435 // not implement operator=. |
| 435 return foldBuiltinEqualsCheck(node); | 436 return foldBuiltinEqualsCheck(node); |
| 436 } | 437 } |
| 437 } | 438 } |
| 438 | 439 |
| 439 if (right.isConstantNull()) { | 440 if (right.isConstantNull()) { |
| 440 if (left.propagatedType.isUseful()) { | 441 if (left.propagatedType.isPrimitive()) { |
| 441 return graph.addConstantBool(false); | 442 return graph.addConstantBool(false); |
| 442 } else { | 443 } else { |
| 443 // TODO(floitsch): cache interceptors. | 444 // TODO(floitsch): cache interceptors. |
| 444 Interceptors interceptors = compiler.builder.interceptors; | 445 Interceptors interceptors = compiler.builder.interceptors; |
| 445 Element equalsElement = interceptors.getEqualsInterceptor(); | 446 Element equalsElement = interceptors.getEqualsInterceptor(); |
| 446 // If we have a different element than [equalsElement], we | 447 // If we have a different element than [equalsElement], we |
| 447 // don't need to optimize this instruction to use another | 448 // don't need to optimize this instruction to use another |
| 448 // element: we know the element is either eqNull or eqNullB. | 449 // element: we know the element is either eqNull or eqNullB. |
| 449 if (node.element === equalsElement) { | 450 if (node.element === equalsElement) { |
| 450 Element targetElement = interceptors.getEqualsNullInterceptor(); | 451 Element targetElement = interceptors.getEqualsNullInterceptor(); |
| (...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1047 newInput = new HTypeConversion(convertedType, input); | 1048 newInput = new HTypeConversion(convertedType, input); |
| 1048 dominator.addBefore(dominator.first, newInput); | 1049 dominator.addBefore(dominator.first, newInput); |
| 1049 } | 1050 } |
| 1050 user.changeUse(input, newInput); | 1051 user.changeUse(input, newInput); |
| 1051 } | 1052 } |
| 1052 } | 1053 } |
| 1053 } | 1054 } |
| 1054 | 1055 |
| 1055 void visitIs(HIs instruction) { | 1056 void visitIs(HIs instruction) { |
| 1056 HInstruction input = instruction.expression; | 1057 HInstruction input = instruction.expression; |
| 1058 HType convertedType = |
| 1059 new HType.fromBoundedType(instruction.typeExpression, compiler); |
| 1060 if (convertedType === null) return; |
| 1061 |
| 1057 List<HInstruction> ifUsers = <HInstruction>[]; | 1062 List<HInstruction> ifUsers = <HInstruction>[]; |
| 1058 List<HInstruction> notIfUsers = <HInstruction>[]; | 1063 List<HInstruction> notIfUsers = <HInstruction>[]; |
| 1059 | 1064 |
| 1060 for (HInstruction user in instruction.usedBy) { | 1065 for (HInstruction user in instruction.usedBy) { |
| 1061 if (user is HIf) { | 1066 if (user is HIf) { |
| 1062 ifUsers.add(user); | 1067 ifUsers.add(user); |
| 1063 } else if (user is HNot) { | 1068 } else if (user is HNot) { |
| 1064 for (HInstruction notUser in user.usedBy) { | 1069 for (HInstruction notUser in user.usedBy) { |
| 1065 if (notUser is HIf) notIfUsers.add(notUser); | 1070 if (notUser is HIf) notIfUsers.add(notUser); |
| 1066 } | 1071 } |
| 1067 } | 1072 } |
| 1068 } | 1073 } |
| 1069 | 1074 |
| 1070 if (ifUsers.isEmpty() && notIfUsers.isEmpty()) return; | 1075 if (ifUsers.isEmpty() && notIfUsers.isEmpty()) return; |
| 1071 | 1076 |
| 1072 HType convertedType = | |
| 1073 new HType.fromBoundedType(instruction.typeExpression, compiler); | |
| 1074 | |
| 1075 for (HIf ifUser in ifUsers) { | 1077 for (HIf ifUser in ifUsers) { |
| 1076 changeUsesDominatedBy(ifUser.thenBlock, input, convertedType); | 1078 changeUsesDominatedBy(ifUser.thenBlock, input, convertedType); |
| 1077 // TODO(ngeoffray): Also change uses for the else block on a HType | 1079 // TODO(ngeoffray): Also change uses for the else block on a HType |
| 1078 // that knows it is not of a specific Type. | 1080 // that knows it is not of a specific Type. |
| 1079 } | 1081 } |
| 1080 | 1082 |
| 1081 for (HIf ifUser in notIfUsers) { | 1083 for (HIf ifUser in notIfUsers) { |
| 1082 if (ifUser.hasElse) { | 1084 if (ifUser.hasElse) { |
| 1083 changeUsesDominatedBy(ifUser.elseBlock, input, convertedType); | 1085 changeUsesDominatedBy(ifUser.elseBlock, input, convertedType); |
| 1084 } else if (ifUser.joinBlock.predecessors.length == 1) { | 1086 } else if (ifUser.joinBlock.predecessors.length == 1) { |
| 1085 // If the join block has only one predecessor, then we know | 1087 // If the join block has only one predecessor, then we know |
| 1086 // the if block terminates. So any use of the instruction | 1088 // the if block terminates. So any use of the instruction |
| 1087 // after the join block should be changed to the new | 1089 // after the join block should be changed to the new |
| 1088 // instruction. | 1090 // instruction. |
| 1089 changeUsesDominatedBy(ifUser.joinBlock, input, convertedType); | 1091 changeUsesDominatedBy(ifUser.joinBlock, input, convertedType); |
| 1090 } | 1092 } |
| 1091 // TODO(ngeoffray): Also change uses for the then block on a HType | 1093 // TODO(ngeoffray): Also change uses for the then block on a HType |
| 1092 // that knows it is not of a specific Type. | 1094 // that knows it is not of a specific Type. |
| 1093 } | 1095 } |
| 1094 } | 1096 } |
| 1095 } | 1097 } |
| OLD | NEW |