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

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: address Srdjan's comments 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/il_printer.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) 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 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 317
323 318
324 LiveRange* FlowGraphAllocator::GetLiveRange(intptr_t vreg) { 319 LiveRange* FlowGraphAllocator::GetLiveRange(intptr_t vreg) {
325 if (live_ranges_[vreg] == NULL) { 320 if (live_ranges_[vreg] == NULL) {
326 live_ranges_[vreg] = new LiveRange(vreg); 321 live_ranges_[vreg] = new LiveRange(vreg);
327 } 322 }
328 return live_ranges_[vreg]; 323 return live_ranges_[vreg];
329 } 324 }
330 325
331 326
327 // Block location from the start of the instruction to its end.
332 void FlowGraphAllocator::BlockLocation(Location loc, intptr_t pos) { 328 void FlowGraphAllocator::BlockLocation(Location loc, intptr_t pos) {
333 ASSERT(loc.IsRegister()); 329 ASSERT(loc.IsRegister());
330 ASSERT(IsInstructionStartPosition(pos));
334 const Register reg = loc.reg(); 331 const Register reg = loc.reg();
335 if (blocked_cpu_regs_[reg]) return; 332 if (blocked_cpu_regs_[reg]) return;
336 if (cpu_regs_[reg].length() == 0) { 333 if (cpu_regs_[reg].length() == 0) {
337 cpu_regs_[reg].Add(new LiveRange(kNoVirtualRegister)); 334 cpu_regs_[reg].Add(new LiveRange(kNoVirtualRegister));
338 } 335 }
339 cpu_regs_[reg][0]->AddUseInterval(pos, pos + 2); 336 cpu_regs_[reg][0]->AddUseInterval(pos, pos + 1);
340 } 337 }
341 338
342 339
343 void LiveRange::Print() { 340 void LiveRange::Print() {
344 OS::Print(" live range v%d [%d, %d)\n", vreg(), Start(), End()); 341 OS::Print(" live range v%d [%d, %d)\n", vreg(), Start(), End());
345 UsePosition* use_pos = uses_; 342 UsePosition* use_pos = uses_;
346 for (UseInterval* interval = first_use_interval_; 343 for (UseInterval* interval = first_use_interval_;
347 interval != NULL; 344 interval != NULL;
348 interval = interval->next()) { 345 interval = interval->next()) {
349 OS::Print(" use interval [%d, %d)\n", 346 OS::Print(" use interval [%d, %d)\n",
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 BlockEntryInstr* block) { 470 BlockEntryInstr* block) {
474 Instruction* last = block->last_instruction(); 471 Instruction* last = block->last_instruction();
475 472
476 GotoInstr* goto_instr = last->AsGoto(); 473 GotoInstr* goto_instr = last->AsGoto();
477 if (goto_instr == NULL) return last; 474 if (goto_instr == NULL) return last;
478 475
479 // If we have a parallel move here then the successor block must be a 476 // 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 477 // join with phis. The phi inputs contribute uses to each predecessor
481 // block (and the phi outputs contribute definitions in the successor 478 // block (and the phi outputs contribute definitions in the successor
482 // block). 479 // block).
483 ParallelMoveInstr* parallel_move = goto_instr->previous()->AsParallelMove(); 480 if (!goto_instr->HasParallelMove()) return goto_instr->previous();
484 if (parallel_move == NULL) return goto_instr->previous(); 481 ParallelMoveInstr* parallel_move = goto_instr->parallel_move();
485 482
486 // All uses are recorded at the position of parallel move preceding goto. 483 // All uses are recorded at the position of parallel move preceding goto.
487 const intptr_t pos = goto_instr->lifetime_position(); 484 const intptr_t pos = goto_instr->lifetime_position();
488 ASSERT(parallel_move->lifetime_position() == pos);
489 485
490 JoinEntryInstr* join = goto_instr->successor(); 486 JoinEntryInstr* join = goto_instr->successor();
491 ASSERT(join != NULL); 487 ASSERT(join != NULL);
492 488
493 // Search for the index of the current block in the predecessors of 489 // Search for the index of the current block in the predecessors of
494 // the join. 490 // the join.
495 const intptr_t pred_idx = join->IndexOfPredecessor(block); 491 const intptr_t pred_idx = join->IndexOfPredecessor(block);
496 492
497 // Record the corresponding phi input use for each phi. 493 // Record the corresponding phi input use for each phi.
498 ZoneGrowableArray<PhiInstr*>* phis = join->phis(); 494 ZoneGrowableArray<PhiInstr*>* phis = join->phis();
(...skipping 20 matching lines...) Expand all
519 move->set_src(Location::PrefersRegister()); 515 move->set_src(Location::PrefersRegister());
520 } else { 516 } else {
521 ASSERT(val->IsConstant()); 517 ASSERT(val->IsConstant());
522 move->set_src(Location::Constant(val->AsConstant()->value())); 518 move->set_src(Location::Constant(val->AsConstant()->value()));
523 } 519 }
524 move_idx++; 520 move_idx++;
525 } 521 }
526 522
527 // Begin backward iteration with the instruction before the parallel 523 // Begin backward iteration with the instruction before the parallel
528 // move. 524 // move.
529 return parallel_move->previous(); 525 return goto_instr->previous();
530 } 526 }
531 527
532 528
533 void FlowGraphAllocator::ConnectIncomingPhiMoves(BlockEntryInstr* block) { 529 void FlowGraphAllocator::ConnectIncomingPhiMoves(BlockEntryInstr* block) {
534 // If this block is a join we need to add destinations of phi 530 // 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 531 // resolution moves to phi's live range so that register allocator will
536 // fill them with moves. 532 // fill them with moves.
537 JoinEntryInstr* join = block->AsJoinEntry(); 533 JoinEntryInstr* join = block->AsJoinEntry();
538 if (join == NULL) return; 534 if (join == NULL) return;
539 535
(...skipping 13 matching lines...) Expand all
553 // Expected shape of live range: 549 // Expected shape of live range:
554 // 550 //
555 // B 551 // B
556 // phi [-------- 552 // phi [--------
557 // 553 //
558 LiveRange* range = GetLiveRange(vreg); 554 LiveRange* range = GetLiveRange(vreg);
559 range->DefineAt(pos); // Shorten live range. 555 range->DefineAt(pos); // Shorten live range.
560 556
561 for (intptr_t pred_idx = 0; pred_idx < phi->InputCount(); pred_idx++) { 557 for (intptr_t pred_idx = 0; pred_idx < phi->InputCount(); pred_idx++) {
562 BlockEntryInstr* pred = block->PredecessorAt(pred_idx); 558 BlockEntryInstr* pred = block->PredecessorAt(pred_idx);
563 ASSERT(pred->last_instruction()->IsGoto()); 559 GotoInstr* goto_instr = pred->last_instruction()->AsGoto();
564 Instruction* move_instr = pred->last_instruction()->previous(); 560 ASSERT((goto_instr != NULL) && (goto_instr->HasParallelMove()));
565 ASSERT(move_instr->IsParallelMove());
566
567 MoveOperands* move = 561 MoveOperands* move =
568 move_instr->AsParallelMove()->MoveOperandsAt(move_idx); 562 goto_instr->parallel_move()->MoveOperandsAt(move_idx);
569 move->set_dest(Location::PrefersRegister()); 563 move->set_dest(Location::PrefersRegister());
570 range->AddUse(pos, move->dest_slot()); 564 range->AddUse(pos, move->dest_slot());
571 } 565 }
572 566
573 // All phi resolution moves are connected. Phi's live range is 567 // All phi resolution moves are connected. Phi's live range is
574 // complete. 568 // complete.
575 AddToUnallocated(range); 569 AddToUnallocated(range);
576 570
577 move_idx++; 571 move_idx++;
578 } 572 }
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
672 range->AddUseInterval(block->start_pos(), pos + 1); 666 range->AddUseInterval(block->start_pos(), pos + 1);
673 range->AddUse(pos + 1, in_ref); 667 range->AddUse(pos + 1, in_ref);
674 } 668 }
675 } 669 }
676 670
677 // Process temps. 671 // Process temps.
678 for (intptr_t j = 0; j < locs->temp_count(); j++) { 672 for (intptr_t j = 0; j < locs->temp_count(); j++) {
679 // Expected shape of live range: 673 // Expected shape of live range:
680 // 674 //
681 // i i' 675 // i i'
682 // [-----) 676 // [--)
683 // 677 //
684 678
685 Location temp = locs->temp(j); 679 Location temp = locs->temp(j);
686 if (temp.IsRegister()) { 680 if (temp.IsRegister()) {
687 BlockLocation(temp, pos); 681 BlockLocation(temp, pos);
688 } else if (temp.IsUnallocated()) { 682 } else if (temp.IsUnallocated()) {
689 LiveRange* range = new LiveRange(kTempVirtualRegister); 683 LiveRange* range = new LiveRange(kTempVirtualRegister);
690 range->AddUseInterval(pos, pos + 1); 684 range->AddUseInterval(pos, pos + 1);
691 range->AddUse(pos, locs->temp_slot(j)); 685 range->AddUse(pos, locs->temp_slot(j));
692 AddToUnallocated(range); 686 AddToUnallocated(range);
693 } else { 687 } else {
694 UNREACHABLE(); 688 UNREACHABLE();
695 } 689 }
696 } 690 }
697 691
698 // Block all allocatable registers for calls. 692 // Block all allocatable registers for calls.
699 if (locs->is_call()) { 693 if (locs->is_call()) {
700 // Expected shape of live range: 694 // Expected shape of live range:
701 // 695 //
702 // i i' 696 // i i'
703 // [-----) 697 // [--)
704 // 698 //
705 699
706 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { 700 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) {
707 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), 701 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)),
708 pos); 702 pos);
709 } 703 }
710 704
711 #ifdef DEBUG 705 #ifdef DEBUG
712 // Verify that temps, inputs and output were specified as fixed 706 // Verify that temps, inputs and output were specified as fixed
713 // locations. Every register is blocked now so attempt to 707 // locations. Every register is blocked now so attempt to
(...skipping 26 matching lines...) Expand all
740 LiveRange* range = (def->ssa_temp_index() >= 0) ? 734 LiveRange* range = (def->ssa_temp_index() >= 0) ?
741 GetLiveRange(def->ssa_temp_index()) : 735 GetLiveRange(def->ssa_temp_index()) :
742 new LiveRange(kTempVirtualRegister); 736 new LiveRange(kTempVirtualRegister);
743 Location* out = locs->out_slot(); 737 Location* out = locs->out_slot();
744 738
745 // Process output and finalize its liverange. 739 // Process output and finalize its liverange.
746 if (out->IsRegister()) { 740 if (out->IsRegister()) {
747 // Fixed output location. Expected shape of live range: 741 // Fixed output location. Expected shape of live range:
748 // 742 //
749 // i i' j j' 743 // i i' j j'
750 // register [-----) 744 // register [--)
751 // output [------- 745 // output [-------
752 // 746 //
753 BlockLocation(*out, pos); 747 BlockLocation(*out, pos);
754 748
755 if (range->vreg() == kTempVirtualRegister) return; 749 if (range->vreg() == kTempVirtualRegister) return;
756 750
757 // We need to emit move connecting fixed register with another location 751 // We need to emit move connecting fixed register with another location
758 // that will be allocated for this output's live range. 752 // that will be allocated for this output's live range.
759 // Special case: fixed output followed by a fixed input last use. 753 // Special case: fixed output followed by a fixed input last use.
760 UsePosition* use = range->first_use(); 754 UsePosition* use = range->first_use();
761 if (use->pos() == (pos + 2)) { 755 if (use->pos() == (pos + 1)) {
762 ASSERT(use->location_slot()->IsUnallocated()); 756 ASSERT(use->location_slot()->IsUnallocated());
763 *(use->location_slot()) = *out; 757 *(use->location_slot()) = *out;
764 758
765 // Remove first use. It was allocated. 759 // Remove first use. It was allocated.
766 range->set_first_use(range->first_use()->next()); 760 range->set_first_use(range->first_use()->next());
767 } 761 }
768 762
769 // Shorten live range to the point of definition, this might make the range 763 // 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 764 // empty (if the only use immediately follows). If range is not empty add
771 // move from a fixed register to an unallocated location. 765 // move from a fixed register to an unallocated location.
772 range->DefineAt(pos + 2); 766 range->DefineAt(pos + 1);
773 if (range->Start() == range->End()) return; 767 if (range->Start() == range->End()) return;
774 768
775 MoveOperands* move = AddMoveAt(pos + 2, Location::PrefersRegister(), *out); 769 MoveOperands* move = AddMoveAt(pos + 1, Location::PrefersRegister(), *out);
776 range->AddUse(pos + 2, move->dest_slot()); 770 range->AddUse(pos + 1, move->dest_slot());
777 } else if (output_same_as_first_input) { 771 } else if (output_same_as_first_input) {
778 // Output register will contain a value of the first input at instruction's 772 // Output register will contain a value of the first input at instruction's
779 // start. Expected shape of live ranges: 773 // start. Expected shape of live ranges:
780 // 774 //
781 // i i' 775 // i i'
782 // input #0 --* 776 // input #0 --*
783 // output [---- 777 // output [----
784 // 778 //
785 ASSERT(locs->in_slot(0)->Equals(Location::RequiresRegister())); 779 ASSERT(locs->in_slot(0)->Equals(Location::RequiresRegister()));
786 780
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
891 JoinEntryInstr* join = block->AsJoinEntry(); 885 JoinEntryInstr* join = block->AsJoinEntry();
892 if ((join != NULL) && (join->phi_count() > 0)) { 886 if ((join != NULL) && (join->phi_count() > 0)) {
893 const intptr_t phi_count = join->phi_count(); 887 const intptr_t phi_count = join->phi_count();
894 for (intptr_t i = 0; i < block->PredecessorCount(); i++) { 888 for (intptr_t i = 0; i < block->PredecessorCount(); i++) {
895 // Insert the move between the last two instructions of the 889 // Insert the move between the last two instructions of the
896 // predecessor block (all such blocks have at least two instructions: 890 // predecessor block (all such blocks have at least two instructions:
897 // the block entry and goto instructions.) 891 // the block entry and goto instructions.)
898 Instruction* last = block->PredecessorAt(i)->last_instruction(); 892 Instruction* last = block->PredecessorAt(i)->last_instruction();
899 ASSERT(last->IsGoto()); 893 ASSERT(last->IsGoto());
900 894
901 ParallelMoveInstr* move = 895 ParallelMoveInstr* move = last->AsGoto()->GetParallelMove();
902 CreateParallelMoveBefore(last, last->lifetime_position());
903 896
904 // Populate the ParallelMove with empty moves. 897 // Populate the ParallelMove with empty moves.
905 for (intptr_t j = 0; j < phi_count; j++) { 898 for (intptr_t j = 0; j < phi_count; j++) {
906 move->AddMove(Location::NoLocation(), Location::NoLocation()); 899 move->AddMove(Location::NoLocation(), Location::NoLocation());
907 } 900 }
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 } 901 }
922 } 902 }
923 } 903 }
924 } 904 }
925 905
926 906
927 Instruction* FlowGraphAllocator::InstructionAt(intptr_t pos) const { 907 Instruction* FlowGraphAllocator::InstructionAt(intptr_t pos) const {
928 return instructions_[pos / 2]; 908 return instructions_[pos / 2];
929 } 909 }
930 910
931 911
932 bool FlowGraphAllocator::IsBlockEntry(intptr_t pos) const { 912 bool FlowGraphAllocator::IsBlockEntry(intptr_t pos) const {
933 return InstructionAt(pos)->IsBlockEntry(); 913 return IsInstructionStartPosition(pos) && InstructionAt(pos)->IsBlockEntry();
934 } 914 }
935 915
936 916
937 void AllocationFinger::Initialize(LiveRange* range) { 917 void AllocationFinger::Initialize(LiveRange* range) {
938 first_pending_use_interval_ = range->first_use_interval(); 918 first_pending_use_interval_ = range->first_use_interval();
939 first_register_use_ = range->first_use(); 919 first_register_use_ = range->first_use();
940 first_register_beneficial_use_ = range->first_use(); 920 first_register_beneficial_use_ = range->first_use();
941 first_hinted_use_ = range->first_use(); 921 first_hinted_use_ = range->first_use();
942 } 922 }
943 923
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1035 UNREACHABLE(); 1015 UNREACHABLE();
1036 return NULL; 1016 return NULL;
1037 } 1017 }
1038 1018
1039 1019
1040 LiveRange* LiveRange::SplitAt(intptr_t split_pos) { 1020 LiveRange* LiveRange::SplitAt(intptr_t split_pos) {
1041 if (Start() == split_pos) return this; 1021 if (Start() == split_pos) return this;
1042 1022
1043 UseInterval* interval = finger_.first_pending_use_interval(); 1023 UseInterval* interval = finger_.first_pending_use_interval();
1044 ASSERT(interval->start() < split_pos); 1024 ASSERT(interval->start() < split_pos);
1025 ASSERT(split_pos < End());
1045 1026
1046 // Corner case. We need to start over to find previous interval. 1027 // Corner case. We need to start over to find previous interval.
1047 if (interval->start() == split_pos) interval = first_use_interval_; 1028 if (interval->start() == split_pos) interval = first_use_interval_;
1048 1029
1049 UseInterval* last_before_split = NULL; 1030 UseInterval* last_before_split = NULL;
1050 while (interval->end() <= split_pos) { 1031 while (interval->end() <= split_pos) {
1051 last_before_split = interval; 1032 last_before_split = interval;
1052 interval = interval->next(); 1033 interval = interval->next();
1053 } 1034 }
1054 1035
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1093 first_after_split : last_use_interval_; 1074 first_after_split : last_use_interval_;
1094 next_sibling_ = new LiveRange(vreg(), 1075 next_sibling_ = new LiveRange(vreg(),
1095 first_use_after_split, 1076 first_use_after_split,
1096 first_after_split, 1077 first_after_split,
1097 last_use_interval, 1078 last_use_interval,
1098 next_sibling_); 1079 next_sibling_);
1099 1080
1100 TRACE_ALLOC((" split sibling [%d, %d)\n", 1081 TRACE_ALLOC((" split sibling [%d, %d)\n",
1101 next_sibling_->Start(), next_sibling_->End())); 1082 next_sibling_->Start(), next_sibling_->End()));
1102 1083
1103 // Split sibling can only start at a parallel move.
1104 ASSERT(IsParallelMovePosition(next_sibling_->Start()));
1105
1106 last_use_interval_ = last_before_split; 1084 last_use_interval_ = last_before_split;
1107 last_use_interval_->next_ = NULL; 1085 last_use_interval_->next_ = NULL;
1108 return next_sibling_; 1086 return next_sibling_;
1109 } 1087 }
1110 1088
1111 1089
1112 LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range, 1090 LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range,
1113 intptr_t from, 1091 intptr_t from,
1114 intptr_t to) { 1092 intptr_t to) {
1115 // TODO(vegorov): select optimal split position based on loop structure. 1093 // TODO(vegorov): select optimal split position based on loop structure.
1116 TRACE_ALLOC(("split %d [%d, %d) between [%d, %d)\n", 1094 TRACE_ALLOC(("split %d [%d, %d) between [%d, %d)\n",
1117 range->vreg(), range->Start(), range->End(), from, to)); 1095 range->vreg(), range->Start(), range->End(), from, to));
1118 1096
1119 // Prefer spliting at instruction starts if possible. 1097 // Prefer spliting at instruction starts if possible.
1120 if (from < ToInstructionStart(to)) { 1098 if (from < ToInstructionStart(to)) {
1121 to = ToInstructionStart(to); 1099 to = ToInstructionStart(to);
1122 } 1100 }
1123 1101
1102 // Splitting at the end is not allowed as it produces an empty
1103 // live range.
1104 if (to == range->End()) to -= 1;
1105 ASSERT(from <= to);
1106
1124 return range->SplitAt(to); 1107 return range->SplitAt(to);
1125 } 1108 }
1126 1109
1127 1110
1128 void FlowGraphAllocator::SpillBetween(LiveRange* range, 1111 void FlowGraphAllocator::SpillBetween(LiveRange* range,
1129 intptr_t from, 1112 intptr_t from,
1130 intptr_t to) { 1113 intptr_t to) {
1131 ASSERT(from < to); 1114 ASSERT(from < to);
1132 TRACE_ALLOC(("spill %d [%d, %d) between [%d, %d)\n", 1115 TRACE_ALLOC(("spill %d [%d, %d) between [%d, %d)\n",
1133 range->vreg(), range->Start(), range->End(), from, to)); 1116 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); 1399 SpillBetween(allocated, spill_position, restore_position);
1417 } 1400 }
1418 1401
1419 return true; 1402 return true;
1420 } 1403 }
1421 1404
1422 1405
1423 MoveOperands* FlowGraphAllocator::AddMoveAt(intptr_t pos, 1406 MoveOperands* FlowGraphAllocator::AddMoveAt(intptr_t pos,
1424 Location to, 1407 Location to,
1425 Location from) { 1408 Location from) {
1409 ASSERT(!IsBlockEntry(pos));
1410
1426 Instruction* instr = InstructionAt(pos); 1411 Instruction* instr = InstructionAt(pos);
1427 ASSERT(!instr->IsBlockEntry());
1428 1412
1429 ParallelMoveInstr* parallel_move = NULL; 1413 ParallelMoveInstr* parallel_move = NULL;
1430 if (IsInstructionStartPosition(pos)) { 1414 if (IsInstructionStartPosition(pos)) {
1431 parallel_move = CreateParallelMoveBefore(instr, pos); 1415 parallel_move = CreateParallelMoveBefore(instr, pos);
1432 } else { 1416 } else {
1433 parallel_move = CreateParallelMoveAfter(instr, pos); 1417 parallel_move = CreateParallelMoveAfter(instr, pos);
1434 } 1418 }
1435 1419
1436 return parallel_move->AddMove(to, from); 1420 return parallel_move->AddMove(to, from);
1437 } 1421 }
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1603 1587
1604 TRACE_ALLOC(("connecting [%d, %d) [%s] to [%d, %d) [%s]\n", 1588 TRACE_ALLOC(("connecting [%d, %d) [%s] to [%d, %d) [%s]\n",
1605 source_cover->Start(), source_cover->End(), source.Name(), 1589 source_cover->Start(), source_cover->End(), source.Name(),
1606 target_cover->Start(), target_cover->End(), target.Name())); 1590 target_cover->Start(), target_cover->End(), target.Name()));
1607 1591
1608 // Siblings were allocated to the same register. 1592 // Siblings were allocated to the same register.
1609 if (source.Equals(target)) return; 1593 if (source.Equals(target)) return;
1610 1594
1611 Instruction* last = source_block->last_instruction(); 1595 Instruction* last = source_block->last_instruction();
1612 if (last->SuccessorCount() == 1) { 1596 if (last->SuccessorCount() == 1) {
1613 CreateParallelMoveBefore(last, last->lifetime_position())-> 1597 ASSERT(last->IsGoto());
1614 AddMove(target, source); 1598 last->AsGoto()->GetParallelMove()->AddMove(target, source);
1615 } else { 1599 } else {
1616 CreateParallelMoveAfter(target_block, target_block->start_pos())-> 1600 target_block->GetParallelMove()->AddMove(target, source);
1617 AddMove(target, source);
1618 } 1601 }
1619 } 1602 }
1620 1603
1621 1604
1622 void FlowGraphAllocator::ResolveControlFlow() { 1605 void FlowGraphAllocator::ResolveControlFlow() {
1623 // Resolve linear control flow between touching split siblings 1606 // Resolve linear control flow between touching split siblings
1624 // inside basic blocks. 1607 // inside basic blocks.
1625 for (intptr_t vreg = 0; vreg < live_ranges_.length(); vreg++) { 1608 for (intptr_t vreg = 0; vreg < live_ranges_.length(); vreg++) {
1626 LiveRange* range = live_ranges_[vreg]; 1609 LiveRange* range = live_ranges_[vreg];
1627 if (range == NULL) continue; 1610 if (range == NULL) continue;
1628 1611
1629 while (range->next_sibling() != NULL) { 1612 while (range->next_sibling() != NULL) {
1630 LiveRange* sibling = range->next_sibling(); 1613 LiveRange* sibling = range->next_sibling();
1614 TRACE_ALLOC(("connecting [%d, %d) [%s] to [%d, %d) [%s]\n",
1615 range->Start(), range->End(),
1616 range->assigned_location().Name(),
1617 sibling->Start(), sibling->End(),
1618 sibling->assigned_location().Name()));
1631 if ((range->End() == sibling->Start()) && 1619 if ((range->End() == sibling->Start()) &&
1632 !range->assigned_location().Equals(sibling->assigned_location()) && 1620 !range->assigned_location().Equals(sibling->assigned_location()) &&
1633 !IsBlockEntry(range->End())) { 1621 !IsBlockEntry(range->End())) {
1634 AddMoveAt(sibling->Start(), 1622 AddMoveAt(sibling->Start(),
1635 sibling->assigned_location(), 1623 sibling->assigned_location(),
1636 range->assigned_location()); 1624 range->assigned_location());
1637 } 1625 }
1638 range = sibling; 1626 range = sibling;
1639 } 1627 }
1640 } 1628 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1676 1664
1677 if (FLAG_trace_ssa_allocator) { 1665 if (FLAG_trace_ssa_allocator) {
1678 OS::Print("-- ir after allocation -------------------------\n"); 1666 OS::Print("-- ir after allocation -------------------------\n");
1679 FlowGraphPrinter printer(Function::Handle(), block_order_, true); 1667 FlowGraphPrinter printer(Function::Handle(), block_order_, true);
1680 printer.PrintBlocks(); 1668 printer.PrintBlocks();
1681 } 1669 }
1682 } 1670 }
1683 1671
1684 1672
1685 } // namespace dart 1673 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/il_printer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698