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 |