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

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

Issue 10821108: Ensure that we never try to split range at its end position. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 4 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.cc » ('j') | runtime/vm/flow_graph_builder.cc » ('J')
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 20 matching lines...) Expand all
31 static const intptr_t kTempVirtualRegister = -2; 31 static const intptr_t kTempVirtualRegister = -2;
32 static const intptr_t kIllegalPosition = -1; 32 static const intptr_t kIllegalPosition = -1;
33 static const intptr_t kMaxPosition = 0x7FFFFFFF; 33 static const intptr_t kMaxPosition = 0x7FFFFFFF;
34 34
35 35
36 static intptr_t MinPosition(intptr_t a, intptr_t b) { 36 static intptr_t MinPosition(intptr_t a, intptr_t b) {
37 return (a < b) ? a : b; 37 return (a < b) ? a : b;
38 } 38 }
39 39
40 40
41 static bool IsParallelMovePosition(intptr_t pos) {
42 return (pos & 1) == 0;
43 }
44
45
46 static bool IsInstructionStartPosition(intptr_t pos) { 41 static bool IsInstructionStartPosition(intptr_t pos) {
47 return (pos & 1) == 0; 42 return (pos & 1) == 0;
48 } 43 }
49 44
50 45
51 static bool IsInstructionEndPosition(intptr_t pos) { 46 static bool IsInstructionEndPosition(intptr_t pos) {
52 return (pos & 1) == 1; 47 return (pos & 1) == 1;
53 } 48 }
54 49
55 50
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 } 324 }
330 325
331 326
332 void FlowGraphAllocator::BlockLocation(Location loc, intptr_t pos) { 327 void FlowGraphAllocator::BlockLocation(Location loc, intptr_t pos) {
333 ASSERT(loc.IsRegister()); 328 ASSERT(loc.IsRegister());
334 const Register reg = loc.reg(); 329 const Register reg = loc.reg();
335 if (blocked_cpu_regs_[reg]) return; 330 if (blocked_cpu_regs_[reg]) return;
336 if (cpu_regs_[reg].length() == 0) { 331 if (cpu_regs_[reg].length() == 0) {
337 cpu_regs_[reg].Add(new LiveRange(kNoVirtualRegister)); 332 cpu_regs_[reg].Add(new LiveRange(kNoVirtualRegister));
338 } 333 }
339 cpu_regs_[reg][0]->AddUseInterval(pos, pos + 2); 334 cpu_regs_[reg][0]->AddUseInterval(pos, pos + 1);
srdjan 2012/07/31 15:58:35 Please add comment about the interval range (begin
Vyacheslav Egorov (Google) 2012/07/31 16:18:49 Done.
340 } 335 }
341 336
342 337
343 void LiveRange::Print() { 338 void LiveRange::Print() {
344 OS::Print(" live range v%d [%d, %d)\n", vreg(), Start(), End()); 339 OS::Print(" live range v%d [%d, %d)\n", vreg(), Start(), End());
345 UsePosition* use_pos = uses_; 340 UsePosition* use_pos = uses_;
346 for (UseInterval* interval = first_use_interval_; 341 for (UseInterval* interval = first_use_interval_;
347 interval != NULL; 342 interval != NULL;
348 interval = interval->next()) { 343 interval = interval->next()) {
349 OS::Print(" use interval [%d, %d)\n", 344 OS::Print(" use interval [%d, %d)\n",
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 BlockEntryInstr* block) { 468 BlockEntryInstr* block) {
474 Instruction* last = block->last_instruction(); 469 Instruction* last = block->last_instruction();
475 470
476 GotoInstr* goto_instr = last->AsGoto(); 471 GotoInstr* goto_instr = last->AsGoto();
477 if (goto_instr == NULL) return last; 472 if (goto_instr == NULL) return last;
478 473
479 // If we have a parallel move here then the successor block must be a 474 // If we have a parallel move here then the successor block must be a
480 // join with phis. The phi inputs contribute uses to each predecessor 475 // join with phis. The phi inputs contribute uses to each predecessor
481 // block (and the phi outputs contribute definitions in the successor 476 // block (and the phi outputs contribute definitions in the successor
482 // block). 477 // block).
483 ParallelMoveInstr* parallel_move = goto_instr->previous()->AsParallelMove(); 478 if (!goto_instr->HasParallelMove()) return goto_instr->previous();
484 if (parallel_move == NULL) return goto_instr->previous(); 479 ParallelMoveInstr* parallel_move = goto_instr->parallel_move();
485 480
486 // All uses are recorded at the position of parallel move preceding goto. 481 // All uses are recorded at the position of parallel move preceding goto.
487 const intptr_t pos = goto_instr->lifetime_position(); 482 const intptr_t pos = goto_instr->lifetime_position();
488 ASSERT(parallel_move->lifetime_position() == pos);
489 483
490 JoinEntryInstr* join = goto_instr->successor(); 484 JoinEntryInstr* join = goto_instr->successor();
491 ASSERT(join != NULL); 485 ASSERT(join != NULL);
492 486
493 // Search for the index of the current block in the predecessors of 487 // Search for the index of the current block in the predecessors of
494 // the join. 488 // the join.
495 const intptr_t pred_idx = join->IndexOfPredecessor(block); 489 const intptr_t pred_idx = join->IndexOfPredecessor(block);
496 490
497 // Record the corresponding phi input use for each phi. 491 // Record the corresponding phi input use for each phi.
498 ZoneGrowableArray<PhiInstr*>* phis = join->phis(); 492 ZoneGrowableArray<PhiInstr*>* phis = join->phis();
(...skipping 20 matching lines...) Expand all
519 move->set_src(Location::PrefersRegister()); 513 move->set_src(Location::PrefersRegister());
520 } else { 514 } else {
521 ASSERT(val->IsConstant()); 515 ASSERT(val->IsConstant());
522 move->set_src(Location::Constant(val->AsConstant()->value())); 516 move->set_src(Location::Constant(val->AsConstant()->value()));
523 } 517 }
524 move_idx++; 518 move_idx++;
525 } 519 }
526 520
527 // Begin backward iteration with the instruction before the parallel 521 // Begin backward iteration with the instruction before the parallel
528 // move. 522 // move.
529 return parallel_move->previous(); 523 return goto_instr->previous();
530 } 524 }
531 525
532 526
533 void FlowGraphAllocator::ConnectIncomingPhiMoves(BlockEntryInstr* block) { 527 void FlowGraphAllocator::ConnectIncomingPhiMoves(BlockEntryInstr* block) {
534 // If this block is a join we need to add destinations of phi 528 // If this block is a join we need to add destinations of phi
535 // resolution moves to phi's live range so that register allocator will 529 // resolution moves to phi's live range so that register allocator will
536 // fill them with moves. 530 // fill them with moves.
537 JoinEntryInstr* join = block->AsJoinEntry(); 531 JoinEntryInstr* join = block->AsJoinEntry();
538 if (join == NULL) return; 532 if (join == NULL) return;
539 533
540 // All uses are recorded at the start position in the block. 534 // All uses are recorded at the start position in the block.
541 const intptr_t pos = join->start_pos(); 535 const intptr_t pos = join->start_pos();
542 536
543 ZoneGrowableArray<PhiInstr*>* phis = join->phis(); 537 ZoneGrowableArray<PhiInstr*>* phis = join->phis();
544 if (phis != NULL) { 538 if (phis != NULL) {
545 intptr_t move_idx = 0; 539 intptr_t move_idx = 0;
546 for (intptr_t phi_idx = 0; phi_idx < phis->length(); phi_idx++) { 540 for (intptr_t phi_idx = 0; phi_idx < phis->length(); phi_idx++) {
547 PhiInstr* phi = (*phis)[phi_idx]; 541 PhiInstr* phi = (*phis)[phi_idx];
548 if (phi == NULL) continue; 542 if (phi == NULL) continue;
549 543
550 const intptr_t vreg = phi->ssa_temp_index(); 544 const intptr_t vreg = phi->ssa_temp_index();
551 ASSERT(vreg != -1); 545 ASSERT(vreg != -1);
552 546
553 // Expected shape of live range: 547 // Expected sfhape of live range:
Florian Schneider 2012/07/31 15:31:59 Accidental edit?
Vyacheslav Egorov (Google) 2012/07/31 16:18:49 Done.
554 // 548 //
555 // B 549 // B
556 // phi [-------- 550 // phi [--------
557 // 551 //
558 LiveRange* range = GetLiveRange(vreg); 552 LiveRange* range = GetLiveRange(vreg);
559 range->DefineAt(pos); // Shorten live range. 553 range->DefineAt(pos); // Shorten live range.
560 554
561 for (intptr_t pred_idx = 0; pred_idx < phi->InputCount(); pred_idx++) { 555 for (intptr_t pred_idx = 0; pred_idx < phi->InputCount(); pred_idx++) {
562 BlockEntryInstr* pred = block->PredecessorAt(pred_idx); 556 BlockEntryInstr* pred = block->PredecessorAt(pred_idx);
563 ASSERT(pred->last_instruction()->IsGoto()); 557 GotoInstr* goto_instr = pred->last_instruction()->AsGoto();
564 Instruction* move_instr = pred->last_instruction()->previous(); 558 ASSERT((goto_instr != NULL) && (goto_instr->HasParallelMove()));
565 ASSERT(move_instr->IsParallelMove());
566
567 MoveOperands* move = 559 MoveOperands* move =
568 move_instr->AsParallelMove()->MoveOperandsAt(move_idx); 560 goto_instr->parallel_move()->MoveOperandsAt(move_idx);
569 move->set_dest(Location::PrefersRegister()); 561 move->set_dest(Location::PrefersRegister());
570 range->AddUse(pos, move->dest_slot()); 562 range->AddUse(pos, move->dest_slot());
571 } 563 }
572 564
573 // All phi resolution moves are connected. Phi's live range is 565 // All phi resolution moves are connected. Phi's live range is
574 // complete. 566 // complete.
575 AddToUnallocated(range); 567 AddToUnallocated(range);
576 568
577 move_idx++; 569 move_idx++;
578 } 570 }
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
672 range->AddUseInterval(block->start_pos(), pos + 1); 664 range->AddUseInterval(block->start_pos(), pos + 1);
673 range->AddUse(pos + 1, in_ref); 665 range->AddUse(pos + 1, in_ref);
674 } 666 }
675 } 667 }
676 668
677 // Process temps. 669 // Process temps.
678 for (intptr_t j = 0; j < locs->temp_count(); j++) { 670 for (intptr_t j = 0; j < locs->temp_count(); j++) {
679 // Expected shape of live range: 671 // Expected shape of live range:
680 // 672 //
681 // i i' 673 // i i'
682 // [-----) 674 // [--)
683 // 675 //
684 676
685 Location temp = locs->temp(j); 677 Location temp = locs->temp(j);
686 if (temp.IsRegister()) { 678 if (temp.IsRegister()) {
687 BlockLocation(temp, pos); 679 BlockLocation(temp, pos);
688 } else if (temp.IsUnallocated()) { 680 } else if (temp.IsUnallocated()) {
689 LiveRange* range = new LiveRange(kTempVirtualRegister); 681 LiveRange* range = new LiveRange(kTempVirtualRegister);
690 range->AddUseInterval(pos, pos + 1); 682 range->AddUseInterval(pos, pos + 1);
691 range->AddUse(pos, locs->temp_slot(j)); 683 range->AddUse(pos, locs->temp_slot(j));
692 AddToUnallocated(range); 684 AddToUnallocated(range);
693 } else { 685 } else {
694 UNREACHABLE(); 686 UNREACHABLE();
695 } 687 }
696 } 688 }
697 689
698 // Block all allocatable registers for calls. 690 // Block all allocatable registers for calls.
699 if (locs->is_call()) { 691 if (locs->is_call()) {
700 // Expected shape of live range: 692 // Expected shape of live range:
701 // 693 //
702 // i i' 694 // i i'
703 // [-----) 695 // [--)
704 // 696 //
705 697
706 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { 698 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) {
707 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), 699 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)),
708 pos); 700 pos);
709 } 701 }
710 702
711 #ifdef DEBUG 703 #ifdef DEBUG
712 // Verify that temps, inputs and output were specified as fixed 704 // Verify that temps, inputs and output were specified as fixed
713 // locations. Every register is blocked now so attempt to 705 // locations. Every register is blocked now so attempt to
(...skipping 26 matching lines...) Expand all
740 LiveRange* range = (def->ssa_temp_index() >= 0) ? 732 LiveRange* range = (def->ssa_temp_index() >= 0) ?
741 GetLiveRange(def->ssa_temp_index()) : 733 GetLiveRange(def->ssa_temp_index()) :
742 new LiveRange(kTempVirtualRegister); 734 new LiveRange(kTempVirtualRegister);
743 Location* out = locs->out_slot(); 735 Location* out = locs->out_slot();
744 736
745 // Process output and finalize its liverange. 737 // Process output and finalize its liverange.
746 if (out->IsRegister()) { 738 if (out->IsRegister()) {
747 // Fixed output location. Expected shape of live range: 739 // Fixed output location. Expected shape of live range:
748 // 740 //
749 // i i' j j' 741 // i i' j j'
750 // register [-----) 742 // register [--)
751 // output [------- 743 // output [-------
752 // 744 //
753 BlockLocation(*out, pos); 745 BlockLocation(*out, pos);
754 746
755 if (range->vreg() == kTempVirtualRegister) return; 747 if (range->vreg() == kTempVirtualRegister) return;
756 748
757 // We need to emit move connecting fixed register with another location 749 // We need to emit move connecting fixed register with another location
758 // that will be allocated for this output's live range. 750 // that will be allocated for this output's live range.
759 // Special case: fixed output followed by a fixed input last use. 751 // Special case: fixed output followed by a fixed input last use.
760 UsePosition* use = range->first_use(); 752 UsePosition* use = range->first_use();
761 if (use->pos() == (pos + 2)) { 753 if (use->pos() == (pos + 1)) {
762 ASSERT(use->location_slot()->IsUnallocated()); 754 ASSERT(use->location_slot()->IsUnallocated());
763 *(use->location_slot()) = *out; 755 *(use->location_slot()) = *out;
764 756
765 // Remove first use. It was allocated. 757 // Remove first use. It was allocated.
766 range->set_first_use(range->first_use()->next()); 758 range->set_first_use(range->first_use()->next());
767 } 759 }
768 760
769 // Shorten live range to the point of definition, this might make the range 761 // Shorten live range to the point of definition, this might make the range
770 // empty (if the only use immediately follows). If range is not empty add 762 // empty (if the only use immediately follows). If range is not empty add
771 // move from a fixed register to an unallocated location. 763 // move from a fixed register to an unallocated location.
772 range->DefineAt(pos + 2); 764 range->DefineAt(pos + 1);
773 if (range->Start() == range->End()) return; 765 if (range->Start() == range->End()) return;
774 766
775 MoveOperands* move = AddMoveAt(pos + 2, Location::PrefersRegister(), *out); 767 MoveOperands* move = AddMoveAt(pos + 1, Location::PrefersRegister(), *out);
776 range->AddUse(pos + 2, move->dest_slot()); 768 range->AddUse(pos + 1, move->dest_slot());
777 } else if (output_same_as_first_input) { 769 } else if (output_same_as_first_input) {
778 // Output register will contain a value of the first input at instruction's 770 // Output register will contain a value of the first input at instruction's
779 // start. Expected shape of live ranges: 771 // start. Expected shape of live ranges:
780 // 772 //
781 // i i' 773 // i i'
782 // input #0 --* 774 // input #0 --*
783 // output [---- 775 // output [----
784 // 776 //
785 ASSERT(locs->in_slot(0)->Equals(Location::RequiresRegister())); 777 ASSERT(locs->in_slot(0)->Equals(Location::RequiresRegister()));
786 778
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
891 JoinEntryInstr* join = block->AsJoinEntry(); 883 JoinEntryInstr* join = block->AsJoinEntry();
892 if ((join != NULL) && (join->phi_count() > 0)) { 884 if ((join != NULL) && (join->phi_count() > 0)) {
893 const intptr_t phi_count = join->phi_count(); 885 const intptr_t phi_count = join->phi_count();
894 for (intptr_t i = 0; i < block->PredecessorCount(); i++) { 886 for (intptr_t i = 0; i < block->PredecessorCount(); i++) {
895 // Insert the move between the last two instructions of the 887 // Insert the move between the last two instructions of the
896 // predecessor block (all such blocks have at least two instructions: 888 // predecessor block (all such blocks have at least two instructions:
897 // the block entry and goto instructions.) 889 // the block entry and goto instructions.)
898 Instruction* last = block->PredecessorAt(i)->last_instruction(); 890 Instruction* last = block->PredecessorAt(i)->last_instruction();
899 ASSERT(last->IsGoto()); 891 ASSERT(last->IsGoto());
900 892
901 ParallelMoveInstr* move = 893 ParallelMoveInstr* move = last->AsGoto()->GetParallelMove();
902 CreateParallelMoveBefore(last, last->lifetime_position());
903 894
904 // Populate the ParallelMove with empty moves. 895 // Populate the ParallelMove with empty moves.
905 for (intptr_t j = 0; j < phi_count; j++) { 896 for (intptr_t j = 0; j < phi_count; j++) {
906 move->AddMove(Location::NoLocation(), Location::NoLocation()); 897 move->AddMove(Location::NoLocation(), Location::NoLocation());
907 } 898 }
908
909 // Replace Goto instruction with the corresponding move in
910 // the array of instructions. This is done to ensure that
911 // this parallel move will be treated as a normal instruction
912 // by AddMoveAt for the purpose of live ranges connections (i.e.
913 // a separate move will be inserted by AddMoveAt)
914 // This move can't be reused by AddMoveAt to insert
915 // moves at Goto position because such range connecting moves might
916 // come into a conflict with phi connecting moves due to implicit
917 // interference: phi-value's liferange starts only at successor block
918 // but the move is actually performed at the predecessor.
919 ASSERT(instructions_[last->lifetime_position() / 2] == last);
920 instructions_[last->lifetime_position() / 2] = move;
921 } 899 }
922 } 900 }
923 } 901 }
924 } 902 }
925 903
926 904
927 Instruction* FlowGraphAllocator::InstructionAt(intptr_t pos) const { 905 Instruction* FlowGraphAllocator::InstructionAt(intptr_t pos) const {
928 return instructions_[pos / 2]; 906 return instructions_[pos / 2];
929 } 907 }
930 908
931 909
932 bool FlowGraphAllocator::IsBlockEntry(intptr_t pos) const { 910 bool FlowGraphAllocator::IsBlockEntry(intptr_t pos) const {
933 return InstructionAt(pos)->IsBlockEntry(); 911 return IsInstructionStartPosition(pos) && InstructionAt(pos)->IsBlockEntry();
934 } 912 }
935 913
936 914
937 void AllocationFinger::Initialize(LiveRange* range) { 915 void AllocationFinger::Initialize(LiveRange* range) {
938 first_pending_use_interval_ = range->first_use_interval(); 916 first_pending_use_interval_ = range->first_use_interval();
939 first_register_use_ = range->first_use(); 917 first_register_use_ = range->first_use();
940 first_register_beneficial_use_ = range->first_use(); 918 first_register_beneficial_use_ = range->first_use();
941 first_hinted_use_ = range->first_use(); 919 first_hinted_use_ = range->first_use();
942 } 920 }
943 921
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
1093 first_after_split : last_use_interval_; 1071 first_after_split : last_use_interval_;
1094 next_sibling_ = new LiveRange(vreg(), 1072 next_sibling_ = new LiveRange(vreg(),
1095 first_use_after_split, 1073 first_use_after_split,
1096 first_after_split, 1074 first_after_split,
1097 last_use_interval, 1075 last_use_interval,
1098 next_sibling_); 1076 next_sibling_);
1099 1077
1100 TRACE_ALLOC((" split sibling [%d, %d)\n", 1078 TRACE_ALLOC((" split sibling [%d, %d)\n",
1101 next_sibling_->Start(), next_sibling_->End())); 1079 next_sibling_->Start(), next_sibling_->End()));
1102 1080
1103 // Split sibling can only start at a parallel move.
1104 ASSERT(IsParallelMovePosition(next_sibling_->Start()));
1105
1106 last_use_interval_ = last_before_split; 1081 last_use_interval_ = last_before_split;
1107 last_use_interval_->next_ = NULL; 1082 last_use_interval_->next_ = NULL;
1108 return next_sibling_; 1083 return next_sibling_;
1109 } 1084 }
1110 1085
1111 1086
1112 LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range, 1087 LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range,
1113 intptr_t from, 1088 intptr_t from,
1114 intptr_t to) { 1089 intptr_t to) {
1115 // TODO(vegorov): select optimal split position based on loop structure. 1090 // TODO(vegorov): select optimal split position based on loop structure.
1116 TRACE_ALLOC(("split %d [%d, %d) between [%d, %d)\n", 1091 TRACE_ALLOC(("split %d [%d, %d) between [%d, %d)\n",
1117 range->vreg(), range->Start(), range->End(), from, to)); 1092 range->vreg(), range->Start(), range->End(), from, to));
1118 1093
1119 // Prefer spliting at instruction starts if possible. 1094 // Prefer spliting at instruction starts if possible.
1120 if (from < ToInstructionStart(to)) { 1095 if (from < ToInstructionStart(to)) {
1121 to = ToInstructionStart(to); 1096 to = ToInstructionStart(to);
1122 } 1097 }
1123 1098
1099 if (to == range->End()) to -= 1;
Florian Schneider 2012/07/31 15:31:59 A comment would be good here.
Vyacheslav Egorov (Google) 2012/07/31 16:18:49 Done.
1100
1124 return range->SplitAt(to); 1101 return range->SplitAt(to);
1125 } 1102 }
1126 1103
1127 1104
1128 void FlowGraphAllocator::SpillBetween(LiveRange* range, 1105 void FlowGraphAllocator::SpillBetween(LiveRange* range,
1129 intptr_t from, 1106 intptr_t from,
1130 intptr_t to) { 1107 intptr_t to) {
1131 ASSERT(from < to); 1108 ASSERT(from < to);
1132 TRACE_ALLOC(("spill %d [%d, %d) between [%d, %d)\n", 1109 TRACE_ALLOC(("spill %d [%d, %d) between [%d, %d)\n",
1133 range->vreg(), range->Start(), range->End(), from, to)); 1110 range->vreg(), range->Start(), range->End(), from, to));
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
1416 SpillBetween(allocated, spill_position, restore_position); 1393 SpillBetween(allocated, spill_position, restore_position);
1417 } 1394 }
1418 1395
1419 return true; 1396 return true;
1420 } 1397 }
1421 1398
1422 1399
1423 MoveOperands* FlowGraphAllocator::AddMoveAt(intptr_t pos, 1400 MoveOperands* FlowGraphAllocator::AddMoveAt(intptr_t pos,
1424 Location to, 1401 Location to,
1425 Location from) { 1402 Location from) {
1403 ASSERT(!IsBlockEntry(pos));
1404
1426 Instruction* instr = InstructionAt(pos); 1405 Instruction* instr = InstructionAt(pos);
1427 ASSERT(!instr->IsBlockEntry());
1428 1406
1429 ParallelMoveInstr* parallel_move = NULL; 1407 ParallelMoveInstr* parallel_move = NULL;
1430 if (IsInstructionStartPosition(pos)) { 1408 if (IsInstructionStartPosition(pos)) {
1431 parallel_move = CreateParallelMoveBefore(instr, pos); 1409 parallel_move = CreateParallelMoveBefore(instr, pos);
1432 } else { 1410 } else {
1433 parallel_move = CreateParallelMoveAfter(instr, pos); 1411 parallel_move = CreateParallelMoveAfter(instr, pos);
1434 } 1412 }
1435 1413
1436 return parallel_move->AddMove(to, from); 1414 return parallel_move->AddMove(to, from);
1437 } 1415 }
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1603 1581
1604 TRACE_ALLOC(("connecting [%d, %d) [%s] to [%d, %d) [%s]\n", 1582 TRACE_ALLOC(("connecting [%d, %d) [%s] to [%d, %d) [%s]\n",
1605 source_cover->Start(), source_cover->End(), source.Name(), 1583 source_cover->Start(), source_cover->End(), source.Name(),
1606 target_cover->Start(), target_cover->End(), target.Name())); 1584 target_cover->Start(), target_cover->End(), target.Name()));
1607 1585
1608 // Siblings were allocated to the same register. 1586 // Siblings were allocated to the same register.
1609 if (source.Equals(target)) return; 1587 if (source.Equals(target)) return;
1610 1588
1611 Instruction* last = source_block->last_instruction(); 1589 Instruction* last = source_block->last_instruction();
1612 if (last->SuccessorCount() == 1) { 1590 if (last->SuccessorCount() == 1) {
1613 CreateParallelMoveBefore(last, last->lifetime_position())-> 1591 ASSERT(last->IsGoto());
1614 AddMove(target, source); 1592 last->AsGoto()->GetParallelMove()->AddMove(target, source);
1615 } else { 1593 } else {
1616 CreateParallelMoveAfter(target_block, target_block->start_pos())-> 1594 target_block->GetParallelMove()->AddMove(target, source);
1617 AddMove(target, source);
1618 } 1595 }
1619 } 1596 }
1620 1597
1621 1598
1622 void FlowGraphAllocator::ResolveControlFlow() { 1599 void FlowGraphAllocator::ResolveControlFlow() {
1623 // Resolve linear control flow between touching split siblings 1600 // Resolve linear control flow between touching split siblings
1624 // inside basic blocks. 1601 // inside basic blocks.
1625 for (intptr_t vreg = 0; vreg < live_ranges_.length(); vreg++) { 1602 for (intptr_t vreg = 0; vreg < live_ranges_.length(); vreg++) {
1626 LiveRange* range = live_ranges_[vreg]; 1603 LiveRange* range = live_ranges_[vreg];
1627 if (range == NULL) continue; 1604 if (range == NULL) continue;
1628 1605
1629 while (range->next_sibling() != NULL) { 1606 while (range->next_sibling() != NULL) {
1630 LiveRange* sibling = range->next_sibling(); 1607 LiveRange* sibling = range->next_sibling();
1608 TRACE_ALLOC(("connecting [%d, %d) [%s] to [%d, %d) [%s]\n",
1609 range->Start(), range->End(),
1610 range->assigned_location().Name(),
1611 sibling->Start(), sibling->End(),
1612 sibling->assigned_location().Name()));
1631 if ((range->End() == sibling->Start()) && 1613 if ((range->End() == sibling->Start()) &&
1632 !range->assigned_location().Equals(sibling->assigned_location()) && 1614 !range->assigned_location().Equals(sibling->assigned_location()) &&
1633 !IsBlockEntry(range->End())) { 1615 !IsBlockEntry(range->End())) {
1634 AddMoveAt(sibling->Start(), 1616 AddMoveAt(sibling->Start(),
1635 sibling->assigned_location(), 1617 sibling->assigned_location(),
1636 range->assigned_location()); 1618 range->assigned_location());
1637 } 1619 }
1638 range = sibling; 1620 range = sibling;
1639 } 1621 }
1640 } 1622 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1676 1658
1677 if (FLAG_trace_ssa_allocator) { 1659 if (FLAG_trace_ssa_allocator) {
1678 OS::Print("-- ir after allocation -------------------------\n"); 1660 OS::Print("-- ir after allocation -------------------------\n");
1679 FlowGraphPrinter printer(Function::Handle(), block_order_, true); 1661 FlowGraphPrinter printer(Function::Handle(), block_order_, true);
1680 printer.PrintBlocks(); 1662 printer.PrintBlocks();
1681 } 1663 }
1682 } 1664 }
1683 1665
1684 1666
1685 } // namespace dart 1667 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/flow_graph_builder.cc » ('j') | runtime/vm/flow_graph_builder.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698