| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 #include "vm/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/dart_entry.h" | 8 #include "vm/dart_entry.h" |
| 9 #include "vm/flow_graph_allocator.h" | 9 #include "vm/flow_graph_allocator.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 set_previous(NULL); | 600 set_previous(NULL); |
| 601 set_next(NULL); | 601 set_next(NULL); |
| 602 } | 602 } |
| 603 | 603 |
| 604 | 604 |
| 605 BranchInstr::BranchInstr(ComparisonInstr* comparison, bool is_checked) | 605 BranchInstr::BranchInstr(ComparisonInstr* comparison, bool is_checked) |
| 606 : comparison_(comparison), | 606 : comparison_(comparison), |
| 607 is_checked_(is_checked), | 607 is_checked_(is_checked), |
| 608 constrained_type_(NULL), | 608 constrained_type_(NULL), |
| 609 constant_target_(NULL) { | 609 constant_target_(NULL) { |
| 610 ASSERT(comparison->env() == NULL); |
| 610 for (intptr_t i = comparison->InputCount() - 1; i >= 0; --i) { | 611 for (intptr_t i = comparison->InputCount() - 1; i >= 0; --i) { |
| 611 comparison->InputAt(i)->set_instruction(this); | 612 comparison->InputAt(i)->set_instruction(this); |
| 612 } | 613 } |
| 613 } | 614 } |
| 614 | 615 |
| 615 | 616 |
| 616 void BranchInstr::RawSetInputAt(intptr_t i, Value* value) { | 617 void BranchInstr::RawSetInputAt(intptr_t i, Value* value) { |
| 617 comparison()->RawSetInputAt(i, value); | 618 comparison()->RawSetInputAt(i, value); |
| 618 } | 619 } |
| 619 | 620 |
| 620 | 621 |
| 621 // A misleadingly named function for use in template functions that replace | 622 // A misleadingly named function for use in template functions that replace |
| 622 // both definitions with definitions and branch comparisons with | 623 // both definitions with definitions and branch comparisons with |
| 623 // comparisons. In the branch case, leave the branch intact and replace its | 624 // comparisons. In the branch case, leave the branch intact and replace its |
| 624 // comparison with a new comparison not currently in the graph. | 625 // comparison with a new comparison not currently in the graph. |
| 625 void BranchInstr::ReplaceWith(ComparisonInstr* other, | 626 void BranchInstr::ReplaceWith(ComparisonInstr* other, |
| 626 ForwardInstructionIterator* ignored) { | 627 ForwardInstructionIterator* ignored) { |
| 627 SetComparison(other); | 628 SetComparison(other); |
| 628 } | 629 } |
| 629 | 630 |
| 630 | 631 |
| 631 void BranchInstr::SetComparison(ComparisonInstr* comp) { | 632 void BranchInstr::SetComparison(ComparisonInstr* new_comparison) { |
| 632 for (intptr_t i = comp->InputCount() - 1; i >= 0; --i) { | 633 for (intptr_t i = new_comparison->InputCount() - 1; i >= 0; --i) { |
| 633 Value* input = comp->InputAt(i); | 634 Value* input = new_comparison->InputAt(i); |
| 634 input->definition()->AddInputUse(input); | 635 input->definition()->AddInputUse(input); |
| 635 input->set_instruction(this); | 636 input->set_instruction(this); |
| 636 } | 637 } |
| 637 // There should be no need to copy or unuse an environment. | 638 // There should be no need to copy or unuse an environment. |
| 638 ASSERT(comparison()->env() == NULL); | 639 ASSERT(comparison()->env() == NULL); |
| 640 ASSERT(new_comparison->env() == NULL); |
| 639 // Remove the current comparison's input uses. | 641 // Remove the current comparison's input uses. |
| 640 comparison()->UnuseAllInputs(); | 642 comparison()->UnuseAllInputs(); |
| 641 ASSERT(!comp->HasUses()); | 643 ASSERT(!new_comparison->HasUses()); |
| 642 comparison_ = comp; | 644 comparison_ = new_comparison; |
| 643 } | 645 } |
| 644 | 646 |
| 645 | 647 |
| 646 // ==== Postorder graph traversal. | 648 // ==== Postorder graph traversal. |
| 647 static bool IsMarked(BlockEntryInstr* block, | 649 static bool IsMarked(BlockEntryInstr* block, |
| 648 GrowableArray<BlockEntryInstr*>* preorder) { | 650 GrowableArray<BlockEntryInstr*>* preorder) { |
| 649 // Detect that a block has been visited as part of the current | 651 // Detect that a block has been visited as part of the current |
| 650 // DiscoverBlocks (we can call DiscoverBlocks multiple times). The block | 652 // DiscoverBlocks (we can call DiscoverBlocks multiple times). The block |
| 651 // will be 'marked' by (1) having a preorder number in the range of the | 653 // will be 'marked' by (1) having a preorder number in the range of the |
| 652 // preorder array and (2) being in the preorder array at that index. | 654 // preorder array and (2) being in the preorder array at that index. |
| (...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1226 ConstantInstr* null_constant = new ConstantInstr(Object::ZoneHandle()); | 1228 ConstantInstr* null_constant = new ConstantInstr(Object::ZoneHandle()); |
| 1227 // It is ok to insert instructions before the current during | 1229 // It is ok to insert instructions before the current during |
| 1228 // forward iteration. | 1230 // forward iteration. |
| 1229 optimizer->InsertBefore(this, null_constant, NULL, Definition::kValue); | 1231 optimizer->InsertBefore(this, null_constant, NULL, Definition::kValue); |
| 1230 instantiator_type_arguments()->BindTo(null_constant); | 1232 instantiator_type_arguments()->BindTo(null_constant); |
| 1231 } | 1233 } |
| 1232 return this; | 1234 return this; |
| 1233 } | 1235 } |
| 1234 | 1236 |
| 1235 | 1237 |
| 1238 // Recognize the bpattern (a & b) == 0 where left is a bitwise and operation |
| 1239 // and right is a constant 0. |
| 1240 static bool RecognizeTestPattern(Value* left, Value* right) { |
| 1241 if (!right->BindsToConstant()) { |
| 1242 return false; |
| 1243 } |
| 1244 |
| 1245 const Object& value = right->BoundConstant(); |
| 1246 if (!value.IsSmi() || (Smi::Cast(value).Value() != 0)) { |
| 1247 return false; |
| 1248 } |
| 1249 |
| 1250 Definition* left_defn = left->definition(); |
| 1251 return left_defn->IsBinarySmiOp() && |
| 1252 (left_defn->AsBinarySmiOp()->op_kind() == Token::kBIT_AND) && |
| 1253 left_defn->HasOnlyUse(left); |
| 1254 } |
| 1255 |
| 1256 |
| 1236 Instruction* BranchInstr::Canonicalize(FlowGraphOptimizer* optimizer) { | 1257 Instruction* BranchInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
| 1237 // Only handle strict-compares. | 1258 // Only handle strict-compares. |
| 1238 if (comparison()->IsStrictCompare()) { | 1259 if (comparison()->IsStrictCompare()) { |
| 1239 Definition* replacement = comparison()->Canonicalize(optimizer); | 1260 Definition* replacement = comparison()->Canonicalize(optimizer); |
| 1240 if ((replacement == comparison()) || (replacement == NULL)) { | 1261 if ((replacement == comparison()) || (replacement == NULL)) { |
| 1241 return this; | 1262 return this; |
| 1242 } | 1263 } |
| 1243 ComparisonInstr* comp = replacement->AsComparison(); | 1264 ComparisonInstr* comp = replacement->AsComparison(); |
| 1244 if ((comp == NULL) || comp->CanDeoptimize()) { | 1265 if ((comp == NULL) || comp->CanDeoptimize()) { |
| 1245 return this; | 1266 return this; |
| 1246 } | 1267 } |
| 1247 | 1268 |
| 1248 // Check that comparison is not serving as a pending deoptimization target | 1269 // Check that comparison is not serving as a pending deoptimization target |
| 1249 // for conversions. | 1270 // for conversions. |
| 1250 for (intptr_t i = 0; i < comp->InputCount(); i++) { | 1271 for (intptr_t i = 0; i < comp->InputCount(); i++) { |
| 1251 if (comp->RequiredInputRepresentation(i) != | 1272 if (comp->RequiredInputRepresentation(i) != |
| 1252 comp->InputAt(i)->definition()->representation()) { | 1273 comp->InputAt(i)->definition()->representation()) { |
| 1253 return this; | 1274 return this; |
| 1254 } | 1275 } |
| 1255 } | 1276 } |
| 1256 | 1277 |
| 1257 // Replace the comparison if the replacement is used at this branch, | 1278 // Replace the comparison if the replacement is used at this branch, |
| 1258 // and has exactly one use. | 1279 // and has exactly one use. |
| 1259 Value* use = comp->input_use_list(); | 1280 Value* use = comp->input_use_list(); |
| 1260 if ((use->instruction() == this) && comp->HasOnlyUse(use)) { | 1281 if ((use->instruction() == this) && comp->HasOnlyUse(use)) { |
| 1261 RemoveEnvironment(); | 1282 RemoveEnvironment(); |
| 1262 InheritDeoptTarget(comp); | 1283 InheritDeoptTarget(comp); |
| 1263 | 1284 |
| 1285 comp->RemoveEnvironment(); |
| 1264 comp->RemoveFromGraph(); | 1286 comp->RemoveFromGraph(); |
| 1265 SetComparison(comp); | 1287 SetComparison(comp); |
| 1266 if (FLAG_trace_optimization) { | 1288 if (FLAG_trace_optimization) { |
| 1267 OS::Print("Merging comparison v%"Pd"\n", comp->ssa_temp_index()); | 1289 OS::Print("Merging comparison v%"Pd"\n", comp->ssa_temp_index()); |
| 1268 } | 1290 } |
| 1269 // Clear the comparison's temp index and ssa temp index since the | 1291 // Clear the comparison's temp index and ssa temp index since the |
| 1270 // value of the comparison is not used outside the branch anymore. | 1292 // value of the comparison is not used outside the branch anymore. |
| 1271 ASSERT(comp->input_use_list() == NULL); | 1293 ASSERT(comp->input_use_list() == NULL); |
| 1272 comp->ClearSSATempIndex(); | 1294 comp->ClearSSATempIndex(); |
| 1273 comp->ClearTempIndex(); | 1295 comp->ClearTempIndex(); |
| 1274 } | 1296 } |
| 1297 } else if (comparison()->IsSmiEquality()) { |
| 1298 BinarySmiOpInstr* bit_and = NULL; |
| 1299 if (RecognizeTestPattern(comparison()->left(), comparison()->right())) { |
| 1300 bit_and = comparison()->left()->definition()->AsBinarySmiOp(); |
| 1301 } else if (RecognizeTestPattern(comparison()->right(), |
| 1302 comparison()->left())) { |
| 1303 bit_and = comparison()->right()->definition()->AsBinarySmiOp(); |
| 1304 } |
| 1305 |
| 1306 if (bit_and != NULL) { |
| 1307 TestSmiInstr* test = new TestSmiInstr(comparison()->kind(), |
| 1308 bit_and->left()->Copy(), |
| 1309 bit_and->right()->Copy()); |
| 1310 ASSERT(!CanDeoptimize()); |
| 1311 InheritDeoptTarget(bit_and); |
| 1312 RemoveEnvironment(); |
| 1313 SetComparison(test); |
| 1314 bit_and->RemoveFromGraph(); |
| 1315 } |
| 1275 } | 1316 } |
| 1276 return this; | 1317 return this; |
| 1277 } | 1318 } |
| 1278 | 1319 |
| 1279 | 1320 |
| 1280 Definition* StrictCompareInstr::Canonicalize(FlowGraphOptimizer* optimizer) { | 1321 Definition* StrictCompareInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
| 1281 if (!right()->BindsToConstant()) { | 1322 if (!right()->BindsToConstant()) { |
| 1282 return this; | 1323 return this; |
| 1283 } | 1324 } |
| 1284 const Object& right_constant = right()->BoundConstant(); | 1325 const Object& right_constant = right()->BoundConstant(); |
| (...skipping 1103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2388 default: | 2429 default: |
| 2389 UNREACHABLE(); | 2430 UNREACHABLE(); |
| 2390 } | 2431 } |
| 2391 return kPowRuntimeEntry; | 2432 return kPowRuntimeEntry; |
| 2392 } | 2433 } |
| 2393 | 2434 |
| 2394 | 2435 |
| 2395 #undef __ | 2436 #undef __ |
| 2396 | 2437 |
| 2397 } // namespace dart | 2438 } // namespace dart |
| OLD | NEW |