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

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

Issue 12638040: 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 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 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 ASSERT(postorder_.Last()->IsGraphEntry()); 425 ASSERT(postorder_.Last()->IsGraphEntry());
516 BitVector* current_interference_set = NULL; 426 BitVector* current_interference_set = NULL;
517 for (intptr_t i = 0; i < (block_count - 1); i++) { 427 for (intptr_t i = 0; i < (block_count - 1); i++) {
518 BlockEntryInstr* block = postorder_[i]; 428 BlockEntryInstr* block = postorder_[i];
519 429
520 BlockInfo* block_info = BlockInfoAt(block->start_pos()); 430 BlockInfo* block_info = BlockInfoAt(block->start_pos());
521 431
522 // For every SSA value that is live out of this block, create an interval 432 // For every SSA value that is live out of this block, create an interval
523 // that covers the whole block. It will be shortened if we encounter a 433 // that covers the whole block. It will be shortened if we encounter a
524 // definition of this value in this block. 434 // definition of this value in this block.
525 for (BitVector::Iterator it(live_out_[i]); !it.Done(); it.Advance()) { 435 for (BitVector::Iterator it(liveness_.GetLiveOutSetAt(i));
436 !it.Done();
437 it.Advance()) {
526 LiveRange* range = GetLiveRange(it.Current()); 438 LiveRange* range = GetLiveRange(it.Current());
527 range->AddUseInterval(block->start_pos(), block->end_pos()); 439 range->AddUseInterval(block->start_pos(), block->end_pos());
528 } 440 }
529 441
530 BlockInfo* loop_header = block_info->loop_header(); 442 BlockInfo* loop_header = block_info->loop_header();
531 if ((loop_header != NULL) && (loop_header->last_block() == block)) { 443 if ((loop_header != NULL) && (loop_header->last_block() == block)) {
532 current_interference_set = 444 current_interference_set =
533 new BitVector(flow_graph_.max_virtual_register_number()); 445 new BitVector(flow_graph_.max_virtual_register_number());
534 ASSERT(loop_header->backedge_interference() == NULL); 446 ASSERT(loop_header->backedge_interference() == NULL);
535 loop_header->set_backedge_interference( 447 loop_header->set_backedge_interference(
(...skipping 11 matching lines...) Expand all
547 if (!current->IsParallelMove()) { 459 if (!current->IsParallelMove()) {
548 ProcessOneInstruction(block, current, current_interference_set); 460 ProcessOneInstruction(block, current, current_interference_set);
549 } 461 }
550 current = current->previous(); 462 current = current->previous();
551 } 463 }
552 464
553 465
554 // Check if any values live into the loop can be spilled for free. 466 // Check if any values live into the loop can be spilled for free.
555 if (block_info->is_loop_header()) { 467 if (block_info->is_loop_header()) {
556 current_interference_set = NULL; 468 current_interference_set = NULL;
557 for (BitVector::Iterator it(live_in_[i]); !it.Done(); it.Advance()) { 469 for (BitVector::Iterator it(liveness_.GetLiveInSetAt(i));
470 !it.Done();
471 it.Advance()) {
558 LiveRange* range = GetLiveRange(it.Current()); 472 LiveRange* range = GetLiveRange(it.Current());
559 if (HasOnlyUnconstrainedUsesInLoop(range, block_info)) { 473 if (HasOnlyUnconstrainedUsesInLoop(range, block_info)) {
560 range->MarkHasOnlyUnconstrainedUsesInLoop(block_info->loop_id()); 474 range->MarkHasOnlyUnconstrainedUsesInLoop(block_info->loop_id());
561 } 475 }
562 } 476 }
563 } 477 }
564 478
565 ConnectIncomingPhiMoves(block); 479 ConnectIncomingPhiMoves(block);
566 } 480 }
567 481
(...skipping 1798 matching lines...) Expand 10 before | Expand all | Expand 10 after
2366 sibling->assigned_location(), 2280 sibling->assigned_location(),
2367 range->assigned_location()); 2281 range->assigned_location());
2368 } 2282 }
2369 range = sibling; 2283 range = sibling;
2370 } 2284 }
2371 } 2285 }
2372 2286
2373 // Resolve non-linear control flow across branches. 2287 // Resolve non-linear control flow across branches.
2374 for (intptr_t i = 1; i < block_order_.length(); i++) { 2288 for (intptr_t i = 1; i < block_order_.length(); i++) {
2375 BlockEntryInstr* block = block_order_[i]; 2289 BlockEntryInstr* block = block_order_[i];
2376 BitVector* live = live_in_[block->postorder_number()]; 2290 BitVector* live = liveness_.GetLiveInSet(block);
2377 for (BitVector::Iterator it(live); !it.Done(); it.Advance()) { 2291 for (BitVector::Iterator it(live); !it.Done(); it.Advance()) {
2378 LiveRange* range = GetLiveRange(it.Current()); 2292 LiveRange* range = GetLiveRange(it.Current());
2379 for (intptr_t j = 0; j < block->PredecessorCount(); j++) { 2293 for (intptr_t j = 0; j < block->PredecessorCount(); j++) {
2380 ConnectSplitSiblings(range, block->PredecessorAt(j), block); 2294 ConnectSplitSiblings(range, block->PredecessorAt(j), block);
2381 } 2295 }
2382 } 2296 }
2383 } 2297 }
2384 2298
2385 // Eagerly spill values. 2299 // Eagerly spill values.
2386 // TODO(vegorov): if value is spilled on the cold path (e.g. by the call) 2300 // 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
2433 } 2347 }
2434 } 2348 }
2435 } 2349 }
2436 2350
2437 2351
2438 void FlowGraphAllocator::AllocateRegisters() { 2352 void FlowGraphAllocator::AllocateRegisters() {
2439 CollectRepresentations(); 2353 CollectRepresentations();
2440 2354
2441 EliminateEnvironments(); 2355 EliminateEnvironments();
2442 2356
2443 AnalyzeLiveness(); 2357 liveness_.Analyze();
2444 2358
2445 NumberInstructions(); 2359 NumberInstructions();
2446 2360
2447 DiscoverLoops(); 2361 DiscoverLoops();
2448 2362
2449 BuildLiveRanges(); 2363 BuildLiveRanges();
2450 2364
2451 if (FLAG_print_ssa_liveness) { 2365 if (FLAG_print_ssa_liveness) {
2452 DumpLiveness(); 2366 liveness_.Dump();
2453 } 2367 }
2454 2368
2455 if (FLAG_print_ssa_liveranges) { 2369 if (FLAG_print_ssa_liveranges) {
2456 const Function& function = flow_graph_.parsed_function().function(); 2370 const Function& function = flow_graph_.parsed_function().function();
2457 2371
2458 OS::Print("-- [before ssa allocator] ranges [%s] ---------\n", 2372 OS::Print("-- [before ssa allocator] ranges [%s] ---------\n",
2459 function.ToFullyQualifiedCString()); 2373 function.ToFullyQualifiedCString());
2460 PrintLiveRanges(); 2374 PrintLiveRanges();
2461 OS::Print("----------------------------------------------\n"); 2375 OS::Print("----------------------------------------------\n");
2462 2376
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2503 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", 2417 OS::Print("-- [after ssa allocator] ir [%s] -------------\n",
2504 function.ToFullyQualifiedCString()); 2418 function.ToFullyQualifiedCString());
2505 FlowGraphPrinter printer(flow_graph_, true); 2419 FlowGraphPrinter printer(flow_graph_, true);
2506 printer.PrintBlocks(); 2420 printer.PrintBlocks();
2507 OS::Print("----------------------------------------------\n"); 2421 OS::Print("----------------------------------------------\n");
2508 } 2422 }
2509 } 2423 }
2510 2424
2511 2425
2512 } // namespace dart 2426 } // 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