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

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

Issue 10824165: Ensure that ia32 build passes all tests with --use-ssa on. (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 | « runtime/vm/flow_graph_allocator.h ('k') | runtime/vm/flow_graph_compiler_ia32.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 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 LiveRange* FlowGraphAllocator::MakeLiveRangeForTemporary() { 344 LiveRange* FlowGraphAllocator::MakeLiveRangeForTemporary() {
345 LiveRange* range = new LiveRange(kTempVirtualRegister); 345 LiveRange* range = new LiveRange(kTempVirtualRegister);
346 #if defined(DEBUG) 346 #if defined(DEBUG)
347 temporaries_.Add(range); 347 temporaries_.Add(range);
348 #endif 348 #endif
349 return range; 349 return range;
350 } 350 }
351 351
352 352
353 // Block location from the start of the instruction to its end. 353 // Block location from the start of the instruction to its end.
354 void FlowGraphAllocator::BlockLocation(Location loc, intptr_t pos) { 354 void FlowGraphAllocator::BlockLocation(Location loc,
355 intptr_t from,
356 intptr_t to) {
355 ASSERT(loc.IsRegister()); 357 ASSERT(loc.IsRegister());
356 ASSERT(IsInstructionStartPosition(pos));
357 const Register reg = loc.reg(); 358 const Register reg = loc.reg();
358 if (blocked_cpu_regs_[reg]) return; 359 if (blocked_cpu_regs_[reg]) return;
359 if (cpu_regs_[reg].length() == 0) { 360 if (cpu_regs_[reg].length() == 0) {
360 LiveRange* range = new LiveRange(kNoVirtualRegister); 361 LiveRange* range = new LiveRange(kNoVirtualRegister);
361 cpu_regs_[reg].Add(range); 362 cpu_regs_[reg].Add(range);
362 range->set_assigned_location(loc); 363 range->set_assigned_location(loc);
363 #if defined(DEBUG) 364 #if defined(DEBUG)
364 temporaries_.Add(range); 365 temporaries_.Add(range);
365 #endif 366 #endif
366 } 367 }
367 cpu_regs_[reg][0]->AddUseInterval(pos, pos + 1); 368 cpu_regs_[reg][0]->AddUseInterval(from, to);
368 } 369 }
369 370
370 371
371 void LiveRange::Print() { 372 void LiveRange::Print() {
372 if (first_use_interval() == NULL) { 373 if (first_use_interval() == NULL) {
373 return; 374 return;
374 } 375 }
375 376
376 OS::Print(" live range v%d [%d, %d) in ", vreg(), Start(), End()); 377 OS::Print(" live range v%d [%d, %d) in ", vreg(), Start(), End());
377 assigned_location().Print(); 378 assigned_location().Print();
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 ASSERT(input->IsUse()); // Can not be a constant currently. 677 ASSERT(input->IsUse()); // Can not be a constant currently.
677 const intptr_t vreg = input->AsUse()->definition()->ssa_temp_index(); 678 const intptr_t vreg = input->AsUse()->definition()->ssa_temp_index();
678 LiveRange* range = GetLiveRange(vreg); 679 LiveRange* range = GetLiveRange(vreg);
679 680
680 Location* in_ref = locs->in_slot(j); 681 Location* in_ref = locs->in_slot(j);
681 682
682 if (in_ref->IsRegister()) { 683 if (in_ref->IsRegister()) {
683 // Input is expected in a fixed register. Expected shape of 684 // Input is expected in a fixed register. Expected shape of
684 // live ranges: 685 // live ranges:
685 // 686 //
686 // i i' 687 // j' i i'
687 // value --* 688 // value --*
688 // register [--) 689 // register [-----)
689 // 690 //
690 MoveOperands* move = 691 MoveOperands* move =
691 AddMoveAt(pos, *in_ref, Location::PrefersRegister()); 692 AddMoveAt(pos - 1, *in_ref, Location::PrefersRegister());
692 BlockLocation(*in_ref, pos); 693 BlockLocation(*in_ref, pos - 1, pos + 1);
693 range->AddUseInterval(block->start_pos(), pos); 694 range->AddUseInterval(block->start_pos(), pos - 1);
694 range->AddUse(pos, move->src_slot()); 695 range->AddUse(pos - 1, move->src_slot());
695 } else { 696 } else {
696 // Normal unallocated input. Expected shape of 697 // Normal unallocated input. Expected shape of
697 // live ranges: 698 // live ranges:
698 // 699 //
699 // i i' 700 // i i'
700 // value -----* 701 // value -----*
701 // 702 //
702 ASSERT(in_ref->IsUnallocated()); 703 ASSERT(in_ref->IsUnallocated());
703 range->AddUseInterval(block->start_pos(), pos + 1); 704 range->AddUseInterval(block->start_pos(), pos + 1);
704 range->AddUse(pos + 1, in_ref); 705 range->AddUse(pos + 1, in_ref);
705 } 706 }
706 } 707 }
707 708
708 // Process temps. 709 // Process temps.
709 for (intptr_t j = 0; j < locs->temp_count(); j++) { 710 for (intptr_t j = 0; j < locs->temp_count(); j++) {
710 // Expected shape of live range: 711 // Expected shape of live range:
711 // 712 //
712 // i i' 713 // i i'
713 // [--) 714 // [--)
714 // 715 //
715 716
716 Location temp = locs->temp(j); 717 Location temp = locs->temp(j);
717 if (temp.IsRegister()) { 718 if (temp.IsRegister()) {
718 BlockLocation(temp, pos); 719 BlockLocation(temp, pos, pos + 1);
719 } else if (temp.IsUnallocated()) { 720 } else if (temp.IsUnallocated()) {
720 LiveRange* range = MakeLiveRangeForTemporary(); 721 LiveRange* range = MakeLiveRangeForTemporary();
721 range->AddUseInterval(pos, pos + 1); 722 range->AddUseInterval(pos, pos + 1);
722 range->AddUse(pos, locs->temp_slot(j)); 723 range->AddUse(pos, locs->temp_slot(j));
723 AddToUnallocated(range); 724 AddToUnallocated(range);
724 } else { 725 } else {
725 UNREACHABLE(); 726 UNREACHABLE();
726 } 727 }
727 } 728 }
728 729
729 // Block all allocatable registers for calls. 730 // Block all allocatable registers for calls.
730 if (locs->is_call()) { 731 if (locs->is_call()) {
731 // Expected shape of live range: 732 // Expected shape of live range:
732 // 733 //
733 // i i' 734 // i i'
734 // [--) 735 // [--)
735 // 736 //
736 737
737 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { 738 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) {
738 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), 739 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)),
739 pos); 740 pos,
741 pos + 1);
740 } 742 }
741 743
742 #if defined(DEBUG) 744 #if defined(DEBUG)
743 // Verify that temps, inputs and output were specified as fixed 745 // Verify that temps, inputs and output were specified as fixed
744 // locations. Every register is blocked now so attempt to 746 // locations. Every register is blocked now so attempt to
745 // allocate will not succeed. 747 // allocate will not succeed.
746 for (intptr_t j = 0; j < locs->temp_count(); j++) { 748 for (intptr_t j = 0; j < locs->temp_count(); j++) {
747 ASSERT(!locs->temp(j).IsUnallocated()); 749 ASSERT(!locs->temp(j).IsUnallocated());
748 } 750 }
749 751
(...skipping 24 matching lines...) Expand all
774 Location* out = locs->out_slot(); 776 Location* out = locs->out_slot();
775 777
776 // Process output and finalize its liverange. 778 // Process output and finalize its liverange.
777 if (out->IsRegister()) { 779 if (out->IsRegister()) {
778 // Fixed output location. Expected shape of live range: 780 // Fixed output location. Expected shape of live range:
779 // 781 //
780 // i i' j j' 782 // i i' j j'
781 // register [--) 783 // register [--)
782 // output [------- 784 // output [-------
783 // 785 //
784 BlockLocation(*out, pos); 786 BlockLocation(*out, pos, pos + 1);
785 787
786 if (range->vreg() == kTempVirtualRegister) return; 788 if (range->vreg() == kTempVirtualRegister) return;
787 789
788 // We need to emit move connecting fixed register with another location 790 // We need to emit move connecting fixed register with another location
789 // that will be allocated for this output's live range. 791 // that will be allocated for this output's live range.
790 // Special case: fixed output followed by a fixed input last use. 792 // Special case: fixed output followed by a fixed input last use.
791 UsePosition* use = range->first_use(); 793 UsePosition* use = range->first_use();
792 794
793 // If the value has no uses we don't need to allocate it. 795 // If the value has no uses we don't need to allocate it.
794 if (use == NULL) return; 796 if (use == NULL) return;
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
1070 (loc->IsRegister() || 1072 (loc->IsRegister() ||
1071 (loc->IsUnallocated() && loc->IsRegisterBeneficial()))) { 1073 (loc->IsUnallocated() && loc->IsRegisterBeneficial()))) {
1072 first_register_beneficial_use_ = use; 1074 first_register_beneficial_use_ = use;
1073 return use; 1075 return use;
1074 } 1076 }
1075 } 1077 }
1076 return NULL; 1078 return NULL;
1077 } 1079 }
1078 1080
1079 1081
1082 void AllocationFinger::UpdateAfterSplit(intptr_t first_use_after_split_pos) {
1083 if ((first_register_use_ != NULL) &&
1084 (first_register_use_->pos() >= first_use_after_split_pos)) {
1085 first_register_use_ = NULL;
1086 }
1087
1088 if ((first_register_beneficial_use_ != NULL) &&
1089 (first_register_beneficial_use_->pos() >= first_use_after_split_pos)) {
1090 first_register_beneficial_use_ = NULL;
1091 }
1092 }
1093
1094
1080 intptr_t UseInterval::Intersect(UseInterval* other) { 1095 intptr_t UseInterval::Intersect(UseInterval* other) {
1081 if (this->start() <= other->start()) { 1096 if (this->start() <= other->start()) {
1082 if (other->start() < this->end()) return other->start(); 1097 if (other->start() < this->end()) return other->start();
1083 } else if (this->start() < other->end()) { 1098 } else if (this->start() < other->end()) {
1084 return this->start(); 1099 return this->start();
1085 } 1100 }
1086 return kIllegalPosition; 1101 return kIllegalPosition;
1087 } 1102 }
1088 1103
1089 1104
(...skipping 21 matching lines...) Expand all
1111 1126
1112 LiveRange* LiveRange::SplitAt(intptr_t split_pos) { 1127 LiveRange* LiveRange::SplitAt(intptr_t split_pos) {
1113 if (Start() == split_pos) return this; 1128 if (Start() == split_pos) return this;
1114 1129
1115 UseInterval* interval = finger_.first_pending_use_interval(); 1130 UseInterval* interval = finger_.first_pending_use_interval();
1116 if (interval == NULL) { 1131 if (interval == NULL) {
1117 finger_.Initialize(this); 1132 finger_.Initialize(this);
1118 interval = finger_.first_pending_use_interval(); 1133 interval = finger_.first_pending_use_interval();
1119 } 1134 }
1120 1135
1121 ASSERT(interval->start() < split_pos);
1122 ASSERT(split_pos < End()); 1136 ASSERT(split_pos < End());
1123 1137
1124 // Corner case. We need to start over to find previous interval. 1138 // Corner case. We need to start over to find previous interval.
1125 if (interval->start() == split_pos) interval = first_use_interval_; 1139 if (interval->start() == split_pos) interval = first_use_interval_;
1126 1140
1127 UseInterval* last_before_split = NULL; 1141 UseInterval* last_before_split = NULL;
1128 while (interval->end() <= split_pos) { 1142 while (interval->end() <= split_pos) {
1129 last_before_split = interval; 1143 last_before_split = interval;
1130 interval = interval->next(); 1144 interval = interval->next();
1131 } 1145 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1173 first_use_after_split, 1187 first_use_after_split,
1174 first_after_split, 1188 first_after_split,
1175 last_use_interval, 1189 last_use_interval,
1176 next_sibling_); 1190 next_sibling_);
1177 1191
1178 TRACE_ALLOC((" split sibling [%d, %d)\n", 1192 TRACE_ALLOC((" split sibling [%d, %d)\n",
1179 next_sibling_->Start(), next_sibling_->End())); 1193 next_sibling_->Start(), next_sibling_->End()));
1180 1194
1181 last_use_interval_ = last_before_split; 1195 last_use_interval_ = last_before_split;
1182 last_use_interval_->next_ = NULL; 1196 last_use_interval_->next_ = NULL;
1197
1198 if (first_use_after_split != NULL) {
1199 finger_.UpdateAfterSplit(first_use_after_split->pos());
1200 }
1201
1183 return next_sibling_; 1202 return next_sibling_;
1184 } 1203 }
1185 1204
1186 1205
1187 LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range, 1206 LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range,
1188 intptr_t from, 1207 intptr_t from,
1189 intptr_t to) { 1208 intptr_t to) {
1190 TRACE_ALLOC(("split %d [%d, %d) between [%d, %d)\n", 1209 TRACE_ALLOC(("split %d [%d, %d) between [%d, %d)\n",
1191 range->vreg(), range->Start(), range->End(), from, to)); 1210 range->vreg(), range->Start(), range->End(), from, to));
1192 1211
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
1422 intptr_t blocked_at = kMaxPosition; 1441 intptr_t blocked_at = kMaxPosition;
1423 const intptr_t start = unallocated->Start(); 1442 const intptr_t start = unallocated->Start();
1424 1443
1425 for (intptr_t i = 0; i < cpu_regs_[reg].length(); i++) { 1444 for (intptr_t i = 0; i < cpu_regs_[reg].length(); i++) {
1426 LiveRange* allocated = cpu_regs_[reg][i]; 1445 LiveRange* allocated = cpu_regs_[reg][i];
1427 1446
1428 UseInterval* first_pending_use_interval = 1447 UseInterval* first_pending_use_interval =
1429 allocated->finger()->first_pending_use_interval(); 1448 allocated->finger()->first_pending_use_interval();
1430 if (first_pending_use_interval->Contains(start)) { 1449 if (first_pending_use_interval->Contains(start)) {
1431 // This is an active interval. 1450 // This is an active interval.
1432 if (allocated->vreg() <= 0) { 1451 if (allocated->vreg() < 0) {
1433 // This register blocked by an interval that 1452 // This register blocked by an interval that
1434 // can't be spilled. 1453 // can't be spilled.
1435 return false; 1454 return false;
1436 } 1455 }
1437 1456
1438 const UsePosition* use = 1457 const UsePosition* use =
1439 allocated->finger()->FirstRegisterBeneficialUse(unallocated->Start()); 1458 allocated->finger()->FirstRegisterBeneficialUse(unallocated->Start());
1440 1459
1441 if ((use != NULL) && ((use->pos() - start) <= 1)) { 1460 if ((use != NULL) && ((use->pos() - start) <= 1)) {
1442 // This register is blocked by interval that is used 1461 // This register is blocked by interval that is used
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
1801 NumberInstructions(); 1820 NumberInstructions();
1802 1821
1803 DiscoverLoops(); 1822 DiscoverLoops();
1804 1823
1805 BuildLiveRanges(); 1824 BuildLiveRanges();
1806 1825
1807 if (FLAG_print_ssa_liveness) { 1826 if (FLAG_print_ssa_liveness) {
1808 DumpLiveness(); 1827 DumpLiveness();
1809 } 1828 }
1810 1829
1830 if (FLAG_print_ssa_liveranges) {
1831 const Function& function = builder_->parsed_function().function();
1832
1833 OS::Print("-- [before ssa allocator] ranges [%s] ---------\n",
1834 function.ToFullyQualifiedCString());
1835 PrintLiveRanges();
1836 OS::Print("----------------------------------------------\n");
1837
1838 OS::Print("-- [before ssa allocator] ir [%s] -------------\n",
1839 function.ToFullyQualifiedCString());
1840 FlowGraphPrinter printer(Function::Handle(), block_order_, true);
1841 printer.PrintBlocks();
1842 OS::Print("----------------------------------------------\n");
1843 }
1844
1811 AllocateCPURegisters(); 1845 AllocateCPURegisters();
1812 1846
1813 ResolveControlFlow(); 1847 ResolveControlFlow();
1814 1848
1815 GraphEntryInstr* entry = block_order_[0]->AsGraphEntry(); 1849 GraphEntryInstr* entry = block_order_[0]->AsGraphEntry();
1816 ASSERT(entry != NULL); 1850 ASSERT(entry != NULL);
1817 entry->set_spill_slot_count(spill_slots_.length()); 1851 entry->set_spill_slot_count(spill_slots_.length());
1818 1852
1819 if (FLAG_print_ssa_liveranges) { 1853 if (FLAG_print_ssa_liveranges) {
1820 const Function& function = builder_->parsed_function().function(); 1854 const Function& function = builder_->parsed_function().function();
1821 1855
1822 OS::Print("-- [after ssa allocator] ranges [%s] ---------\n", 1856 OS::Print("-- [after ssa allocator] ranges [%s] ---------\n",
1823 function.ToFullyQualifiedCString()); 1857 function.ToFullyQualifiedCString());
1824 PrintLiveRanges(); 1858 PrintLiveRanges();
1825 OS::Print("----------------------------------------------\n"); 1859 OS::Print("----------------------------------------------\n");
1826 1860
1827 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", 1861 OS::Print("-- [after ssa allocator] ir [%s] -------------\n",
1828 function.ToFullyQualifiedCString()); 1862 function.ToFullyQualifiedCString());
1829 FlowGraphPrinter printer(Function::Handle(), block_order_, true); 1863 FlowGraphPrinter printer(Function::Handle(), block_order_, true);
1830 printer.PrintBlocks(); 1864 printer.PrintBlocks();
1831 OS::Print("----------------------------------------------\n"); 1865 OS::Print("----------------------------------------------\n");
1832 } 1866 }
1833 } 1867 }
1834 1868
1835 1869
1836 } // namespace dart 1870 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_allocator.h ('k') | runtime/vm/flow_graph_compiler_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698