| 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 |