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* comp) { |
632 for (intptr_t i = comp->InputCount() - 1; i >= 0; --i) { | 633 for (intptr_t i = comp->InputCount() - 1; i >= 0; --i) { |
633 Value* input = comp->InputAt(i); | 634 Value* input = comp->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(comp->env() == NULL); | |
639 // Remove the current comparison's input uses. | 641 // Remove the current comparison's input uses. |
srdjan
2013/04/15 20:27:27
Would be probable more readable if CompareInstr* w
Vyacheslav Egorov (Google)
2013/04/16 11:51:16
I think instr is somewhat confusing as well. I ren
| |
640 comparison()->UnuseAllInputs(); | 642 comparison()->UnuseAllInputs(); |
641 ASSERT(!comp->HasUses()); | 643 ASSERT(!comp->HasUses()); |
642 comparison_ = comp; | 644 comparison_ = comp; |
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 |
(...skipping 576 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 static bool RecognizeTestPattern(Value* left, Value* right) { | |
srdjan
2013/04/15 20:27:27
Add comment what pattern is being recognized.
Vyacheslav Egorov (Google)
2013/04/16 11:51:16
Done.
| |
1239 if (!right->BindsToConstant()) { | |
1240 return false; | |
1241 } | |
1242 | |
1243 const Object& value = right->BoundConstant(); | |
1244 if (!value.IsSmi() || (Smi::Cast(value).Value() != 0)) { | |
1245 return false; | |
1246 } | |
1247 | |
1248 Definition* left_defn = left->definition(); | |
1249 return left_defn->IsBinarySmiOp() && | |
1250 (left_defn->AsBinarySmiOp()->op_kind() == Token::kBIT_AND) && | |
1251 left_defn->HasOnlyUse(left); | |
1252 } | |
1253 | |
1254 | |
1236 Instruction* BranchInstr::Canonicalize(FlowGraphOptimizer* optimizer) { | 1255 Instruction* BranchInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
1237 // Only handle strict-compares. | 1256 // Only handle strict-compares. |
1238 if (comparison()->IsStrictCompare()) { | 1257 if (comparison()->IsStrictCompare()) { |
1239 Definition* replacement = comparison()->Canonicalize(optimizer); | 1258 Definition* replacement = comparison()->Canonicalize(optimizer); |
1240 if ((replacement == comparison()) || (replacement == NULL)) { | 1259 if ((replacement == comparison()) || (replacement == NULL)) { |
1241 return this; | 1260 return this; |
1242 } | 1261 } |
1243 ComparisonInstr* comp = replacement->AsComparison(); | 1262 ComparisonInstr* comp = replacement->AsComparison(); |
1244 if ((comp == NULL) || comp->CanDeoptimize()) { | 1263 if ((comp == NULL) || comp->CanDeoptimize()) { |
1245 return this; | 1264 return this; |
1246 } | 1265 } |
1247 | 1266 |
1248 // Check that comparison is not serving as a pending deoptimization target | 1267 // Check that comparison is not serving as a pending deoptimization target |
1249 // for conversions. | 1268 // for conversions. |
1250 for (intptr_t i = 0; i < comp->InputCount(); i++) { | 1269 for (intptr_t i = 0; i < comp->InputCount(); i++) { |
1251 if (comp->RequiredInputRepresentation(i) != | 1270 if (comp->RequiredInputRepresentation(i) != |
1252 comp->InputAt(i)->definition()->representation()) { | 1271 comp->InputAt(i)->definition()->representation()) { |
1253 return this; | 1272 return this; |
1254 } | 1273 } |
1255 } | 1274 } |
1256 | 1275 |
1257 // Replace the comparison if the replacement is used at this branch, | 1276 // Replace the comparison if the replacement is used at this branch, |
1258 // and has exactly one use. | 1277 // and has exactly one use. |
1259 Value* use = comp->input_use_list(); | 1278 Value* use = comp->input_use_list(); |
1260 if ((use->instruction() == this) && comp->HasOnlyUse(use)) { | 1279 if ((use->instruction() == this) && comp->HasOnlyUse(use)) { |
1261 RemoveEnvironment(); | 1280 RemoveEnvironment(); |
1262 InheritDeoptTarget(comp); | 1281 InheritDeoptTarget(comp); |
1263 | 1282 |
1283 comp->RemoveEnvironment(); | |
1264 comp->RemoveFromGraph(); | 1284 comp->RemoveFromGraph(); |
1265 SetComparison(comp); | 1285 SetComparison(comp); |
1266 if (FLAG_trace_optimization) { | 1286 if (FLAG_trace_optimization) { |
1267 OS::Print("Merging comparison v%"Pd"\n", comp->ssa_temp_index()); | 1287 OS::Print("Merging comparison v%"Pd"\n", comp->ssa_temp_index()); |
1268 } | 1288 } |
1269 // Clear the comparison's temp index and ssa temp index since the | 1289 // Clear the comparison's temp index and ssa temp index since the |
1270 // value of the comparison is not used outside the branch anymore. | 1290 // value of the comparison is not used outside the branch anymore. |
1271 ASSERT(comp->input_use_list() == NULL); | 1291 ASSERT(comp->input_use_list() == NULL); |
1272 comp->ClearSSATempIndex(); | 1292 comp->ClearSSATempIndex(); |
1273 comp->ClearTempIndex(); | 1293 comp->ClearTempIndex(); |
1274 } | 1294 } |
1295 } else if (comparison()->IsSmiEquality()) { | |
1296 BinarySmiOpInstr* bit_and = NULL; | |
1297 if (RecognizeTestPattern(comparison()->left(), comparison()->right())) { | |
1298 bit_and = comparison()->left()->definition()->AsBinarySmiOp(); | |
1299 } else if (RecognizeTestPattern(comparison()->right(), | |
1300 comparison()->left())) { | |
1301 bit_and = comparison()->right()->definition()->AsBinarySmiOp(); | |
1302 } | |
1303 | |
1304 if (bit_and != NULL) { | |
1305 TestSmiInstr* test = new TestSmiInstr(comparison()->kind(), | |
1306 bit_and->left()->Copy(), | |
1307 bit_and->right()->Copy()); | |
1308 ASSERT(!CanDeoptimize()); | |
1309 InheritDeoptTarget(bit_and); | |
1310 RemoveEnvironment(); | |
1311 SetComparison(test); | |
1312 bit_and->RemoveFromGraph(); | |
1313 } | |
1275 } | 1314 } |
1276 return this; | 1315 return this; |
1277 } | 1316 } |
1278 | 1317 |
1279 | 1318 |
1280 Definition* StrictCompareInstr::Canonicalize(FlowGraphOptimizer* optimizer) { | 1319 Definition* StrictCompareInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
1281 if (!right()->BindsToConstant()) { | 1320 if (!right()->BindsToConstant()) { |
1282 return this; | 1321 return this; |
1283 } | 1322 } |
1284 const Object& right_constant = right()->BoundConstant(); | 1323 const Object& right_constant = right()->BoundConstant(); |
(...skipping 1103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2388 default: | 2427 default: |
2389 UNREACHABLE(); | 2428 UNREACHABLE(); |
2390 } | 2429 } |
2391 return kPowRuntimeEntry; | 2430 return kPowRuntimeEntry; |
2392 } | 2431 } |
2393 | 2432 |
2394 | 2433 |
2395 #undef __ | 2434 #undef __ |
2396 | 2435 |
2397 } // namespace dart | 2436 } // namespace dart |
OLD | NEW |