Chromium Code Reviews| 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 #include "vm/flow_graph_allocator.h" | 5 #include "vm/flow_graph_allocator.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 #include "vm/il_printer.h" | 9 #include "vm/il_printer.h" |
| 10 #include "vm/flow_graph.h" | 10 #include "vm/flow_graph.h" |
| (...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 489 #endif | 489 #endif |
| 490 | 490 |
| 491 for (intptr_t i = 0; i < live_ranges_.length(); i++) { | 491 for (intptr_t i = 0; i < live_ranges_.length(); i++) { |
| 492 if (live_ranges_[i] != NULL) { | 492 if (live_ranges_[i] != NULL) { |
| 493 live_ranges_[i]->Print(); | 493 live_ranges_[i]->Print(); |
| 494 } | 494 } |
| 495 } | 495 } |
| 496 } | 496 } |
| 497 | 497 |
| 498 | 498 |
| 499 // Returns true if all uses of the given range inside the given loop | |
| 500 // have Any allocation policy. | |
| 501 static bool HasOnlyUnconstrainedUsesInLoop(LiveRange* range, | |
| 502 BlockInfo* loop_header) { | |
| 503 const intptr_t boundary = loop_header->last_block()->end_pos(); | |
| 504 | |
| 505 UsePosition* use = range->first_use(); | |
| 506 while ((use != NULL) && (use->pos() < boundary)) { | |
| 507 if (!use->location_slot()->Equals(Location::Any())) { | |
| 508 return false; | |
| 509 } | |
| 510 use = use->next(); | |
| 511 } | |
| 512 | |
| 513 return true; | |
| 514 } | |
| 515 | |
| 516 | |
| 499 void FlowGraphAllocator::BuildLiveRanges() { | 517 void FlowGraphAllocator::BuildLiveRanges() { |
| 500 const intptr_t block_count = postorder_.length(); | 518 const intptr_t block_count = postorder_.length(); |
| 501 ASSERT(postorder_.Last()->IsGraphEntry()); | 519 ASSERT(postorder_.Last()->IsGraphEntry()); |
| 502 for (intptr_t i = 0; i < (block_count - 1); i++) { | 520 for (intptr_t i = 0; i < (block_count - 1); i++) { |
| 503 BlockEntryInstr* block = postorder_[i]; | 521 BlockEntryInstr* block = postorder_[i]; |
| 504 | 522 |
| 505 // For every SSA value that is live out of this block, create an interval | 523 // For every SSA value that is live out of this block, create an interval |
| 506 // that covers the whole block. It will be shortened if we encounter a | 524 // that covers the whole block. It will be shortened if we encounter a |
| 507 // definition of this value in this block. | 525 // definition of this value in this block. |
| 508 for (BitVector::Iterator it(live_out_[i]); !it.Done(); it.Advance()) { | 526 for (BitVector::Iterator it(live_out_[i]); !it.Done(); it.Advance()) { |
| 509 LiveRange* range = GetLiveRange(it.Current()); | 527 LiveRange* range = GetLiveRange(it.Current()); |
| 510 range->AddUseInterval(block->start_pos(), block->end_pos()); | 528 range->AddUseInterval(block->start_pos(), block->end_pos()); |
| 511 } | 529 } |
| 512 | 530 |
| 513 // Connect outgoing phi-moves that were created in NumberInstructions | 531 // Connect outgoing phi-moves that were created in NumberInstructions |
| 514 // and find last instruction that contributes to liveness. | 532 // and find last instruction that contributes to liveness. |
| 515 Instruction* current = ConnectOutgoingPhiMoves(block); | 533 Instruction* current = ConnectOutgoingPhiMoves(block); |
| 516 | 534 |
| 517 // Now process all instructions in reverse order. | 535 // Now process all instructions in reverse order. |
| 518 while (current != block) { | 536 while (current != block) { |
| 519 // Skip parallel moves that we insert while processing instructions. | 537 // Skip parallel moves that we insert while processing instructions. |
| 520 if (!current->IsParallelMove()) { | 538 if (!current->IsParallelMove()) { |
| 521 ProcessOneInstruction(block, current); | 539 ProcessOneInstruction(block, current); |
| 522 } | 540 } |
| 523 current = current->previous(); | 541 current = current->previous(); |
| 524 } | 542 } |
| 525 | 543 |
| 544 | |
| 545 // Check if any values live into the loop can be spilled for free. | |
| 546 BlockInfo* block_info = BlockInfoAt(block->start_pos()); | |
| 547 if (block_info->is_loop_header()) { | |
| 548 for (BitVector::Iterator it(live_in_[i]); !it.Done(); it.Advance()) { | |
| 549 LiveRange* range = GetLiveRange(it.Current()); | |
| 550 if (HasOnlyUnconstrainedUsesInLoop(range, block_info)) { | |
| 551 range->MarkHasOnlyUnconstrainedUsesInLoop(block_info->loop_id()); | |
| 552 } | |
| 553 } | |
| 554 } | |
| 555 | |
| 526 ConnectIncomingPhiMoves(block); | 556 ConnectIncomingPhiMoves(block); |
| 527 } | 557 } |
| 528 | 558 |
| 529 // Process incoming parameters and constants. Do this after all other | 559 // Process incoming parameters and constants. Do this after all other |
| 530 // instructions so that safepoints for all calls have already been found. | 560 // instructions so that safepoints for all calls have already been found. |
| 531 GraphEntryInstr* graph_entry = flow_graph_.graph_entry(); | 561 GraphEntryInstr* graph_entry = flow_graph_.graph_entry(); |
| 532 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) { | 562 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) { |
| 533 Definition* defn = (*graph_entry->initial_definitions())[i]; | 563 Definition* defn = (*graph_entry->initial_definitions())[i]; |
| 534 LiveRange* range = GetLiveRange(defn->ssa_temp_index()); | 564 LiveRange* range = GetLiveRange(defn->ssa_temp_index()); |
| 535 range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos()); | 565 range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos()); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 684 void FlowGraphAllocator::ConnectIncomingPhiMoves(BlockEntryInstr* block) { | 714 void FlowGraphAllocator::ConnectIncomingPhiMoves(BlockEntryInstr* block) { |
| 685 // If this block is a join we need to add destinations of phi | 715 // If this block is a join we need to add destinations of phi |
| 686 // resolution moves to phi's live range so that register allocator will | 716 // resolution moves to phi's live range so that register allocator will |
| 687 // fill them with moves. | 717 // fill them with moves. |
| 688 JoinEntryInstr* join = block->AsJoinEntry(); | 718 JoinEntryInstr* join = block->AsJoinEntry(); |
| 689 if (join == NULL) return; | 719 if (join == NULL) return; |
| 690 | 720 |
| 691 // All uses are recorded at the start position in the block. | 721 // All uses are recorded at the start position in the block. |
| 692 const intptr_t pos = join->start_pos(); | 722 const intptr_t pos = join->start_pos(); |
| 693 | 723 |
| 724 const intptr_t is_loop_header = join->loop_info() != NULL; | |
|
Florian Schneider
2012/11/08 02:05:36
Move this down to the use.
Vyacheslav Egorov (Google)
2012/11/08 02:13:43
Done.
| |
| 725 | |
| 694 ZoneGrowableArray<PhiInstr*>* phis = join->phis(); | 726 ZoneGrowableArray<PhiInstr*>* phis = join->phis(); |
| 695 if (phis != NULL) { | 727 if (phis != NULL) { |
| 696 intptr_t move_idx = 0; | 728 intptr_t move_idx = 0; |
| 697 for (intptr_t phi_idx = 0; phi_idx < phis->length(); phi_idx++) { | 729 for (intptr_t phi_idx = 0; phi_idx < phis->length(); phi_idx++) { |
| 698 PhiInstr* phi = (*phis)[phi_idx]; | 730 PhiInstr* phi = (*phis)[phi_idx]; |
| 699 if (phi == NULL) continue; | 731 if (phi == NULL) continue; |
| 700 | 732 |
| 701 const intptr_t vreg = phi->ssa_temp_index(); | 733 const intptr_t vreg = phi->ssa_temp_index(); |
| 702 ASSERT(vreg != -1); | 734 ASSERT(vreg != -1); |
| 703 | 735 |
| 704 // Expected shape of live range: | 736 // Expected shape of live range: |
| 705 // | 737 // |
| 706 // B | 738 // B |
| 707 // phi [-------- | 739 // phi [-------- |
| 708 // | 740 // |
| 709 LiveRange* range = GetLiveRange(vreg); | 741 LiveRange* range = GetLiveRange(vreg); |
| 710 range->DefineAt(pos); // Shorten live range. | 742 range->DefineAt(pos); // Shorten live range. |
| 711 | 743 |
| 744 if (is_loop_header) range->mark_loop_phi(); | |
| 745 | |
| 712 for (intptr_t pred_idx = 0; pred_idx < phi->InputCount(); pred_idx++) { | 746 for (intptr_t pred_idx = 0; pred_idx < phi->InputCount(); pred_idx++) { |
| 713 BlockEntryInstr* pred = block->PredecessorAt(pred_idx); | 747 BlockEntryInstr* pred = block->PredecessorAt(pred_idx); |
| 714 GotoInstr* goto_instr = pred->last_instruction()->AsGoto(); | 748 GotoInstr* goto_instr = pred->last_instruction()->AsGoto(); |
| 715 ASSERT((goto_instr != NULL) && (goto_instr->HasParallelMove())); | 749 ASSERT((goto_instr != NULL) && (goto_instr->HasParallelMove())); |
| 716 MoveOperands* move = | 750 MoveOperands* move = |
| 717 goto_instr->parallel_move()->MoveOperandsAt(move_idx); | 751 goto_instr->parallel_move()->MoveOperandsAt(move_idx); |
| 718 move->set_dest(Location::PrefersRegister()); | 752 move->set_dest(Location::PrefersRegister()); |
| 719 range->AddUse(pos, move->dest_slot()); | 753 range->AddUse(pos, move->dest_slot()); |
| 720 } | 754 } |
| 721 | 755 |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1012 ASSERT(locs->in(0).Equals(Location::RequiresRegister()) || | 1046 ASSERT(locs->in(0).Equals(Location::RequiresRegister()) || |
| 1013 locs->in(0).Equals(Location::RequiresXmmRegister())); | 1047 locs->in(0).Equals(Location::RequiresXmmRegister())); |
| 1014 | 1048 |
| 1015 // Create move that will copy value between input and output. | 1049 // Create move that will copy value between input and output. |
| 1016 locs->set_out(Location::RequiresRegister()); | 1050 locs->set_out(Location::RequiresRegister()); |
| 1017 MoveOperands* move = AddMoveAt(pos, | 1051 MoveOperands* move = AddMoveAt(pos, |
| 1018 Location::RequiresRegister(), | 1052 Location::RequiresRegister(), |
| 1019 Location::Any()); | 1053 Location::Any()); |
| 1020 | 1054 |
| 1021 // Add uses to the live range of the input. | 1055 // Add uses to the live range of the input. |
| 1022 Value* input = current->InputAt(0); | 1056 Definition* input = current->InputAt(0)->definition(); |
| 1023 LiveRange* input_range = | 1057 LiveRange* input_range = |
| 1024 GetLiveRange(input->definition()->ssa_temp_index()); | 1058 GetLiveRange(input->ssa_temp_index()); |
| 1025 input_range->AddUseInterval(block->start_pos(), pos); | 1059 input_range->AddUseInterval(block->start_pos(), pos); |
| 1026 input_range->AddUse(pos, move->src_slot()); | 1060 input_range->AddUse(pos, move->src_slot()); |
| 1027 | 1061 |
| 1028 // Shorten output live range to the point of definition and add both input | 1062 // Shorten output live range to the point of definition and add both input |
| 1029 // and output uses slots to be filled by allocator. | 1063 // and output uses slots to be filled by allocator. |
| 1030 range->DefineAt(pos); | 1064 range->DefineAt(pos); |
| 1031 range->AddHintedUse(pos, out, move->src_slot()); | 1065 range->AddHintedUse(pos, out, move->src_slot()); |
| 1032 range->AddUse(pos, move->dest_slot()); | 1066 range->AddUse(pos, move->dest_slot()); |
| 1033 range->AddUse(pos, locs->in_slot(0)); | 1067 range->AddUse(pos, locs->in_slot(0)); |
| 1034 } else { | 1068 } else { |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1141 | 1175 |
| 1142 // Discover structural (reducible) loops nesting structure. | 1176 // Discover structural (reducible) loops nesting structure. |
| 1143 void FlowGraphAllocator::DiscoverLoops() { | 1177 void FlowGraphAllocator::DiscoverLoops() { |
| 1144 // This algorithm relies on the assumption that we emit blocks in reverse | 1178 // This algorithm relies on the assumption that we emit blocks in reverse |
| 1145 // postorder, so postorder number can be used to identify loop nesting. | 1179 // postorder, so postorder number can be used to identify loop nesting. |
| 1146 // | 1180 // |
| 1147 // TODO(vegorov): consider using a generic algorithm to correctly discover | 1181 // TODO(vegorov): consider using a generic algorithm to correctly discover |
| 1148 // both headers of reducible and irreducible loops. | 1182 // both headers of reducible and irreducible loops. |
| 1149 BlockInfo* current_loop = NULL; | 1183 BlockInfo* current_loop = NULL; |
| 1150 | 1184 |
| 1185 intptr_t loop_id = 0; // All loop headers have a unique id. | |
| 1186 | |
| 1151 const intptr_t block_count = postorder_.length(); | 1187 const intptr_t block_count = postorder_.length(); |
| 1152 for (intptr_t i = 0; i < block_count; i++) { | 1188 for (intptr_t i = 0; i < block_count; i++) { |
| 1153 BlockEntryInstr* block = postorder_[i]; | 1189 BlockEntryInstr* block = postorder_[i]; |
| 1154 GotoInstr* goto_instr = block->last_instruction()->AsGoto(); | 1190 GotoInstr* goto_instr = block->last_instruction()->AsGoto(); |
| 1155 if (goto_instr != NULL) { | 1191 if (goto_instr != NULL) { |
| 1156 JoinEntryInstr* successor = goto_instr->successor(); | 1192 JoinEntryInstr* successor = goto_instr->successor(); |
| 1157 if (successor->postorder_number() > i) { | 1193 if (successor->postorder_number() > i) { |
| 1158 // This is back-edge. | 1194 // This is back-edge. |
| 1159 BlockInfo* successor_info = BlockInfoAt(successor->lifetime_position()); | 1195 BlockInfo* successor_info = BlockInfoAt(successor->lifetime_position()); |
| 1160 ASSERT(successor_info->entry() == successor); | 1196 ASSERT(successor_info->entry() == successor); |
| 1161 if (!successor_info->is_loop_header() && | 1197 if (!successor_info->is_loop_header() && |
| 1162 ((current_loop == NULL) || | 1198 ((current_loop == NULL) || |
| 1163 (current_loop->entry()->postorder_number() > | 1199 (current_loop->entry()->postorder_number() > |
| 1164 successor_info->entry()->postorder_number()))) { | 1200 successor_info->entry()->postorder_number()))) { |
| 1165 ASSERT(successor_info != current_loop); | 1201 ASSERT(successor_info != current_loop); |
| 1166 | 1202 |
| 1167 successor_info->mark_loop_header(); | 1203 successor_info->mark_loop_header(); |
| 1204 successor_info->set_loop_id(loop_id++); | |
| 1205 successor_info->set_last_block(block); | |
| 1168 // For loop header loop information points to the outer loop. | 1206 // For loop header loop information points to the outer loop. |
| 1169 successor_info->set_loop(current_loop); | 1207 successor_info->set_loop(current_loop); |
| 1170 current_loop = successor_info; | 1208 current_loop = successor_info; |
| 1171 } | 1209 } |
| 1172 } | 1210 } |
| 1173 } | 1211 } |
| 1174 | 1212 |
| 1175 if (current_loop != NULL) { | 1213 if (current_loop != NULL) { |
| 1176 BlockInfo* current_info = BlockInfoAt(block->lifetime_position()); | 1214 BlockInfo* current_info = BlockInfoAt(block->lifetime_position()); |
| 1177 if (current_info == current_loop) { | 1215 if (current_info == current_loop) { |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1464 } else { | 1502 } else { |
| 1465 // No intersection between tail and [from, to). | 1503 // No intersection between tail and [from, to). |
| 1466 AddToUnallocated(tail); | 1504 AddToUnallocated(tail); |
| 1467 } | 1505 } |
| 1468 } | 1506 } |
| 1469 | 1507 |
| 1470 | 1508 |
| 1471 void FlowGraphAllocator::SpillAfter(LiveRange* range, intptr_t from) { | 1509 void FlowGraphAllocator::SpillAfter(LiveRange* range, intptr_t from) { |
| 1472 TRACE_ALLOC(OS::Print("spill %"Pd" [%"Pd", %"Pd") after %"Pd"\n", | 1510 TRACE_ALLOC(OS::Print("spill %"Pd" [%"Pd", %"Pd") after %"Pd"\n", |
| 1473 range->vreg(), range->Start(), range->End(), from)); | 1511 range->vreg(), range->Start(), range->End(), from)); |
| 1512 | |
| 1513 // When spilling the value inside the loop check if this spill can | |
| 1514 // be moved outside. | |
| 1515 BlockInfo* block_info = BlockInfoAt(from); | |
| 1516 if (block_info->is_loop_header() || (block_info->loop() != NULL)) { | |
| 1517 BlockInfo* loop_header = | |
| 1518 block_info->is_loop_header() ? block_info : block_info->loop(); | |
| 1519 | |
| 1520 if ((range->Start() <= loop_header->entry()->start_pos()) && | |
| 1521 RangeHasOnlyUnconstrainedUsesInLoop(range, loop_header->loop_id())) { | |
| 1522 ASSERT(loop_header->entry()->start_pos() <= from); | |
| 1523 from = loop_header->entry()->start_pos(); | |
| 1524 TRACE_ALLOC(OS::Print(" moved spill position to loop header %"Pd"\n", | |
| 1525 from)); | |
|
Florian Schneider
2012/11/08 02:05:36
Please make sure that this code is covered in our
Vyacheslav Egorov (Google)
2012/11/08 02:13:43
Done.
| |
| 1526 } | |
| 1527 } | |
| 1528 | |
| 1474 LiveRange* tail = range->SplitAt(from); | 1529 LiveRange* tail = range->SplitAt(from); |
| 1475 Spill(tail); | 1530 Spill(tail); |
| 1476 } | 1531 } |
| 1477 | 1532 |
| 1478 | 1533 |
| 1479 void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) { | 1534 void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) { |
| 1480 ASSERT(range->spill_slot().IsInvalid()); | 1535 ASSERT(range->spill_slot().IsInvalid()); |
| 1481 | 1536 |
| 1482 intptr_t idx = 0; | 1537 intptr_t idx = 0; |
| 1483 for (; idx < spill_slots_.length(); idx++) { | 1538 for (; idx < spill_slots_.length(); idx++) { |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1616 } | 1671 } |
| 1617 | 1672 |
| 1618 registers_[candidate].Add(unallocated); | 1673 registers_[candidate].Add(unallocated); |
| 1619 unallocated->set_assigned_location( | 1674 unallocated->set_assigned_location( |
| 1620 MakeRegisterLocation(candidate, unallocated->representation())); | 1675 MakeRegisterLocation(candidate, unallocated->representation())); |
| 1621 | 1676 |
| 1622 return true; | 1677 return true; |
| 1623 } | 1678 } |
| 1624 | 1679 |
| 1625 | 1680 |
| 1681 bool FlowGraphAllocator::RangeHasOnlyUnconstrainedUsesInLoop(LiveRange* range, | |
| 1682 intptr_t loop_id) { | |
| 1683 if (range->vreg() >= 0) { | |
| 1684 return GetLiveRange(range->vreg())->HasOnlyUnconstrainedUsesInLoop(loop_id); | |
| 1685 } | |
| 1686 return false; | |
| 1687 } | |
| 1688 | |
| 1689 | |
| 1690 bool FlowGraphAllocator::IsCheapToEvictRegisterInLoop(BlockInfo* loop, | |
| 1691 int reg) { | |
| 1692 const intptr_t loop_start = loop->entry()->start_pos(); | |
| 1693 const intptr_t loop_end = loop->last_block()->end_pos(); | |
| 1694 | |
| 1695 for (intptr_t i = 0; i < registers_[reg].length(); i++) { | |
| 1696 LiveRange* allocated = registers_[reg][i]; | |
| 1697 | |
| 1698 UseInterval* interval = allocated->finger()->first_pending_use_interval(); | |
| 1699 if (interval->Contains(loop_start)) { | |
| 1700 if (!RangeHasOnlyUnconstrainedUsesInLoop(allocated, loop->loop_id())) { | |
| 1701 return false; | |
| 1702 } | |
| 1703 } else { | |
|
Florian Schneider
2012/11/08 02:05:36
} else if (interval->start() < loop_end) {
Vyacheslav Egorov (Google)
2012/11/08 02:13:43
Done.
| |
| 1704 if (interval->start() < loop_end) { | |
| 1705 return false; | |
| 1706 } | |
| 1707 } | |
| 1708 } | |
| 1709 | |
| 1710 return true; | |
| 1711 } | |
| 1712 | |
| 1713 | |
| 1714 bool FlowGraphAllocator::HasCheapEvictionCandidate(LiveRange* phi_range) { | |
| 1715 ASSERT(phi_range->is_loop_phi()); | |
| 1716 | |
| 1717 BlockInfo* loop_header = BlockInfoAt(phi_range->Start()); | |
| 1718 ASSERT(loop_header->is_loop_header()); | |
| 1719 ASSERT(phi_range->Start() == loop_header->entry()->start_pos()); | |
| 1720 | |
| 1721 for (int reg = 0; reg < NumberOfRegisters(); ++reg) { | |
|
Florian Schneider
2012/11/08 02:05:36
intptr_t?
Vyacheslav Egorov (Google)
2012/11/08 02:13:43
Done.
| |
| 1722 if (blocked_registers_[reg]) continue; | |
| 1723 if (IsCheapToEvictRegisterInLoop(loop_header, reg)) { | |
| 1724 return true; | |
| 1725 } | |
| 1726 } | |
| 1727 | |
| 1728 return false; | |
| 1729 } | |
| 1730 | |
| 1731 | |
| 1626 void FlowGraphAllocator::AllocateAnyRegister(LiveRange* unallocated) { | 1732 void FlowGraphAllocator::AllocateAnyRegister(LiveRange* unallocated) { |
| 1733 // If a loop phi has no register uses we might still want to allocate it | |
|
Florian Schneider
2012/11/08 02:05:36
Please split this 4-line sentence into simpler phr
Vyacheslav Egorov (Google)
2012/11/08 02:13:43
Done.
| |
| 1734 // to the register to minimize amount of memory moves on the back edge | |
| 1735 // especially if there is a register blocked by a range that can be | |
| 1736 // cheaply evicated i.e. it has no register beneficial uses inside the | |
|
Florian Schneider
2012/11/08 02:05:36
s/evicated/evicted/g
Vyacheslav Egorov (Google)
2012/11/08 02:13:43
Done.
| |
| 1737 // loop. | |
| 1627 UsePosition* register_use = | 1738 UsePosition* register_use = |
| 1628 unallocated->finger()->FirstRegisterUse(unallocated->Start()); | 1739 unallocated->finger()->FirstRegisterUse(unallocated->Start()); |
| 1629 if (register_use == NULL) { | 1740 if ((register_use == NULL) && |
| 1741 !(unallocated->is_loop_phi() && HasCheapEvictionCandidate(unallocated))) { | |
|
Florian Schneider
2012/11/08 02:05:36
Please make sure that this part is hit in our test
Vyacheslav Egorov (Google)
2012/11/08 02:13:43
Done.
| |
| 1630 Spill(unallocated); | 1742 Spill(unallocated); |
| 1631 return; | 1743 return; |
| 1632 } | 1744 } |
| 1633 | 1745 |
| 1634 intptr_t candidate = kNoRegister; | 1746 intptr_t candidate = kNoRegister; |
| 1635 intptr_t free_until = 0; | 1747 intptr_t free_until = 0; |
| 1636 intptr_t blocked_at = kMaxPosition; | 1748 intptr_t blocked_at = kMaxPosition; |
| 1637 | 1749 |
| 1638 for (int reg = 0; reg < NumberOfRegisters(); ++reg) { | 1750 for (int reg = 0; reg < NumberOfRegisters(); ++reg) { |
| 1639 if (blocked_registers_[reg]) continue; | 1751 if (blocked_registers_[reg]) continue; |
| 1640 if (UpdateFreeUntil(reg, unallocated, &free_until, &blocked_at)) { | 1752 if (UpdateFreeUntil(reg, unallocated, &free_until, &blocked_at)) { |
| 1641 candidate = reg; | 1753 candidate = reg; |
| 1642 } | 1754 } |
| 1643 } | 1755 } |
| 1644 | 1756 |
| 1645 if (free_until < register_use->pos()) { | 1757 const intptr_t register_use_pos = |
| 1758 (register_use != NULL) ? register_use->pos() | |
| 1759 : unallocated->Start(); | |
| 1760 if (free_until < register_use_pos) { | |
| 1646 // Can't acquire free register. Spill until we really need one. | 1761 // Can't acquire free register. Spill until we really need one. |
| 1647 ASSERT(unallocated->Start() < ToInstructionStart(register_use->pos())); | 1762 ASSERT(unallocated->Start() < ToInstructionStart(register_use_pos)); |
| 1648 SpillBetween(unallocated, unallocated->Start(), register_use->pos()); | 1763 SpillBetween(unallocated, unallocated->Start(), register_use->pos()); |
| 1649 return; | 1764 return; |
| 1650 } | 1765 } |
| 1651 | 1766 |
| 1652 TRACE_ALLOC(OS::Print("assigning blocked register ")); | 1767 TRACE_ALLOC(OS::Print("assigning blocked register ")); |
| 1653 TRACE_ALLOC(MakeRegisterLocation(candidate, Location::kDouble).Print()); | 1768 TRACE_ALLOC(MakeRegisterLocation(candidate, Location::kDouble).Print()); |
| 1654 TRACE_ALLOC(OS::Print(" to live range %"Pd" until %"Pd"\n", | 1769 TRACE_ALLOC(OS::Print(" to live range %"Pd" until %"Pd"\n", |
| 1655 unallocated->vreg(), blocked_at)); | 1770 unallocated->vreg(), blocked_at)); |
| 1656 | 1771 |
| 1657 if (blocked_at < unallocated->End()) { | 1772 if (blocked_at < unallocated->End()) { |
| (...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2235 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", | 2350 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", |
| 2236 function.ToFullyQualifiedCString()); | 2351 function.ToFullyQualifiedCString()); |
| 2237 FlowGraphPrinter printer(flow_graph_, true); | 2352 FlowGraphPrinter printer(flow_graph_, true); |
| 2238 printer.PrintBlocks(); | 2353 printer.PrintBlocks(); |
| 2239 OS::Print("----------------------------------------------\n"); | 2354 OS::Print("----------------------------------------------\n"); |
| 2240 } | 2355 } |
| 2241 } | 2356 } |
| 2242 | 2357 |
| 2243 | 2358 |
| 2244 } // namespace dart | 2359 } // namespace dart |
| OLD | NEW |