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

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

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