Chromium Code Reviews| 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()); |
| 165 if (current_def->HasPairRepresentation()) { | 174 if (current_def->HasPairRepresentation()) { |
| 166 kill->Add(ToSecondPairVreg(current_def->ssa_temp_index())); | 175 kill->Add(ToSecondPairVreg(current_def->ssa_temp_index())); |
| 167 live_in->Remove(ToSecondPairVreg(current_def->ssa_temp_index())); | 176 live_in->Remove(ToSecondPairVreg(current_def->ssa_temp_index())); |
| 168 } | 177 } |
| 169 } | 178 } |
| 170 | 179 |
| 171 // Handle uses. | 180 // Handle uses. |
| 181 if (locs->input_count() != current->InputCount()) { | |
|
Florian Schneider
2016/05/19 13:21:39
Left-over from debugging?
Vyacheslav Egorov (Google)
2016/05/19 15:19:40
Done.
| |
| 182 fprintf(stderr, "%s\n", current->ToCString()); | |
| 183 } | |
| 172 ASSERT(locs->input_count() == current->InputCount()); | 184 ASSERT(locs->input_count() == current->InputCount()); |
| 173 for (intptr_t j = 0; j < current->InputCount(); j++) { | 185 for (intptr_t j = 0; j < current->InputCount(); j++) { |
| 174 Value* input = current->InputAt(j); | 186 Value* input = current->InputAt(j); |
| 175 | 187 |
| 176 ASSERT(!locs->in(j).IsConstant() || input->BindsToConstant()); | 188 ASSERT(!locs->in(j).IsConstant() || input->BindsToConstant()); |
| 177 if (locs->in(j).IsConstant()) continue; | 189 if (locs->in(j).IsConstant()) continue; |
| 178 | 190 |
| 179 live_in->Add(input->definition()->ssa_temp_index()); | 191 live_in->Add(input->definition()->ssa_temp_index()); |
| 180 if (input->definition()->HasPairRepresentation()) { | 192 if (input->definition()->HasPairRepresentation()) { |
| 181 live_in->Add(ToSecondPairVreg(input->definition()->ssa_temp_index())); | 193 live_in->Add(ToSecondPairVreg(input->definition()->ssa_temp_index())); |
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 591 range->MarkHasOnlyUnconstrainedUsesInLoop(block_info->loop_id()); | 603 range->MarkHasOnlyUnconstrainedUsesInLoop(block_info->loop_id()); |
| 592 } | 604 } |
| 593 } | 605 } |
| 594 } | 606 } |
| 595 | 607 |
| 596 if (block->IsJoinEntry()) { | 608 if (block->IsJoinEntry()) { |
| 597 ConnectIncomingPhiMoves(block->AsJoinEntry()); | 609 ConnectIncomingPhiMoves(block->AsJoinEntry()); |
| 598 } else if (block->IsCatchBlockEntry()) { | 610 } else if (block->IsCatchBlockEntry()) { |
| 599 // Process initial definitions. | 611 // Process initial definitions. |
| 600 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry(); | 612 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry(); |
| 613 #if defined(TARGET_ARCH_DBC) | |
| 614 flow_graph_.parsed_function().Bailout("FlowGraphAllocator", "Catch"); | |
|
Florian Schneider
2016/05/19 13:21:39
Add TODO to implement try-catch.
Vyacheslav Egorov (Google)
2016/05/19 15:19:40
Done.
| |
| 615 #endif | |
| 601 for (intptr_t i = 0; | 616 for (intptr_t i = 0; |
| 602 i < catch_entry->initial_definitions()->length(); | 617 i < catch_entry->initial_definitions()->length(); |
| 603 i++) { | 618 i++) { |
| 604 Definition* defn = (*catch_entry->initial_definitions())[i]; | 619 Definition* defn = (*catch_entry->initial_definitions())[i]; |
| 605 LiveRange* range = GetLiveRange(defn->ssa_temp_index()); | 620 LiveRange* range = GetLiveRange(defn->ssa_temp_index()); |
| 606 range->DefineAt(catch_entry->start_pos()); // Defined at block entry. | 621 range->DefineAt(catch_entry->start_pos()); // Defined at block entry. |
| 607 ProcessInitialDefinition(defn, range, catch_entry); | 622 ProcessInitialDefinition(defn, range, catch_entry); |
| 608 } | 623 } |
| 609 // Block the two fixed registers used by CatchBlockEntryInstr from the | 624 // Block the two fixed registers used by CatchBlockEntryInstr from the |
| 610 // block start to until the end of the instruction so that they are | 625 // 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) || | 660 ASSERT((flow_graph_.num_copied_params() == 0) || |
| 646 (flow_graph_.num_non_copied_params() == 0)); | 661 (flow_graph_.num_non_copied_params() == 0)); |
| 647 intptr_t slot_index = param->index(); | 662 intptr_t slot_index = param->index(); |
| 648 ASSERT((param->base_reg() == FPREG) || (param->base_reg() == SPREG)); | 663 ASSERT((param->base_reg() == FPREG) || (param->base_reg() == SPREG)); |
| 649 if (param->base_reg() == FPREG) { | 664 if (param->base_reg() == FPREG) { |
| 650 // Slot index for the leftmost copied parameter is 0. | 665 // Slot index for the leftmost copied parameter is 0. |
| 651 // Slot index for the rightmost fixed parameter is -1. | 666 // Slot index for the rightmost fixed parameter is -1. |
| 652 slot_index -= flow_graph_.num_non_copied_params(); | 667 slot_index -= flow_graph_.num_non_copied_params(); |
| 653 } | 668 } |
| 654 | 669 |
| 670 #if defined(TARGET_ARCH_DBC) | |
| 671 ASSERT(param->base_reg() == FPREG); | |
| 672 if (slot_index >= 0) { | |
| 673 AssignSafepoints(defn, range); | |
| 674 range->finger()->Initialize(range); | |
| 675 range->set_assigned_location(Location::RegisterLocation(slot_index)); | |
| 676 if (range->End() > kNormalEntryPos) { | |
| 677 LiveRange* tail = range->SplitAt(kNormalEntryPos); | |
| 678 CompleteRange(tail, Location::kRegister); | |
| 679 } | |
| 680 ConvertAllUses(range); | |
| 681 return; | |
| 682 } | |
| 683 #endif // defined(TARGET_ARCH_DBC) | |
| 655 range->set_assigned_location(Location::StackSlot(slot_index, | 684 range->set_assigned_location(Location::StackSlot(slot_index, |
| 656 param->base_reg())); | 685 param->base_reg())); |
| 657 range->set_spill_slot(Location::StackSlot(slot_index, | 686 range->set_spill_slot(Location::StackSlot(slot_index, |
| 658 param->base_reg())); | 687 param->base_reg())); |
| 688 | |
| 659 } else if (defn->IsCurrentContext()) { | 689 } else if (defn->IsCurrentContext()) { |
| 690 #if !defined(TARGET_ARCH_DBC) | |
| 691 const Register context_reg = CTX; | |
| 692 #else | |
| 693 const intptr_t context_reg = flow_graph_.num_copied_params(); | |
| 694 #endif | |
| 695 | |
| 660 AssignSafepoints(defn, range); | 696 AssignSafepoints(defn, range); |
| 661 range->finger()->Initialize(range); | 697 range->finger()->Initialize(range); |
| 662 range->set_assigned_location(Location::RegisterLocation(CTX)); | 698 range->set_assigned_location(Location::RegisterLocation(context_reg)); |
| 663 if (range->End() > kNormalEntryPos) { | 699 if (range->End() > kNormalEntryPos) { |
| 664 LiveRange* tail = range->SplitAt(kNormalEntryPos); | 700 LiveRange* tail = range->SplitAt(kNormalEntryPos); |
| 665 CompleteRange(tail, Location::kRegister); | 701 CompleteRange(tail, Location::kRegister); |
| 666 } | 702 } |
| 667 ConvertAllUses(range); | 703 ConvertAllUses(range); |
| 668 return; | 704 return; |
| 669 } else { | 705 } else { |
| 670 ConstantInstr* constant = defn->AsConstant(); | 706 ConstantInstr* constant = defn->AsConstant(); |
| 671 ASSERT(constant != NULL); | 707 ASSERT(constant != NULL); |
| 672 range->set_assigned_location(Location::Constant(constant)); | 708 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()) { | 1352 } else if (temp.IsUnallocated()) { |
| 1317 LiveRange* range = MakeLiveRangeForTemporary(); | 1353 LiveRange* range = MakeLiveRangeForTemporary(); |
| 1318 range->AddUseInterval(pos, pos + 1); | 1354 range->AddUseInterval(pos, pos + 1); |
| 1319 range->AddUse(pos, locs->temp_slot(j)); | 1355 range->AddUse(pos, locs->temp_slot(j)); |
| 1320 CompleteRange(range, RegisterKindFromPolicy(temp)); | 1356 CompleteRange(range, RegisterKindFromPolicy(temp)); |
| 1321 } else { | 1357 } else { |
| 1322 UNREACHABLE(); | 1358 UNREACHABLE(); |
| 1323 } | 1359 } |
| 1324 } | 1360 } |
| 1325 | 1361 |
| 1326 // Block all allocatable registers for calls and record the stack bitmap. | 1362 // Block all allocatable registers for calls. |
| 1363 // Note that on DBC registers are always essentially spilled so | |
| 1364 // we don't need to block anything. | |
| 1365 #if !defined(TARGET_ARCH_DBC) | |
| 1327 if (locs->always_calls()) { | 1366 if (locs->always_calls()) { |
| 1328 // Expected shape of live range: | 1367 // Expected shape of live range: |
| 1329 // | 1368 // |
| 1330 // i i' | 1369 // i i' |
| 1331 // [--) | 1370 // [--) |
| 1332 // | 1371 // |
| 1333 // The stack bitmap describes the position i. | 1372 // The stack bitmap describes the position i. |
| 1334 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { | 1373 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { |
| 1335 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), | 1374 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), |
| 1336 pos, | 1375 pos, |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 1366 | 1405 |
| 1367 if (locs->out(0).IsPairLocation()) { | 1406 if (locs->out(0).IsPairLocation()) { |
| 1368 PairLocation* pair = locs->out_slot(0)->AsPairLocation(); | 1407 PairLocation* pair = locs->out_slot(0)->AsPairLocation(); |
| 1369 ASSERT(!pair->At(0).IsUnallocated()); | 1408 ASSERT(!pair->At(0).IsUnallocated()); |
| 1370 ASSERT(!pair->At(1).IsUnallocated()); | 1409 ASSERT(!pair->At(1).IsUnallocated()); |
| 1371 } else { | 1410 } else { |
| 1372 ASSERT(!locs->out(0).IsUnallocated()); | 1411 ASSERT(!locs->out(0).IsUnallocated()); |
| 1373 } | 1412 } |
| 1374 #endif | 1413 #endif |
| 1375 } | 1414 } |
| 1415 #endif | |
| 1376 | 1416 |
| 1377 if (locs->can_call()) { | 1417 if (locs->can_call()) { |
| 1378 safepoints_.Add(current); | 1418 safepoints_.Add(current); |
| 1379 } | 1419 } |
| 1380 | 1420 |
| 1381 if (def == NULL) { | 1421 if (def == NULL) { |
| 1382 ASSERT(locs->out(0).IsInvalid()); | 1422 ASSERT(locs->out(0).IsInvalid()); |
| 1383 return; | 1423 return; |
| 1384 } | 1424 } |
| 1385 | 1425 |
| (...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1899 from)); | 1939 from)); |
| 1900 } | 1940 } |
| 1901 } | 1941 } |
| 1902 | 1942 |
| 1903 LiveRange* tail = range->SplitAt(from); | 1943 LiveRange* tail = range->SplitAt(from); |
| 1904 Spill(tail); | 1944 Spill(tail); |
| 1905 } | 1945 } |
| 1906 | 1946 |
| 1907 | 1947 |
| 1908 void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) { | 1948 void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) { |
| 1949 #if defined(TARGET_ARCH_DBC) | |
| 1950 // We don't support spilling on DBC for now because we have access | |
|
Florian Schneider
2016/05/19 13:21:39
unterminated sentence?
Vyacheslav Egorov (Google)
2016/05/19 15:19:40
Done.
| |
| 1951 flow_graph_.parsed_function().Bailout("FlowGraphAllocator", "SPILL"); | |
|
Florian Schneider
2016/05/19 13:21:40
Indentation.
Vyacheslav Egorov (Google)
2016/05/19 15:19:40
Done.
| |
| 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); | |
|
Florian Schneider
2016/05/19 13:21:40
Is this reachable?
Vyacheslav Egorov (Google)
2016/05/19 15:19:40
It is - allocating non-free registers does not imp
| |
| 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 entry->set_spill_slot_count(Utils::Maximum((last_used_cpu_register + 1) + | |
|
Florian Schneider
2016/05/19 13:21:40
spill_slot_count is a confusing name... maybe stac
Vyacheslav Egorov (Google)
2016/05/19 15:19:40
I added a comment.
| |
| 3072 (last_used_fpu_register + 1), | |
| 3073 flow_graph_.num_copied_params())); | |
| 3074 #endif | |
| 3075 | |
| 3000 if (FLAG_print_ssa_liveranges) { | 3076 if (FLAG_print_ssa_liveranges) { |
| 3001 const Function& function = flow_graph_.function(); | 3077 const Function& function = flow_graph_.function(); |
| 3002 | 3078 |
| 3003 THR_Print("-- [after ssa allocator] ranges [%s] ---------\n", | 3079 THR_Print("-- [after ssa allocator] ranges [%s] ---------\n", |
| 3004 function.ToFullyQualifiedCString()); | 3080 function.ToFullyQualifiedCString()); |
| 3005 PrintLiveRanges(); | 3081 PrintLiveRanges(); |
| 3006 THR_Print("----------------------------------------------\n"); | 3082 THR_Print("----------------------------------------------\n"); |
| 3007 | 3083 |
| 3008 THR_Print("-- [after ssa allocator] ir [%s] -------------\n", | 3084 THR_Print("-- [after ssa allocator] ir [%s] -------------\n", |
| 3009 function.ToFullyQualifiedCString()); | 3085 function.ToFullyQualifiedCString()); |
| 3010 if (FLAG_support_il_printer) { | 3086 if (FLAG_support_il_printer) { |
| 3011 #ifndef PRODUCT | 3087 #ifndef PRODUCT |
| 3012 FlowGraphPrinter printer(flow_graph_, true); | 3088 FlowGraphPrinter printer(flow_graph_, true); |
| 3013 printer.PrintBlocks(); | 3089 printer.PrintBlocks(); |
| 3014 #endif | 3090 #endif |
| 3015 } | 3091 } |
| 3016 THR_Print("----------------------------------------------\n"); | 3092 THR_Print("----------------------------------------------\n"); |
| 3017 } | 3093 } |
| 3018 } | 3094 } |
| 3019 | 3095 |
| 3020 | 3096 |
| 3021 } // namespace dart | 3097 } // namespace dart |
| OLD | NEW |