register_allocator.cc revision 6c2dff8ff8e1440fa4d9e1b2ba2a44d036882801
1a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray/* 2a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * Copyright (C) 2014 The Android Open Source Project 3a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * 4a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License"); 5a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * you may not use this file except in compliance with the License. 6a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * You may obtain a copy of the License at 7a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * 8a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * http://www.apache.org/licenses/LICENSE-2.0 9a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * 10a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * Unless required by applicable law or agreed to in writing, software 11a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS, 12a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * See the License for the specific language governing permissions and 14a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * limitations under the License. 15a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray */ 16a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 17a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray#include "register_allocator.h" 18a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 19c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers#include <sstream> 20c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers 21e77493c7217efdd1a0ecef521a6845a13da0305bIan Rogers#include "base/bit_vector-inl.h" 22a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray#include "code_generator.h" 23a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray#include "ssa_liveness_analysis.h" 24a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 25a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffraynamespace art { 26a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 27a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffraystatic constexpr size_t kMaxLifetimePosition = -1; 2831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffraystatic constexpr size_t kDefaultNumberOfSpillSlots = 4; 29a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 30840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray// For simplicity, we implement register pairs as (reg, reg + 1). 31840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray// Note that this is a requirement for double registers on ARM, since we 32840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray// allocate SRegister. 33840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffraystatic int GetHighForLowRegister(int reg) { return reg + 1; } 34840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffraystatic bool IsLowRegister(int reg) { return (reg & 1) == 0; } 35840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray 3686dbb9a12119273039ce272b41c809fa548b37b6Nicolas GeoffrayRegisterAllocator::RegisterAllocator(ArenaAllocator* allocator, 3786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray CodeGenerator* codegen, 3886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray const SsaLivenessAnalysis& liveness) 39a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray : allocator_(allocator), 40a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray codegen_(codegen), 4186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray liveness_(liveness), 423946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray unhandled_core_intervals_(allocator, 0), 433946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray unhandled_fp_intervals_(allocator, 0), 443946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray unhandled_(nullptr), 45a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray handled_(allocator, 0), 46a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray active_(allocator, 0), 47a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray inactive_(allocator, 0), 48102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray physical_core_register_intervals_(allocator, codegen->GetNumberOfCoreRegisters()), 49102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray physical_fp_register_intervals_(allocator, codegen->GetNumberOfFloatingPointRegisters()), 503946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray temp_intervals_(allocator, 4), 5131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray spill_slots_(allocator, kDefaultNumberOfSpillSlots), 523946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray safepoints_(allocator, 0), 53a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray processing_core_registers_(false), 54a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray number_of_registers_(-1), 55a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray registers_array_(nullptr), 56102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray blocked_core_registers_(codegen->GetBlockedCoreRegisters()), 57102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray blocked_fp_registers_(codegen->GetBlockedFloatingPointRegisters()), 583bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray reserved_out_slots_(0), 59f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell maximum_number_of_live_core_registers_(0), 60f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell maximum_number_of_live_fp_registers_(0) { 6171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray codegen->SetupBlockedRegisters(); 62102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray physical_core_register_intervals_.SetSize(codegen->GetNumberOfCoreRegisters()); 63102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray physical_fp_register_intervals_.SetSize(codegen->GetNumberOfFloatingPointRegisters()); 643946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // Always reserve for the current method and the graph's max out registers. 653946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // TODO: compute it instead. 663946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray reserved_out_slots_ = 1 + codegen->GetGraph()->GetMaximumNumberOfOutVRegs(); 67a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray} 68a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 6986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffraybool RegisterAllocator::CanAllocateRegistersFor(const HGraph& graph, 7086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray InstructionSet instruction_set) { 7186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (!Supports(instruction_set)) { 7286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray return false; 7386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 746c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray if (instruction_set == kArm64 756c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray || instruction_set == kX86_64 766c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray || instruction_set == kArm 776c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray || instruction_set == kThumb2) { 783e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames return true; 793e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames } 8086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray for (size_t i = 0, e = graph.GetBlocks().Size(); i < e; ++i) { 8186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray for (HInstructionIterator it(graph.GetBlocks().Get(i)->GetInstructions()); 8286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray !it.Done(); 8386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray it.Advance()) { 8486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HInstruction* current = it.Current(); 85840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (instruction_set == kX86) { 86840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (current->GetType() == Primitive::kPrimLong || 87840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray current->GetType() == Primitive::kPrimFloat || 88840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray current->GetType() == Primitive::kPrimDouble) { 89840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray return false; 90840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 91102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray } 9286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 9386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 9486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray return true; 9586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray} 9686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 9786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffraystatic bool ShouldProcess(bool processing_core_registers, LiveInterval* interval) { 983946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray if (interval == nullptr) return false; 9986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray bool is_core_register = (interval->GetType() != Primitive::kPrimDouble) 10086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray && (interval->GetType() != Primitive::kPrimFloat); 101a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray return processing_core_registers == is_core_register; 102a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray} 103a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 10486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::AllocateRegisters() { 10586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray AllocateRegistersInternal(); 10686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray Resolve(); 10786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 10886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (kIsDebugBuild) { 10986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray processing_core_registers_ = true; 11086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray ValidateInternal(true); 11186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray processing_core_registers_ = false; 11286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray ValidateInternal(true); 1135976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray // Check that the linear order is still correct with regards to lifetime positions. 1145976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray // Since only parallel moves have been inserted during the register allocation, 1155976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray // these checks are mostly for making sure these moves have been added correctly. 1165976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray size_t current_liveness = 0; 1175976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray for (HLinearOrderIterator it(liveness_); !it.Done(); it.Advance()) { 1185976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray HBasicBlock* block = it.Current(); 1195976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray for (HInstructionIterator inst_it(block->GetPhis()); !inst_it.Done(); inst_it.Advance()) { 1205976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray HInstruction* instruction = inst_it.Current(); 1215976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray DCHECK_LE(current_liveness, instruction->GetLifetimePosition()); 1225976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray current_liveness = instruction->GetLifetimePosition(); 1235976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray } 1245976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray for (HInstructionIterator inst_it(block->GetInstructions()); 1255976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray !inst_it.Done(); 1265976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray inst_it.Advance()) { 1275976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray HInstruction* instruction = inst_it.Current(); 1285976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray DCHECK_LE(current_liveness, instruction->GetLifetimePosition()) << instruction->DebugName(); 1295976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray current_liveness = instruction->GetLifetimePosition(); 1305976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray } 1315976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray } 13286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 13386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray} 13486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 13586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::BlockRegister(Location location, 13686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray size_t start, 137102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray size_t end) { 13856b9ee6fe1d6880c5fca0e7feb28b25a1ded2e2fNicolas Geoffray int reg = location.reg(); 139102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray DCHECK(location.IsRegister() || location.IsFpuRegister()); 140102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray LiveInterval* interval = location.IsRegister() 141102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray ? physical_core_register_intervals_.Get(reg) 142102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray : physical_fp_register_intervals_.Get(reg); 143102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray Primitive::Type type = location.IsRegister() 144102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray ? Primitive::kPrimInt 145840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray : Primitive::kPrimFloat; 14686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (interval == nullptr) { 14786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray interval = LiveInterval::MakeFixedInterval(allocator_, reg, type); 148102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray if (location.IsRegister()) { 149102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray physical_core_register_intervals_.Put(reg, interval); 150102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray } else { 151102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray physical_fp_register_intervals_.Put(reg, interval); 152102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray } 15386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 15486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray DCHECK(interval->GetRegister() == reg); 15586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray interval->AddRange(start, end); 15686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray} 15786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 15886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::AllocateRegistersInternal() { 1593946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // Iterate post-order, to ensure the list is sorted, and the last added interval 1603946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // is the one with the lowest start position. 1613946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray for (HLinearPostOrderIterator it(liveness_); !it.Done(); it.Advance()) { 1623946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray HBasicBlock* block = it.Current(); 163277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe for (HBackwardInstructionIterator back_it(block->GetInstructions()); !back_it.Done(); 164277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe back_it.Advance()) { 165277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe ProcessInstruction(back_it.Current()); 1663946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 167277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe for (HInstructionIterator inst_it(block->GetPhis()); !inst_it.Done(); inst_it.Advance()) { 168277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe ProcessInstruction(inst_it.Current()); 1693946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 1703946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 171a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 1723946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray number_of_registers_ = codegen_->GetNumberOfCoreRegisters(); 173a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_); 1743946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray processing_core_registers_ = true; 1753946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray unhandled_ = &unhandled_core_intervals_; 176102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray for (size_t i = 0, e = physical_core_register_intervals_.Size(); i < e; ++i) { 177102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray LiveInterval* fixed = physical_core_register_intervals_.Get(i); 178102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray if (fixed != nullptr) { 179296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // Fixed interval is added to inactive_ instead of unhandled_. 180296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // It's also the only type of inactive interval whose start position 181296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // can be after the current interval during linear scan. 182296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // Fixed interval is never split and never moves to unhandled_. 183102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray inactive_.Add(fixed); 184102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray } 185102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray } 1863946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray LinearScan(); 187a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 1883946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray inactive_.Reset(); 1893946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray active_.Reset(); 1903946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray handled_.Reset(); 191a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 1923946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray number_of_registers_ = codegen_->GetNumberOfFloatingPointRegisters(); 1933946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_); 1943946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray processing_core_registers_ = false; 1953946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray unhandled_ = &unhandled_fp_intervals_; 196102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray for (size_t i = 0, e = physical_fp_register_intervals_.Size(); i < e; ++i) { 197102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray LiveInterval* fixed = physical_fp_register_intervals_.Get(i); 198102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray if (fixed != nullptr) { 199296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // Fixed interval is added to inactive_ instead of unhandled_. 200296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // It's also the only type of inactive interval whose start position 201296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // can be after the current interval during linear scan. 202296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // Fixed interval is never split and never moves to unhandled_. 203102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray inactive_.Add(fixed); 204102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray } 205102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray } 2063946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray LinearScan(); 2073946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray} 20886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 2093946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffrayvoid RegisterAllocator::ProcessInstruction(HInstruction* instruction) { 2103946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray LocationSummary* locations = instruction->GetLocations(); 2113946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray size_t position = instruction->GetLifetimePosition(); 2123946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 2133946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray if (locations == nullptr) return; 2143946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 2153946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // Create synthesized intervals for temporaries. 2163946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray for (size_t i = 0; i < locations->GetTempCount(); ++i) { 2173946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray Location temp = locations->GetTemp(i); 21852839d17c06175e19ca4a093fb878450d1c4310dNicolas Geoffray if (temp.IsRegister() || temp.IsFpuRegister()) { 219102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray BlockRegister(temp, position, position + 1); 2203946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } else { 221102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray DCHECK(temp.IsUnallocated()); 2225368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain switch (temp.GetPolicy()) { 2235368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain case Location::kRequiresRegister: { 2245368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain LiveInterval* interval = 2255368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain LiveInterval::MakeTempInterval(allocator_, Primitive::kPrimInt); 2265368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain temp_intervals_.Add(interval); 2275368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain interval->AddRange(position, position + 1); 2285368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain unhandled_core_intervals_.Add(interval); 2295368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain break; 2305368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain } 2315368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain 2325368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain case Location::kRequiresFpuRegister: { 2335368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain LiveInterval* interval = 2345368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain LiveInterval::MakeTempInterval(allocator_, Primitive::kPrimDouble); 2355368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain temp_intervals_.Add(interval); 2365368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain interval->AddRange(position, position + 1); 237840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (codegen_->NeedsTwoRegisters(Primitive::kPrimDouble)) { 238840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray interval->AddHighInterval(true); 239840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray LiveInterval* high = interval->GetHighInterval(); 240840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray temp_intervals_.Add(high); 241840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray unhandled_fp_intervals_.Add(high); 242840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 2435368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain unhandled_fp_intervals_.Add(interval); 2445368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain break; 2455368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain } 2465368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain 2475368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain default: 2485368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain LOG(FATAL) << "Unexpected policy for temporary location " 2495368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain << temp.GetPolicy(); 2505368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain } 251a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 252a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 25386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 2543bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray bool core_register = (instruction->GetType() != Primitive::kPrimDouble) 2553bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray && (instruction->GetType() != Primitive::kPrimFloat); 2563bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray 2573946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray if (locations->CanCall()) { 2583bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray if (!instruction->IsSuspendCheck()) { 2593bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray codegen_->MarkNotLeaf(); 2603bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray } 2613946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray safepoints_.Add(instruction); 2623bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray if (locations->OnlyCallsOnSlowPath()) { 2633bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray // We add a synthesized range at this position to record the live registers 2643bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray // at this position. Ideally, we could just update the safepoints when locations 2653bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray // are updated, but we currently need to know the full stack size before updating 2663bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray // locations (because of parameters and the fact that we don't have a frame pointer). 2673bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray // And knowing the full stack size requires to know the maximum number of live 2683bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray // registers at calls in slow paths. 2693bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray // By adding the following interval in the algorithm, we can compute this 2703bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray // maximum before updating locations. 2713bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray LiveInterval* interval = LiveInterval::MakeSlowPathInterval(allocator_, instruction); 272acd033994aced8246c2fd8e931340dbf82d06d1aNicolas Geoffray interval->AddRange(position, position + 1); 27387d03761f35ad6cbe0bffbf1ec739875a471da6dNicolas Geoffray AddSorted(&unhandled_core_intervals_, interval); 27487d03761f35ad6cbe0bffbf1ec739875a471da6dNicolas Geoffray AddSorted(&unhandled_fp_intervals_, interval); 2753bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray } 2763bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray } 2773bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray 2783bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray if (locations->WillCall()) { 2793946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // Block all registers. 2803946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray for (size_t i = 0; i < codegen_->GetNumberOfCoreRegisters(); ++i) { 28156b9ee6fe1d6880c5fca0e7feb28b25a1ded2e2fNicolas Geoffray BlockRegister(Location::RegisterLocation(i), 2823946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray position, 283102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray position + 1); 284102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray } 285102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray for (size_t i = 0; i < codegen_->GetNumberOfFloatingPointRegisters(); ++i) { 286102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray BlockRegister(Location::FpuRegisterLocation(i), 287102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray position, 288102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray position + 1); 2893946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 2903946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 2913946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 2923946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray for (size_t i = 0; i < instruction->InputCount(); ++i) { 2933946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray Location input = locations->InAt(i); 294102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray if (input.IsRegister() || input.IsFpuRegister()) { 295102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray BlockRegister(input, position, position + 1); 296840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } else if (input.IsPair()) { 297840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray BlockRegister(input.ToLow(), position, position + 1); 298840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray BlockRegister(input.ToHigh(), position, position + 1); 2993946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 3003946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 3013946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 3023946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray LiveInterval* current = instruction->GetLiveInterval(); 3033946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray if (current == nullptr) return; 3043946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 305102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray GrowableArray<LiveInterval*>& unhandled = core_register 306102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray ? unhandled_core_intervals_ 307102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray : unhandled_fp_intervals_; 308102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray 3097690562d40878f44823d5fb03a2084cfc677ec4aNicolas Geoffray DCHECK(unhandled.IsEmpty() || current->StartsBeforeOrAt(unhandled.Peek())); 31087d03761f35ad6cbe0bffbf1ec739875a471da6dNicolas Geoffray 311840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (codegen_->NeedsTwoRegisters(current->GetType())) { 312840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray current->AddHighInterval(); 313840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 314840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray 3153946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // Some instructions define their output in fixed register/stack slot. We need 3163946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // to ensure we know these locations before doing register allocation. For a 3173946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // given register, we create an interval that covers these locations. The register 3183946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // will be unavailable at these locations when trying to allocate one for an 3193946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // interval. 3203946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // 3213946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // The backwards walking ensures the ranges are ordered on increasing start positions. 3223946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray Location output = locations->Out(); 323d0d4852847432368b090c184d6639e573538dccfCalin Juravle if (output.IsUnallocated() && output.GetPolicy() == Location::kSameAsFirstInput) { 324d0d4852847432368b090c184d6639e573538dccfCalin Juravle Location first = locations->InAt(0); 325d0d4852847432368b090c184d6639e573538dccfCalin Juravle if (first.IsRegister() || first.IsFpuRegister()) { 326d0d4852847432368b090c184d6639e573538dccfCalin Juravle current->SetFrom(position + 1); 327d0d4852847432368b090c184d6639e573538dccfCalin Juravle current->SetRegister(first.reg()); 328840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } else if (first.IsPair()) { 329840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray current->SetFrom(position + 1); 330840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray current->SetRegister(first.low()); 331840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray LiveInterval* high = current->GetHighInterval(); 332840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray high->SetRegister(first.high()); 333840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray high->SetFrom(position + 1); 334d0d4852847432368b090c184d6639e573538dccfCalin Juravle } 335d0d4852847432368b090c184d6639e573538dccfCalin Juravle } else if (output.IsRegister() || output.IsFpuRegister()) { 3363946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // Shift the interval's start by one to account for the blocked register. 3373946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray current->SetFrom(position + 1); 33856b9ee6fe1d6880c5fca0e7feb28b25a1ded2e2fNicolas Geoffray current->SetRegister(output.reg()); 339102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray BlockRegister(output, position, position + 1); 340840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } else if (output.IsPair()) { 341840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray current->SetFrom(position + 1); 342840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray current->SetRegister(output.low()); 343840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray LiveInterval* high = current->GetHighInterval(); 344840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray high->SetRegister(output.high()); 345840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray high->SetFrom(position + 1); 346840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray BlockRegister(output.ToLow(), position, position + 1); 347840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray BlockRegister(output.ToHigh(), position, position + 1); 3483946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } else if (output.IsStackSlot() || output.IsDoubleStackSlot()) { 3493946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray current->SetSpillSlot(output.GetStackIndex()); 350840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } else { 351840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray DCHECK(output.IsUnallocated() || output.IsConstant()); 3523946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 3533946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 3543946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // If needed, add interval to the list of unhandled intervals. 3553946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray if (current->HasSpillSlot() || instruction->IsConstant()) { 356c8147a76ed2f440f38329dc08ff889d393b5c535Nicolas Geoffray // Split just before first register use. 3573946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray size_t first_register_use = current->FirstRegisterUse(); 3583946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray if (first_register_use != kNoLifetime) { 359c8147a76ed2f440f38329dc08ff889d393b5c535Nicolas Geoffray LiveInterval* split = Split(current, first_register_use - 1); 360b5f62b3dc5ac2731ba8ad53cdf3d9bdb14fbf86bNicolas Geoffray // Don't add directly to `unhandled`, it needs to be sorted and the start 3613946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // of this new interval might be after intervals already in the list. 3623946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray AddSorted(&unhandled, split); 3633946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } else { 3643946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // Nothing to do, we won't allocate a register for this value. 3653946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 3663946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } else { 367b5f62b3dc5ac2731ba8ad53cdf3d9bdb14fbf86bNicolas Geoffray // Don't add directly to `unhandled`, temp or safepoint intervals 368b5f62b3dc5ac2731ba8ad53cdf3d9bdb14fbf86bNicolas Geoffray // for this instruction may have been added, and those can be 369b5f62b3dc5ac2731ba8ad53cdf3d9bdb14fbf86bNicolas Geoffray // processed first. 370b5f62b3dc5ac2731ba8ad53cdf3d9bdb14fbf86bNicolas Geoffray AddSorted(&unhandled, current); 3713946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 372a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray} 373a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 37431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffrayclass AllRangesIterator : public ValueObject { 37531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray public: 37631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray explicit AllRangesIterator(LiveInterval* interval) 37731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray : current_interval_(interval), 37831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray current_range_(interval->GetFirstRange()) {} 37931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray 38031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray bool Done() const { return current_interval_ == nullptr; } 38131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray LiveRange* CurrentRange() const { return current_range_; } 38231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray LiveInterval* CurrentInterval() const { return current_interval_; } 38331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray 38431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray void Advance() { 38531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray current_range_ = current_range_->GetNext(); 38631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray if (current_range_ == nullptr) { 38731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray current_interval_ = current_interval_->GetNextSibling(); 38831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray if (current_interval_ != nullptr) { 38931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray current_range_ = current_interval_->GetFirstRange(); 39031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray } 39131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray } 39231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray } 39331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray 39431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray private: 39531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray LiveInterval* current_interval_; 39631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray LiveRange* current_range_; 39731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray 39831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray DISALLOW_COPY_AND_ASSIGN(AllRangesIterator); 39931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray}; 40031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray 40186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffraybool RegisterAllocator::ValidateInternal(bool log_fatal_on_failure) const { 40286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // To simplify unit testing, we eagerly create the array of intervals, and 40386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // call the helper method. 40486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray GrowableArray<LiveInterval*> intervals(allocator_, 0); 40586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray for (size_t i = 0; i < liveness_.GetNumberOfSsaValues(); ++i) { 40686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i); 40786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (ShouldProcess(processing_core_registers_, instruction->GetLiveInterval())) { 40886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray intervals.Add(instruction->GetLiveInterval()); 40986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 41086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 41186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 412102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray if (processing_core_registers_) { 413102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray for (size_t i = 0, e = physical_core_register_intervals_.Size(); i < e; ++i) { 414102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray LiveInterval* fixed = physical_core_register_intervals_.Get(i); 415102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray if (fixed != nullptr) { 416102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray intervals.Add(fixed); 417102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray } 418102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray } 419102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray } else { 420102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray for (size_t i = 0, e = physical_fp_register_intervals_.Size(); i < e; ++i) { 421102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray LiveInterval* fixed = physical_fp_register_intervals_.Get(i); 422102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray if (fixed != nullptr) { 423102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray intervals.Add(fixed); 424102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray } 42586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 42686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 42786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 4283946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray for (size_t i = 0, e = temp_intervals_.Size(); i < e; ++i) { 4293946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray LiveInterval* temp = temp_intervals_.Get(i); 4303946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray if (ShouldProcess(processing_core_registers_, temp)) { 4313946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray intervals.Add(temp); 4323946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 4333946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 4343946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 4353946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray return ValidateIntervals(intervals, spill_slots_.Size(), reserved_out_slots_, *codegen_, 4363946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray allocator_, processing_core_registers_, log_fatal_on_failure); 43786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray} 43886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 43931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffraybool RegisterAllocator::ValidateIntervals(const GrowableArray<LiveInterval*>& intervals, 44031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray size_t number_of_spill_slots, 4413946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray size_t number_of_out_slots, 442a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray const CodeGenerator& codegen, 443a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray ArenaAllocator* allocator, 444a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray bool processing_core_registers, 445a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray bool log_fatal_on_failure) { 446a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray size_t number_of_registers = processing_core_registers 447a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray ? codegen.GetNumberOfCoreRegisters() 448a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray : codegen.GetNumberOfFloatingPointRegisters(); 44931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray GrowableArray<ArenaBitVector*> liveness_of_values( 45031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray allocator, number_of_registers + number_of_spill_slots); 451a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 452a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // Allocate a bit vector per register. A live interval that has a register 453a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // allocated will populate the associated bit vector based on its live ranges. 45431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray for (size_t i = 0; i < number_of_registers + number_of_spill_slots; ++i) { 45531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray liveness_of_values.Add(new (allocator) ArenaBitVector(allocator, 0, true)); 456a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 457a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 45831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray for (size_t i = 0, e = intervals.Size(); i < e; ++i) { 45931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray for (AllRangesIterator it(intervals.Get(i)); !it.Done(); it.Advance()) { 46031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray LiveInterval* current = it.CurrentInterval(); 46186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HInstruction* defined_by = current->GetParent()->GetDefinedBy(); 46286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (current->GetParent()->HasSpillSlot() 46386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // Parameters have their own stack slot. 46486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray && !(defined_by != nullptr && defined_by->IsParameterValue())) { 4653946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray BitVector* liveness_of_spill_slot = liveness_of_values.Get(number_of_registers 4663946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray + current->GetParent()->GetSpillSlot() / kVRegSize 4673946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray - number_of_out_slots); 46831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray for (size_t j = it.CurrentRange()->GetStart(); j < it.CurrentRange()->GetEnd(); ++j) { 46931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray if (liveness_of_spill_slot->IsBitSet(j)) { 47031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray if (log_fatal_on_failure) { 47131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray std::ostringstream message; 47231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray message << "Spill slot conflict at " << j; 47331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray LOG(FATAL) << message.str(); 47431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray } else { 47531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray return false; 47631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray } 47731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray } else { 47831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray liveness_of_spill_slot->SetBit(j); 47931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray } 48031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray } 481a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 48231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray 48331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray if (current->HasRegister()) { 48431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray BitVector* liveness_of_register = liveness_of_values.Get(current->GetRegister()); 48531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray for (size_t j = it.CurrentRange()->GetStart(); j < it.CurrentRange()->GetEnd(); ++j) { 48631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray if (liveness_of_register->IsBitSet(j)) { 487a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray if (log_fatal_on_failure) { 488a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray std::ostringstream message; 4893946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray message << "Register conflict at " << j << " "; 4903946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray if (defined_by != nullptr) { 4913946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray message << "(" << defined_by->DebugName() << ")"; 4923946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 4933946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray message << "for "; 494a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray if (processing_core_registers) { 495a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray codegen.DumpCoreRegister(message, current->GetRegister()); 496a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } else { 497a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray codegen.DumpFloatingPointRegister(message, current->GetRegister()); 498a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 499a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray LOG(FATAL) << message.str(); 500a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } else { 501a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray return false; 502a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 503a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } else { 50431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray liveness_of_register->SetBit(j); 505a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 506a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 50731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray } 50831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray } 509a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 510a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray return true; 511a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray} 512a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 51386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::DumpInterval(std::ostream& stream, LiveInterval* interval) const { 514a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray interval->Dump(stream); 515a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray stream << ": "; 516a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray if (interval->HasRegister()) { 517102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray if (interval->IsFloatingPoint()) { 51886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray codegen_->DumpFloatingPointRegister(stream, interval->GetRegister()); 519102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray } else { 520102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray codegen_->DumpCoreRegister(stream, interval->GetRegister()); 521a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 522a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } else { 523a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray stream << "spilled"; 524a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 525a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray stream << std::endl; 526a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray} 527a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 528296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yangvoid RegisterAllocator::DumpAllIntervals(std::ostream& stream) const { 529296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang stream << "inactive: " << std::endl; 530296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang for (size_t i = 0; i < inactive_.Size(); i ++) { 531296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang DumpInterval(stream, inactive_.Get(i)); 532296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang } 533296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang stream << "active: " << std::endl; 534296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang for (size_t i = 0; i < active_.Size(); i ++) { 535296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang DumpInterval(stream, active_.Get(i)); 536296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang } 537296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang stream << "unhandled: " << std::endl; 538296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang auto unhandled = (unhandled_ != nullptr) ? 539296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang unhandled_ : &unhandled_core_intervals_; 540296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang for (size_t i = 0; i < unhandled->Size(); i ++) { 541296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang DumpInterval(stream, unhandled->Get(i)); 542296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang } 543296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang stream << "handled: " << std::endl; 544296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang for (size_t i = 0; i < handled_.Size(); i ++) { 545296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang DumpInterval(stream, handled_.Get(i)); 546296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang } 547296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang} 548296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang 549a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray// By the book implementation of a linear scan register allocator. 550a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffrayvoid RegisterAllocator::LinearScan() { 5513946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray while (!unhandled_->IsEmpty()) { 552a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // (1) Remove interval with the lowest start position from unhandled. 5533946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray LiveInterval* current = unhandled_->Pop(); 5543946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray DCHECK(!current->IsFixed() && !current->HasSpillSlot()); 555c8147a76ed2f440f38329dc08ff889d393b5c535Nicolas Geoffray DCHECK(unhandled_->IsEmpty() || unhandled_->Peek()->GetStart() >= current->GetStart()); 556840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray DCHECK(!current->IsLowInterval() || unhandled_->Peek()->IsHighInterval()); 55787d03761f35ad6cbe0bffbf1ec739875a471da6dNicolas Geoffray 558a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray size_t position = current->GetStart(); 559a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 560296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // Remember the inactive_ size here since the ones moved to inactive_ from 561296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // active_ below shouldn't need to be re-checked. 562296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang size_t inactive_intervals_to_handle = inactive_.Size(); 563296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang 564a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // (2) Remove currently active intervals that are dead at this position. 565a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // Move active intervals that have a lifetime hole at this position 566a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // to inactive. 567a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray for (size_t i = 0; i < active_.Size(); ++i) { 568a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray LiveInterval* interval = active_.Get(i); 569a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray if (interval->IsDeadAt(position)) { 570a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray active_.Delete(interval); 571a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray --i; 572a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray handled_.Add(interval); 573a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } else if (!interval->Covers(position)) { 574a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray active_.Delete(interval); 575a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray --i; 576a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray inactive_.Add(interval); 577a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 578a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 579a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 580a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // (3) Remove currently inactive intervals that are dead at this position. 581a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // Move inactive intervals that cover this position to active. 582296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang for (size_t i = 0; i < inactive_intervals_to_handle; ++i) { 583a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray LiveInterval* interval = inactive_.Get(i); 584296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang DCHECK(interval->GetStart() < position || interval->IsFixed()); 585a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray if (interval->IsDeadAt(position)) { 586a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray inactive_.Delete(interval); 587a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray --i; 588296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang --inactive_intervals_to_handle; 589a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray handled_.Add(interval); 590a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } else if (interval->Covers(position)) { 591a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray inactive_.Delete(interval); 592a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray --i; 593296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang --inactive_intervals_to_handle; 594a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray active_.Add(interval); 595a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 596a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 597a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 598acd033994aced8246c2fd8e931340dbf82d06d1aNicolas Geoffray if (current->IsSlowPathSafepoint()) { 599acd033994aced8246c2fd8e931340dbf82d06d1aNicolas Geoffray // Synthesized interval to record the maximum number of live registers 600acd033994aced8246c2fd8e931340dbf82d06d1aNicolas Geoffray // at safepoints. No need to allocate a register for it. 601f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell if (processing_core_registers_) { 602f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell maximum_number_of_live_core_registers_ = 603f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell std::max(maximum_number_of_live_core_registers_, active_.Size()); 604f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell } else { 605f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell maximum_number_of_live_fp_registers_ = 606f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell std::max(maximum_number_of_live_fp_registers_, active_.Size()); 607f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell } 608acd033994aced8246c2fd8e931340dbf82d06d1aNicolas Geoffray DCHECK(unhandled_->IsEmpty() || unhandled_->Peek()->GetStart() > current->GetStart()); 609acd033994aced8246c2fd8e931340dbf82d06d1aNicolas Geoffray continue; 610acd033994aced8246c2fd8e931340dbf82d06d1aNicolas Geoffray } 611acd033994aced8246c2fd8e931340dbf82d06d1aNicolas Geoffray 612840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (current->IsHighInterval() && !current->GetLowInterval()->HasRegister()) { 613840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray DCHECK(!current->HasRegister()); 614840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray // Allocating the low part was unsucessful. The splitted interval for the high part 615840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray // will be handled next (it is in the `unhandled_` list). 616840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray continue; 617840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 618840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray 619a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // (4) Try to find an available register. 620a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray bool success = TryAllocateFreeReg(current); 621a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 622a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // (5) If no register could be found, we need to spill. 623a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray if (!success) { 624a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray success = AllocateBlockedReg(current); 625a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 626a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 627a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // (6) If the interval had a register allocated, add it to the list of active 628a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // intervals. 629a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray if (success) { 630a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray active_.Add(current); 631840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (current->HasHighInterval() && !current->GetHighInterval()->HasRegister()) { 632840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray current->GetHighInterval()->SetRegister(GetHighForLowRegister(current->GetRegister())); 633840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 634a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 635a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 636a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray} 637a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 638a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray// Find a free register. If multiple are found, pick the register that 639a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray// is free the longest. 640a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffraybool RegisterAllocator::TryAllocateFreeReg(LiveInterval* current) { 641a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray size_t* free_until = registers_array_; 642a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 643a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // First set all registers to be free. 644a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray for (size_t i = 0; i < number_of_registers_; ++i) { 645a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray free_until[i] = kMaxLifetimePosition; 646a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 647a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 648296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // For each active interval, set its register to not free. 649296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang for (size_t i = 0, e = active_.Size(); i < e; ++i) { 650296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang LiveInterval* interval = active_.Get(i); 651296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang DCHECK(interval->HasRegister()); 652296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang free_until[interval->GetRegister()] = 0; 653296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang } 654296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang 655a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // For each inactive interval, set its register to be free until 656a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // the next intersection with `current`. 657a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray for (size_t i = 0, e = inactive_.Size(); i < e; ++i) { 658a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray LiveInterval* inactive = inactive_.Get(i); 659296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // Temp/Slow-path-safepoint interval has no holes. 660296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang DCHECK(!inactive->IsTemp() && !inactive->IsSlowPathSafepoint()); 661296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang if (!current->IsSplit() && !inactive->IsFixed()) { 662296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // Neither current nor inactive are fixed. 663296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // Thanks to SSA, a non-split interval starting in a hole of an 664296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // inactive interval should never intersect with that inactive interval. 665296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // Only if it's not fixed though, because fixed intervals don't come from SSA. 666296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang DCHECK_EQ(inactive->FirstIntersectionWith(current), kNoLifetime); 667296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang continue; 668296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang } 669296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang 670a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray DCHECK(inactive->HasRegister()); 671296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang if (free_until[inactive->GetRegister()] == 0) { 672296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // Already used by some active interval. No need to intersect. 673296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang continue; 674296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang } 675a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray size_t next_intersection = inactive->FirstIntersectionWith(current); 676a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray if (next_intersection != kNoLifetime) { 677aac0f39a3501a7f7dd04b2342c2a16961969f139Nicolas Geoffray free_until[inactive->GetRegister()] = 678aac0f39a3501a7f7dd04b2342c2a16961969f139Nicolas Geoffray std::min(free_until[inactive->GetRegister()], next_intersection); 679a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 680a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 681a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 6826c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray int reg = kNoRegister; 6833946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray if (current->HasRegister()) { 6843946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // Some instructions have a fixed register output. 6853946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray reg = current->GetRegister(); 686840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (free_until[reg] == 0) { 687840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray DCHECK(current->IsHighInterval()); 688840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray // AllocateBlockedReg will spill the holder of the register. 689840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray return false; 690840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 6913946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } else { 692840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray DCHECK(!current->IsHighInterval()); 69301ef345767ea609417fc511e42007705c9667546Nicolas Geoffray int hint = current->FindFirstRegisterHint(free_until); 69401ef345767ea609417fc511e42007705c9667546Nicolas Geoffray if (hint != kNoRegister) { 69501ef345767ea609417fc511e42007705c9667546Nicolas Geoffray DCHECK(!IsBlocked(hint)); 69601ef345767ea609417fc511e42007705c9667546Nicolas Geoffray reg = hint; 697840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } else if (current->IsLowInterval()) { 6986c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray reg = FindAvailableRegisterPair(free_until, current->GetStart()); 69901ef345767ea609417fc511e42007705c9667546Nicolas Geoffray } else { 700840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray reg = FindAvailableRegister(free_until); 701a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 702a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 703a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 7046c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray DCHECK_NE(reg, kNoRegister); 705a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // If we could not find a register, we need to spill. 706840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (free_until[reg] == 0) { 707840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray return false; 708840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 709840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray 710840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (current->IsLowInterval() && free_until[GetHighForLowRegister(reg)] == 0) { 711a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray return false; 712a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 713a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 714a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray current->SetRegister(reg); 715a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray if (!current->IsDeadAt(free_until[reg])) { 716a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // If the register is only available for a subset of live ranges 717a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // covered by `current`, split `current` at the position where 718a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // the register is not available anymore. 719a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray LiveInterval* split = Split(current, free_until[reg]); 720a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray DCHECK(split != nullptr); 7213946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray AddSorted(unhandled_, split); 722a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 723a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray return true; 724a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray} 725a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 726a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffraybool RegisterAllocator::IsBlocked(int reg) const { 727102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray return processing_core_registers_ 728102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray ? blocked_core_registers_[reg] 729102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray : blocked_fp_registers_[reg]; 730a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray} 731a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 7326c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffrayint RegisterAllocator::FindAvailableRegisterPair(size_t* next_use, size_t starting_at) const { 7336c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray int reg = kNoRegister; 734840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray // Pick the register pair that is used the last. 735840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray for (size_t i = 0; i < number_of_registers_; ++i) { 736840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (IsBlocked(i)) continue; 737840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (!IsLowRegister(i)) continue; 738840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray int high_register = GetHighForLowRegister(i); 739840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (IsBlocked(high_register)) continue; 740840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray int existing_high_register = GetHighForLowRegister(reg); 7416c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray if ((reg == kNoRegister) || (next_use[i] >= next_use[reg] 742840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray && next_use[high_register] >= next_use[existing_high_register])) { 743840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray reg = i; 744840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (next_use[i] == kMaxLifetimePosition 745840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray && next_use[high_register] == kMaxLifetimePosition) { 746840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray break; 747840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 7486c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray } else if (next_use[reg] <= starting_at || next_use[existing_high_register] <= starting_at) { 7496c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray // If one of the current register is known to be unavailable, just unconditionally 7506c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray // try a new one. 7516c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray reg = i; 752840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 753840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 754840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray return reg; 755840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray} 756840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray 757840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffrayint RegisterAllocator::FindAvailableRegister(size_t* next_use) const { 7586c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray int reg = kNoRegister; 759840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray // Pick the register that is used the last. 760840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray for (size_t i = 0; i < number_of_registers_; ++i) { 761840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (IsBlocked(i)) continue; 7626c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray if (reg == kNoRegister || next_use[i] > next_use[reg]) { 763840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray reg = i; 764840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (next_use[i] == kMaxLifetimePosition) break; 765840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 766840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 767840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray return reg; 768840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray} 769840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray 7706c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffraybool RegisterAllocator::TrySplitNonPairIntervalAt(size_t position, 7716c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray size_t first_register_use, 7726c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray size_t* next_use) { 7736c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray for (size_t i = 0, e = active_.Size(); i < e; ++i) { 7746c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray LiveInterval* active = active_.Get(i); 7756c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray DCHECK(active->HasRegister()); 7766c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray // Split the first interval found. 7776c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray if (first_register_use <= next_use[active->GetRegister()] 7786c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray && !active->IsLowInterval() 7796c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray && !active->IsHighInterval()) { 7806c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray LiveInterval* split = Split(active, position); 7816c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray active_.DeleteAt(i); 7826c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray if (split != active) { 7836c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray handled_.Add(active); 7846c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray } 7856c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray AddSorted(unhandled_, split); 7866c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray return true; 7876c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray } 7886c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray } 7896c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray return false; 7906c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray} 7916c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray 792a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray// Find the register that is used the last, and spill the interval 793a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray// that holds it. If the first use of `current` is after that register 794a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray// we spill `current` instead. 795a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffraybool RegisterAllocator::AllocateBlockedReg(LiveInterval* current) { 796a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray size_t first_register_use = current->FirstRegisterUse(); 797412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray if (first_register_use == kNoLifetime) { 79831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray AllocateSpillSlotFor(current); 799a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray return false; 800a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 801a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 802a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // First set all registers as not being used. 803a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray size_t* next_use = registers_array_; 804a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray for (size_t i = 0; i < number_of_registers_; ++i) { 805a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray next_use[i] = kMaxLifetimePosition; 806a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 807a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 808a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // For each active interval, find the next use of its register after the 809a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // start of current. 810a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray for (size_t i = 0, e = active_.Size(); i < e; ++i) { 811a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray LiveInterval* active = active_.Get(i); 812a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray DCHECK(active->HasRegister()); 81386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (active->IsFixed()) { 81486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray next_use[active->GetRegister()] = current->GetStart(); 81586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } else { 81686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray size_t use = active->FirstRegisterUseAfter(current->GetStart()); 81786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (use != kNoLifetime) { 81886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray next_use[active->GetRegister()] = use; 81986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 820a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 821a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 822a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 823a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // For each inactive interval, find the next use of its register after the 824a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // start of current. 825a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray for (size_t i = 0, e = inactive_.Size(); i < e; ++i) { 826a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray LiveInterval* inactive = inactive_.Get(i); 827296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // Temp/Slow-path-safepoint interval has no holes. 828296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang DCHECK(!inactive->IsTemp() && !inactive->IsSlowPathSafepoint()); 829296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang if (!current->IsSplit() && !inactive->IsFixed()) { 830296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // Neither current nor inactive are fixed. 831296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // Thanks to SSA, a non-split interval starting in a hole of an 832296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // inactive interval should never intersect with that inactive interval. 833296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // Only if it's not fixed though, because fixed intervals don't come from SSA. 834296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang DCHECK_EQ(inactive->FirstIntersectionWith(current), kNoLifetime); 835296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang continue; 836296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang } 837a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray DCHECK(inactive->HasRegister()); 83886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray size_t next_intersection = inactive->FirstIntersectionWith(current); 83986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (next_intersection != kNoLifetime) { 84086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (inactive->IsFixed()) { 84186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray next_use[inactive->GetRegister()] = 84286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray std::min(next_intersection, next_use[inactive->GetRegister()]); 84386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } else { 84486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray size_t use = inactive->FirstRegisterUseAfter(current->GetStart()); 84586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (use != kNoLifetime) { 84686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray next_use[inactive->GetRegister()] = std::min(use, next_use[inactive->GetRegister()]); 84786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 84886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 849a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 850a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 851a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 8526c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray int reg = kNoRegister; 8536c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray bool should_spill = false; 854840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (current->HasRegister()) { 855840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray DCHECK(current->IsHighInterval()); 856840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray reg = current->GetRegister(); 8576c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray // When allocating the low part, we made sure the high register was available. 8586c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray DCHECK_LT(first_register_use, next_use[reg]); 859840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } else if (current->IsLowInterval()) { 8606c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray reg = FindAvailableRegisterPair(next_use, current->GetStart()); 8616c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray // We should spill if both registers are not available. 8626c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray should_spill = (first_register_use >= next_use[reg]) 8636c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray || (first_register_use >= next_use[GetHighForLowRegister(reg)]); 864840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } else { 865840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray DCHECK(!current->IsHighInterval()); 866840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray reg = FindAvailableRegister(next_use); 8676c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray should_spill = (first_register_use >= next_use[reg]); 868a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 869a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 8706c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray DCHECK_NE(reg, kNoRegister); 8716c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray if (should_spill) { 872840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray DCHECK(!current->IsHighInterval()); 8736c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray bool is_allocation_at_use_site = (current->GetStart() == (first_register_use - 1)); 8746c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray if (current->IsLowInterval() 8756c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray && is_allocation_at_use_site 8766c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray && TrySplitNonPairIntervalAt(current->GetStart(), first_register_use, next_use)) { 8776c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray // If we're allocating a register for `current` because the instruction at 8786c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray // that position requires it, but we think we should spill, then there are 8796c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray // non-pair intervals blocking the allocation. We split the first 8806c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray // interval found, and put ourselves first in the `unhandled_` list. 8816c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray LiveInterval* existing = unhandled_->Peek(); 8826c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray DCHECK(existing->IsHighInterval()); 8836c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray DCHECK_EQ(existing->GetLowInterval(), current); 8846c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray unhandled_->Add(current); 8856c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray } else { 8866c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray // If the first use of that instruction is after the last use of the found 8876c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray // register, we split this interval just before its first register use. 8886c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray AllocateSpillSlotFor(current); 8896c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray LiveInterval* split = Split(current, first_register_use - 1); 8906c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray DCHECK_NE(current, split) << "There is not enough registers available for " 8916c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray << split->GetParent()->GetDefinedBy()->DebugName() << " " 8926c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray << split->GetParent()->GetDefinedBy()->GetId() 8936c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray << " at " << first_register_use - 1; 8946c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray AddSorted(unhandled_, split); 8956c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray } 896a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray return false; 897a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } else { 898a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // Use this register and spill the active and inactives interval that 899a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // have that register. 900a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray current->SetRegister(reg); 901a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 902a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray for (size_t i = 0, e = active_.Size(); i < e; ++i) { 903a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray LiveInterval* active = active_.Get(i); 904a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray if (active->GetRegister() == reg) { 90586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray DCHECK(!active->IsFixed()); 906a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray LiveInterval* split = Split(active, current->GetStart()); 907a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray active_.DeleteAt(i); 908dd8f887e81b894bc8075d8bacdb223747b6a8018Nicolas Geoffray if (split != active) { 909dd8f887e81b894bc8075d8bacdb223747b6a8018Nicolas Geoffray handled_.Add(active); 910dd8f887e81b894bc8075d8bacdb223747b6a8018Nicolas Geoffray } 9113946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray AddSorted(unhandled_, split); 9126c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray 9136c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray if (active->IsLowInterval() || active->IsHighInterval()) { 9146c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray LiveInterval* other_half = active->IsLowInterval() 9156c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray ? active->GetHighInterval() 9166c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray : active->GetLowInterval(); 9176c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray // We also need to remove the other half from the list of actives. 9186c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray bool found = false; 9196c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray for (size_t j = 0; j < active_.Size(); ++j) { 9206c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray if (active_.Get(j) == other_half) { 9216c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray found = true; 9226c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray active_.DeleteAt(j); 9236c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray handled_.Add(other_half); 9246c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray break; 9256c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray } 9266c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray } 9276c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray DCHECK(found); 9286c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray } 929a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray break; 930a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 931a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 932a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 933296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang for (size_t i = 0, e = inactive_.Size(); i < e; ++i) { 934a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray LiveInterval* inactive = inactive_.Get(i); 935a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray if (inactive->GetRegister() == reg) { 936296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang if (!current->IsSplit() && !inactive->IsFixed()) { 937296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // Neither current nor inactive are fixed. 938296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // Thanks to SSA, a non-split interval starting in a hole of an 939296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // inactive interval should never intersect with that inactive interval. 940296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang // Only if it's not fixed though, because fixed intervals don't come from SSA. 941296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang DCHECK_EQ(inactive->FirstIntersectionWith(current), kNoLifetime); 942296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang continue; 943296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang } 94486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray size_t next_intersection = inactive->FirstIntersectionWith(current); 94586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (next_intersection != kNoLifetime) { 94686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (inactive->IsFixed()) { 94786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray LiveInterval* split = Split(current, next_intersection); 948dd8f887e81b894bc8075d8bacdb223747b6a8018Nicolas Geoffray DCHECK_NE(split, current); 9493946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray AddSorted(unhandled_, split); 95086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } else { 951dd8f887e81b894bc8075d8bacdb223747b6a8018Nicolas Geoffray // Split at the start of `current`, which will lead to splitting 952dd8f887e81b894bc8075d8bacdb223747b6a8018Nicolas Geoffray // at the end of the lifetime hole of `inactive`. 953dd8f887e81b894bc8075d8bacdb223747b6a8018Nicolas Geoffray LiveInterval* split = Split(inactive, current->GetStart()); 954dd8f887e81b894bc8075d8bacdb223747b6a8018Nicolas Geoffray // If it's inactive, it must start before the current interval. 955dd8f887e81b894bc8075d8bacdb223747b6a8018Nicolas Geoffray DCHECK_NE(split, inactive); 95686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray inactive_.DeleteAt(i); 957296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang --i; 958296bd60423e0630d8152b99fb7afb20fbff5a18aMingyao Yang --e; 95986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray handled_.Add(inactive); 9603946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray AddSorted(unhandled_, split); 9616c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray 9626c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray if (inactive->IsLowInterval() || inactive->IsHighInterval()) { 9636c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray LiveInterval* other_half = inactive->IsLowInterval() 9646c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray ? inactive->GetHighInterval() 9656c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray : inactive->GetLowInterval(); 9666c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray 9676c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray // We also need to remove the other half from the list of inactives. 9686c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray bool found = false; 9696c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray for (size_t j = 0; j < inactive_.Size(); ++j) { 9706c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray if (inactive_.Get(j) == other_half) { 9716c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray found = true; 9726c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray inactive_.DeleteAt(j); 9736c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray --e; 9746c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray handled_.Add(other_half); 9756c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray break; 9766c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray } 9776c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray } 9786c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray DCHECK(found); 9796c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray } 98086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 98186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 982a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 983a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 984a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 985a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray return true; 986a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 987a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray} 988a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 9893946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffrayvoid RegisterAllocator::AddSorted(GrowableArray<LiveInterval*>* array, LiveInterval* interval) { 990c8147a76ed2f440f38329dc08ff889d393b5c535Nicolas Geoffray DCHECK(!interval->IsFixed() && !interval->HasSpillSlot()); 99186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray size_t insert_at = 0; 9923946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray for (size_t i = array->Size(); i > 0; --i) { 9933946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray LiveInterval* current = array->Get(i - 1); 9946c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray // High intervals must be processed right after their low equivalent. 9956c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray if (current->StartsAfter(interval) && !current->IsHighInterval()) { 99686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray insert_at = i; 997a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray break; 998acd033994aced8246c2fd8e931340dbf82d06d1aNicolas Geoffray } else if ((current->GetStart() == interval->GetStart()) && current->IsSlowPathSafepoint()) { 999acd033994aced8246c2fd8e931340dbf82d06d1aNicolas Geoffray // Ensure the slow path interval is the last to be processed at its location: we want the 1000acd033994aced8246c2fd8e931340dbf82d06d1aNicolas Geoffray // interval to know all live registers at this location. 1001acd033994aced8246c2fd8e931340dbf82d06d1aNicolas Geoffray DCHECK(i == 1 || array->Get(i - 2)->StartsAfter(current)); 1002acd033994aced8246c2fd8e931340dbf82d06d1aNicolas Geoffray insert_at = i; 1003acd033994aced8246c2fd8e931340dbf82d06d1aNicolas Geoffray break; 1004a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 1005a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 1006840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray 10073946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray array->InsertAt(insert_at, interval); 1008840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray // Insert the high interval before the low, to ensure the low is processed before. 1009840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (interval->HasHighInterval()) { 1010840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray array->InsertAt(insert_at, interval->GetHighInterval()); 1011840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } else if (interval->HasLowInterval()) { 1012840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray array->InsertAt(insert_at + 1, interval->GetLowInterval()); 1013840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 1014a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray} 1015a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 1016a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas GeoffrayLiveInterval* RegisterAllocator::Split(LiveInterval* interval, size_t position) { 1017840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray DCHECK_GE(position, interval->GetStart()); 1018a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray DCHECK(!interval->IsDeadAt(position)); 1019a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray if (position == interval->GetStart()) { 1020a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray // Spill slot will be allocated when handling `interval` again. 1021a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray interval->ClearRegister(); 1022840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (interval->HasHighInterval()) { 1023840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray interval->GetHighInterval()->ClearRegister(); 1024840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } else if (interval->HasLowInterval()) { 1025840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray interval->GetLowInterval()->ClearRegister(); 1026840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 1027a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray return interval; 1028a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } else { 1029a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray LiveInterval* new_interval = interval->SplitAt(position); 1030840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (interval->HasHighInterval()) { 1031840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray LiveInterval* high = interval->GetHighInterval()->SplitAt(position); 1032840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray new_interval->SetHighInterval(high); 1033840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray high->SetLowInterval(new_interval); 1034840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } else if (interval->HasLowInterval()) { 1035840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray LiveInterval* low = interval->GetLowInterval()->SplitAt(position); 1036840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray new_interval->SetLowInterval(low); 1037840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray low->SetHighInterval(new_interval); 1038840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 1039a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray return new_interval; 1040a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 1041a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray} 1042a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 104331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffrayvoid RegisterAllocator::AllocateSpillSlotFor(LiveInterval* interval) { 1044840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (interval->IsHighInterval()) { 1045840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray // The low interval will contain the spill slot. 1046840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray return; 1047840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 1048840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray 104931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray LiveInterval* parent = interval->GetParent(); 105031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray 105131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray // An instruction gets a spill slot for its entire lifetime. If the parent 105231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray // of this interval already has a spill slot, there is nothing to do. 105331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray if (parent->HasSpillSlot()) { 105431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray return; 105531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray } 105631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray 105786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HInstruction* defined_by = parent->GetDefinedBy(); 105886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (defined_by->IsParameterValue()) { 105986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // Parameters have their own stack slot. 106086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray parent->SetSpillSlot(codegen_->GetStackSlotOfParameter(defined_by->AsParameterValue())); 106186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray return; 106286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 106386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 106496f89a290eb67d7bf4b1636798fa28df14309cc7Nicolas Geoffray if (defined_by->IsConstant()) { 106596f89a290eb67d7bf4b1636798fa28df14309cc7Nicolas Geoffray // Constants don't need a spill slot. 106696f89a290eb67d7bf4b1636798fa28df14309cc7Nicolas Geoffray return; 106796f89a290eb67d7bf4b1636798fa28df14309cc7Nicolas Geoffray } 106896f89a290eb67d7bf4b1636798fa28df14309cc7Nicolas Geoffray 106931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray LiveInterval* last_sibling = interval; 107031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray while (last_sibling->GetNextSibling() != nullptr) { 107131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray last_sibling = last_sibling->GetNextSibling(); 107231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray } 107331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray size_t end = last_sibling->GetEnd(); 107431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray 1075412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray // Find an available spill slot. 1076412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray size_t slot = 0; 1077412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray for (size_t e = spill_slots_.Size(); slot < e; ++slot) { 1078412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray // We check if it is less rather than less or equal because the parallel move 1079412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray // resolver does not work when a single spill slot needs to be exchanged with 1080412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray // a double spill slot. The strict comparison avoids needing to exchange these 1081412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray // locations at the same lifetime position. 1082412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray if (spill_slots_.Get(slot) < parent->GetStart() 1083412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray && (slot == (e - 1) || spill_slots_.Get(slot + 1) < parent->GetStart())) { 1084412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray break; 1085412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray } 1086412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray } 1087412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray 108801ef345767ea609417fc511e42007705c9667546Nicolas Geoffray if (parent->NeedsTwoSpillSlots()) { 10893c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray if (slot == spill_slots_.Size()) { 10903c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray // We need a new spill slot. 10913c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray spill_slots_.Add(end); 10923c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray spill_slots_.Add(end); 10933c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray } else if (slot == spill_slots_.Size() - 1) { 10943c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray spill_slots_.Put(slot, end); 10953c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray spill_slots_.Add(end); 10963c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray } else { 10973c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray spill_slots_.Put(slot, end); 10983c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray spill_slots_.Put(slot + 1, end); 109931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray } 110031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray } else { 11013c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray if (slot == spill_slots_.Size()) { 11023c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray // We need a new spill slot. 11033c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray spill_slots_.Add(end); 11043c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray } else { 11053c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray spill_slots_.Put(slot, end); 11063c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray } 110731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray } 110831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray 11093946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray parent->SetSpillSlot((slot + reserved_out_slots_) * kVRegSize); 111086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray} 111186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 11122a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffraystatic bool IsValidDestination(Location destination) { 1113102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray return destination.IsRegister() 11146c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray || destination.IsRegisterPair() 1115102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray || destination.IsFpuRegister() 1116840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray || destination.IsFpuRegisterPair() 1117102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray || destination.IsStackSlot() 1118102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray || destination.IsDoubleStackSlot(); 11192a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffray} 11202a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffray 1121740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffrayvoid RegisterAllocator::AddInputMoveFor(HInstruction* user, 112286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray Location source, 112386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray Location destination) const { 112486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (source.Equals(destination)) return; 112586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 1126476df557fed5f0b3f32f8d11a654674bb403a8f8Roland Levillain DCHECK(!user->IsPhi()); 112786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 1128740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray HInstruction* previous = user->GetPrevious(); 112986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HParallelMove* move = nullptr; 113086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (previous == nullptr 1131476df557fed5f0b3f32f8d11a654674bb403a8f8Roland Levillain || !previous->IsParallelMove() 11328e3964b766652a0478e8e0e303e8556c997675f1Nicolas Geoffray || previous->GetLifetimePosition() < user->GetLifetimePosition()) { 113386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray move = new (allocator_) HParallelMove(allocator_); 11348e3964b766652a0478e8e0e303e8556c997675f1Nicolas Geoffray move->SetLifetimePosition(user->GetLifetimePosition()); 1135740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray user->GetBlock()->InsertInstructionBefore(move, user); 113686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } else { 113786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray move = previous->AsParallelMove(); 113886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 11398e3964b766652a0478e8e0e303e8556c997675f1Nicolas Geoffray DCHECK_EQ(move->GetLifetimePosition(), user->GetLifetimePosition()); 114042d1f5f006c8bdbcbf855c53036cd50f9c69753eNicolas Geoffray move->AddMove(source, destination, nullptr); 114186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray} 114286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 114346fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffraystatic bool IsInstructionStart(size_t position) { 114446fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray return (position & 1) == 0; 114546fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray} 114646fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray 114746fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffraystatic bool IsInstructionEnd(size_t position) { 114846fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray return (position & 1) == 1; 114946fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray} 115046fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray 115186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::InsertParallelMoveAt(size_t position, 1152740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray HInstruction* instruction, 115386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray Location source, 115486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray Location destination) const { 11556c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray DCHECK(IsValidDestination(destination)) << destination; 115686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (source.Equals(destination)) return; 115786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 115886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HInstruction* at = liveness_.GetInstructionFromPosition(position / 2); 115986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HParallelMove* move; 116046fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray if (at == nullptr) { 116146fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray if (IsInstructionStart(position)) { 116246fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray // Block boundary, don't do anything the connection of split siblings will handle it. 116346fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray return; 116446fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray } else { 116546fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray // Move must happen before the first instruction of the block. 116646fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray at = liveness_.GetInstructionFromPosition((position + 1) / 2); 11675976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray // Note that parallel moves may have already been inserted, so we explicitly 11685976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray // ask for the first instruction of the block: `GetInstructionFromPosition` does 11695976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray // not contain the moves. 11705976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray at = at->GetBlock()->GetFirstInstruction(); 11715976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray if (at->GetLifetimePosition() != position) { 11725976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray DCHECK_GT(at->GetLifetimePosition(), position); 117346fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray move = new (allocator_) HParallelMove(allocator_); 117446fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray move->SetLifetimePosition(position); 117546fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray at->GetBlock()->InsertInstructionBefore(move, at); 11765976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray } else { 11775976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray DCHECK(at->IsParallelMove()); 11785976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray move = at->AsParallelMove(); 117946fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray } 118046fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray } 118146fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray } else if (IsInstructionEnd(position)) { 118286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // Move must happen after the instruction. 118386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray DCHECK(!at->IsControlFlow()); 118486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray move = at->GetNext()->AsParallelMove(); 1185e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray // This is a parallel move for connecting siblings in a same block. We need to 1186e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray // differentiate it with moves for connecting blocks, and input moves. 11878e3964b766652a0478e8e0e303e8556c997675f1Nicolas Geoffray if (move == nullptr || move->GetLifetimePosition() > position) { 118886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray move = new (allocator_) HParallelMove(allocator_); 118986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray move->SetLifetimePosition(position); 119086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray at->GetBlock()->InsertInstructionBefore(move, at->GetNext()); 119186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 119286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } else { 119386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // Move must happen before the instruction. 119486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HInstruction* previous = at->GetPrevious(); 1195740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray if (previous == nullptr 1196740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray || !previous->IsParallelMove() 1197740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray || previous->GetLifetimePosition() != position) { 1198740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray // If the previous is a parallel move, then its position must be lower 1199740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray // than the given `position`: it was added just after the non-parallel 1200740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray // move instruction that precedes `instruction`. 1201740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray DCHECK(previous == nullptr 1202740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray || !previous->IsParallelMove() 1203740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray || previous->GetLifetimePosition() < position); 120486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray move = new (allocator_) HParallelMove(allocator_); 120586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray move->SetLifetimePosition(position); 120686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray at->GetBlock()->InsertInstructionBefore(move, at); 120786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } else { 120886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray move = previous->AsParallelMove(); 120986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 121086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 121101ef345767ea609417fc511e42007705c9667546Nicolas Geoffray DCHECK_EQ(move->GetLifetimePosition(), position); 121242d1f5f006c8bdbcbf855c53036cd50f9c69753eNicolas Geoffray move->AddMove(source, destination, instruction); 121386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray} 121486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 121586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::InsertParallelMoveAtExitOf(HBasicBlock* block, 1216740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray HInstruction* instruction, 121786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray Location source, 121886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray Location destination) const { 12196c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray DCHECK(IsValidDestination(destination)) << destination; 122086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (source.Equals(destination)) return; 122186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 122286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray DCHECK_EQ(block->GetSuccessors().Size(), 1u); 122386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HInstruction* last = block->GetLastInstruction(); 1224360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray // We insert moves at exit for phi predecessors and connecting blocks. 1225360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray // A block ending with an if cannot branch to a block with phis because 1226360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray // we do not allow critical edges. It can also not connect 1227360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray // a split interval between two blocks: the move has to happen in the successor. 1228360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray DCHECK(!last->IsIf()); 122986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HInstruction* previous = last->GetPrevious(); 123086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HParallelMove* move; 1231e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray // This is a parallel move for connecting blocks. We need to differentiate 1232e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray // it with moves for connecting siblings in a same block, and output moves. 12335976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray size_t position = last->GetLifetimePosition(); 1234740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray if (previous == nullptr || !previous->IsParallelMove() 12355976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray || previous->AsParallelMove()->GetLifetimePosition() != position) { 123686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray move = new (allocator_) HParallelMove(allocator_); 12375976857e65d3d0e7be0c4e3183e9483c85a76bb8Nicolas Geoffray move->SetLifetimePosition(position); 123886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray block->InsertInstructionBefore(move, last); 123986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } else { 124086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray move = previous->AsParallelMove(); 124186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 124242d1f5f006c8bdbcbf855c53036cd50f9c69753eNicolas Geoffray move->AddMove(source, destination, instruction); 124386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray} 124486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 124586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::InsertParallelMoveAtEntryOf(HBasicBlock* block, 1246740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray HInstruction* instruction, 124786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray Location source, 124886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray Location destination) const { 12496c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray DCHECK(IsValidDestination(destination)) << destination; 125086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (source.Equals(destination)) return; 125186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 125286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HInstruction* first = block->GetFirstInstruction(); 125386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HParallelMove* move = first->AsParallelMove(); 1254e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray // This is a parallel move for connecting blocks. We need to differentiate 1255e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray // it with moves for connecting siblings in a same block, and input moves. 1256e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray if (move == nullptr || move->GetLifetimePosition() != block->GetLifetimeStart()) { 125786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray move = new (allocator_) HParallelMove(allocator_); 125886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray move->SetLifetimePosition(block->GetLifetimeStart()); 125986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray block->InsertInstructionBefore(move, first); 126086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 126142d1f5f006c8bdbcbf855c53036cd50f9c69753eNicolas Geoffray move->AddMove(source, destination, instruction); 126286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray} 126386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 126486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::InsertMoveAfter(HInstruction* instruction, 126586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray Location source, 126686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray Location destination) const { 12676c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray DCHECK(IsValidDestination(destination)) << destination; 126886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (source.Equals(destination)) return; 126986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 1270476df557fed5f0b3f32f8d11a654674bb403a8f8Roland Levillain if (instruction->IsPhi()) { 1271740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray InsertParallelMoveAtEntryOf(instruction->GetBlock(), instruction, source, destination); 127286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray return; 127386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 127486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 1275e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray size_t position = instruction->GetLifetimePosition() + 1; 127686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HParallelMove* move = instruction->GetNext()->AsParallelMove(); 1277e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray // This is a parallel move for moving the output of an instruction. We need 1278e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray // to differentiate with input moves, moves for connecting siblings in a 1279e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray // and moves for connecting blocks. 1280e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray if (move == nullptr || move->GetLifetimePosition() != position) { 128186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray move = new (allocator_) HParallelMove(allocator_); 1282e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray move->SetLifetimePosition(position); 128386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray instruction->GetBlock()->InsertInstructionBefore(move, instruction->GetNext()); 128486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 128542d1f5f006c8bdbcbf855c53036cd50f9c69753eNicolas Geoffray move->AddMove(source, destination, instruction); 128686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray} 128786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 128886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::ConnectSiblings(LiveInterval* interval) { 128986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray LiveInterval* current = interval; 129086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (current->HasSpillSlot() && current->HasRegister()) { 129186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // We spill eagerly, so move must be at definition. 129286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray InsertMoveAfter(interval->GetDefinedBy(), 1293840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray interval->ToLocation(), 129401ef345767ea609417fc511e42007705c9667546Nicolas Geoffray interval->NeedsTwoSpillSlots() 1295412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray ? Location::DoubleStackSlot(interval->GetParent()->GetSpillSlot()) 1296412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray : Location::StackSlot(interval->GetParent()->GetSpillSlot())); 129786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 129886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray UsePosition* use = current->GetFirstUse(); 129986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 130086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // Walk over all siblings, updating locations of use positions, and 130186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // connecting them when they are adjacent. 130286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray do { 130301ef345767ea609417fc511e42007705c9667546Nicolas Geoffray Location source = current->ToLocation(); 130486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 130586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // Walk over all uses covered by this interval, and update the location 130686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // information. 130786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray while (use != nullptr && use->GetPosition() <= current->GetEnd()) { 13083946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray LocationSummary* locations = use->GetUser()->GetLocations(); 13093946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray if (use->GetIsEnvironment()) { 13103946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray locations->SetEnvironmentAt(use->GetInputIndex(), source); 13113946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } else { 131286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray Location expected_location = locations->InAt(use->GetInputIndex()); 131371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // The expected (actual) location may be invalid in case the input is unused. Currently 131471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // this only happens for intrinsics. 131571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe if (expected_location.IsValid()) { 131671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe if (expected_location.IsUnallocated()) { 131771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe locations->SetInAt(use->GetInputIndex(), source); 131871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } else if (!expected_location.IsConstant()) { 131971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe AddInputMoveFor(use->GetUser(), source, expected_location); 132071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 132171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } else { 132271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe DCHECK(use->GetUser()->IsInvoke()); 132371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe DCHECK(use->GetUser()->AsInvoke()->GetIntrinsic() != Intrinsics::kNone); 132486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 132586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 132686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray use = use->GetNext(); 132786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 132886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 132986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // If the next interval starts just after this one, and has a register, 133086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // insert a move. 133186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray LiveInterval* next_sibling = current->GetNextSibling(); 133286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (next_sibling != nullptr 133386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray && next_sibling->HasRegister() 133486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray && current->GetEnd() == next_sibling->GetStart()) { 133501ef345767ea609417fc511e42007705c9667546Nicolas Geoffray Location destination = next_sibling->ToLocation(); 1336740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray InsertParallelMoveAt(current->GetEnd(), interval->GetDefinedBy(), source, destination); 133786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 13383946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 13393946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // At each safepoint, we record stack and register information. 13403946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray for (size_t i = 0, e = safepoints_.Size(); i < e; ++i) { 13413946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray HInstruction* safepoint = safepoints_.Get(i); 13423946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray size_t position = safepoint->GetLifetimePosition(); 13433946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray LocationSummary* locations = safepoint->GetLocations(); 1344b5f62b3dc5ac2731ba8ad53cdf3d9bdb14fbf86bNicolas Geoffray if (!current->Covers(position)) { 1345b5f62b3dc5ac2731ba8ad53cdf3d9bdb14fbf86bNicolas Geoffray continue; 1346b5f62b3dc5ac2731ba8ad53cdf3d9bdb14fbf86bNicolas Geoffray } 1347b5f62b3dc5ac2731ba8ad53cdf3d9bdb14fbf86bNicolas Geoffray if (interval->GetStart() == position) { 1348b5f62b3dc5ac2731ba8ad53cdf3d9bdb14fbf86bNicolas Geoffray // The safepoint is for this instruction, so the location of the instruction 1349b5f62b3dc5ac2731ba8ad53cdf3d9bdb14fbf86bNicolas Geoffray // does not need to be saved. 1350b5f62b3dc5ac2731ba8ad53cdf3d9bdb14fbf86bNicolas Geoffray continue; 1351b5f62b3dc5ac2731ba8ad53cdf3d9bdb14fbf86bNicolas Geoffray } 13523946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 13533bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray if ((current->GetType() == Primitive::kPrimNot) && current->GetParent()->HasSpillSlot()) { 13543946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray locations->SetStackBit(current->GetParent()->GetSpillSlot() / kVRegSize); 13553946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 13563946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 13573946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray switch (source.GetKind()) { 13583946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray case Location::kRegister: { 13593bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray locations->AddLiveRegister(source); 1360f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell DCHECK_LE(locations->GetNumberOfLiveRegisters(), 1361f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell maximum_number_of_live_core_registers_ + 1362f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell maximum_number_of_live_fp_registers_); 13633946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray if (current->GetType() == Primitive::kPrimNot) { 136456b9ee6fe1d6880c5fca0e7feb28b25a1ded2e2fNicolas Geoffray locations->SetRegisterBit(source.reg()); 13653946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 13663946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray break; 13673946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 1368102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray case Location::kFpuRegister: { 1369102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray locations->AddLiveRegister(source); 1370102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray break; 1371102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray } 13726c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray 13736c2dff8ff8e1440fa4d9e1b2ba2a44d036882801Nicolas Geoffray case Location::kRegisterPair: 1374840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray case Location::kFpuRegisterPair: { 1375840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray locations->AddLiveRegister(source.ToLow()); 1376840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray locations->AddLiveRegister(source.ToHigh()); 1377840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray break; 1378840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 13793946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray case Location::kStackSlot: // Fall-through 13803946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray case Location::kDoubleStackSlot: // Fall-through 13813946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray case Location::kConstant: { 13823946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // Nothing to do. 13833946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray break; 13843946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 13853946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray default: { 13863946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray LOG(FATAL) << "Unexpected location for object"; 13873946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 13883946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 13893946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 139086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray current = next_sibling; 139186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } while (current != nullptr); 139286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray DCHECK(use == nullptr); 139386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray} 139486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 139586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::ConnectSplitSiblings(LiveInterval* interval, 139686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HBasicBlock* from, 139786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HBasicBlock* to) const { 139886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (interval->GetNextSibling() == nullptr) { 139986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // Nothing to connect. The whole range was allocated to the same location. 140086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray return; 140186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 140286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 140346fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray // Intervals end at the lifetime end of a block. The decrement by one 140446fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray // ensures the `Cover` call will return true. 140586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray size_t from_position = from->GetLifetimeEnd() - 1; 140646fbaab1bf2981f2768b046abf43e368663daacdNicolas Geoffray size_t to_position = to->GetLifetimeStart(); 140786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 140886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray LiveInterval* destination = nullptr; 140986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray LiveInterval* source = nullptr; 141086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 141186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray LiveInterval* current = interval; 141286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 141386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // Check the intervals that cover `from` and `to`. 141486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray while ((current != nullptr) && (source == nullptr || destination == nullptr)) { 141586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (current->Covers(from_position)) { 141686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray DCHECK(source == nullptr); 141786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray source = current; 141886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 141986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (current->Covers(to_position)) { 142086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray DCHECK(destination == nullptr); 142186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray destination = current; 142286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 142386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 142486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray current = current->GetNextSibling(); 142586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 142686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 142786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (destination == source) { 142886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // Interval was not split. 142986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray return; 143086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 143186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 14328ddb00ca935733f5d3b07816e5bb33d6cabe6ec4Nicolas Geoffray DCHECK(destination != nullptr && source != nullptr); 14338ddb00ca935733f5d3b07816e5bb33d6cabe6ec4Nicolas Geoffray 143486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (!destination->HasRegister()) { 143586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // Values are eagerly spilled. Spill slot already contains appropriate value. 143686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray return; 143786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 143886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 143986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // If `from` has only one successor, we can put the moves at the exit of it. Otherwise 144086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // we need to put the moves at the entry of `to`. 144186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (from->GetSuccessors().Size() == 1) { 1442740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray InsertParallelMoveAtExitOf(from, 1443740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray interval->GetParent()->GetDefinedBy(), 144401ef345767ea609417fc511e42007705c9667546Nicolas Geoffray source->ToLocation(), 144501ef345767ea609417fc511e42007705c9667546Nicolas Geoffray destination->ToLocation()); 144686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } else { 144786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray DCHECK_EQ(to->GetPredecessors().Size(), 1u); 1448740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray InsertParallelMoveAtEntryOf(to, 1449740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray interval->GetParent()->GetDefinedBy(), 145001ef345767ea609417fc511e42007705c9667546Nicolas Geoffray source->ToLocation(), 145101ef345767ea609417fc511e42007705c9667546Nicolas Geoffray destination->ToLocation()); 145286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 145386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray} 145486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 145586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::Resolve() { 14563bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray codegen_->ComputeFrameSize( 1457f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell spill_slots_.Size(), maximum_number_of_live_core_registers_, 1458f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell maximum_number_of_live_fp_registers_, reserved_out_slots_); 145986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 146086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // Adjust the Out Location of instructions. 146186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // TODO: Use pointers of Location inside LiveInterval to avoid doing another iteration. 146286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray for (size_t i = 0, e = liveness_.GetNumberOfSsaValues(); i < e; ++i) { 146386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i); 146486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray LiveInterval* current = instruction->GetLiveInterval(); 146586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray LocationSummary* locations = instruction->GetLocations(); 146686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray Location location = locations->Out(); 1467476df557fed5f0b3f32f8d11a654674bb403a8f8Roland Levillain if (instruction->IsParameterValue()) { 146886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // Now that we know the frame size, adjust the parameter's location. 146986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (location.IsStackSlot()) { 147086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize()); 147186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray current->SetSpillSlot(location.GetStackIndex()); 1472f43083d560565aea46c602adb86423daeefe589dNicolas Geoffray locations->UpdateOut(location); 147386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } else if (location.IsDoubleStackSlot()) { 147486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize()); 147586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray current->SetSpillSlot(location.GetStackIndex()); 1476f43083d560565aea46c602adb86423daeefe589dNicolas Geoffray locations->UpdateOut(location); 147786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } else if (current->HasSpillSlot()) { 147886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray current->SetSpillSlot(current->GetSpillSlot() + codegen_->GetFrameSize()); 147986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 148086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 148186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 148201ef345767ea609417fc511e42007705c9667546Nicolas Geoffray Location source = current->ToLocation(); 148386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 148486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (location.IsUnallocated()) { 148586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray if (location.GetPolicy() == Location::kSameAsFirstInput) { 1486d0d4852847432368b090c184d6639e573538dccfCalin Juravle if (locations->InAt(0).IsUnallocated()) { 1487d0d4852847432368b090c184d6639e573538dccfCalin Juravle locations->SetInAt(0, source); 1488d0d4852847432368b090c184d6639e573538dccfCalin Juravle } else { 1489d0d4852847432368b090c184d6639e573538dccfCalin Juravle DCHECK(locations->InAt(0).Equals(source)); 1490d0d4852847432368b090c184d6639e573538dccfCalin Juravle } 149186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 149286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray locations->SetOut(source); 149386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } else { 149486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray DCHECK(source.Equals(location)); 149586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 149686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 149786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 149886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // Connect siblings. 149986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray for (size_t i = 0, e = liveness_.GetNumberOfSsaValues(); i < e; ++i) { 150086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i); 150186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray ConnectSiblings(instruction->GetLiveInterval()); 150286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 150386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 150486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // Resolve non-linear control flow across branches. Order does not matter. 150586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray for (HLinearOrderIterator it(liveness_); !it.Done(); it.Advance()) { 150686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HBasicBlock* block = it.Current(); 150786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray BitVector* live = liveness_.GetLiveInSet(*block); 150886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray for (uint32_t idx : live->Indexes()) { 150986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HInstruction* current = liveness_.GetInstructionFromSsaIndex(idx); 151086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray LiveInterval* interval = current->GetLiveInterval(); 151186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray for (size_t i = 0, e = block->GetPredecessors().Size(); i < e; ++i) { 151286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray ConnectSplitSiblings(interval, block->GetPredecessors().Get(i), block); 151386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 151486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 151586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 151686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 151786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // Resolve phi inputs. Order does not matter. 151886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray for (HLinearOrderIterator it(liveness_); !it.Done(); it.Advance()) { 151986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HBasicBlock* current = it.Current(); 1520277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe for (HInstructionIterator inst_it(current->GetPhis()); !inst_it.Done(); inst_it.Advance()) { 1521277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe HInstruction* phi = inst_it.Current(); 152286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray for (size_t i = 0, e = current->GetPredecessors().Size(); i < e; ++i) { 152386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HBasicBlock* predecessor = current->GetPredecessors().Get(i); 152486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray DCHECK_EQ(predecessor->GetSuccessors().Size(), 1u); 152586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray HInstruction* input = phi->InputAt(i); 152601ef345767ea609417fc511e42007705c9667546Nicolas Geoffray Location source = input->GetLiveInterval()->GetLocationAt( 152701ef345767ea609417fc511e42007705c9667546Nicolas Geoffray predecessor->GetLifetimeEnd() - 1); 152801ef345767ea609417fc511e42007705c9667546Nicolas Geoffray Location destination = phi->GetLiveInterval()->ToLocation(); 1529740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray InsertParallelMoveAtExitOf(predecessor, nullptr, source, destination); 153086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 153186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 153286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 15333946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 15343946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray // Assign temp locations. 15353946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray HInstruction* current = nullptr; 15363946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray size_t temp_index = 0; 15373946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray for (size_t i = 0; i < temp_intervals_.Size(); ++i) { 15383946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray LiveInterval* temp = temp_intervals_.Get(i); 1539840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (temp->IsHighInterval()) { 1540840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray // High intervals can be skipped, they are already handled by the low interval. 1541840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray continue; 1542840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 154301ef345767ea609417fc511e42007705c9667546Nicolas Geoffray HInstruction* at = liveness_.GetTempUser(temp); 154401ef345767ea609417fc511e42007705c9667546Nicolas Geoffray if (at != current) { 15453946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray temp_index = 0; 154601ef345767ea609417fc511e42007705c9667546Nicolas Geoffray current = at; 15473946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 154801ef345767ea609417fc511e42007705c9667546Nicolas Geoffray LocationSummary* locations = at->GetLocations(); 15495368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain switch (temp->GetType()) { 15505368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain case Primitive::kPrimInt: 15515368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain locations->SetTempAt( 15525368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain temp_index++, Location::RegisterLocation(temp->GetRegister())); 15535368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain break; 15545368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain 15555368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain case Primitive::kPrimDouble: 1556840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray if (codegen_->NeedsTwoRegisters(Primitive::kPrimDouble)) { 1557840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray Location location = Location::FpuRegisterPairLocation( 1558840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray temp->GetRegister(), temp->GetHighInterval()->GetRegister()); 1559840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray locations->SetTempAt(temp_index++, location); 1560840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } else { 1561840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray locations->SetTempAt( 1562840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray temp_index++, Location::FpuRegisterLocation(temp->GetRegister())); 1563840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 15645368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain break; 15655368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain 15665368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain default: 15675368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain LOG(FATAL) << "Unexpected type for temporary location " 15685368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain << temp->GetType(); 15695368c219a462defc90c4b896b34eb7506ba5c142Roland Levillain } 15703946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 157131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray} 157231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray 1573a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray} // namespace art 1574