OLD | NEW |
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 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 | 145 |
146 BitVector* kill = kill_[i]; | 146 BitVector* kill = kill_[i]; |
147 BitVector* live_in = live_in_[i]; | 147 BitVector* live_in = live_in_[i]; |
148 | 148 |
149 // Iterate backwards starting at the last instruction. | 149 // Iterate backwards starting at the last instruction. |
150 for (BackwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 150 for (BackwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
151 Instruction* current = it.Current(); | 151 Instruction* current = it.Current(); |
152 | 152 |
153 // Initialize location summary for instruction. | 153 // Initialize location summary for instruction. |
154 current->InitializeLocationSummary(zone(), true); // opt | 154 current->InitializeLocationSummary(zone(), true); // opt |
| 155 #if defined(TARGET_ARCH_DBC) |
| 156 // TODO(vegorov) remove this once we have ported all necessary |
| 157 // instructions to DBC. |
| 158 if (!current->HasLocs()) { |
| 159 graph_entry_->parsed_function().Bailout("SSALivenessAnalysis", |
| 160 current->ToCString()); |
| 161 } |
| 162 #endif |
| 163 |
155 LocationSummary* locs = current->locs(); | 164 LocationSummary* locs = current->locs(); |
156 #if defined(DEBUG) | 165 #if defined(DEBUG) |
157 locs->DiscoverWritableInputs(); | 166 locs->DiscoverWritableInputs(); |
158 #endif | 167 #endif |
159 | 168 |
160 // Handle definitions. | 169 // Handle definitions. |
161 Definition* current_def = current->AsDefinition(); | 170 Definition* current_def = current->AsDefinition(); |
162 if ((current_def != NULL) && current_def->HasSSATemp()) { | 171 if ((current_def != NULL) && current_def->HasSSATemp()) { |
163 kill->Add(current_def->ssa_temp_index()); | 172 kill->Add(current_def->ssa_temp_index()); |
164 live_in->Remove(current_def->ssa_temp_index()); | 173 live_in->Remove(current_def->ssa_temp_index()); |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
591 range->MarkHasOnlyUnconstrainedUsesInLoop(block_info->loop_id()); | 600 range->MarkHasOnlyUnconstrainedUsesInLoop(block_info->loop_id()); |
592 } | 601 } |
593 } | 602 } |
594 } | 603 } |
595 | 604 |
596 if (block->IsJoinEntry()) { | 605 if (block->IsJoinEntry()) { |
597 ConnectIncomingPhiMoves(block->AsJoinEntry()); | 606 ConnectIncomingPhiMoves(block->AsJoinEntry()); |
598 } else if (block->IsCatchBlockEntry()) { | 607 } else if (block->IsCatchBlockEntry()) { |
599 // Process initial definitions. | 608 // Process initial definitions. |
600 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry(); | 609 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry(); |
| 610 #if defined(TARGET_ARCH_DBC) |
| 611 // TODO(vegorov) support try-catch/finally for DBC. |
| 612 flow_graph_.parsed_function().Bailout("FlowGraphAllocator", "Catch"); |
| 613 #endif |
601 for (intptr_t i = 0; | 614 for (intptr_t i = 0; |
602 i < catch_entry->initial_definitions()->length(); | 615 i < catch_entry->initial_definitions()->length(); |
603 i++) { | 616 i++) { |
604 Definition* defn = (*catch_entry->initial_definitions())[i]; | 617 Definition* defn = (*catch_entry->initial_definitions())[i]; |
605 LiveRange* range = GetLiveRange(defn->ssa_temp_index()); | 618 LiveRange* range = GetLiveRange(defn->ssa_temp_index()); |
606 range->DefineAt(catch_entry->start_pos()); // Defined at block entry. | 619 range->DefineAt(catch_entry->start_pos()); // Defined at block entry. |
607 ProcessInitialDefinition(defn, range, catch_entry); | 620 ProcessInitialDefinition(defn, range, catch_entry); |
608 } | 621 } |
609 // Block the two fixed registers used by CatchBlockEntryInstr from the | 622 // Block the two fixed registers used by CatchBlockEntryInstr from the |
610 // block start to until the end of the instruction so that they are | 623 // block start to until the end of the instruction so that they are |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
645 ASSERT((flow_graph_.num_copied_params() == 0) || | 658 ASSERT((flow_graph_.num_copied_params() == 0) || |
646 (flow_graph_.num_non_copied_params() == 0)); | 659 (flow_graph_.num_non_copied_params() == 0)); |
647 intptr_t slot_index = param->index(); | 660 intptr_t slot_index = param->index(); |
648 ASSERT((param->base_reg() == FPREG) || (param->base_reg() == SPREG)); | 661 ASSERT((param->base_reg() == FPREG) || (param->base_reg() == SPREG)); |
649 if (param->base_reg() == FPREG) { | 662 if (param->base_reg() == FPREG) { |
650 // Slot index for the leftmost copied parameter is 0. | 663 // Slot index for the leftmost copied parameter is 0. |
651 // Slot index for the rightmost fixed parameter is -1. | 664 // Slot index for the rightmost fixed parameter is -1. |
652 slot_index -= flow_graph_.num_non_copied_params(); | 665 slot_index -= flow_graph_.num_non_copied_params(); |
653 } | 666 } |
654 | 667 |
| 668 #if defined(TARGET_ARCH_DBC) |
| 669 ASSERT(param->base_reg() == FPREG); |
| 670 if (slot_index >= 0) { |
| 671 AssignSafepoints(defn, range); |
| 672 range->finger()->Initialize(range); |
| 673 range->set_assigned_location(Location::RegisterLocation(slot_index)); |
| 674 if (range->End() > kNormalEntryPos) { |
| 675 LiveRange* tail = range->SplitAt(kNormalEntryPos); |
| 676 CompleteRange(tail, Location::kRegister); |
| 677 } |
| 678 ConvertAllUses(range); |
| 679 return; |
| 680 } |
| 681 #endif // defined(TARGET_ARCH_DBC) |
655 range->set_assigned_location(Location::StackSlot(slot_index, | 682 range->set_assigned_location(Location::StackSlot(slot_index, |
656 param->base_reg())); | 683 param->base_reg())); |
657 range->set_spill_slot(Location::StackSlot(slot_index, | 684 range->set_spill_slot(Location::StackSlot(slot_index, |
658 param->base_reg())); | 685 param->base_reg())); |
| 686 |
659 } else if (defn->IsCurrentContext()) { | 687 } else if (defn->IsCurrentContext()) { |
| 688 #if !defined(TARGET_ARCH_DBC) |
| 689 const Register context_reg = CTX; |
| 690 #else |
| 691 const intptr_t context_reg = flow_graph_.num_copied_params(); |
| 692 #endif |
| 693 |
660 AssignSafepoints(defn, range); | 694 AssignSafepoints(defn, range); |
661 range->finger()->Initialize(range); | 695 range->finger()->Initialize(range); |
662 range->set_assigned_location(Location::RegisterLocation(CTX)); | 696 range->set_assigned_location(Location::RegisterLocation(context_reg)); |
663 if (range->End() > kNormalEntryPos) { | 697 if (range->End() > kNormalEntryPos) { |
664 LiveRange* tail = range->SplitAt(kNormalEntryPos); | 698 LiveRange* tail = range->SplitAt(kNormalEntryPos); |
665 CompleteRange(tail, Location::kRegister); | 699 CompleteRange(tail, Location::kRegister); |
666 } | 700 } |
667 ConvertAllUses(range); | 701 ConvertAllUses(range); |
668 return; | 702 return; |
669 } else { | 703 } else { |
670 ConstantInstr* constant = defn->AsConstant(); | 704 ConstantInstr* constant = defn->AsConstant(); |
671 ASSERT(constant != NULL); | 705 ASSERT(constant != NULL); |
672 range->set_assigned_location(Location::Constant(constant)); | 706 range->set_assigned_location(Location::Constant(constant)); |
(...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1316 } else if (temp.IsUnallocated()) { | 1350 } else if (temp.IsUnallocated()) { |
1317 LiveRange* range = MakeLiveRangeForTemporary(); | 1351 LiveRange* range = MakeLiveRangeForTemporary(); |
1318 range->AddUseInterval(pos, pos + 1); | 1352 range->AddUseInterval(pos, pos + 1); |
1319 range->AddUse(pos, locs->temp_slot(j)); | 1353 range->AddUse(pos, locs->temp_slot(j)); |
1320 CompleteRange(range, RegisterKindFromPolicy(temp)); | 1354 CompleteRange(range, RegisterKindFromPolicy(temp)); |
1321 } else { | 1355 } else { |
1322 UNREACHABLE(); | 1356 UNREACHABLE(); |
1323 } | 1357 } |
1324 } | 1358 } |
1325 | 1359 |
1326 // Block all allocatable registers for calls and record the stack bitmap. | 1360 // Block all allocatable registers for calls. |
| 1361 // Note that on DBC registers are always essentially spilled so |
| 1362 // we don't need to block anything. |
| 1363 #if !defined(TARGET_ARCH_DBC) |
1327 if (locs->always_calls()) { | 1364 if (locs->always_calls()) { |
1328 // Expected shape of live range: | 1365 // Expected shape of live range: |
1329 // | 1366 // |
1330 // i i' | 1367 // i i' |
1331 // [--) | 1368 // [--) |
1332 // | 1369 // |
1333 // The stack bitmap describes the position i. | 1370 // The stack bitmap describes the position i. |
1334 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { | 1371 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { |
1335 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), | 1372 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), |
1336 pos, | 1373 pos, |
(...skipping 29 matching lines...) Expand all Loading... |
1366 | 1403 |
1367 if (locs->out(0).IsPairLocation()) { | 1404 if (locs->out(0).IsPairLocation()) { |
1368 PairLocation* pair = locs->out_slot(0)->AsPairLocation(); | 1405 PairLocation* pair = locs->out_slot(0)->AsPairLocation(); |
1369 ASSERT(!pair->At(0).IsUnallocated()); | 1406 ASSERT(!pair->At(0).IsUnallocated()); |
1370 ASSERT(!pair->At(1).IsUnallocated()); | 1407 ASSERT(!pair->At(1).IsUnallocated()); |
1371 } else { | 1408 } else { |
1372 ASSERT(!locs->out(0).IsUnallocated()); | 1409 ASSERT(!locs->out(0).IsUnallocated()); |
1373 } | 1410 } |
1374 #endif | 1411 #endif |
1375 } | 1412 } |
| 1413 #endif |
1376 | 1414 |
1377 if (locs->can_call()) { | 1415 if (locs->can_call()) { |
1378 safepoints_.Add(current); | 1416 safepoints_.Add(current); |
1379 } | 1417 } |
1380 | 1418 |
1381 if (def == NULL) { | 1419 if (def == NULL) { |
1382 ASSERT(locs->out(0).IsInvalid()); | 1420 ASSERT(locs->out(0).IsInvalid()); |
1383 return; | 1421 return; |
1384 } | 1422 } |
1385 | 1423 |
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1899 from)); | 1937 from)); |
1900 } | 1938 } |
1901 } | 1939 } |
1902 | 1940 |
1903 LiveRange* tail = range->SplitAt(from); | 1941 LiveRange* tail = range->SplitAt(from); |
1904 Spill(tail); | 1942 Spill(tail); |
1905 } | 1943 } |
1906 | 1944 |
1907 | 1945 |
1908 void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) { | 1946 void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) { |
| 1947 #if defined(TARGET_ARCH_DBC) |
| 1948 // There is no need to support spilling on DBC because we have a lot of |
| 1949 // registers and registers and spill-slots have the same performance |
| 1950 // characteristics. |
| 1951 flow_graph_.parsed_function().Bailout("FlowGraphAllocator", "SPILL"); |
| 1952 UNREACHABLE(); |
| 1953 #endif |
| 1954 |
1909 ASSERT(range->spill_slot().IsInvalid()); | 1955 ASSERT(range->spill_slot().IsInvalid()); |
1910 | 1956 |
1911 // Compute range start and end. | 1957 // Compute range start and end. |
1912 LiveRange* last_sibling = range; | 1958 LiveRange* last_sibling = range; |
1913 while (last_sibling->next_sibling() != NULL) { | 1959 while (last_sibling->next_sibling() != NULL) { |
1914 last_sibling = last_sibling->next_sibling(); | 1960 last_sibling = last_sibling->next_sibling(); |
1915 } | 1961 } |
1916 | 1962 |
1917 const intptr_t start = range->Start(); | 1963 const intptr_t start = range->Start(); |
1918 const intptr_t end = last_sibling->End(); | 1964 const intptr_t end = last_sibling->End(); |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2235 | 2281 |
2236 if (free_until != kMaxPosition) { | 2282 if (free_until != kMaxPosition) { |
2237 // There was an intersection. Split unallocated. | 2283 // There was an intersection. Split unallocated. |
2238 TRACE_ALLOC(THR_Print(" splitting at %" Pd "\n", free_until)); | 2284 TRACE_ALLOC(THR_Print(" splitting at %" Pd "\n", free_until)); |
2239 LiveRange* tail = unallocated->SplitAt(free_until); | 2285 LiveRange* tail = unallocated->SplitAt(free_until); |
2240 AddToUnallocated(tail); | 2286 AddToUnallocated(tail); |
2241 } | 2287 } |
2242 | 2288 |
2243 registers_[candidate]->Add(unallocated); | 2289 registers_[candidate]->Add(unallocated); |
2244 unallocated->set_assigned_location(MakeRegisterLocation(candidate)); | 2290 unallocated->set_assigned_location(MakeRegisterLocation(candidate)); |
| 2291 #if defined(TARGET_ARCH_DBC) |
| 2292 last_used_register_ = Utils::Maximum(last_used_register_, candidate); |
| 2293 #endif |
2245 | 2294 |
2246 return true; | 2295 return true; |
2247 } | 2296 } |
2248 | 2297 |
2249 | 2298 |
2250 bool FlowGraphAllocator::RangeHasOnlyUnconstrainedUsesInLoop(LiveRange* range, | 2299 bool FlowGraphAllocator::RangeHasOnlyUnconstrainedUsesInLoop(LiveRange* range, |
2251 intptr_t loop_id) { | 2300 intptr_t loop_id) { |
2252 if (range->vreg() >= 0) { | 2301 if (range->vreg() >= 0) { |
2253 LiveRange* parent = GetLiveRange(range->vreg()); | 2302 LiveRange* parent = GetLiveRange(range->vreg()); |
2254 return parent->HasOnlyUnconstrainedUsesInLoop(loop_id); | 2303 return parent->HasOnlyUnconstrainedUsesInLoop(loop_id); |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2434 (*registers_[reg])[i] = NULL; | 2483 (*registers_[reg])[i] = NULL; |
2435 first_evicted = i; | 2484 first_evicted = i; |
2436 } | 2485 } |
2437 } | 2486 } |
2438 | 2487 |
2439 // Remove evicted ranges from the array. | 2488 // Remove evicted ranges from the array. |
2440 if (first_evicted != -1) RemoveEvicted(reg, first_evicted); | 2489 if (first_evicted != -1) RemoveEvicted(reg, first_evicted); |
2441 | 2490 |
2442 registers_[reg]->Add(unallocated); | 2491 registers_[reg]->Add(unallocated); |
2443 unallocated->set_assigned_location(MakeRegisterLocation(reg)); | 2492 unallocated->set_assigned_location(MakeRegisterLocation(reg)); |
| 2493 #if defined(TARGET_ARCH_DBC) |
| 2494 last_used_register_ = Utils::Maximum(last_used_register_, reg); |
| 2495 #endif |
2444 } | 2496 } |
2445 | 2497 |
2446 | 2498 |
2447 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated, | 2499 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated, |
2448 LiveRange* unallocated) { | 2500 LiveRange* unallocated) { |
2449 UseInterval* first_unallocated = | 2501 UseInterval* first_unallocated = |
2450 unallocated->finger()->first_pending_use_interval(); | 2502 unallocated->finger()->first_pending_use_interval(); |
2451 const intptr_t intersection = FirstIntersection( | 2503 const intptr_t intersection = FirstIntersection( |
2452 allocated->finger()->first_pending_use_interval(), | 2504 allocated->finger()->first_pending_use_interval(), |
2453 first_unallocated); | 2505 first_unallocated); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2523 for (UsePosition* use = range->first_use(); use != NULL; use = use->next()) { | 2575 for (UsePosition* use = range->first_use(); use != NULL; use = use->next()) { |
2524 ConvertUseTo(use, loc); | 2576 ConvertUseTo(use, loc); |
2525 } | 2577 } |
2526 | 2578 |
2527 // Add live registers at all safepoints for instructions with slow-path | 2579 // Add live registers at all safepoints for instructions with slow-path |
2528 // code. | 2580 // code. |
2529 if (loc.IsMachineRegister()) { | 2581 if (loc.IsMachineRegister()) { |
2530 for (SafepointPosition* safepoint = range->first_safepoint(); | 2582 for (SafepointPosition* safepoint = range->first_safepoint(); |
2531 safepoint != NULL; | 2583 safepoint != NULL; |
2532 safepoint = safepoint->next()) { | 2584 safepoint = safepoint->next()) { |
| 2585 #if !defined(TARGET_ARCH_DBC) |
2533 if (!safepoint->locs()->always_calls()) { | 2586 if (!safepoint->locs()->always_calls()) { |
2534 ASSERT(safepoint->locs()->can_call()); | 2587 ASSERT(safepoint->locs()->can_call()); |
2535 safepoint->locs()->live_registers()->Add(loc, range->representation()); | 2588 safepoint->locs()->live_registers()->Add(loc, range->representation()); |
2536 } | 2589 } |
| 2590 #else |
| 2591 if (range->representation() == kTagged) { |
| 2592 safepoint->locs()->SetStackBit(loc.reg()); |
| 2593 } |
| 2594 #endif // !defined(TARGET_ARCH_DBC) |
2537 } | 2595 } |
2538 } | 2596 } |
2539 } | 2597 } |
2540 | 2598 |
2541 | 2599 |
2542 void FlowGraphAllocator::AdvanceActiveIntervals(const intptr_t start) { | 2600 void FlowGraphAllocator::AdvanceActiveIntervals(const intptr_t start) { |
2543 for (intptr_t reg = 0; reg < NumberOfRegisters(); reg++) { | 2601 for (intptr_t reg = 0; reg < NumberOfRegisters(); reg++) { |
2544 if (registers_[reg]->is_empty()) continue; | 2602 if (registers_[reg]->is_empty()) continue; |
2545 | 2603 |
2546 intptr_t first_evicted = -1; | 2604 intptr_t first_evicted = -1; |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2676 for (intptr_t reg = 0; reg < number_of_registers; reg++) { | 2734 for (intptr_t reg = 0; reg < number_of_registers; reg++) { |
2677 blocked_registers_[reg] = blocked_registers[reg]; | 2735 blocked_registers_[reg] = blocked_registers[reg]; |
2678 ASSERT(registers_[reg]->is_empty()); | 2736 ASSERT(registers_[reg]->is_empty()); |
2679 | 2737 |
2680 LiveRange* range = blocking_ranges[reg]; | 2738 LiveRange* range = blocking_ranges[reg]; |
2681 if (range != NULL) { | 2739 if (range != NULL) { |
2682 range->finger()->Initialize(range); | 2740 range->finger()->Initialize(range); |
2683 registers_[reg]->Add(range); | 2741 registers_[reg]->Add(range); |
2684 } | 2742 } |
2685 } | 2743 } |
| 2744 |
| 2745 #if defined(TARGET_ARCH_DBC) |
| 2746 last_used_register_ = -1; |
| 2747 #endif |
2686 } | 2748 } |
2687 | 2749 |
2688 | 2750 |
2689 void FlowGraphAllocator::AllocateUnallocatedRanges() { | 2751 void FlowGraphAllocator::AllocateUnallocatedRanges() { |
2690 #if defined(DEBUG) | 2752 #if defined(DEBUG) |
2691 ASSERT(UnallocatedIsSorted()); | 2753 ASSERT(UnallocatedIsSorted()); |
2692 #endif | 2754 #endif |
2693 | 2755 |
2694 while (!unallocated_.is_empty()) { | 2756 while (!unallocated_.is_empty()) { |
2695 LiveRange* range = unallocated_.RemoveLast(); | 2757 LiveRange* range = unallocated_.RemoveLast(); |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2942 CollectRepresentations(); | 3004 CollectRepresentations(); |
2943 | 3005 |
2944 liveness_.Analyze(); | 3006 liveness_.Analyze(); |
2945 | 3007 |
2946 NumberInstructions(); | 3008 NumberInstructions(); |
2947 | 3009 |
2948 DiscoverLoops(); | 3010 DiscoverLoops(); |
2949 | 3011 |
2950 BuildLiveRanges(); | 3012 BuildLiveRanges(); |
2951 | 3013 |
2952 if (FLAG_print_ssa_liveness) { | |
2953 liveness_.Dump(); | |
2954 } | |
2955 | |
2956 if (FLAG_print_ssa_liveranges) { | 3014 if (FLAG_print_ssa_liveranges) { |
2957 const Function& function = flow_graph_.function(); | 3015 const Function& function = flow_graph_.function(); |
2958 THR_Print("-- [before ssa allocator] ranges [%s] ---------\n", | 3016 THR_Print("-- [before ssa allocator] ranges [%s] ---------\n", |
2959 function.ToFullyQualifiedCString()); | 3017 function.ToFullyQualifiedCString()); |
2960 PrintLiveRanges(); | 3018 PrintLiveRanges(); |
2961 THR_Print("----------------------------------------------\n"); | 3019 THR_Print("----------------------------------------------\n"); |
2962 | 3020 |
2963 THR_Print("-- [before ssa allocator] ir [%s] -------------\n", | 3021 THR_Print("-- [before ssa allocator] ir [%s] -------------\n", |
2964 function.ToFullyQualifiedCString()); | 3022 function.ToFullyQualifiedCString()); |
2965 if (FLAG_support_il_printer) { | 3023 if (FLAG_support_il_printer) { |
2966 #ifndef PRODUCT | 3024 #ifndef PRODUCT |
2967 FlowGraphPrinter printer(flow_graph_, true); | 3025 FlowGraphPrinter printer(flow_graph_, true); |
2968 printer.PrintBlocks(); | 3026 printer.PrintBlocks(); |
2969 #endif | 3027 #endif |
2970 } | 3028 } |
2971 THR_Print("----------------------------------------------\n"); | 3029 THR_Print("----------------------------------------------\n"); |
2972 } | 3030 } |
2973 | 3031 |
2974 PrepareForAllocation(Location::kRegister, | 3032 PrepareForAllocation(Location::kRegister, |
2975 kNumberOfCpuRegisters, | 3033 kNumberOfCpuRegisters, |
2976 unallocated_cpu_, | 3034 unallocated_cpu_, |
2977 cpu_regs_, | 3035 cpu_regs_, |
2978 blocked_cpu_registers_); | 3036 blocked_cpu_registers_); |
2979 AllocateUnallocatedRanges(); | 3037 AllocateUnallocatedRanges(); |
| 3038 #if defined(TARGET_ARCH_DBC) |
| 3039 const intptr_t last_used_cpu_register = last_used_register_; |
| 3040 #endif |
2980 | 3041 |
2981 cpu_spill_slot_count_ = spill_slots_.length(); | 3042 cpu_spill_slot_count_ = spill_slots_.length(); |
2982 spill_slots_.Clear(); | 3043 spill_slots_.Clear(); |
2983 quad_spill_slots_.Clear(); | 3044 quad_spill_slots_.Clear(); |
2984 untagged_spill_slots_.Clear(); | 3045 untagged_spill_slots_.Clear(); |
2985 | 3046 |
2986 PrepareForAllocation(Location::kFpuRegister, | 3047 PrepareForAllocation(Location::kFpuRegister, |
2987 kNumberOfFpuRegisters, | 3048 kNumberOfFpuRegisters, |
2988 unallocated_xmm_, | 3049 unallocated_xmm_, |
2989 fpu_regs_, | 3050 fpu_regs_, |
2990 blocked_fpu_registers_); | 3051 blocked_fpu_registers_); |
2991 AllocateUnallocatedRanges(); | 3052 AllocateUnallocatedRanges(); |
| 3053 #if defined(TARGET_ARCH_DBC) |
| 3054 const intptr_t last_used_fpu_register = last_used_register_; |
| 3055 ASSERT(last_used_fpu_register == -1); // Not supported right now. |
| 3056 #endif |
2992 | 3057 |
2993 ResolveControlFlow(); | 3058 ResolveControlFlow(); |
2994 | 3059 |
2995 GraphEntryInstr* entry = block_order_[0]->AsGraphEntry(); | 3060 GraphEntryInstr* entry = block_order_[0]->AsGraphEntry(); |
2996 ASSERT(entry != NULL); | 3061 ASSERT(entry != NULL); |
2997 intptr_t double_spill_slot_count = spill_slots_.length() * kDoubleSpillFactor; | 3062 intptr_t double_spill_slot_count = spill_slots_.length() * kDoubleSpillFactor; |
2998 entry->set_spill_slot_count(cpu_spill_slot_count_ + double_spill_slot_count); | 3063 entry->set_spill_slot_count(cpu_spill_slot_count_ + double_spill_slot_count); |
2999 | 3064 |
| 3065 #if defined(TARGET_ARCH_DBC) |
| 3066 // Spilling is unsupported on DBC. |
| 3067 if (entry->spill_slot_count() != 0) { |
| 3068 UNREACHABLE(); |
| 3069 } |
| 3070 |
| 3071 // We store number of used DBC registers in the spill slot count to avoid |
| 3072 // introducing a separate field. It has roughly the same meaning: |
| 3073 // number of used registers determines how big of a frame to reserve for |
| 3074 // this function on DBC stack. |
| 3075 entry->set_spill_slot_count(Utils::Maximum((last_used_cpu_register + 1) + |
| 3076 (last_used_fpu_register + 1), |
| 3077 flow_graph_.num_copied_params())); |
| 3078 #endif |
| 3079 |
3000 if (FLAG_print_ssa_liveranges) { | 3080 if (FLAG_print_ssa_liveranges) { |
3001 const Function& function = flow_graph_.function(); | 3081 const Function& function = flow_graph_.function(); |
3002 | 3082 |
3003 THR_Print("-- [after ssa allocator] ranges [%s] ---------\n", | 3083 THR_Print("-- [after ssa allocator] ranges [%s] ---------\n", |
3004 function.ToFullyQualifiedCString()); | 3084 function.ToFullyQualifiedCString()); |
3005 PrintLiveRanges(); | 3085 PrintLiveRanges(); |
3006 THR_Print("----------------------------------------------\n"); | 3086 THR_Print("----------------------------------------------\n"); |
3007 | 3087 |
3008 THR_Print("-- [after ssa allocator] ir [%s] -------------\n", | 3088 THR_Print("-- [after ssa allocator] ir [%s] -------------\n", |
3009 function.ToFullyQualifiedCString()); | 3089 function.ToFullyQualifiedCString()); |
3010 if (FLAG_support_il_printer) { | 3090 if (FLAG_support_il_printer) { |
3011 #ifndef PRODUCT | 3091 #ifndef PRODUCT |
3012 FlowGraphPrinter printer(flow_graph_, true); | 3092 FlowGraphPrinter printer(flow_graph_, true); |
3013 printer.PrintBlocks(); | 3093 printer.PrintBlocks(); |
3014 #endif | 3094 #endif |
3015 } | 3095 } |
3016 THR_Print("----------------------------------------------\n"); | 3096 THR_Print("----------------------------------------------\n"); |
3017 } | 3097 } |
3018 } | 3098 } |
3019 | 3099 |
3020 | 3100 |
3021 } // namespace dart | 3101 } // namespace dart |
OLD | NEW |