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

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

Issue 12827027: Revert "Compute local variable liveness before translation to SSA." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 9 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
« no previous file with comments | « runtime/vm/flow_graph_allocator.h ('k') | runtime/vm/flow_graph_optimizer.cc » ('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) 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 liveness_(flow_graph), 69 live_out_(block_order_.length()),
70 kill_(block_order_.length()),
71 live_in_(block_order_.length()),
70 vreg_count_(flow_graph.max_virtual_register_number()), 72 vreg_count_(flow_graph.max_virtual_register_number()),
71 live_ranges_(flow_graph.max_virtual_register_number()), 73 live_ranges_(flow_graph.max_virtual_register_number()),
72 cpu_regs_(), 74 cpu_regs_(),
73 fpu_regs_(), 75 fpu_regs_(),
74 blocked_cpu_registers_(), 76 blocked_cpu_registers_(),
75 blocked_fpu_registers_(), 77 blocked_fpu_registers_(),
76 cpu_spill_slot_count_(0) { 78 cpu_spill_slot_count_(0) {
77 for (intptr_t i = 0; i < vreg_count_; i++) live_ranges_.Add(NULL); 79 for (intptr_t i = 0; i < vreg_count_; i++) live_ranges_.Add(NULL);
78 for (intptr_t i = 0; i < vreg_count_; i++) { 80 for (intptr_t i = 0; i < vreg_count_; i++) {
79 value_representations_.Add(kNoRepresentation); 81 value_representations_.Add(kNoRepresentation);
(...skipping 27 matching lines...) Expand all
107 for (intptr_t i = 0; i < block_order_.length(); ++i) { 109 for (intptr_t i = 0; i < block_order_.length(); ++i) {
108 BlockEntryInstr* block = block_order_[i]; 110 BlockEntryInstr* block = block_order_[i];
109 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 111 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
110 Instruction* current = it.Current(); 112 Instruction* current = it.Current();
111 if (!current->CanDeoptimize()) current->RemoveEnvironment(); 113 if (!current->CanDeoptimize()) current->RemoveEnvironment();
112 } 114 }
113 } 115 }
114 } 116 }
115 117
116 118
117 void SSALivenessAnalysis::ComputeInitialSets() { 119 void FlowGraphAllocator::ComputeInitialSets() {
118 const intptr_t block_count = postorder_.length(); 120 const intptr_t block_count = postorder_.length();
119 for (intptr_t i = 0; i < block_count; i++) { 121 for (intptr_t i = 0; i < block_count; i++) {
120 BlockEntryInstr* block = postorder_[i]; 122 BlockEntryInstr* block = postorder_[i];
121 123
122 BitVector* kill = kill_[i]; 124 BitVector* kill = kill_[i];
123 BitVector* live_in = live_in_[i]; 125 BitVector* live_in = live_in_[i];
124 126
125 // Iterate backwards starting at the last instruction. 127 // Iterate backwards starting at the last instruction.
126 for (BackwardInstructionIterator it(block); !it.Done(); it.Advance()) { 128 for (BackwardInstructionIterator it(block); !it.Done(); it.Advance()) {
127 Instruction* current = it.Current(); 129 Instruction* current = it.Current();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 const intptr_t use = val->definition()->ssa_temp_index(); 182 const intptr_t use = val->definition()->ssa_temp_index();
181 if (!kill_[pred->postorder_number()]->Contains(use)) { 183 if (!kill_[pred->postorder_number()]->Contains(use)) {
182 live_in_[pred->postorder_number()]->Add(use); 184 live_in_[pred->postorder_number()]->Add(use);
183 } 185 }
184 } 186 }
185 } 187 }
186 } 188 }
187 } 189 }
188 190
189 // Process initial definitions, ie, constants and incoming parameters. 191 // Process initial definitions, ie, constants and incoming parameters.
190 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); i++) { 192 GraphEntryInstr* graph_entry = flow_graph_.graph_entry();
191 intptr_t vreg = (*graph_entry_->initial_definitions())[i]->ssa_temp_index(); 193 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) {
192 kill_[graph_entry_->postorder_number()]->Add(vreg); 194 intptr_t vreg = (*graph_entry->initial_definitions())[i]->ssa_temp_index();
193 live_in_[graph_entry_->postorder_number()]->Remove(vreg); 195 kill_[graph_entry->postorder_number()]->Add(vreg);
196 live_in_[graph_entry->postorder_number()]->Remove(vreg);
194 } 197 }
195 198
196 // Update initial live_in sets to match live_out sets. Has to be 199 // Update initial live_in sets to match live_out sets. Has to be
197 // done in a separate path because of backwards branches. 200 // done in a separate path because of backwards branches.
198 for (intptr_t i = 0; i < block_count; i++) { 201 for (intptr_t i = 0; i < block_count; i++) {
199 UpdateLiveIn(*postorder_[i]); 202 UpdateLiveIn(*postorder_[i]);
200 } 203 }
201 } 204 }
202 205
203 206
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
204 void LiveRange::AddUse(intptr_t pos, Location* location_slot) { 294 void LiveRange::AddUse(intptr_t pos, Location* location_slot) {
205 ASSERT(location_slot != NULL); 295 ASSERT(location_slot != NULL);
206 ASSERT((first_use_interval_->start_ <= pos) && 296 ASSERT((first_use_interval_->start_ <= pos) &&
207 (pos <= first_use_interval_->end_)); 297 (pos <= first_use_interval_->end_));
208 if ((uses_ != NULL) && 298 if ((uses_ != NULL) &&
209 (uses_->pos() == pos) && 299 (uses_->pos() == pos) &&
210 (uses_->location_slot() == location_slot)) { 300 (uses_->location_slot() == location_slot)) {
211 return; 301 return;
212 } 302 }
213 uses_ = new UsePosition(pos, uses_, location_slot); 303 uses_ = new UsePosition(pos, uses_, location_slot);
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
438 ASSERT(postorder_.Last()->IsGraphEntry()); 528 ASSERT(postorder_.Last()->IsGraphEntry());
439 BitVector* current_interference_set = NULL; 529 BitVector* current_interference_set = NULL;
440 for (intptr_t i = 0; i < (block_count - 1); i++) { 530 for (intptr_t i = 0; i < (block_count - 1); i++) {
441 BlockEntryInstr* block = postorder_[i]; 531 BlockEntryInstr* block = postorder_[i];
442 532
443 BlockInfo* block_info = BlockInfoAt(block->start_pos()); 533 BlockInfo* block_info = BlockInfoAt(block->start_pos());
444 534
445 // 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
446 // 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
447 // definition of this value in this block. 537 // definition of this value in this block.
448 for (BitVector::Iterator it(liveness_.GetLiveOutSetAt(i)); 538 for (BitVector::Iterator it(live_out_[i]); !it.Done(); it.Advance()) {
449 !it.Done();
450 it.Advance()) {
451 LiveRange* range = GetLiveRange(it.Current()); 539 LiveRange* range = GetLiveRange(it.Current());
452 range->AddUseInterval(block->start_pos(), block->end_pos()); 540 range->AddUseInterval(block->start_pos(), block->end_pos());
453 } 541 }
454 542
455 BlockInfo* loop_header = block_info->loop_header(); 543 BlockInfo* loop_header = block_info->loop_header();
456 if ((loop_header != NULL) && (loop_header->last_block() == block)) { 544 if ((loop_header != NULL) && (loop_header->last_block() == block)) {
457 current_interference_set = 545 current_interference_set =
458 new BitVector(flow_graph_.max_virtual_register_number()); 546 new BitVector(flow_graph_.max_virtual_register_number());
459 ASSERT(loop_header->backedge_interference() == NULL); 547 ASSERT(loop_header->backedge_interference() == NULL);
460 // All values flowing into the loop header are live at the back-edge and 548 // All values flowing into the loop header are live at the back-edge and
461 // can interfere with phi moves. 549 // can interfere with phi moves.
462 current_interference_set->AddAll( 550 current_interference_set->AddAll(
463 liveness_.GetLiveInSet(loop_header->entry())); 551 live_in_[loop_header->entry()->postorder_number()]);
464 loop_header->set_backedge_interference( 552 loop_header->set_backedge_interference(
465 current_interference_set); 553 current_interference_set);
466 } 554 }
467 555
468 // Connect outgoing phi-moves that were created in NumberInstructions 556 // Connect outgoing phi-moves that were created in NumberInstructions
469 // and find last instruction that contributes to liveness. 557 // and find last instruction that contributes to liveness.
470 Instruction* current = ConnectOutgoingPhiMoves(block, 558 Instruction* current = ConnectOutgoingPhiMoves(block,
471 current_interference_set); 559 current_interference_set);
472 560
473 // Now process all instructions in reverse order. 561 // Now process all instructions in reverse order.
474 while (current != block) { 562 while (current != block) {
475 // Skip parallel moves that we insert while processing instructions. 563 // Skip parallel moves that we insert while processing instructions.
476 if (!current->IsParallelMove()) { 564 if (!current->IsParallelMove()) {
477 ProcessOneInstruction(block, current, current_interference_set); 565 ProcessOneInstruction(block, current, current_interference_set);
478 } 566 }
479 current = current->previous(); 567 current = current->previous();
480 } 568 }
481 569
482 570
483 // Check if any values live into the loop can be spilled for free. 571 // Check if any values live into the loop can be spilled for free.
484 if (block_info->is_loop_header()) { 572 if (block_info->is_loop_header()) {
485 current_interference_set = NULL; 573 current_interference_set = NULL;
486 for (BitVector::Iterator it(liveness_.GetLiveInSetAt(i)); 574 for (BitVector::Iterator it(live_in_[i]); !it.Done(); it.Advance()) {
487 !it.Done();
488 it.Advance()) {
489 LiveRange* range = GetLiveRange(it.Current()); 575 LiveRange* range = GetLiveRange(it.Current());
490 if (HasOnlyUnconstrainedUsesInLoop(range, block_info)) { 576 if (HasOnlyUnconstrainedUsesInLoop(range, block_info)) {
491 range->MarkHasOnlyUnconstrainedUsesInLoop(block_info->loop_id()); 577 range->MarkHasOnlyUnconstrainedUsesInLoop(block_info->loop_id());
492 } 578 }
493 } 579 }
494 } 580 }
495 581
496 ConnectIncomingPhiMoves(block); 582 ConnectIncomingPhiMoves(block);
497 } 583 }
498 584
(...skipping 1815 matching lines...) Expand 10 before | Expand all | Expand 10 after
2314 sibling->assigned_location(), 2400 sibling->assigned_location(),
2315 range->assigned_location()); 2401 range->assigned_location());
2316 } 2402 }
2317 range = sibling; 2403 range = sibling;
2318 } 2404 }
2319 } 2405 }
2320 2406
2321 // Resolve non-linear control flow across branches. 2407 // Resolve non-linear control flow across branches.
2322 for (intptr_t i = 1; i < block_order_.length(); i++) { 2408 for (intptr_t i = 1; i < block_order_.length(); i++) {
2323 BlockEntryInstr* block = block_order_[i]; 2409 BlockEntryInstr* block = block_order_[i];
2324 BitVector* live = liveness_.GetLiveInSet(block); 2410 BitVector* live = live_in_[block->postorder_number()];
2325 for (BitVector::Iterator it(live); !it.Done(); it.Advance()) { 2411 for (BitVector::Iterator it(live); !it.Done(); it.Advance()) {
2326 LiveRange* range = GetLiveRange(it.Current()); 2412 LiveRange* range = GetLiveRange(it.Current());
2327 for (intptr_t j = 0; j < block->PredecessorCount(); j++) { 2413 for (intptr_t j = 0; j < block->PredecessorCount(); j++) {
2328 ConnectSplitSiblings(range, block->PredecessorAt(j), block); 2414 ConnectSplitSiblings(range, block->PredecessorAt(j), block);
2329 } 2415 }
2330 } 2416 }
2331 } 2417 }
2332 2418
2333 // Eagerly spill values. 2419 // Eagerly spill values.
2334 // TODO(vegorov): if value is spilled on the cold path (e.g. by the call) 2420 // 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
2381 } 2467 }
2382 } 2468 }
2383 } 2469 }
2384 2470
2385 2471
2386 void FlowGraphAllocator::AllocateRegisters() { 2472 void FlowGraphAllocator::AllocateRegisters() {
2387 CollectRepresentations(); 2473 CollectRepresentations();
2388 2474
2389 EliminateEnvironments(); 2475 EliminateEnvironments();
2390 2476
2391 liveness_.Analyze(); 2477 AnalyzeLiveness();
2392 2478
2393 NumberInstructions(); 2479 NumberInstructions();
2394 2480
2395 DiscoverLoops(); 2481 DiscoverLoops();
2396 2482
2397 BuildLiveRanges(); 2483 BuildLiveRanges();
2398 2484
2399 if (FLAG_print_ssa_liveness) { 2485 if (FLAG_print_ssa_liveness) {
2400 liveness_.Dump(); 2486 DumpLiveness();
2401 } 2487 }
2402 2488
2403 if (FLAG_print_ssa_liveranges) { 2489 if (FLAG_print_ssa_liveranges) {
2404 const Function& function = flow_graph_.parsed_function().function(); 2490 const Function& function = flow_graph_.parsed_function().function();
2405 2491
2406 OS::Print("-- [before ssa allocator] ranges [%s] ---------\n", 2492 OS::Print("-- [before ssa allocator] ranges [%s] ---------\n",
2407 function.ToFullyQualifiedCString()); 2493 function.ToFullyQualifiedCString());
2408 PrintLiveRanges(); 2494 PrintLiveRanges();
2409 OS::Print("----------------------------------------------\n"); 2495 OS::Print("----------------------------------------------\n");
2410 2496
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2451 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", 2537 OS::Print("-- [after ssa allocator] ir [%s] -------------\n",
2452 function.ToFullyQualifiedCString()); 2538 function.ToFullyQualifiedCString());
2453 FlowGraphPrinter printer(flow_graph_, true); 2539 FlowGraphPrinter printer(flow_graph_, true);
2454 printer.PrintBlocks(); 2540 printer.PrintBlocks();
2455 OS::Print("----------------------------------------------\n"); 2541 OS::Print("----------------------------------------------\n");
2456 } 2542 }
2457 } 2543 }
2458 2544
2459 2545
2460 } // namespace dart 2546 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_allocator.h ('k') | runtime/vm/flow_graph_optimizer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698