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

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

Issue 10735071: Introduce Goto instructions to the flow graph. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Tweaked instruction numbering. Created 8 years, 5 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 | « no previous file | runtime/vm/flow_graph_builder.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_builder.h" 10 #include "vm/flow_graph_builder.h"
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 BlockEntryInstr* block = postorder_[i]; 378 BlockEntryInstr* block = postorder_[i];
379 379
380 // For every SSA value that is live out of this block create an interval 380 // For every SSA value that is live out of this block create an interval
381 // that covers the hole block. It will be shortened if we encounter a 381 // that covers the hole block. It will be shortened if we encounter a
382 // definition of this value in this block. 382 // definition of this value in this block.
383 for (BitVector::Iterator it(live_out_[i]); !it.Done(); it.Advance()) { 383 for (BitVector::Iterator it(live_out_[i]); !it.Done(); it.Advance()) {
384 LiveRange* range = GetLiveRange(it.Current()); 384 LiveRange* range = GetLiveRange(it.Current());
385 range->AddUseInterval(block->start_pos(), block->end_pos()); 385 range->AddUseInterval(block->start_pos(), block->end_pos());
386 } 386 }
387 387
388 // Position corresponding to the end of the last instruction in the block. 388 // Position corresponding to the beginning of the last instruction in the
389 // block.
389 intptr_t pos = block->end_pos() - 1; 390 intptr_t pos = block->end_pos() - 1;
390
391 Instruction* current = block->last_instruction(); 391 Instruction* current = block->last_instruction();
392 392
393 // If last instruction is a parallel move we need to perform phi resolution. 393 // Goto instructions do not contribute liveness information.
394 if (current->IsParallelMove()) { 394 GotoInstr* goto_instr = current->AsGoto();
395 if (goto_instr != NULL) {
396 current = current->previous();
397 // If we have a parallel move here then the successor block must be a
srdjan 2012/07/16 16:50:45 must start with a join with phis
398 // join with phis. The phi inputs contribute uses to each predecessor
399 // block (and the phi outputs contribute definitions in the successor
400 // block).
401 //
402 // We record those uses at the end of the instruction preceding the
403 // parallel move. This position is 'pos', because we do not assign
404 // instruction numbers to parallel moves.
395 ParallelMoveInstr* parallel_move = current->AsParallelMove(); 405 ParallelMoveInstr* parallel_move = current->AsParallelMove();
396 JoinEntryInstr* join = current->next()->AsJoinEntry(); 406 if (parallel_move != NULL) {
397 ASSERT(join != NULL); 407 JoinEntryInstr* join = goto_instr->successor();
408 ASSERT(join != NULL);
398 409
399 // Find index of the current block in predecessors of join. 410 // Search for the index of the current block in the predecessors of
400 intptr_t pred_idx = -1; 411 // the join.
401 for (intptr_t j = 0; j < join->PredecessorCount(); j++) { 412 // TODO(kmillikin): record the predecessor index in the goto when
402 BlockEntryInstr* pred = join->PredecessorAt(j); 413 // building the predecessor list to avoid this search.
403 if (pred == block) { 414 intptr_t pred_idx = 0;
404 pred_idx = j; 415 for (; pred_idx < join->PredecessorCount(); pred_idx++) {
405 break; 416 if (join->PredecessorAt(pred_idx) == block) break;
406 } 417 }
407 } 418 ASSERT(pred_idx < join->PredecessorCount());
408 ASSERT(pred_idx != -1);
409 419
410 // For every phi we have a reserved phi resolution move and we need 420 // Record the corresponding phi input use for each phi.
411 // to either initialize its source with constant or to register a use, so 421 ZoneGrowableArray<PhiInstr*>* phis = join->phis();
412 // that register allocator will populate source slot with location of 422 for (intptr_t move_idx = 0; move_idx < phis->length(); move_idx++) {
413 // the appropriate SSA value. 423 PhiInstr* phi = (*phis)[move_idx];
414 ZoneGrowableArray<PhiInstr*>* phis = join->phis(); 424 if (phi == NULL) continue;
415 intptr_t move_idx = 0;
416 for (intptr_t j = 0; j < phis->length(); j++) {
417 PhiInstr* phi = (*phis)[j];
418 if (phi == NULL) continue;
419 425
420 Value* val = phi->InputAt(pred_idx); 426 Value* val = phi->InputAt(pred_idx);
421 427 MoveOperands move = parallel_move->moves()[move_idx];
422 MoveOperands move = parallel_move->moves()[move_idx]; 428 if (val->IsUse()) {
423 if (val->IsUse()) { 429 const intptr_t virtual_register =
424 const intptr_t use = val->AsUse()->definition()->ssa_temp_index(); 430 val->AsUse()->definition()->ssa_temp_index();
425 Location* slot = move.src_slot(); 431 Location* slot = move.src_slot();
426 *slot = Location::RequiresRegister(); 432 *slot = Location::RequiresRegister();
427 GetLiveRange(use)->head()->AddUse(NULL, pos, slot); 433 GetLiveRange(virtual_register)->head()->AddUse(NULL, pos, slot);
428 } else { 434 } else {
429 ASSERT(val->IsConstant()); 435 ASSERT(val->IsConstant());
430 move.set_src(Location::Constant(val->AsConstant()->value())); 436 move.set_src(Location::Constant(val->AsConstant()->value()));
437 }
431 } 438 }
432 439
433 move_idx++; 440 // Begin backward iteration with the instruction before the parallel
441 // move.
442 current = current->previous();
srdjan 2012/07/16 16:50:45 According to the comment this should this be 'curr
Kevin Millikin (Google) 2012/07/18 09:47:11 Yes. It's hard to see on the codereview tool, but
434 } 443 }
435
436 current = current->previous();
437 } 444 }
438 445
439 // Now process all instructions in reverse order. 446 // Now process all instructions in reverse order.
440 // Advance position to the start of the last instruction in the block. 447 --pos; // 'pos' is now the start position for the current instruction.
441 pos -= 1;
442 while (current != block) { 448 while (current != block) {
443 LocationSummary* locs = current->locs(); 449 LocationSummary* locs = current->locs();
444 450
445 const bool output_same_as_first_input = 451 const bool output_same_as_first_input =
446 locs->out().IsUnallocated() && 452 locs->out().IsUnallocated() &&
447 locs->out().policy() == Location::kSameAsFirstInput; 453 locs->out().policy() == Location::kSameAsFirstInput;
448 454
449 // TODO(vegorov): number of inputs should match number of input locations. 455 // TODO(vegorov): number of inputs should match number of input locations.
450 // TODO(vegorov): generic support for writable registers? 456 // TODO(vegorov): generic support for writable registers?
451 for (intptr_t j = 0; j < current->InputCount(); j++) { 457 for (intptr_t j = 0; j < current->InputCount(); j++) {
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 // All phi resolution moves are connected. Phi's live range is complete. 561 // All phi resolution moves are connected. Phi's live range is complete.
556 AddToUnallocated(interval); 562 AddToUnallocated(interval);
557 563
558 move_idx++; 564 move_idx++;
559 } 565 }
560 } 566 }
561 } 567 }
562 } 568 }
563 569
564 570
571 // Linearize the control flow graph. The chosen order will be used by the
572 // linear-scan register allocator. Number most instructions with a pair of
573 // numbers representing lifetime positions. Introduce explicit parallel
574 // move instructions in the predecessors of join nodes. The moves are used
575 // for phi resolution.
Vyacheslav Egorov (Google) 2012/07/16 14:16:41 there is a comment in the header file. you can cop
565 void FlowGraphAllocator::NumberInstructions() { 576 void FlowGraphAllocator::NumberInstructions() {
566 intptr_t pos = 0; 577 intptr_t pos = 0;
567 578
579 // The basic block order is reverse postorder.
568 const intptr_t block_count = postorder_.length(); 580 const intptr_t block_count = postorder_.length();
569 for (intptr_t i = block_count - 1; i >= 0; i--) { 581 for (intptr_t i = block_count - 1; i >= 0; i--) {
570 BlockEntryInstr* block = postorder_[i]; 582 BlockEntryInstr* block = postorder_[i];
571
572 block->set_start_pos(pos); 583 block->set_start_pos(pos);
584 block->set_lifetime_position(pos);
573 pos += 2; 585 pos += 2;
574 Instruction* current = block->next(); 586 // We do not assign an instruction number to the block entry.
Kevin Millikin (Google) 2012/07/16 13:49:18 Ooops, this comment described the situation before
575 587 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
576 Instruction* last = block->last_instruction(); 588 Instruction* current = it.Current();
577 if (!last->IsParallelMove()) last = last->next(); 589 // Do not assign numbers to parallel moves or goto instructions.
578 590 if (!current->IsParallelMove() && !current->IsGoto()) {
579 while (current != last) { 591 current->set_lifetime_position(pos);
580 current->set_lifetime_position(pos); 592 pos += 2;
581 current = current->next(); 593 }
582 pos += 2;
583 } 594 }
584 block->set_end_pos(pos); 595 block->set_end_pos(pos);
585 596
586 // For join entry predecessors create phi resolution moves if 597 // For join entry predecessors create phi resolution moves if
587 // necessary. They will be populated by the register allocator. 598 // necessary. They will be populated by the register allocator.
588 if (block->IsJoinEntry() && (block->AsJoinEntry()->phi_count() > 0)) { 599 JoinEntryInstr* join = block->AsJoinEntry();
589 const intptr_t phi_count = block->AsJoinEntry()->phi_count(); 600 if ((join != NULL) && (join->phi_count() > 0)) {
601 const intptr_t phi_count = join->phi_count();
590 for (intptr_t i = 0; i < block->PredecessorCount(); i++) { 602 for (intptr_t i = 0; i < block->PredecessorCount(); i++) {
591 BlockEntryInstr* pred = block->PredecessorAt(i);
592 ASSERT(!pred->last_instruction()->IsParallelMove());
593
594 ParallelMoveInstr* move = new ParallelMoveInstr(); 603 ParallelMoveInstr* move = new ParallelMoveInstr();
595 move->set_next(block); 604 // Populate the ParallelMove with empty moves.
596 move->set_previous(pred->last_instruction());
597 pred->last_instruction()->set_next(move);
598 pred->set_last_instruction(move);
599
600 // Populate ParallelMove with empty moves.
601 for (intptr_t j = 0; j < phi_count; j++) { 605 for (intptr_t j = 0; j < phi_count; j++) {
602 move->AddMove(Location::NoLocation(), Location::NoLocation()); 606 move->AddMove(Location::NoLocation(), Location::NoLocation());
603 } 607 }
608
609 // Insert the move between the last two instructions of the
610 // predecessor block (all such blocks have at least two instructions:
611 // the block entry and goto instructions.)
612 BlockEntryInstr* pred = block->PredecessorAt(i);
613 Instruction* next = pred->last_instruction();
614 Instruction* previous = next->previous();
615 ASSERT(next->IsGoto());
616 ASSERT(!previous->IsParallelMove());
617 previous->set_next(move);
618 move->set_previous(previous);
619 move->set_next(next);
620 next->set_previous(move);
604 } 621 }
605 } 622 }
606 } 623 }
607 } 624 }
608 625
609 626
610 intptr_t UseInterval::Intersect(UseInterval* other) { 627 intptr_t UseInterval::Intersect(UseInterval* other) {
611 if (this->start() <= other->start()) { 628 if (this->start() <= other->start()) {
612 if (other->start() < this->end()) return other->start(); 629 if (other->start() < this->end()) return other->start();
613 } else if (this->start() < other->end()) { 630 } else if (this->start() < other->end()) {
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
927 944
928 if (FLAG_trace_ssa_allocator) { 945 if (FLAG_trace_ssa_allocator) {
929 OS::Print("-- ir after allocation -------------------------\n"); 946 OS::Print("-- ir after allocation -------------------------\n");
930 FlowGraphPrinter printer(Function::Handle(), block_order_, true); 947 FlowGraphPrinter printer(Function::Handle(), block_order_, true);
931 printer.PrintBlocks(); 948 printer.PrintBlocks();
932 } 949 }
933 } 950 }
934 951
935 952
936 } // namespace dart 953 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/flow_graph_builder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698