Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(420)

Side by Side Diff: runtime/vm/flow_graph_allocator.cc

Issue 11418135: Heuristically predict interference on the back edge and use it to minimize number of register reshu… (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_allocator.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 } 55 }
56 56
57 57
58 static intptr_t ToInstructionEnd(intptr_t pos) { 58 static intptr_t ToInstructionEnd(intptr_t pos) {
59 return (pos | 1); 59 return (pos | 1);
60 } 60 }
61 61
62 62
63 FlowGraphAllocator::FlowGraphAllocator(const FlowGraph& flow_graph) 63 FlowGraphAllocator::FlowGraphAllocator(const FlowGraph& flow_graph)
64 : flow_graph_(flow_graph), 64 : flow_graph_(flow_graph),
65 reaching_defs_(flow_graph),
65 mint_values_(NULL), 66 mint_values_(NULL),
66 block_order_(flow_graph.reverse_postorder()), 67 block_order_(flow_graph.reverse_postorder()),
67 postorder_(flow_graph.postorder()), 68 postorder_(flow_graph.postorder()),
68 live_out_(block_order_.length()), 69 live_out_(block_order_.length()),
69 kill_(block_order_.length()), 70 kill_(block_order_.length()),
70 live_in_(block_order_.length()), 71 live_in_(block_order_.length()),
71 vreg_count_(flow_graph.max_virtual_register_number()), 72 vreg_count_(flow_graph.max_virtual_register_number()),
72 live_ranges_(flow_graph.max_virtual_register_number()), 73 live_ranges_(flow_graph.max_virtual_register_number()),
73 cpu_regs_(), 74 cpu_regs_(),
74 xmm_regs_(), 75 xmm_regs_(),
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 Instruction* current = it.Current(); 140 Instruction* current = it.Current();
140 141
141 // Handle definitions. 142 // Handle definitions.
142 Definition* current_def = current->AsDefinition(); 143 Definition* current_def = current->AsDefinition();
143 if ((current_def != NULL) && current_def->HasSSATemp()) { 144 if ((current_def != NULL) && current_def->HasSSATemp()) {
144 kill->Add(current_def->ssa_temp_index()); 145 kill->Add(current_def->ssa_temp_index());
145 live_in->Remove(current_def->ssa_temp_index()); 146 live_in->Remove(current_def->ssa_temp_index());
146 } 147 }
147 148
148 // Handle uses. 149 // Handle uses.
150 LocationSummary* locs = current->locs();
151 ASSERT(locs->input_count() == current->InputCount());
149 for (intptr_t j = 0; j < current->InputCount(); j++) { 152 for (intptr_t j = 0; j < current->InputCount(); j++) {
150 Value* input = current->InputAt(j); 153 Value* input = current->InputAt(j);
151 const intptr_t use = input->definition()->ssa_temp_index(); 154 const intptr_t use = input->definition()->ssa_temp_index();
155
156 ASSERT(!locs->in(j).IsConstant() || input->BindsToConstant());
157 if (locs->in(j).IsConstant()) continue;
158
152 live_in->Add(use); 159 live_in->Add(use);
153 } 160 }
154 161
155 // Add non-argument uses from the deoptimization environment (pushed 162 // Add non-argument uses from the deoptimization environment (pushed
156 // arguments are not allocated by the register allocator). 163 // arguments are not allocated by the register allocator).
157 if (current->env() != NULL) { 164 if (current->env() != NULL) {
158 for (Environment::DeepIterator env_it(current->env()); 165 for (Environment::DeepIterator env_it(current->env());
159 !env_it.Done(); 166 !env_it.Done();
160 env_it.Advance()) { 167 env_it.Advance()) {
161 Value* value = env_it.CurrentValue(); 168 Value* value = env_it.CurrentValue();
(...skipping 13 matching lines...) Expand all
175 PhiInstr* phi = (*join->phis())[j]; 182 PhiInstr* phi = (*join->phis())[j];
176 if (phi == NULL) continue; 183 if (phi == NULL) continue;
177 184
178 kill->Add(phi->ssa_temp_index()); 185 kill->Add(phi->ssa_temp_index());
179 live_in->Remove(phi->ssa_temp_index()); 186 live_in->Remove(phi->ssa_temp_index());
180 187
181 // If phi-operand is not defined by a predecessor it must be marked 188 // If phi-operand is not defined by a predecessor it must be marked
182 // live-in for a predecessor. 189 // live-in for a predecessor.
183 for (intptr_t k = 0; k < phi->InputCount(); k++) { 190 for (intptr_t k = 0; k < phi->InputCount(); k++) {
184 Value* val = phi->InputAt(k); 191 Value* val = phi->InputAt(k);
192 if (val->BindsToConstant()) continue;
193
185 BlockEntryInstr* pred = block->PredecessorAt(k); 194 BlockEntryInstr* pred = block->PredecessorAt(k);
186 const intptr_t use = val->definition()->ssa_temp_index(); 195 const intptr_t use = val->definition()->ssa_temp_index();
187 if (!kill_[pred->postorder_number()]->Contains(use)) { 196 if (!kill_[pred->postorder_number()]->Contains(use)) {
188 live_in_[pred->postorder_number()]->Add(use); 197 live_in_[pred->postorder_number()]->Add(use);
189 } 198 }
190 } 199 }
191 } 200 }
192 } 201 }
193 } 202 }
194 } 203 }
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 use = use->next(); 519 use = use->next();
511 } 520 }
512 521
513 return true; 522 return true;
514 } 523 }
515 524
516 525
517 void FlowGraphAllocator::BuildLiveRanges() { 526 void FlowGraphAllocator::BuildLiveRanges() {
518 const intptr_t block_count = postorder_.length(); 527 const intptr_t block_count = postorder_.length();
519 ASSERT(postorder_.Last()->IsGraphEntry()); 528 ASSERT(postorder_.Last()->IsGraphEntry());
529 BitVector* current_interference_set = NULL;
520 for (intptr_t i = 0; i < (block_count - 1); i++) { 530 for (intptr_t i = 0; i < (block_count - 1); i++) {
521 BlockEntryInstr* block = postorder_[i]; 531 BlockEntryInstr* block = postorder_[i];
522 532
533 BlockInfo* block_info = BlockInfoAt(block->start_pos());
534
523 // For every SSA value that is live out of this block, create an interval 535 // For every SSA value that is live out of this block, create an interval
524 // that covers the whole block. It will be shortened if we encounter a 536 // that covers the whole block. It will be shortened if we encounter a
525 // definition of this value in this block. 537 // definition of this value in this block.
526 for (BitVector::Iterator it(live_out_[i]); !it.Done(); it.Advance()) { 538 for (BitVector::Iterator it(live_out_[i]); !it.Done(); it.Advance()) {
527 LiveRange* range = GetLiveRange(it.Current()); 539 LiveRange* range = GetLiveRange(it.Current());
528 range->AddUseInterval(block->start_pos(), block->end_pos()); 540 range->AddUseInterval(block->start_pos(), block->end_pos());
529 } 541 }
530 542
543 BlockInfo* loop_header = block_info->loop_header();
544 if ((loop_header != NULL) && (loop_header->last_block() == block)) {
545 current_interference_set =
546 new BitVector(flow_graph_.max_virtual_register_number());
547 ASSERT(loop_header->backedge_interference() == NULL);
548 loop_header->set_backedge_interference(
549 current_interference_set);
550 }
551
531 // Connect outgoing phi-moves that were created in NumberInstructions 552 // Connect outgoing phi-moves that were created in NumberInstructions
532 // and find last instruction that contributes to liveness. 553 // and find last instruction that contributes to liveness.
533 Instruction* current = ConnectOutgoingPhiMoves(block); 554 Instruction* current = ConnectOutgoingPhiMoves(block,
555 current_interference_set);
534 556
535 // Now process all instructions in reverse order. 557 // Now process all instructions in reverse order.
536 while (current != block) { 558 while (current != block) {
537 // Skip parallel moves that we insert while processing instructions. 559 // Skip parallel moves that we insert while processing instructions.
538 if (!current->IsParallelMove()) { 560 if (!current->IsParallelMove()) {
539 ProcessOneInstruction(block, current); 561 ProcessOneInstruction(block, current, current_interference_set);
540 } 562 }
541 current = current->previous(); 563 current = current->previous();
542 } 564 }
543 565
544 566
545 // Check if any values live into the loop can be spilled for free. 567 // 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()) { 568 if (block_info->is_loop_header()) {
569 current_interference_set = NULL;
548 for (BitVector::Iterator it(live_in_[i]); !it.Done(); it.Advance()) { 570 for (BitVector::Iterator it(live_in_[i]); !it.Done(); it.Advance()) {
549 LiveRange* range = GetLiveRange(it.Current()); 571 LiveRange* range = GetLiveRange(it.Current());
550 if (HasOnlyUnconstrainedUsesInLoop(range, block_info)) { 572 if (HasOnlyUnconstrainedUsesInLoop(range, block_info)) {
551 range->MarkHasOnlyUnconstrainedUsesInLoop(block_info->loop_id()); 573 range->MarkHasOnlyUnconstrainedUsesInLoop(block_info->loop_id());
552 } 574 }
553 } 575 }
554 } 576 }
555 577
556 ConnectIncomingPhiMoves(block); 578 ConnectIncomingPhiMoves(block);
557 } 579 }
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
643 // 665 //
644 // i i' 666 // i i'
645 // value --*--) 667 // value --*--)
646 // 668 //
647 // can be read as: use interval for value starts somewhere before instruction 669 // can be read as: use interval for value starts somewhere before instruction
648 // and extends until currently processed instruction, there is a use of value 670 // and extends until currently processed instruction, there is a use of value
649 // at the start of the instruction. 671 // at the start of the instruction.
650 // 672 //
651 673
652 Instruction* FlowGraphAllocator::ConnectOutgoingPhiMoves( 674 Instruction* FlowGraphAllocator::ConnectOutgoingPhiMoves(
653 BlockEntryInstr* block) { 675 BlockEntryInstr* block, BitVector* interfere_at_backedge) {
654 Instruction* last = block->last_instruction(); 676 Instruction* last = block->last_instruction();
655 677
656 GotoInstr* goto_instr = last->AsGoto(); 678 GotoInstr* goto_instr = last->AsGoto();
657 if (goto_instr == NULL) return last; 679 if (goto_instr == NULL) return last;
658 680
659 // If we have a parallel move here then the successor block must be a 681 // If we have a parallel move here then the successor block must be a
660 // join with phis. The phi inputs contribute uses to each predecessor 682 // join with phis. The phi inputs contribute uses to each predecessor
661 // block (and the phi outputs contribute definitions in the successor 683 // block (and the phi outputs contribute definitions in the successor
662 // block). 684 // block).
663 if (!goto_instr->HasParallelMove()) return goto_instr->previous(); 685 if (!goto_instr->HasParallelMove()) return goto_instr->previous();
(...skipping 25 matching lines...) Expand all
689 move_idx++; 711 move_idx++;
690 continue; 712 continue;
691 } 713 }
692 714
693 // Expected shape of live ranges: 715 // Expected shape of live ranges:
694 // 716 //
695 // g g' 717 // g g'
696 // value --* 718 // value --*
697 // 719 //
698 720
699 LiveRange* range = GetLiveRange(val->definition()->ssa_temp_index()); 721 const intptr_t vreg = val->definition()->ssa_temp_index();
722 LiveRange* range = GetLiveRange(vreg);
723 if (interfere_at_backedge != NULL) interfere_at_backedge->Add(vreg);
700 724
701 range->AddUseInterval(block->start_pos(), pos); 725 range->AddUseInterval(block->start_pos(), pos);
702 range->AddHintedUse(pos, move->src_slot(), move->dest_slot()); 726 range->AddHintedUse(pos, move->src_slot(), move->dest_slot());
703 727
704 move->set_src(Location::PrefersRegister()); 728 move->set_src(Location::PrefersRegister());
705 move_idx++; 729 move_idx++;
706 } 730 }
707 731
708 // Begin backward iteration with the instruction before the parallel 732 // Begin backward iteration with the instruction before the parallel
709 // move. 733 // move.
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
814 838
815 env->set_locations(locations); 839 env->set_locations(locations);
816 env = env->outer(); 840 env = env->outer();
817 } 841 }
818 } 842 }
819 843
820 844
821 // Create and update live ranges corresponding to instruction's inputs, 845 // Create and update live ranges corresponding to instruction's inputs,
822 // temporaries and output. 846 // temporaries and output.
823 void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block, 847 void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block,
824 Instruction* current) { 848 Instruction* current,
849 BitVector* interference_set) {
825 LocationSummary* locs = current->locs(); 850 LocationSummary* locs = current->locs();
826 851
827 Definition* def = current->AsDefinition(); 852 Definition* def = current->AsDefinition();
828 if ((def != NULL) && 853 if ((def != NULL) &&
829 (def->AsConstant() != NULL) && 854 (def->AsConstant() != NULL) &&
830 ((def->ssa_temp_index() == -1) || 855 ((def->ssa_temp_index() == -1) ||
831 (GetLiveRange(def->ssa_temp_index())->first_use() == NULL))) { 856 (GetLiveRange(def->ssa_temp_index())->first_use() == NULL))) {
832 // Drop definitions of constants that have no uses. 857 // Drop definitions of constants that have no uses.
833 locs->set_out(Location::NoLocation()); 858 locs->set_out(Location::NoLocation());
834 return; 859 return;
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
1058 GetLiveRange(input->ssa_temp_index()); 1083 GetLiveRange(input->ssa_temp_index());
1059 input_range->AddUseInterval(block->start_pos(), pos); 1084 input_range->AddUseInterval(block->start_pos(), pos);
1060 input_range->AddUse(pos, move->src_slot()); 1085 input_range->AddUse(pos, move->src_slot());
1061 1086
1062 // Shorten output live range to the point of definition and add both input 1087 // Shorten output live range to the point of definition and add both input
1063 // and output uses slots to be filled by allocator. 1088 // and output uses slots to be filled by allocator.
1064 range->DefineAt(pos); 1089 range->DefineAt(pos);
1065 range->AddHintedUse(pos, out, move->src_slot()); 1090 range->AddHintedUse(pos, out, move->src_slot());
1066 range->AddUse(pos, move->dest_slot()); 1091 range->AddUse(pos, move->dest_slot());
1067 range->AddUse(pos, locs->in_slot(0)); 1092 range->AddUse(pos, locs->in_slot(0));
1093
1094 if ((interference_set != NULL) &&
1095 (range->vreg() >= 0) &&
1096 interference_set->Contains(range->vreg())) {
1097 interference_set->Add(input->ssa_temp_index());
1098 }
1068 } else { 1099 } else {
1069 // Normal unallocated location that requires a register. Expected shape of 1100 // Normal unallocated location that requires a register. Expected shape of
1070 // live range: 1101 // live range:
1071 // 1102 //
1072 // i i' 1103 // i i'
1073 // output [------- 1104 // output [-------
1074 // 1105 //
1075 ASSERT(locs->out().Equals(Location::RequiresRegister()) || 1106 ASSERT(locs->out().Equals(Location::RequiresRegister()) ||
1076 locs->out().Equals(Location::RequiresXmmRegister())); 1107 locs->out().Equals(Location::RequiresXmmRegister()));
1077 1108
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
1444 finger_.UpdateAfterSplit(first_use_after_split->pos()); 1475 finger_.UpdateAfterSplit(first_use_after_split->pos());
1445 } 1476 }
1446 1477
1447 return next_sibling_; 1478 return next_sibling_;
1448 } 1479 }
1449 1480
1450 1481
1451 LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range, 1482 LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range,
1452 intptr_t from, 1483 intptr_t from,
1453 intptr_t to) { 1484 intptr_t to) {
1454 TRACE_ALLOC(OS::Print("split %"Pd" [%"Pd", %"Pd") between [%"Pd", %"Pd")\n", 1485 TRACE_ALLOC(OS::Print("split v%"Pd" [%"Pd", %"Pd") between [%"Pd", %"Pd")\n",
1455 range->vreg(), range->Start(), range->End(), from, to)); 1486 range->vreg(), range->Start(), range->End(), from, to));
1456 1487
1457 intptr_t split_pos = kIllegalPosition; 1488 intptr_t split_pos = kIllegalPosition;
1458 1489
1459 BlockInfo* split_block = BlockInfoAt(to); 1490 BlockInfo* split_block = BlockInfoAt(to);
1460 if (from < split_block->entry()->lifetime_position()) { 1491 if (from < split_block->entry()->lifetime_position()) {
1461 // Interval [from, to) spans multiple blocks. 1492 // Interval [from, to) spans multiple blocks.
1462 1493
1463 // If last block is inside a loop prefer splitting at outermost loop's 1494 // If last block is inside a loop prefer splitting at outermost loop's
1464 // header. 1495 // header.
(...skipping 17 matching lines...) Expand all
1482 ASSERT((split_pos != kIllegalPosition) && (from < split_pos)); 1513 ASSERT((split_pos != kIllegalPosition) && (from < split_pos));
1483 1514
1484 return range->SplitAt(split_pos); 1515 return range->SplitAt(split_pos);
1485 } 1516 }
1486 1517
1487 1518
1488 void FlowGraphAllocator::SpillBetween(LiveRange* range, 1519 void FlowGraphAllocator::SpillBetween(LiveRange* range,
1489 intptr_t from, 1520 intptr_t from,
1490 intptr_t to) { 1521 intptr_t to) {
1491 ASSERT(from < to); 1522 ASSERT(from < to);
1492 TRACE_ALLOC(OS::Print("spill %"Pd" [%"Pd", %"Pd") " 1523 TRACE_ALLOC(OS::Print("spill v%"Pd" [%"Pd", %"Pd") "
1493 "between [%"Pd", %"Pd")\n", 1524 "between [%"Pd", %"Pd")\n",
1494 range->vreg(), range->Start(), range->End(), from, to)); 1525 range->vreg(), range->Start(), range->End(), from, to));
1495 LiveRange* tail = range->SplitAt(from); 1526 LiveRange* tail = range->SplitAt(from);
1496 1527
1497 if (tail->Start() < to) { 1528 if (tail->Start() < to) {
1498 // There is an intersection of tail and [from, to). 1529 // There is an intersection of tail and [from, to).
1499 LiveRange* tail_tail = SplitBetween(tail, tail->Start(), to); 1530 LiveRange* tail_tail = SplitBetween(tail, tail->Start(), to);
1500 Spill(tail); 1531 Spill(tail);
1501 AddToUnallocated(tail_tail); 1532 AddToUnallocated(tail_tail);
1502 } else { 1533 } else {
1503 // No intersection between tail and [from, to). 1534 // No intersection between tail and [from, to).
1504 AddToUnallocated(tail); 1535 AddToUnallocated(tail);
1505 } 1536 }
1506 } 1537 }
1507 1538
1508 1539
1509 void FlowGraphAllocator::SpillAfter(LiveRange* range, intptr_t from) { 1540 void FlowGraphAllocator::SpillAfter(LiveRange* range, intptr_t from) {
1510 TRACE_ALLOC(OS::Print("spill %"Pd" [%"Pd", %"Pd") after %"Pd"\n", 1541 TRACE_ALLOC(OS::Print("spill v%"Pd" [%"Pd", %"Pd") after %"Pd"\n",
1511 range->vreg(), range->Start(), range->End(), from)); 1542 range->vreg(), range->Start(), range->End(), from));
1512 1543
1513 // When spilling the value inside the loop check if this spill can 1544 // When spilling the value inside the loop check if this spill can
1514 // be moved outside. 1545 // be moved outside.
1515 BlockInfo* block_info = BlockInfoAt(from); 1546 BlockInfo* block_info = BlockInfoAt(from);
1516 if (block_info->is_loop_header() || (block_info->loop() != NULL)) { 1547 if (block_info->is_loop_header() || (block_info->loop() != NULL)) {
1517 BlockInfo* loop_header = 1548 BlockInfo* loop_header =
1518 block_info->is_loop_header() ? block_info : block_info->loop(); 1549 block_info->is_loop_header() ? block_info : block_info->loop();
1519 1550
1520 if ((range->Start() <= loop_header->entry()->start_pos()) && 1551 if ((range->Start() <= loop_header->entry()->start_pos()) &&
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1607 1638
1608 const intptr_t pos = FirstIntersection( 1639 const intptr_t pos = FirstIntersection(
1609 unallocated->finger()->first_pending_use_interval(), 1640 unallocated->finger()->first_pending_use_interval(),
1610 allocated_head); 1641 allocated_head);
1611 if (pos < intersection) intersection = pos; 1642 if (pos < intersection) intersection = pos;
1612 } 1643 }
1613 return intersection; 1644 return intersection;
1614 } 1645 }
1615 1646
1616 1647
1648 void ReachingDefs::AddPhi(PhiInstr* phi) {
1649 if (phi->reaching_defs() == NULL) {
1650 phi->set_reaching_defs(
1651 new BitVector(flow_graph_.max_virtual_register_number()));
1652
1653 // Compute initial set reaching defs set.
1654 bool depends_on_phi = false;
1655 for (intptr_t i = 0; i < phi->InputCount(); i++) {
1656 Definition* input = phi->InputAt(i)->definition();
1657 if (input->IsPhi()) {
1658 depends_on_phi = true;
1659 }
1660 phi->reaching_defs()->Add(input->ssa_temp_index());
1661 }
1662
1663 // If this phi depends on another phi then we need fix point iteration.
1664 if (depends_on_phi) phis_.Add(phi);
1665 }
1666 }
1667
1668
1669 void ReachingDefs::Compute() {
1670 // Transitively collect all phis that are used by the given phi.
1671 for (intptr_t i = 0; i < phis_.length(); i++) {
1672 PhiInstr* phi = phis_[i];
1673
1674 // Add all phis that affect this phi to the list.
1675 for (intptr_t i = 0; i < phi->InputCount(); i++) {
1676 Definition* input = phi->InputAt(i)->definition();
1677 if (input->IsPhi()) {
1678 AddPhi(input->AsPhi());
1679 }
1680 }
1681 }
1682
1683 // Propagate values until fix point is reached.
1684 bool changed;
1685 do {
1686 changed = false;
1687 for (intptr_t i = 0; i < phis_.length(); i++) {
1688 PhiInstr* phi = phis_[i];
1689 for (intptr_t i = 0; i < phi->InputCount(); i++) {
1690 Definition* input = phi->InputAt(i)->definition();
Florian Schneider 2012/11/23 13:58:06 Or shorter: input_phi = phi->InputAt(i)->definiti
Vyacheslav Egorov (Google) 2012/11/23 15:38:53 Done.
1691 if (input->IsPhi()) {
1692 if (phi->reaching_defs()->AddAll(input->AsPhi()->reaching_defs())) {
1693 changed = true;
1694 }
1695 }
1696 }
1697 }
1698 } while (changed);
1699
1700 phis_.Clear();
1701 }
1702
1703
1704 BitVector* ReachingDefs::Get(PhiInstr* phi) {
1705 if (phi->reaching_defs() == NULL) {
1706 ASSERT(phis_.is_empty());
1707 AddPhi(phi);
1708 Compute();
1709 }
1710 return phi->reaching_defs();
1711 }
1712
1713
1617 bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) { 1714 bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) {
1618 intptr_t candidate = kNoRegister; 1715 intptr_t candidate = kNoRegister;
1619 intptr_t free_until = 0; 1716 intptr_t free_until = 0;
1620 1717
1621 // If hint is available try hint first. 1718 // If hint is available try hint first.
1622 // TODO(vegorov): ensure that phis are hinted on the back edge. 1719 // TODO(vegorov): ensure that phis are hinted on the back edge.
1623 Location hint = unallocated->finger()->FirstHint(); 1720 Location hint = unallocated->finger()->FirstHint();
1624 if (hint.IsMachineRegister()) { 1721 if (hint.IsMachineRegister()) {
1625 if (!blocked_registers_[hint.register_code()]) { 1722 if (!blocked_registers_[hint.register_code()]) {
1626 free_until = FirstIntersectionWithAllocated(hint.register_code(), 1723 free_until = FirstIntersectionWithAllocated(hint.register_code(),
1627 unallocated); 1724 unallocated);
1628 candidate = hint.register_code(); 1725 candidate = hint.register_code();
1629 } 1726 }
1630 1727
1631 TRACE_ALLOC(OS::Print("found hint ")); 1728 TRACE_ALLOC(OS::Print("found hint %s for v%"Pd": free until %"Pd"\n",
1632 TRACE_ALLOC(hint.Print()); 1729 hint.Name(),
1633 TRACE_ALLOC(OS::Print(" for %"Pd": free until %"Pd"\n", 1730 unallocated->vreg(),
1634 unallocated->vreg(), free_until)); 1731 free_until));
1635 } else if (free_until != kMaxPosition) { 1732 } else if (free_until != kMaxPosition) {
1636 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) { 1733 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
1637 if (!blocked_registers_[reg] && (registers_[reg].length() == 0)) { 1734 if (!blocked_registers_[reg] && (registers_[reg].length() == 0)) {
1638 candidate = reg; 1735 candidate = reg;
1639 free_until = kMaxPosition; 1736 free_until = kMaxPosition;
1640 break; 1737 break;
1641 } 1738 }
1642 } 1739 }
1643 } 1740 }
1644 1741
1742 // We have a very good candidate (either hinted to us or completely free).
1743 // If we are in the loop try to reduce number of moves on the back edge by
Florian Schneider 2012/11/23 13:58:06 Which loop? s/the/a/?
Vyacheslav Egorov (Google) 2012/11/23 15:38:53 Done.
1744 // searching for a candidate that does not interfere with phis on the back
1745 // edge.
1746 BlockInfo* loop_header = BlockInfoAt(unallocated->Start())->loop_header();
1747 if ((unallocated->vreg() >= 0) &&
1748 (loop_header != NULL) &&
1749 (free_until >= loop_header->last_block()->end_pos()) &&
1750 loop_header->backedge_interference()->Contains(unallocated->vreg())) {
1751 ASSERT(static_cast<intptr_t>(kNumberOfXmmRegisters) <=
Florian Schneider 2012/11/23 13:58:06 COMPILE_ASSERT?
Vyacheslav Egorov (Google) 2012/11/23 15:38:53 COMPILE_ASSERT seems to be available only in debug
1752 kNumberOfCpuRegisters);
1753 bool used_on_backedge[kNumberOfCpuRegisters] = { false };
1754
1755 for (PhiIterator it(loop_header->entry()->AsJoinEntry());
1756 !it.Done();
1757 it.Advance()) {
1758 PhiInstr* phi = it.Current();
1759 if (phi->is_alive()) {
1760 const intptr_t phi_vreg = phi->ssa_temp_index();
1761 LiveRange* range = GetLiveRange(phi_vreg);
1762 if (range->assigned_location().kind() == register_kind_) {
1763 const intptr_t reg = range->assigned_location().register_code();
1764
1765 if ((unallocated->vreg() >= 0) &&
Florian Schneider 2012/11/23 13:58:06 This condition is already tested in line 1747.
Vyacheslav Egorov (Google) 2012/11/23 15:38:53 Done.
1766 !reaching_defs_.Get(phi)->Contains(unallocated->vreg())) {
1767 used_on_backedge[reg] = true;
1768 }
1769 }
1770 }
1771 }
1772
1773 if (used_on_backedge[candidate]) {
1774 TRACE_ALLOC(OS::Print(
1775 "considering %s for v%"Pd": has interference on the back edge"
1776 " {loop [%"Pd", %"Pd")}\n",
1777 MakeRegisterLocation(candidate, Location::kDouble).Name(),
1778 unallocated->vreg(),
1779 loop_header->entry()->start_pos(),
1780 loop_header->last_block()->end_pos()));
1781 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
1782 if (blocked_registers_[reg] ||
1783 (reg == candidate) ||
1784 used_on_backedge[reg]) {
1785 continue;
1786 }
1787
1788 const intptr_t intersection =
1789 FirstIntersectionWithAllocated(reg, unallocated);
1790 if (intersection >= free_until) {
1791 candidate = reg;
1792 free_until = intersection;
1793 TRACE_ALLOC(OS::Print(
1794 "found %s for v%"Pd" with no interference on the back edge\n",
1795 MakeRegisterLocation(candidate, Location::kDouble).Name(),
1796 candidate));
1797 break;
1798 }
1799 }
1800 }
1801 }
1802
1645 ASSERT(0 <= kMaxPosition); 1803 ASSERT(0 <= kMaxPosition);
1646 if (free_until != kMaxPosition) { 1804 if (free_until != kMaxPosition) {
1647 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) { 1805 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
1648 if (blocked_registers_[reg] || (reg == candidate)) continue; 1806 if (blocked_registers_[reg] || (reg == candidate)) continue;
1649 const intptr_t intersection = 1807 const intptr_t intersection =
1650 FirstIntersectionWithAllocated(reg, unallocated); 1808 FirstIntersectionWithAllocated(reg, unallocated);
1651 if (intersection > free_until) { 1809 if (intersection > free_until) {
1652 candidate = reg; 1810 candidate = reg;
1653 free_until = intersection; 1811 free_until = intersection;
1654 if (free_until == kMaxPosition) break; 1812 if (free_until == kMaxPosition) break;
1655 } 1813 }
1656 } 1814 }
1657 } 1815 }
1658 1816
1659 // All registers are blocked by active ranges. 1817 // All registers are blocked by active ranges.
1660 if (free_until <= unallocated->Start()) return false; 1818 if (free_until <= unallocated->Start()) return false;
1661 1819
1662 TRACE_ALLOC(OS::Print("assigning free register ")); 1820 TRACE_ALLOC(OS::Print("assigning free register "));
1663 TRACE_ALLOC(MakeRegisterLocation(candidate, Location::kDouble).Print()); 1821 TRACE_ALLOC(MakeRegisterLocation(candidate, Location::kDouble).Print());
1664 TRACE_ALLOC(OS::Print(" to %"Pd"\n", unallocated->vreg())); 1822 TRACE_ALLOC(OS::Print(" to v%"Pd"\n", unallocated->vreg()));
1665 1823
1666 if (free_until != kMaxPosition) { 1824 if (free_until != kMaxPosition) {
1667 // There was an intersection. Split unallocated. 1825 // There was an intersection. Split unallocated.
1668 TRACE_ALLOC(OS::Print(" splitting at %"Pd"\n", free_until)); 1826 TRACE_ALLOC(OS::Print(" splitting at %"Pd"\n", free_until));
1669 LiveRange* tail = unallocated->SplitAt(free_until); 1827 LiveRange* tail = unallocated->SplitAt(free_until);
1670 AddToUnallocated(tail); 1828 AddToUnallocated(tail);
1671 } 1829 }
1672 1830
1673 registers_[candidate].Add(unallocated); 1831 registers_[candidate].Add(unallocated);
1674 unallocated->set_assigned_location( 1832 unallocated->set_assigned_location(
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1757 : unallocated->Start(); 1915 : unallocated->Start();
1758 if (free_until < register_use_pos) { 1916 if (free_until < register_use_pos) {
1759 // Can't acquire free register. Spill until we really need one. 1917 // Can't acquire free register. Spill until we really need one.
1760 ASSERT(unallocated->Start() < ToInstructionStart(register_use_pos)); 1918 ASSERT(unallocated->Start() < ToInstructionStart(register_use_pos));
1761 SpillBetween(unallocated, unallocated->Start(), register_use->pos()); 1919 SpillBetween(unallocated, unallocated->Start(), register_use->pos());
1762 return; 1920 return;
1763 } 1921 }
1764 1922
1765 TRACE_ALLOC(OS::Print("assigning blocked register ")); 1923 TRACE_ALLOC(OS::Print("assigning blocked register "));
1766 TRACE_ALLOC(MakeRegisterLocation(candidate, Location::kDouble).Print()); 1924 TRACE_ALLOC(MakeRegisterLocation(candidate, Location::kDouble).Print());
1767 TRACE_ALLOC(OS::Print(" to live range %"Pd" until %"Pd"\n", 1925 TRACE_ALLOC(OS::Print(" to live range v%"Pd" until %"Pd"\n",
1768 unallocated->vreg(), blocked_at)); 1926 unallocated->vreg(), blocked_at));
1769 1927
1770 if (blocked_at < unallocated->End()) { 1928 if (blocked_at < unallocated->End()) {
1771 // Register is blocked before the end of the live range. Split the range 1929 // Register is blocked before the end of the live range. Split the range
1772 // at latest at blocked_at position. 1930 // at latest at blocked_at position.
1773 LiveRange* tail = SplitBetween(unallocated, 1931 LiveRange* tail = SplitBetween(unallocated,
1774 unallocated->Start(), 1932 unallocated->Start(),
1775 blocked_at + 1); 1933 blocked_at + 1);
1776 AddToUnallocated(tail); 1934 AddToUnallocated(tail);
1777 } 1935 }
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
2063 } 2221 }
2064 #endif 2222 #endif
2065 2223
2066 2224
2067 void FlowGraphAllocator::PrepareForAllocation( 2225 void FlowGraphAllocator::PrepareForAllocation(
2068 Location::Kind register_kind, 2226 Location::Kind register_kind,
2069 intptr_t number_of_registers, 2227 intptr_t number_of_registers,
2070 const GrowableArray<LiveRange*>& unallocated, 2228 const GrowableArray<LiveRange*>& unallocated,
2071 LiveRange** blocking_ranges, 2229 LiveRange** blocking_ranges,
2072 bool* blocked_registers) { 2230 bool* blocked_registers) {
2231 ASSERT(number_of_registers <= kNumberOfCpuRegisters);
2073 register_kind_ = register_kind; 2232 register_kind_ = register_kind;
2074 number_of_registers_ = number_of_registers; 2233 number_of_registers_ = number_of_registers;
2075 2234
2076 ASSERT(unallocated_.is_empty()); 2235 ASSERT(unallocated_.is_empty());
2077 unallocated_.AddArray(unallocated); 2236 unallocated_.AddArray(unallocated);
2078 2237
2079 for (intptr_t reg = 0; reg < number_of_registers; reg++) { 2238 for (intptr_t reg = 0; reg < number_of_registers; reg++) {
2080 blocked_registers_[reg] = blocked_registers[reg]; 2239 blocked_registers_[reg] = blocked_registers[reg];
2081 ASSERT(registers_[reg].is_empty()); 2240 ASSERT(registers_[reg].is_empty());
2082 2241
2083 LiveRange* range = blocking_ranges[reg]; 2242 LiveRange* range = blocking_ranges[reg];
2084 if (range != NULL) { 2243 if (range != NULL) {
2085 range->finger()->Initialize(range); 2244 range->finger()->Initialize(range);
2086 registers_[reg].Add(range); 2245 registers_[reg].Add(range);
2087 } 2246 }
2088 } 2247 }
2089 } 2248 }
2090 2249
2091 2250
2092 void FlowGraphAllocator::AllocateUnallocatedRanges() { 2251 void FlowGraphAllocator::AllocateUnallocatedRanges() {
2093 #if defined(DEBUG) 2252 #if defined(DEBUG)
2094 ASSERT(UnallocatedIsSorted()); 2253 ASSERT(UnallocatedIsSorted());
2095 #endif 2254 #endif
2096 2255
2097 while (!unallocated_.is_empty()) { 2256 while (!unallocated_.is_empty()) {
2098 LiveRange* range = unallocated_.RemoveLast(); 2257 LiveRange* range = unallocated_.RemoveLast();
2099 const intptr_t start = range->Start(); 2258 const intptr_t start = range->Start();
2100 TRACE_ALLOC(OS::Print("Processing live range for vreg %"Pd" " 2259 TRACE_ALLOC(OS::Print("Processing live range for v%"Pd" "
2101 "starting at %"Pd"\n", 2260 "starting at %"Pd"\n",
2102 range->vreg(), 2261 range->vreg(),
2103 start)); 2262 start));
2104 2263
2105 // TODO(vegorov): eagerly spill liveranges without register uses. 2264 // TODO(vegorov): eagerly spill liveranges without register uses.
2106 AdvanceActiveIntervals(start); 2265 AdvanceActiveIntervals(start);
2107 2266
2108 if (!AllocateFreeRegister(range)) { 2267 if (!AllocateFreeRegister(range)) {
2109 AllocateAnyRegister(range); 2268 AllocateAnyRegister(range);
2110 } 2269 }
(...skipping 16 matching lines...) Expand all
2127 ASSERT(GetLiveRange(range->vreg())->spill_slot().Equals(target)); 2286 ASSERT(GetLiveRange(range->vreg())->spill_slot().Equals(target));
2128 return true; 2287 return true;
2129 } 2288 }
2130 return false; 2289 return false;
2131 } 2290 }
2132 2291
2133 2292
2134 void FlowGraphAllocator::ConnectSplitSiblings(LiveRange* parent, 2293 void FlowGraphAllocator::ConnectSplitSiblings(LiveRange* parent,
2135 BlockEntryInstr* source_block, 2294 BlockEntryInstr* source_block,
2136 BlockEntryInstr* target_block) { 2295 BlockEntryInstr* target_block) {
2137 TRACE_ALLOC(OS::Print("Connect source_block=%"Pd", target_block=%"Pd"\n", 2296 TRACE_ALLOC(OS::Print("Connect v%"Pd" on the edge B%"Pd" -> B%"Pd"\n",
2297 parent->vreg(),
2138 source_block->block_id(), 2298 source_block->block_id(),
2139 target_block->block_id())); 2299 target_block->block_id()));
2140 if (parent->next_sibling() == NULL) { 2300 if (parent->next_sibling() == NULL) {
2141 // Nothing to connect. The whole range was allocated to the same location. 2301 // Nothing to connect. The whole range was allocated to the same location.
2142 TRACE_ALLOC(OS::Print("range %"Pd" has no siblings\n", parent->vreg())); 2302 TRACE_ALLOC(OS::Print("range v%"Pd" has no siblings\n", parent->vreg()));
2143 return; 2303 return;
2144 } 2304 }
2145 2305
2146 const intptr_t source_pos = source_block->end_pos() - 1; 2306 const intptr_t source_pos = source_block->end_pos() - 1;
2147 ASSERT(IsInstructionEndPosition(source_pos)); 2307 ASSERT(IsInstructionEndPosition(source_pos));
2148 2308
2149 const intptr_t target_pos = target_block->start_pos(); 2309 const intptr_t target_pos = target_block->start_pos();
2150 2310
2151 Location target; 2311 Location target;
2152 Location source; 2312 Location source;
(...skipping 16 matching lines...) Expand all
2169 ASSERT(target.IsInvalid()); 2329 ASSERT(target.IsInvalid());
2170 target = range->assigned_location(); 2330 target = range->assigned_location();
2171 #if defined(DEBUG) 2331 #if defined(DEBUG)
2172 target_cover = range; 2332 target_cover = range;
2173 #endif 2333 #endif
2174 } 2334 }
2175 2335
2176 range = range->next_sibling(); 2336 range = range->next_sibling();
2177 } 2337 }
2178 2338
2179 TRACE_ALLOC(OS::Print("connecting [%"Pd", %"Pd") [", 2339 TRACE_ALLOC(OS::Print("connecting v%"Pd" between [%"Pd", %"Pd") {%s} "
2180 source_cover->Start(), source_cover->End())); 2340 "to [%"Pd", %"Pd") {%s}\n",
2181 TRACE_ALLOC(source.Print()); 2341 parent->vreg(),
2182 TRACE_ALLOC(OS::Print("] to [%"Pd", %"Pd") [", 2342 source_cover->Start(),
2183 target_cover->Start(), target_cover->End())); 2343 source_cover->End(),
2184 TRACE_ALLOC(target.Print()); 2344 source.Name(),
2185 TRACE_ALLOC(OS::Print("]\n")); 2345 target_cover->Start(),
2346 target_cover->End(),
2347 target.Name()));
2186 2348
2187 // Siblings were allocated to the same register. 2349 // Siblings were allocated to the same register.
2188 if (source.Equals(target)) return; 2350 if (source.Equals(target)) return;
2189 2351
2190 // Values are eagerly spilled. Spill slot already contains appropriate value. 2352 // Values are eagerly spilled. Spill slot already contains appropriate value.
2191 if (TargetLocationIsSpillSlot(parent, target)) { 2353 if (TargetLocationIsSpillSlot(parent, target)) {
2192 return; 2354 return;
2193 } 2355 }
2194 2356
2195 Instruction* last = source_block->last_instruction(); 2357 Instruction* last = source_block->last_instruction();
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
2348 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", 2510 OS::Print("-- [after ssa allocator] ir [%s] -------------\n",
2349 function.ToFullyQualifiedCString()); 2511 function.ToFullyQualifiedCString());
2350 FlowGraphPrinter printer(flow_graph_, true); 2512 FlowGraphPrinter printer(flow_graph_, true);
2351 printer.PrintBlocks(); 2513 printer.PrintBlocks();
2352 OS::Print("----------------------------------------------\n"); 2514 OS::Print("----------------------------------------------\n");
2353 } 2515 }
2354 } 2516 }
2355 2517
2356 2518
2357 } // namespace dart 2519 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_allocator.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698