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

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

Issue 286973011: Fix register allocator to properly allocate containers. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 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
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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.h" 10 #include "vm/flow_graph.h"
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 value_representations_(flow_graph.max_virtual_register_number()), 78 value_representations_(flow_graph.max_virtual_register_number()),
79 block_order_(flow_graph.reverse_postorder()), 79 block_order_(flow_graph.reverse_postorder()),
80 postorder_(flow_graph.postorder()), 80 postorder_(flow_graph.postorder()),
81 liveness_(flow_graph), 81 liveness_(flow_graph),
82 vreg_count_(flow_graph.max_virtual_register_number()), 82 vreg_count_(flow_graph.max_virtual_register_number()),
83 live_ranges_(flow_graph.max_virtual_register_number()), 83 live_ranges_(flow_graph.max_virtual_register_number()),
84 cpu_regs_(), 84 cpu_regs_(),
85 fpu_regs_(), 85 fpu_regs_(),
86 blocked_cpu_registers_(), 86 blocked_cpu_registers_(),
87 blocked_fpu_registers_(), 87 blocked_fpu_registers_(),
88 number_of_registers_(0),
89 registers_(),
90 blocked_registers_(),
88 cpu_spill_slot_count_(0) { 91 cpu_spill_slot_count_(0) {
89 for (intptr_t i = 0; i < vreg_count_; i++) { 92 for (intptr_t i = 0; i < vreg_count_; i++) {
90 live_ranges_.Add(NULL); 93 live_ranges_.Add(NULL);
91 } 94 }
92 for (intptr_t i = 0; i < vreg_count_; i++) { 95 for (intptr_t i = 0; i < vreg_count_; i++) {
93 value_representations_.Add(kNoRepresentation); 96 value_representations_.Add(kNoRepresentation);
94 } 97 }
95 98
96 // All registers are marked as "not blocked" (array initialized to false). 99 // All registers are marked as "not blocked" (array initialized to false).
97 // Mark the unavailable ones as "blocked" (true). 100 // Mark the unavailable ones as "blocked" (true).
(...skipping 1756 matching lines...) Expand 10 before | Expand all | Expand 10 after
1854 } 1857 }
1855 } 1858 }
1856 range->set_assigned_location(parent->spill_slot()); 1859 range->set_assigned_location(parent->spill_slot());
1857 ConvertAllUses(range); 1860 ConvertAllUses(range);
1858 } 1861 }
1859 1862
1860 1863
1861 intptr_t FlowGraphAllocator::FirstIntersectionWithAllocated( 1864 intptr_t FlowGraphAllocator::FirstIntersectionWithAllocated(
1862 intptr_t reg, LiveRange* unallocated) { 1865 intptr_t reg, LiveRange* unallocated) {
1863 intptr_t intersection = kMaxPosition; 1866 intptr_t intersection = kMaxPosition;
1864 for (intptr_t i = 0; i < registers_[reg].length(); i++) { 1867 for (intptr_t i = 0; i < registers_[reg]->length(); i++) {
1865 LiveRange* allocated = registers_[reg][i]; 1868 LiveRange* allocated = (*registers_[reg])[i];
1866 if (allocated == NULL) continue; 1869 if (allocated == NULL) continue;
1867 1870
1868 UseInterval* allocated_head = 1871 UseInterval* allocated_head =
1869 allocated->finger()->first_pending_use_interval(); 1872 allocated->finger()->first_pending_use_interval();
1870 if (allocated_head->start() >= intersection) continue; 1873 if (allocated_head->start() >= intersection) continue;
1871 1874
1872 const intptr_t pos = FirstIntersection( 1875 const intptr_t pos = FirstIntersection(
1873 unallocated->finger()->first_pending_use_interval(), 1876 unallocated->finger()->first_pending_use_interval(),
1874 allocated_head); 1877 allocated_head);
1875 if (pos < intersection) intersection = pos; 1878 if (pos < intersection) intersection = pos;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1959 unallocated); 1962 unallocated);
1960 candidate = hint.register_code(); 1963 candidate = hint.register_code();
1961 } 1964 }
1962 1965
1963 TRACE_ALLOC(OS::Print("found hint %s for v%" Pd ": free until %" Pd "\n", 1966 TRACE_ALLOC(OS::Print("found hint %s for v%" Pd ": free until %" Pd "\n",
1964 hint.Name(), 1967 hint.Name(),
1965 unallocated->vreg(), 1968 unallocated->vreg(),
1966 free_until)); 1969 free_until));
1967 } else { 1970 } else {
1968 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) { 1971 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
1969 if (!blocked_registers_[reg] && (registers_[reg].length() == 0)) { 1972 if (!blocked_registers_[reg] && (registers_[reg]->length() == 0)) {
1970 candidate = reg; 1973 candidate = reg;
1971 free_until = kMaxPosition; 1974 free_until = kMaxPosition;
1972 break; 1975 break;
1973 } 1976 }
1974 } 1977 }
1975 } 1978 }
1976 1979
1977 ASSERT(0 <= kMaxPosition); 1980 ASSERT(0 <= kMaxPosition);
1978 if (free_until != kMaxPosition) { 1981 if (free_until != kMaxPosition) {
1979 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) { 1982 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
2055 TRACE_ALLOC(MakeRegisterLocation(candidate).Print()); 2058 TRACE_ALLOC(MakeRegisterLocation(candidate).Print());
2056 TRACE_ALLOC(OS::Print(" to v%" Pd "\n", unallocated->vreg())); 2059 TRACE_ALLOC(OS::Print(" to v%" Pd "\n", unallocated->vreg()));
2057 2060
2058 if (free_until != kMaxPosition) { 2061 if (free_until != kMaxPosition) {
2059 // There was an intersection. Split unallocated. 2062 // There was an intersection. Split unallocated.
2060 TRACE_ALLOC(OS::Print(" splitting at %" Pd "\n", free_until)); 2063 TRACE_ALLOC(OS::Print(" splitting at %" Pd "\n", free_until));
2061 LiveRange* tail = unallocated->SplitAt(free_until); 2064 LiveRange* tail = unallocated->SplitAt(free_until);
2062 AddToUnallocated(tail); 2065 AddToUnallocated(tail);
2063 } 2066 }
2064 2067
2065 registers_[candidate].Add(unallocated); 2068 registers_[candidate]->Add(unallocated);
2066 unallocated->set_assigned_location(MakeRegisterLocation(candidate)); 2069 unallocated->set_assigned_location(MakeRegisterLocation(candidate));
2067 2070
2068 return true; 2071 return true;
2069 } 2072 }
2070 2073
2071 2074
2072 bool FlowGraphAllocator::RangeHasOnlyUnconstrainedUsesInLoop(LiveRange* range, 2075 bool FlowGraphAllocator::RangeHasOnlyUnconstrainedUsesInLoop(LiveRange* range,
2073 intptr_t loop_id) { 2076 intptr_t loop_id) {
2074 if (range->vreg() >= 0) { 2077 if (range->vreg() >= 0) {
2075 LiveRange* parent = GetLiveRange(range->vreg()); 2078 LiveRange* parent = GetLiveRange(range->vreg());
2076 return parent->HasOnlyUnconstrainedUsesInLoop(loop_id); 2079 return parent->HasOnlyUnconstrainedUsesInLoop(loop_id);
2077 } 2080 }
2078 return false; 2081 return false;
2079 } 2082 }
2080 2083
2081 2084
2082 bool FlowGraphAllocator::IsCheapToEvictRegisterInLoop(BlockInfo* loop, 2085 bool FlowGraphAllocator::IsCheapToEvictRegisterInLoop(BlockInfo* loop,
2083 intptr_t reg) { 2086 intptr_t reg) {
2084 const intptr_t loop_start = loop->entry()->start_pos(); 2087 const intptr_t loop_start = loop->entry()->start_pos();
2085 const intptr_t loop_end = loop->last_block()->end_pos(); 2088 const intptr_t loop_end = loop->last_block()->end_pos();
2086 2089
2087 for (intptr_t i = 0; i < registers_[reg].length(); i++) { 2090 for (intptr_t i = 0; i < registers_[reg]->length(); i++) {
2088 LiveRange* allocated = registers_[reg][i]; 2091 LiveRange* allocated = (*registers_[reg])[i];
2089 2092
2090 UseInterval* interval = allocated->finger()->first_pending_use_interval(); 2093 UseInterval* interval = allocated->finger()->first_pending_use_interval();
2091 if (interval->Contains(loop_start)) { 2094 if (interval->Contains(loop_start)) {
2092 if (!RangeHasOnlyUnconstrainedUsesInLoop(allocated, loop->loop_id())) { 2095 if (!RangeHasOnlyUnconstrainedUsesInLoop(allocated, loop->loop_id())) {
2093 return false; 2096 return false;
2094 } 2097 }
2095 } else if (interval->start() < loop_end) { 2098 } else if (interval->start() < loop_end) {
2096 return false; 2099 return false;
2097 } 2100 }
2098 } 2101 }
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2175 2178
2176 2179
2177 bool FlowGraphAllocator::UpdateFreeUntil(intptr_t reg, 2180 bool FlowGraphAllocator::UpdateFreeUntil(intptr_t reg,
2178 LiveRange* unallocated, 2181 LiveRange* unallocated,
2179 intptr_t* cur_free_until, 2182 intptr_t* cur_free_until,
2180 intptr_t* cur_blocked_at) { 2183 intptr_t* cur_blocked_at) {
2181 intptr_t free_until = kMaxPosition; 2184 intptr_t free_until = kMaxPosition;
2182 intptr_t blocked_at = kMaxPosition; 2185 intptr_t blocked_at = kMaxPosition;
2183 const intptr_t start = unallocated->Start(); 2186 const intptr_t start = unallocated->Start();
2184 2187
2185 for (intptr_t i = 0; i < registers_[reg].length(); i++) { 2188 for (intptr_t i = 0; i < registers_[reg]->length(); i++) {
2186 LiveRange* allocated = registers_[reg][i]; 2189 LiveRange* allocated = (*registers_[reg])[i];
2187 2190
2188 UseInterval* first_pending_use_interval = 2191 UseInterval* first_pending_use_interval =
2189 allocated->finger()->first_pending_use_interval(); 2192 allocated->finger()->first_pending_use_interval();
2190 if (first_pending_use_interval->Contains(start)) { 2193 if (first_pending_use_interval->Contains(start)) {
2191 // This is an active interval. 2194 // This is an active interval.
2192 if (allocated->vreg() < 0) { 2195 if (allocated->vreg() < 0) {
2193 // This register blocked by an interval that 2196 // This register blocked by an interval that
2194 // can't be spilled. 2197 // can't be spilled.
2195 return false; 2198 return false;
2196 } 2199 }
(...skipping 30 matching lines...) Expand all
2227 ASSERT(free_until > *cur_free_until); 2230 ASSERT(free_until > *cur_free_until);
2228 *cur_free_until = free_until; 2231 *cur_free_until = free_until;
2229 *cur_blocked_at = blocked_at; 2232 *cur_blocked_at = blocked_at;
2230 return true; 2233 return true;
2231 } 2234 }
2232 2235
2233 2236
2234 void FlowGraphAllocator::RemoveEvicted(intptr_t reg, intptr_t first_evicted) { 2237 void FlowGraphAllocator::RemoveEvicted(intptr_t reg, intptr_t first_evicted) {
2235 intptr_t to = first_evicted; 2238 intptr_t to = first_evicted;
2236 intptr_t from = first_evicted + 1; 2239 intptr_t from = first_evicted + 1;
2237 while (from < registers_[reg].length()) { 2240 while (from < registers_[reg]->length()) {
2238 LiveRange* allocated = registers_[reg][from++]; 2241 LiveRange* allocated = (*registers_[reg])[from++];
2239 if (allocated != NULL) registers_[reg][to++] = allocated; 2242 if (allocated != NULL) (*registers_[reg])[to++] = allocated;
2240 } 2243 }
2241 registers_[reg].TruncateTo(to); 2244 registers_[reg]->TruncateTo(to);
2242 } 2245 }
2243 2246
2244 2247
2245 void FlowGraphAllocator::AssignNonFreeRegister(LiveRange* unallocated, 2248 void FlowGraphAllocator::AssignNonFreeRegister(LiveRange* unallocated,
2246 intptr_t reg) { 2249 intptr_t reg) {
2247 intptr_t first_evicted = -1; 2250 intptr_t first_evicted = -1;
2248 for (intptr_t i = registers_[reg].length() - 1; i >= 0; i--) { 2251 for (intptr_t i = registers_[reg]->length() - 1; i >= 0; i--) {
2249 LiveRange* allocated = registers_[reg][i]; 2252 LiveRange* allocated = (*registers_[reg])[i];
2250 if (allocated->vreg() < 0) continue; // Can't be evicted. 2253 if (allocated->vreg() < 0) continue; // Can't be evicted.
2251 if (EvictIntersection(allocated, unallocated)) { 2254 if (EvictIntersection(allocated, unallocated)) {
2252 // If allocated was not spilled convert all pending uses. 2255 // If allocated was not spilled convert all pending uses.
2253 if (allocated->assigned_location().IsMachineRegister()) { 2256 if (allocated->assigned_location().IsMachineRegister()) {
2254 ASSERT(allocated->End() <= unallocated->Start()); 2257 ASSERT(allocated->End() <= unallocated->Start());
2255 ConvertAllUses(allocated); 2258 ConvertAllUses(allocated);
2256 } 2259 }
2257 registers_[reg][i] = NULL; 2260 (*registers_[reg])[i] = NULL;
2258 first_evicted = i; 2261 first_evicted = i;
2259 } 2262 }
2260 } 2263 }
2261 2264
2262 // Remove evicted ranges from the array. 2265 // Remove evicted ranges from the array.
2263 if (first_evicted != -1) RemoveEvicted(reg, first_evicted); 2266 if (first_evicted != -1) RemoveEvicted(reg, first_evicted);
2264 2267
2265 registers_[reg].Add(unallocated); 2268 registers_[reg]->Add(unallocated);
2266 unallocated->set_assigned_location(MakeRegisterLocation(reg)); 2269 unallocated->set_assigned_location(MakeRegisterLocation(reg));
2267 } 2270 }
2268 2271
2269 2272
2270 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated, 2273 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated,
2271 LiveRange* unallocated) { 2274 LiveRange* unallocated) {
2272 UseInterval* first_unallocated = 2275 UseInterval* first_unallocated =
2273 unallocated->finger()->first_pending_use_interval(); 2276 unallocated->finger()->first_pending_use_interval();
2274 const intptr_t intersection = FirstIntersection( 2277 const intptr_t intersection = FirstIntersection(
2275 allocated->finger()->first_pending_use_interval(), 2278 allocated->finger()->first_pending_use_interval(),
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
2348 ASSERT(safepoint->locs()->can_call()); 2351 ASSERT(safepoint->locs()->can_call());
2349 safepoint->locs()->live_registers()->Add(loc); 2352 safepoint->locs()->live_registers()->Add(loc);
2350 } 2353 }
2351 } 2354 }
2352 } 2355 }
2353 } 2356 }
2354 2357
2355 2358
2356 void FlowGraphAllocator::AdvanceActiveIntervals(const intptr_t start) { 2359 void FlowGraphAllocator::AdvanceActiveIntervals(const intptr_t start) {
2357 for (intptr_t reg = 0; reg < NumberOfRegisters(); reg++) { 2360 for (intptr_t reg = 0; reg < NumberOfRegisters(); reg++) {
2358 if (registers_[reg].is_empty()) continue; 2361 if (registers_[reg]->is_empty()) continue;
2359 2362
2360 intptr_t first_evicted = -1; 2363 intptr_t first_evicted = -1;
2361 for (intptr_t i = registers_[reg].length() - 1; i >= 0; i--) { 2364 for (intptr_t i = registers_[reg]->length() - 1; i >= 0; i--) {
2362 LiveRange* range = registers_[reg][i]; 2365 LiveRange* range = (*registers_[reg])[i];
2363 if (range->finger()->Advance(start)) { 2366 if (range->finger()->Advance(start)) {
2364 ConvertAllUses(range); 2367 ConvertAllUses(range);
2365 registers_[reg][i] = NULL; 2368 (*registers_[reg])[i] = NULL;
2366 first_evicted = i; 2369 first_evicted = i;
2367 } 2370 }
2368 } 2371 }
2369 2372
2370 if (first_evicted != -1) RemoveEvicted(reg, first_evicted); 2373 if (first_evicted != -1) RemoveEvicted(reg, first_evicted);
2371 } 2374 }
2372 } 2375 }
2373 2376
2374 2377
2375 bool LiveRange::Contains(intptr_t pos) const { 2378 bool LiveRange::Contains(intptr_t pos) const {
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
2454 UNREACHABLE(); 2457 UNREACHABLE();
2455 return false; 2458 return false;
2456 } 2459 }
2457 } 2460 }
2458 return true; 2461 return true;
2459 } 2462 }
2460 #endif 2463 #endif
2461 2464
2462 2465
2463 void FlowGraphAllocator::PrepareForAllocation( 2466 void FlowGraphAllocator::PrepareForAllocation(
2464 Location::Kind register_kind, 2467 Location::Kind register_kind,
2465 intptr_t number_of_registers, 2468 intptr_t number_of_registers,
2466 const GrowableArray<LiveRange*>& unallocated, 2469 const GrowableArray<LiveRange*>& unallocated,
2467 LiveRange** blocking_ranges, 2470 LiveRange** blocking_ranges,
2468 bool* blocked_registers) { 2471 bool* blocked_registers) {
2469 ASSERT(number_of_registers <= kNumberOfCpuRegisters);
2470 register_kind_ = register_kind; 2472 register_kind_ = register_kind;
2471 number_of_registers_ = number_of_registers; 2473 number_of_registers_ = number_of_registers;
2472 2474
2475 blocked_registers_.Clear();
2476 registers_.Clear();
2477 for (intptr_t i = 0; i < number_of_registers_; i++) {
2478 blocked_registers_.Add(false);
2479 registers_.Add(new ZoneGrowableArray<LiveRange*>);
2480 }
2473 ASSERT(unallocated_.is_empty()); 2481 ASSERT(unallocated_.is_empty());
2474 unallocated_.AddArray(unallocated); 2482 unallocated_.AddArray(unallocated);
2475 2483
2476 for (intptr_t reg = 0; reg < number_of_registers; reg++) { 2484 for (intptr_t reg = 0; reg < number_of_registers; reg++) {
2477 blocked_registers_[reg] = blocked_registers[reg]; 2485 blocked_registers_[reg] = blocked_registers[reg];
2478 ASSERT(registers_[reg].is_empty()); 2486 ASSERT(registers_[reg]->is_empty());
2479 2487
2480 LiveRange* range = blocking_ranges[reg]; 2488 LiveRange* range = blocking_ranges[reg];
2481 if (range != NULL) { 2489 if (range != NULL) {
2482 range->finger()->Initialize(range); 2490 range->finger()->Initialize(range);
2483 registers_[reg].Add(range); 2491 registers_[reg]->Add(range);
2484 } 2492 }
2485 } 2493 }
2486 } 2494 }
2487 2495
2488 2496
2489 void FlowGraphAllocator::AllocateUnallocatedRanges() { 2497 void FlowGraphAllocator::AllocateUnallocatedRanges() {
2490 #if defined(DEBUG) 2498 #if defined(DEBUG)
2491 ASSERT(UnallocatedIsSorted()); 2499 ASSERT(UnallocatedIsSorted());
2492 #endif 2500 #endif
2493 2501
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
2778 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", 2786 OS::Print("-- [after ssa allocator] ir [%s] -------------\n",
2779 function.ToFullyQualifiedCString()); 2787 function.ToFullyQualifiedCString());
2780 FlowGraphPrinter printer(flow_graph_, true); 2788 FlowGraphPrinter printer(flow_graph_, true);
2781 printer.PrintBlocks(); 2789 printer.PrintBlocks();
2782 OS::Print("----------------------------------------------\n"); 2790 OS::Print("----------------------------------------------\n");
2783 } 2791 }
2784 } 2792 }
2785 2793
2786 2794
2787 } // namespace dart 2795 } // namespace dart
OLDNEW
« runtime/vm/flow_graph_allocator.h ('K') | « runtime/vm/flow_graph_allocator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698