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

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: Incorporated review comments. 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 intptr_t pos = block->end_pos() - 1; 389 // block.
390 390 intptr_t pos = block->end_pos() - 2;
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();
Vyacheslav Egorov (Google) 2012/07/16 12:42:55 I suggest you just don't give goto a position in N
395 if (goto_instr != NULL) {
396 --pos; // The end of the previous instruction.
397 current = current->previous();
398 // If we have a parallel move here then the successor block must be a
399 // join with phis. The phi inputs contribute uses to the predecessor
400 // blocks (and the phi outputs are definitions in the successor block).
395 ParallelMoveInstr* parallel_move = current->AsParallelMove(); 401 ParallelMoveInstr* parallel_move = current->AsParallelMove();
396 JoinEntryInstr* join = current->next()->AsJoinEntry(); 402 if (parallel_move != NULL) {
397 ASSERT(join != NULL); 403 JoinEntryInstr* join = goto_instr->successor();
404 ASSERT(join != NULL);
398 405
399 // Find index of the current block in predecessors of join. 406 // Search for the index of the current block in the predecessors of
400 intptr_t pred_idx = -1; 407 // the join. TODO(kmillikin): record the predecessor index in the
401 for (intptr_t j = 0; j < join->PredecessorCount(); j++) { 408 // goto when building the predecessor list to avoid this search.
402 BlockEntryInstr* pred = join->PredecessorAt(j); 409 intptr_t pred_idx = 0;
403 if (pred == block) { 410 for (; pred_idx < join->PredecessorCount(); pred_idx++) {
404 pred_idx = j; 411 if (join->PredecessorAt(pred_idx) == block) break;
405 break;
406 } 412 }
407 } 413 ASSERT(pred_idx < join->PredecessorCount());
408 ASSERT(pred_idx != -1);
409 414
410 // For every phi we have a reserved phi resolution move and we need 415 // Record the corresponding phi input use for each phi.
411 // to either initialize its source with constant or to register a use, so 416 ZoneGrowableArray<PhiInstr*>* phis = join->phis();
412 // that register allocator will populate source slot with location of 417 for (intptr_t move_idx = 0; move_idx < phis->length(); move_idx++) {
413 // the appropriate SSA value. 418 PhiInstr* phi = (*phis)[move_idx];
414 ZoneGrowableArray<PhiInstr*>* phis = join->phis(); 419 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 420
420 Value* val = phi->InputAt(pred_idx); 421 Value* val = phi->InputAt(pred_idx);
421 422 MoveOperands move = parallel_move->moves()[move_idx];
422 MoveOperands move = parallel_move->moves()[move_idx]; 423 if (val->IsUse()) {
423 if (val->IsUse()) { 424 const intptr_t virtual_register =
424 const intptr_t use = val->AsUse()->definition()->ssa_temp_index(); 425 val->AsUse()->definition()->ssa_temp_index();
425 Location* slot = move.src_slot(); 426 Location* slot = move.src_slot();
426 *slot = Location::RequiresRegister(); 427 *slot = Location::RequiresRegister();
427 GetLiveRange(use)->head()->AddUse(NULL, pos, slot); 428 GetLiveRange(virtual_register)->head()->AddUse(NULL, pos, slot);
428 } else { 429 } else {
429 ASSERT(val->IsConstant()); 430 ASSERT(val->IsConstant());
430 move.set_src(Location::Constant(val->AsConstant()->value())); 431 move.set_src(Location::Constant(val->AsConstant()->value()));
432 }
431 } 433 }
432 434
433 move_idx++; 435 // Skip to the instruction before the parallel move.
436 pos -= 3; // The beginning of the previous instruction.
Vyacheslav Egorov (Google) 2012/07/16 12:42:55 I don't get where -3 comes from. we now have -6 in
Kevin Millikin (Google) 2012/07/16 13:47:48 I was counting both the goto and the parallel move
437 current = current->previous();
434 } 438 }
435
436 current = current->previous();
437 } 439 }
438 440
439 // Now process all instructions in reverse order. 441 // Now process all instructions in reverse order.
440 // Advance position to the start of the last instruction in the block.
441 pos -= 1;
442 while (current != block) { 442 while (current != block) {
443 LocationSummary* locs = current->locs(); 443 LocationSummary* locs = current->locs();
444 444
445 const bool output_same_as_first_input = 445 const bool output_same_as_first_input =
446 locs->out().IsUnallocated() && 446 locs->out().IsUnallocated() &&
447 locs->out().policy() == Location::kSameAsFirstInput; 447 locs->out().policy() == Location::kSameAsFirstInput;
448 448
449 // TODO(vegorov): number of inputs should match number of input locations. 449 // TODO(vegorov): number of inputs should match number of input locations.
450 // TODO(vegorov): generic support for writable registers? 450 // TODO(vegorov): generic support for writable registers?
451 for (intptr_t j = 0; j < current->InputCount(); j++) { 451 for (intptr_t j = 0; j < current->InputCount(); j++) {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 } 513 }
514 514
515 Definition* def = current->AsDefinition(); 515 Definition* def = current->AsDefinition();
516 if ((def != NULL) && (def->ssa_temp_index() >= 0)) { 516 if ((def != NULL) && (def->ssa_temp_index() >= 0)) {
517 Define(output_same_as_first_input ? current : NULL, 517 Define(output_same_as_first_input ? current : NULL,
518 pos, 518 pos,
519 def->ssa_temp_index(), 519 def->ssa_temp_index(),
520 locs->out_slot()); 520 locs->out_slot());
521 } 521 }
522 522
523 pos -= 2;
523 current = current->previous(); 524 current = current->previous();
524 pos -= 2;
525 } 525 }
526 526
527 // If this block is a join we need to add destinations of phi 527 // If this block is a join we need to add destinations of phi
528 // resolution moves to phi's live range so that register allocator will 528 // resolution moves to phi's live range so that register allocator will
529 // fill them with moves. 529 // fill them with moves.
530 if (block->IsJoinEntry() && block->AsJoinEntry()->phis() != NULL) { 530 if (block->IsJoinEntry() && block->AsJoinEntry()->phis() != NULL) {
531 ZoneGrowableArray<PhiInstr*>* phis = block->AsJoinEntry()->phis(); 531 ZoneGrowableArray<PhiInstr*>* phis = block->AsJoinEntry()->phis();
532 532
533 intptr_t move_idx = 0; 533 intptr_t move_idx = 0;
534 for (intptr_t j = 0; j < phis->length(); j++) { 534 for (intptr_t j = 0; j < phis->length(); j++) {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 current = current->next(); 581 current = current->next();
582 pos += 2; 582 pos += 2;
583 } 583 }
584 block->set_end_pos(pos); 584 block->set_end_pos(pos);
585 585
586 // For join entry predecessors create phi resolution moves if 586 // For join entry predecessors create phi resolution moves if
587 // necessary. They will be populated by the register allocator. 587 // necessary. They will be populated by the register allocator.
588 if (block->IsJoinEntry() && (block->AsJoinEntry()->phi_count() > 0)) { 588 if (block->IsJoinEntry() && (block->AsJoinEntry()->phi_count() > 0)) {
589 const intptr_t phi_count = block->AsJoinEntry()->phi_count(); 589 const intptr_t phi_count = block->AsJoinEntry()->phi_count();
590 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
594 ParallelMoveInstr* move = new ParallelMoveInstr(); 591 ParallelMoveInstr* move = new ParallelMoveInstr();
595 move->set_next(block); 592 // 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++) { 593 for (intptr_t j = 0; j < phi_count; j++) {
602 move->AddMove(Location::NoLocation(), Location::NoLocation()); 594 move->AddMove(Location::NoLocation(), Location::NoLocation());
603 } 595 }
596
597 // Insert the move between the last two instructions of the
598 // predecessor block (all such blocks have at least two instructions:
599 // the block entry and goto instructions.)
600 BlockEntryInstr* pred = block->PredecessorAt(i);
601 Instruction* next = pred->last_instruction();
602 Instruction* previous = next->previous();
603 ASSERT(next->IsGoto());
604 ASSERT(!previous->IsParallelMove()); // Why??
Vyacheslav Egorov (Google) 2012/07/16 12:42:55 ParallelMove should be created only once. (verific
Kevin Millikin (Google) 2012/07/16 13:47:48 It seems like an indirect way to assert that. It
605 previous->set_next(move);
606 move->set_previous(previous);
607 move->set_next(next);
608 next->set_previous(move);
604 } 609 }
605 } 610 }
606 } 611 }
607 } 612 }
608 613
609 614
610 intptr_t UseInterval::Intersect(UseInterval* other) { 615 intptr_t UseInterval::Intersect(UseInterval* other) {
611 if (this->start() <= other->start()) { 616 if (this->start() <= other->start()) {
612 if (other->start() < this->end()) return other->start(); 617 if (other->start() < this->end()) return other->start();
613 } else if (this->start() < other->end()) { 618 } else if (this->start() < other->end()) {
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
927 932
928 if (FLAG_trace_ssa_allocator) { 933 if (FLAG_trace_ssa_allocator) {
929 OS::Print("-- ir after allocation -------------------------\n"); 934 OS::Print("-- ir after allocation -------------------------\n");
930 FlowGraphPrinter printer(Function::Handle(), block_order_, true); 935 FlowGraphPrinter printer(Function::Handle(), block_order_, true);
931 printer.PrintBlocks(); 936 printer.PrintBlocks();
932 } 937 }
933 } 938 }
934 939
935 940
936 } // namespace dart 941 } // 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