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_builder.h" | 10 #include "vm/flow_graph_builder.h" |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
132 BlockEntryInstr* pred = block->PredecessorAt(k); | 132 BlockEntryInstr* pred = block->PredecessorAt(k); |
133 const intptr_t use = val->AsUse()->definition()->ssa_temp_index(); | 133 const intptr_t use = val->AsUse()->definition()->ssa_temp_index(); |
134 live_out_[pred->postorder_number()]->Add(use); | 134 live_out_[pred->postorder_number()]->Add(use); |
135 } | 135 } |
136 } | 136 } |
137 } | 137 } |
138 } | 138 } |
139 } | 139 } |
140 } | 140 } |
141 | 141 |
142 // Process incomming parameters. | |
srdjan
2012/07/26 00:33:56
s/incomming/incoming/
Vyacheslav Egorov (Google)
2012/07/26 11:33:53
Done.
| |
143 GraphEntryInstr* graph_entry = postorder_[block_count - 1]->AsGraphEntry(); | |
144 for (intptr_t i = 0; i < graph_entry->start_env()->values().length(); i++) { | |
145 Value* val = graph_entry->start_env()->values()[i]; | |
146 if (val->IsUse()) { | |
147 const intptr_t vreg = val->AsUse()->definition()->ssa_temp_index(); | |
148 kill_[0]->Add(vreg); | |
Kevin Millikin (Google)
2012/07/26 09:29:08
It probably doesn't make a big difference to anyth
Vyacheslav Egorov (Google)
2012/07/26 11:33:53
It does not change anything. I just choose to defi
| |
149 live_in_[0]->Remove(vreg); | |
150 } | |
151 } | |
152 | |
142 // Update initial live_in sets to match live_out sets. Has to be | 153 // Update initial live_in sets to match live_out sets. Has to be |
143 // done in a separate path because of backwards branches. | 154 // done in a separate path because of backwards branches. |
144 for (intptr_t i = 0; i < block_count; i++) { | 155 for (intptr_t i = 0; i < block_count; i++) { |
145 UpdateLiveIn(*postorder_[i]); | 156 UpdateLiveIn(*postorder_[i]); |
146 } | 157 } |
147 } | 158 } |
148 | 159 |
149 | 160 |
150 bool FlowGraphAllocator::UpdateLiveOut(const BlockEntryInstr& instr) { | 161 bool FlowGraphAllocator::UpdateLiveOut(const BlockEntryInstr& instr) { |
151 BitVector* live_out = live_out_[instr.postorder_number()]; | 162 BitVector* live_out = live_out_[instr.postorder_number()]; |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
389 while (current != block) { | 400 while (current != block) { |
390 // Skip parallel moves that we insert while processing instructions. | 401 // Skip parallel moves that we insert while processing instructions. |
391 if (!current->IsParallelMove()) { | 402 if (!current->IsParallelMove()) { |
392 ProcessOneInstruction(block, current); | 403 ProcessOneInstruction(block, current); |
393 } | 404 } |
394 current = current->previous(); | 405 current = current->previous(); |
395 } | 406 } |
396 | 407 |
397 ConnectIncomingPhiMoves(block); | 408 ConnectIncomingPhiMoves(block); |
398 } | 409 } |
410 | |
411 // Process incomming parameters. | |
srdjan
2012/07/26 00:33:56
ditto
Vyacheslav Egorov (Google)
2012/07/26 11:33:53
Done.
| |
412 GraphEntryInstr* graph_entry = postorder_[block_count - 1]->AsGraphEntry(); | |
413 for (intptr_t i = 0; i < graph_entry->start_env()->values().length(); i++) { | |
414 Value* val = graph_entry->start_env()->values()[i]; | |
415 if (val->IsUse()) { | |
416 ParameterInstr* param = val->AsUse()->definition()->AsParameter(); | |
417 | |
418 LiveRange* range = GetLiveRange(param->ssa_temp_index()); | |
419 range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos()); | |
420 range->DefineAt(graph_entry->start_pos()); | |
421 range->set_assigned_location(Location::StackSlot(param->index())); | |
422 | |
423 range->finger()->Initialize(range); | |
424 UsePosition* use = range->finger()->FirstRegisterBeneficialUse( | |
425 graph_entry->start_pos()); | |
426 if (use != NULL) { | |
427 LiveRange* tail = SplitBetween(range, | |
428 graph_entry->start_pos(), | |
429 use->pos()); | |
430 AddToUnallocated(tail); | |
431 } | |
432 ConvertAllUses(range); | |
433 } | |
434 } | |
399 } | 435 } |
400 | 436 |
401 // | 437 // |
402 // When describing shape of live ranges in comments below we are going to use | 438 // When describing shape of live ranges in comments below we are going to use |
403 // the following notation: | 439 // the following notation: |
404 // | 440 // |
405 // B block entry | 441 // B block entry |
406 // g goto instruction | 442 // g goto instruction |
407 // m parallel move | 443 // m parallel move |
408 // i any other instruction | 444 // i any other instruction |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
540 const intptr_t pos = current->lifetime_position(); | 576 const intptr_t pos = current->lifetime_position(); |
541 ASSERT(IsInstructionPosition(pos)); | 577 ASSERT(IsInstructionPosition(pos)); |
542 | 578 |
543 LocationSummary* locs = current->locs(); | 579 LocationSummary* locs = current->locs(); |
544 | 580 |
545 // TODO(vegorov): number of inputs must match number of input locations. | 581 // TODO(vegorov): number of inputs must match number of input locations. |
546 if (locs->input_count() != current->InputCount()) { | 582 if (locs->input_count() != current->InputCount()) { |
547 builder_->Bailout("ssa allocator: number of input locations mismatch"); | 583 builder_->Bailout("ssa allocator: number of input locations mismatch"); |
548 } | 584 } |
549 | 585 |
586 // Normalize same-as-first-input output if input is specified as | |
587 // fixed register. | |
588 if (locs->out().IsUnallocated() && | |
589 (locs->out().policy() == Location::kSameAsFirstInput) && | |
590 (locs->in(0).IsRegister())) { | |
591 locs->set_out(locs->in(0)); | |
592 } | |
593 | |
550 const bool output_same_as_first_input = | 594 const bool output_same_as_first_input = |
551 locs->out().IsUnallocated() && | 595 locs->out().IsUnallocated() && |
552 (locs->out().policy() == Location::kSameAsFirstInput); | 596 (locs->out().policy() == Location::kSameAsFirstInput); |
553 | 597 |
554 // Add uses from the deoptimization environment. | 598 // Add uses from the deoptimization environment. |
555 if (current->env() != NULL) { | 599 if (current->env() != NULL) { |
556 // Any value mentioned in the deoptimization environment should survive | 600 // Any value mentioned in the deoptimization environment should survive |
557 // until the end of instruction but it does not need to be in the register. | 601 // until the end of instruction but it does not need to be in the register. |
558 // Expected shape of live range: | 602 // Expected shape of live range: |
559 // | 603 // |
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1088 return i; | 1132 return i; |
1089 } | 1133 } |
1090 } | 1134 } |
1091 spill_slots_.Add(0); | 1135 spill_slots_.Add(0); |
1092 return spill_slots_.length() - 1; | 1136 return spill_slots_.length() - 1; |
1093 } | 1137 } |
1094 | 1138 |
1095 | 1139 |
1096 void FlowGraphAllocator::Spill(LiveRange* range) { | 1140 void FlowGraphAllocator::Spill(LiveRange* range) { |
1097 const intptr_t spill_index = AllocateSpillSlotFor(range); | 1141 const intptr_t spill_index = AllocateSpillSlotFor(range); |
1098 ASSERT(spill_slots_[spill_index] < range->Start()); | 1142 ASSERT(spill_slots_[spill_index] <= range->Start()); |
1099 spill_slots_[spill_index] = range->End(); | 1143 spill_slots_[spill_index] = range->End(); |
1100 range->set_assigned_location(Location::SpillSlot(spill_index)); | 1144 range->set_assigned_location(Location::StackSlot(spill_index)); |
1101 ConvertAllUses(range); | 1145 ConvertAllUses(range); |
1102 } | 1146 } |
1103 | 1147 |
1104 | 1148 |
1105 intptr_t FlowGraphAllocator::FirstIntersectionWithAllocated( | 1149 intptr_t FlowGraphAllocator::FirstIntersectionWithAllocated( |
1106 Register reg, LiveRange* unallocated) { | 1150 Register reg, LiveRange* unallocated) { |
1107 intptr_t intersection = kMaxPosition; | 1151 intptr_t intersection = kMaxPosition; |
1108 for (intptr_t i = 0; i < cpu_regs_[reg].length(); i++) { | 1152 for (intptr_t i = 0; i < cpu_regs_[reg].length(); i++) { |
1109 LiveRange* allocated = cpu_regs_[reg][i]; | 1153 LiveRange* allocated = cpu_regs_[reg][i]; |
1110 if (allocated == NULL) continue; | 1154 if (allocated == NULL) continue; |
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1568 LiveRange* range = GetLiveRange(it.Current()); | 1612 LiveRange* range = GetLiveRange(it.Current()); |
1569 for (intptr_t j = 0; j < block->PredecessorCount(); j++) { | 1613 for (intptr_t j = 0; j < block->PredecessorCount(); j++) { |
1570 ConnectSplitSiblings(range, block->PredecessorAt(j), block); | 1614 ConnectSplitSiblings(range, block->PredecessorAt(j), block); |
1571 } | 1615 } |
1572 } | 1616 } |
1573 } | 1617 } |
1574 } | 1618 } |
1575 | 1619 |
1576 | 1620 |
1577 void FlowGraphAllocator::AllocateRegisters() { | 1621 void FlowGraphAllocator::AllocateRegisters() { |
1578 GraphEntryInstr* entry = block_order_[0]->AsGraphEntry(); | |
1579 ASSERT(entry != NULL); | |
1580 | |
1581 for (intptr_t i = 0; i < entry->start_env()->values().length(); i++) { | |
1582 if (entry->start_env()->values()[i]->IsUse()) { | |
1583 builder_->Bailout("ssa allocator: unsupported start environment"); | |
1584 } | |
1585 } | |
1586 | |
1587 AnalyzeLiveness(); | 1622 AnalyzeLiveness(); |
1588 | 1623 |
1589 BuildLiveRanges(); | 1624 BuildLiveRanges(); |
1590 | 1625 |
1591 if (FLAG_print_ssa_liveness) { | 1626 if (FLAG_print_ssa_liveness) { |
1592 DumpLiveness(); | 1627 DumpLiveness(); |
1593 } | 1628 } |
1594 | 1629 |
1595 if (FLAG_trace_ssa_allocator) { | 1630 if (FLAG_trace_ssa_allocator) { |
1596 PrintLiveRanges(); | 1631 PrintLiveRanges(); |
1597 } | 1632 } |
1598 | 1633 |
1599 AllocateCPURegisters(); | 1634 AllocateCPURegisters(); |
1600 | 1635 |
1601 ResolveControlFlow(); | 1636 ResolveControlFlow(); |
1602 | 1637 |
1638 GraphEntryInstr* entry = block_order_[0]->AsGraphEntry(); | |
1639 ASSERT(entry != NULL); | |
1640 entry->set_spill_slot_count(spill_slots_.length()); | |
1641 | |
1603 if (FLAG_trace_ssa_allocator) { | 1642 if (FLAG_trace_ssa_allocator) { |
1604 OS::Print("-- ir after allocation -------------------------\n"); | 1643 OS::Print("-- ir after allocation -------------------------\n"); |
1605 FlowGraphPrinter printer(Function::Handle(), block_order_, true); | 1644 FlowGraphPrinter printer(Function::Handle(), block_order_, true); |
1606 printer.PrintBlocks(); | 1645 printer.PrintBlocks(); |
1607 } | 1646 } |
1608 } | 1647 } |
1609 | 1648 |
1610 | 1649 |
1611 } // namespace dart | 1650 } // namespace dart |
OLD | NEW |