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

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

Issue 14215006: Re-apply r20377. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 8 months 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
OLDNEW
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/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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 reaching_defs_(flow_graph),
66 value_representations_(flow_graph.max_virtual_register_number()), 66 value_representations_(flow_graph.max_virtual_register_number()),
67 block_order_(flow_graph.reverse_postorder()), 67 block_order_(flow_graph.reverse_postorder()),
68 postorder_(flow_graph.postorder()), 68 postorder_(flow_graph.postorder()),
69 live_out_(block_order_.length()), 69 liveness_(flow_graph),
70 kill_(block_order_.length()),
71 live_in_(block_order_.length()),
72 vreg_count_(flow_graph.max_virtual_register_number()), 70 vreg_count_(flow_graph.max_virtual_register_number()),
73 live_ranges_(flow_graph.max_virtual_register_number()), 71 live_ranges_(flow_graph.max_virtual_register_number()),
74 cpu_regs_(), 72 cpu_regs_(),
75 fpu_regs_(), 73 fpu_regs_(),
76 blocked_cpu_registers_(), 74 blocked_cpu_registers_(),
77 blocked_fpu_registers_(), 75 blocked_fpu_registers_(),
78 cpu_spill_slot_count_(0) { 76 cpu_spill_slot_count_(0) {
79 for (intptr_t i = 0; i < vreg_count_; i++) live_ranges_.Add(NULL); 77 for (intptr_t i = 0; i < vreg_count_; i++) live_ranges_.Add(NULL);
80 for (intptr_t i = 0; i < vreg_count_; i++) { 78 for (intptr_t i = 0; i < vreg_count_; i++) {
81 value_representations_.Add(kNoRepresentation); 79 value_representations_.Add(kNoRepresentation);
(...skipping 27 matching lines...) Expand all
109 for (intptr_t i = 0; i < block_order_.length(); ++i) { 107 for (intptr_t i = 0; i < block_order_.length(); ++i) {
110 BlockEntryInstr* block = block_order_[i]; 108 BlockEntryInstr* block = block_order_[i];
111 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 109 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
112 Instruction* current = it.Current(); 110 Instruction* current = it.Current();
113 if (!current->CanDeoptimize()) current->RemoveEnvironment(); 111 if (!current->CanDeoptimize()) current->RemoveEnvironment();
114 } 112 }
115 } 113 }
116 } 114 }
117 115
118 116
119 void FlowGraphAllocator::ComputeInitialSets() { 117 void SSALivenessAnalysis::ComputeInitialSets() {
120 const intptr_t block_count = postorder_.length(); 118 const intptr_t block_count = postorder_.length();
121 for (intptr_t i = 0; i < block_count; i++) { 119 for (intptr_t i = 0; i < block_count; i++) {
122 BlockEntryInstr* block = postorder_[i]; 120 BlockEntryInstr* block = postorder_[i];
123 121
124 BitVector* kill = kill_[i]; 122 BitVector* kill = kill_[i];
125 BitVector* live_in = live_in_[i]; 123 BitVector* live_in = live_in_[i];
126 124
127 // Iterate backwards starting at the last instruction. 125 // Iterate backwards starting at the last instruction.
128 for (BackwardInstructionIterator it(block); !it.Done(); it.Advance()) { 126 for (BackwardInstructionIterator it(block); !it.Done(); it.Advance()) {
129 Instruction* current = it.Current(); 127 Instruction* current = it.Current();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 const intptr_t use = val->definition()->ssa_temp_index(); 180 const intptr_t use = val->definition()->ssa_temp_index();
183 if (!kill_[pred->postorder_number()]->Contains(use)) { 181 if (!kill_[pred->postorder_number()]->Contains(use)) {
184 live_in_[pred->postorder_number()]->Add(use); 182 live_in_[pred->postorder_number()]->Add(use);
185 } 183 }
186 } 184 }
187 } 185 }
188 } 186 }
189 } 187 }
190 188
191 // Process initial definitions, ie, constants and incoming parameters. 189 // Process initial definitions, ie, constants and incoming parameters.
192 GraphEntryInstr* graph_entry = flow_graph_.graph_entry(); 190 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); i++) {
193 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) { 191 intptr_t vreg = (*graph_entry_->initial_definitions())[i]->ssa_temp_index();
194 intptr_t vreg = (*graph_entry->initial_definitions())[i]->ssa_temp_index(); 192 kill_[graph_entry_->postorder_number()]->Add(vreg);
195 kill_[graph_entry->postorder_number()]->Add(vreg); 193 live_in_[graph_entry_->postorder_number()]->Remove(vreg);
196 live_in_[graph_entry->postorder_number()]->Remove(vreg);
197 } 194 }
198 195
199 // Update initial live_in sets to match live_out sets. Has to be 196 // Update initial live_in sets to match live_out sets. Has to be
200 // done in a separate path because of backwards branches. 197 // done in a separate path because of backwards branches.
201 for (intptr_t i = 0; i < block_count; i++) { 198 for (intptr_t i = 0; i < block_count; i++) {
202 UpdateLiveIn(*postorder_[i]); 199 UpdateLiveIn(*postorder_[i]);
203 } 200 }
204 } 201 }
205 202
206 203
207 bool FlowGraphAllocator::UpdateLiveOut(const BlockEntryInstr& instr) {
208 BitVector* live_out = live_out_[instr.postorder_number()];
209 bool changed = false;
210 Instruction* last = instr.last_instruction();
211 ASSERT(last != NULL);
212 for (intptr_t i = 0; i < last->SuccessorCount(); i++) {
213 BlockEntryInstr* succ = last->SuccessorAt(i);
214 ASSERT(succ != NULL);
215 if (live_out->AddAll(live_in_[succ->postorder_number()])) {
216 changed = true;
217 }
218 }
219 return changed;
220 }
221
222
223 bool FlowGraphAllocator::UpdateLiveIn(const BlockEntryInstr& instr) {
224 BitVector* live_out = live_out_[instr.postorder_number()];
225 BitVector* kill = kill_[instr.postorder_number()];
226 BitVector* live_in = live_in_[instr.postorder_number()];
227 return live_in->KillAndAdd(kill, live_out);
228 }
229
230
231 void FlowGraphAllocator::ComputeLiveInAndLiveOutSets() {
232 const intptr_t block_count = postorder_.length();
233 bool changed;
234 do {
235 changed = false;
236
237 for (intptr_t i = 0; i < block_count; i++) {
238 const BlockEntryInstr& block = *postorder_[i];
239
240 // Live-in set depends only on kill set which does not
241 // change in this loop and live-out set. If live-out
242 // set does not change there is no need to recompute
243 // live-in set.
244 if (UpdateLiveOut(block) && UpdateLiveIn(block)) {
245 changed = true;
246 }
247 }
248 } while (changed);
249 }
250
251
252 void FlowGraphAllocator::AnalyzeLiveness() {
253 const intptr_t block_count = postorder_.length();
254 for (intptr_t i = 0; i < block_count; i++) {
255 live_out_.Add(new BitVector(vreg_count_));
256 kill_.Add(new BitVector(vreg_count_));
257 live_in_.Add(new BitVector(vreg_count_));
258 }
259
260 ComputeInitialSets();
261 ComputeLiveInAndLiveOutSets();
262 }
263
264
265 static void PrintBitVector(const char* tag, BitVector* v) {
266 OS::Print("%s:", tag);
267 for (BitVector::Iterator it(v); !it.Done(); it.Advance()) {
268 OS::Print(" %"Pd"", it.Current());
269 }
270 OS::Print("\n");
271 }
272
273
274 void FlowGraphAllocator::DumpLiveness() {
275 const intptr_t block_count = postorder_.length();
276 for (intptr_t i = 0; i < block_count; i++) {
277 BlockEntryInstr* block = postorder_[i];
278 OS::Print("block @%"Pd" -> ", block->block_id());
279
280 Instruction* last = block->last_instruction();
281 for (intptr_t j = 0; j < last->SuccessorCount(); j++) {
282 BlockEntryInstr* succ = last->SuccessorAt(j);
283 OS::Print(" @%"Pd"", succ->block_id());
284 }
285 OS::Print("\n");
286
287 PrintBitVector(" live out", live_out_[i]);
288 PrintBitVector(" kill", kill_[i]);
289 PrintBitVector(" live in", live_in_[i]);
290 }
291 }
292
293
294 void LiveRange::AddUse(intptr_t pos, Location* location_slot) { 204 void LiveRange::AddUse(intptr_t pos, Location* location_slot) {
295 ASSERT(location_slot != NULL); 205 ASSERT(location_slot != NULL);
296 ASSERT((first_use_interval_->start_ <= pos) && 206 ASSERT((first_use_interval_->start_ <= pos) &&
297 (pos <= first_use_interval_->end_)); 207 (pos <= first_use_interval_->end_));
298 if ((uses_ != NULL) && 208 if ((uses_ != NULL) &&
299 (uses_->pos() == pos) && 209 (uses_->pos() == pos) &&
300 (uses_->location_slot() == location_slot)) { 210 (uses_->location_slot() == location_slot)) {
301 return; 211 return;
302 } 212 }
303 uses_ = new UsePosition(pos, uses_, location_slot); 213 uses_ = new UsePosition(pos, uses_, location_slot);
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 ASSERT(postorder_.Last()->IsGraphEntry()); 438 ASSERT(postorder_.Last()->IsGraphEntry());
529 BitVector* current_interference_set = NULL; 439 BitVector* current_interference_set = NULL;
530 for (intptr_t i = 0; i < (block_count - 1); i++) { 440 for (intptr_t i = 0; i < (block_count - 1); i++) {
531 BlockEntryInstr* block = postorder_[i]; 441 BlockEntryInstr* block = postorder_[i];
532 442
533 BlockInfo* block_info = BlockInfoAt(block->start_pos()); 443 BlockInfo* block_info = BlockInfoAt(block->start_pos());
534 444
535 // For every SSA value that is live out of this block, create an interval 445 // For every SSA value that is live out of this block, create an interval
536 // that covers the whole block. It will be shortened if we encounter a 446 // that covers the whole block. It will be shortened if we encounter a
537 // definition of this value in this block. 447 // definition of this value in this block.
538 for (BitVector::Iterator it(live_out_[i]); !it.Done(); it.Advance()) { 448 for (BitVector::Iterator it(liveness_.GetLiveOutSetAt(i));
449 !it.Done();
450 it.Advance()) {
539 LiveRange* range = GetLiveRange(it.Current()); 451 LiveRange* range = GetLiveRange(it.Current());
540 range->AddUseInterval(block->start_pos(), block->end_pos()); 452 range->AddUseInterval(block->start_pos(), block->end_pos());
541 } 453 }
542 454
543 BlockInfo* loop_header = block_info->loop_header(); 455 BlockInfo* loop_header = block_info->loop_header();
544 if ((loop_header != NULL) && (loop_header->last_block() == block)) { 456 if ((loop_header != NULL) && (loop_header->last_block() == block)) {
545 current_interference_set = 457 current_interference_set =
546 new BitVector(flow_graph_.max_virtual_register_number()); 458 new BitVector(flow_graph_.max_virtual_register_number());
547 ASSERT(loop_header->backedge_interference() == NULL); 459 ASSERT(loop_header->backedge_interference() == NULL);
548 // All values flowing into the loop header are live at the back-edge and 460 // All values flowing into the loop header are live at the back-edge and
549 // can interfere with phi moves. 461 // can interfere with phi moves.
550 current_interference_set->AddAll( 462 current_interference_set->AddAll(
551 live_in_[loop_header->entry()->postorder_number()]); 463 liveness_.GetLiveInSet(loop_header->entry()));
552 loop_header->set_backedge_interference( 464 loop_header->set_backedge_interference(
553 current_interference_set); 465 current_interference_set);
554 } 466 }
555 467
556 // Connect outgoing phi-moves that were created in NumberInstructions 468 // Connect outgoing phi-moves that were created in NumberInstructions
557 // and find last instruction that contributes to liveness. 469 // and find last instruction that contributes to liveness.
558 Instruction* current = ConnectOutgoingPhiMoves(block, 470 Instruction* current = ConnectOutgoingPhiMoves(block,
559 current_interference_set); 471 current_interference_set);
560 472
561 // Now process all instructions in reverse order. 473 // Now process all instructions in reverse order.
562 while (current != block) { 474 while (current != block) {
563 // Skip parallel moves that we insert while processing instructions. 475 // Skip parallel moves that we insert while processing instructions.
564 if (!current->IsParallelMove()) { 476 if (!current->IsParallelMove()) {
565 ProcessOneInstruction(block, current, current_interference_set); 477 ProcessOneInstruction(block, current, current_interference_set);
566 } 478 }
567 current = current->previous(); 479 current = current->previous();
568 } 480 }
569 481
570 482
571 // Check if any values live into the loop can be spilled for free. 483 // Check if any values live into the loop can be spilled for free.
572 if (block_info->is_loop_header()) { 484 if (block_info->is_loop_header()) {
573 current_interference_set = NULL; 485 current_interference_set = NULL;
574 for (BitVector::Iterator it(live_in_[i]); !it.Done(); it.Advance()) { 486 for (BitVector::Iterator it(liveness_.GetLiveInSetAt(i));
487 !it.Done();
488 it.Advance()) {
575 LiveRange* range = GetLiveRange(it.Current()); 489 LiveRange* range = GetLiveRange(it.Current());
576 if (HasOnlyUnconstrainedUsesInLoop(range, block_info)) { 490 if (HasOnlyUnconstrainedUsesInLoop(range, block_info)) {
577 range->MarkHasOnlyUnconstrainedUsesInLoop(block_info->loop_id()); 491 range->MarkHasOnlyUnconstrainedUsesInLoop(block_info->loop_id());
578 } 492 }
579 } 493 }
580 } 494 }
581 495
582 ConnectIncomingPhiMoves(block); 496 ConnectIncomingPhiMoves(block);
583 } 497 }
584 498
(...skipping 1861 matching lines...) Expand 10 before | Expand all | Expand 10 after
2446 sibling->assigned_location(), 2360 sibling->assigned_location(),
2447 range->assigned_location()); 2361 range->assigned_location());
2448 } 2362 }
2449 range = sibling; 2363 range = sibling;
2450 } 2364 }
2451 } 2365 }
2452 2366
2453 // Resolve non-linear control flow across branches. 2367 // Resolve non-linear control flow across branches.
2454 for (intptr_t i = 1; i < block_order_.length(); i++) { 2368 for (intptr_t i = 1; i < block_order_.length(); i++) {
2455 BlockEntryInstr* block = block_order_[i]; 2369 BlockEntryInstr* block = block_order_[i];
2456 BitVector* live = live_in_[block->postorder_number()]; 2370 BitVector* live = liveness_.GetLiveInSet(block);
2457 for (BitVector::Iterator it(live); !it.Done(); it.Advance()) { 2371 for (BitVector::Iterator it(live); !it.Done(); it.Advance()) {
2458 LiveRange* range = GetLiveRange(it.Current()); 2372 LiveRange* range = GetLiveRange(it.Current());
2459 for (intptr_t j = 0; j < block->PredecessorCount(); j++) { 2373 for (intptr_t j = 0; j < block->PredecessorCount(); j++) {
2460 ConnectSplitSiblings(range, block->PredecessorAt(j), block); 2374 ConnectSplitSiblings(range, block->PredecessorAt(j), block);
2461 } 2375 }
2462 } 2376 }
2463 } 2377 }
2464 2378
2465 // Eagerly spill values. 2379 // Eagerly spill values.
2466 // TODO(vegorov): if value is spilled on the cold path (e.g. by the call) 2380 // TODO(vegorov): if value is spilled on the cold path (e.g. by the call)
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
2513 } 2427 }
2514 } 2428 }
2515 } 2429 }
2516 2430
2517 2431
2518 void FlowGraphAllocator::AllocateRegisters() { 2432 void FlowGraphAllocator::AllocateRegisters() {
2519 CollectRepresentations(); 2433 CollectRepresentations();
2520 2434
2521 EliminateEnvironments(); 2435 EliminateEnvironments();
2522 2436
2523 AnalyzeLiveness(); 2437 liveness_.Analyze();
2524 2438
2525 NumberInstructions(); 2439 NumberInstructions();
2526 2440
2527 DiscoverLoops(); 2441 DiscoverLoops();
2528 2442
2529 BuildLiveRanges(); 2443 BuildLiveRanges();
2530 2444
2531 if (FLAG_print_ssa_liveness) { 2445 if (FLAG_print_ssa_liveness) {
2532 DumpLiveness(); 2446 liveness_.Dump();
2533 } 2447 }
2534 2448
2535 if (FLAG_print_ssa_liveranges) { 2449 if (FLAG_print_ssa_liveranges) {
2536 const Function& function = flow_graph_.parsed_function().function(); 2450 const Function& function = flow_graph_.parsed_function().function();
2537 2451
2538 OS::Print("-- [before ssa allocator] ranges [%s] ---------\n", 2452 OS::Print("-- [before ssa allocator] ranges [%s] ---------\n",
2539 function.ToFullyQualifiedCString()); 2453 function.ToFullyQualifiedCString());
2540 PrintLiveRanges(); 2454 PrintLiveRanges();
2541 OS::Print("----------------------------------------------\n"); 2455 OS::Print("----------------------------------------------\n");
2542 2456
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2583 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", 2497 OS::Print("-- [after ssa allocator] ir [%s] -------------\n",
2584 function.ToFullyQualifiedCString()); 2498 function.ToFullyQualifiedCString());
2585 FlowGraphPrinter printer(flow_graph_, true); 2499 FlowGraphPrinter printer(flow_graph_, true);
2586 printer.PrintBlocks(); 2500 printer.PrintBlocks();
2587 OS::Print("----------------------------------------------\n"); 2501 OS::Print("----------------------------------------------\n");
2588 } 2502 }
2589 } 2503 }
2590 2504
2591 2505
2592 } // namespace dart 2506 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698