16527b2a4SSebastian Neubauer //===-- GCNNSAReassign.cpp - Reassign registers in NSA instructions -------===// 2c29d4915SStanislav Mekhanoshin // 3c29d4915SStanislav Mekhanoshin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4c29d4915SStanislav Mekhanoshin // See https://llvm.org/LICENSE.txt for license information. 5c29d4915SStanislav Mekhanoshin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6c29d4915SStanislav Mekhanoshin // 7c29d4915SStanislav Mekhanoshin //===----------------------------------------------------------------------===// 8c29d4915SStanislav Mekhanoshin // 9c29d4915SStanislav Mekhanoshin /// \file 10c29d4915SStanislav Mekhanoshin /// \brief Try to reassign registers on GFX10+ from non-sequential to sequential 116527b2a4SSebastian Neubauer /// in NSA image instructions. Later SIShrinkInstructions pass will replace NSA 12c29d4915SStanislav Mekhanoshin /// with sequential versions where possible. 13c29d4915SStanislav Mekhanoshin /// 14c29d4915SStanislav Mekhanoshin //===----------------------------------------------------------------------===// 15c29d4915SStanislav Mekhanoshin 16c29d4915SStanislav Mekhanoshin #include "AMDGPU.h" 17560d7e04Sdfukalov #include "GCNSubtarget.h" 18c29d4915SStanislav Mekhanoshin #include "SIMachineFunctionInfo.h" 19c29d4915SStanislav Mekhanoshin #include "llvm/ADT/Statistic.h" 20c29d4915SStanislav Mekhanoshin #include "llvm/CodeGen/LiveIntervals.h" 21c29d4915SStanislav Mekhanoshin #include "llvm/CodeGen/LiveRegMatrix.h" 22c29d4915SStanislav Mekhanoshin #include "llvm/CodeGen/MachineFunctionPass.h" 23*989f1c72Sserge-sans-paille #include "llvm/CodeGen/VirtRegMap.h" 2405da2fe5SReid Kleckner #include "llvm/InitializePasses.h" 25c29d4915SStanislav Mekhanoshin 26c29d4915SStanislav Mekhanoshin using namespace llvm; 27c29d4915SStanislav Mekhanoshin 28c29d4915SStanislav Mekhanoshin #define DEBUG_TYPE "amdgpu-nsa-reassign" 29c29d4915SStanislav Mekhanoshin 30c29d4915SStanislav Mekhanoshin STATISTIC(NumNSAInstructions, 31c29d4915SStanislav Mekhanoshin "Number of NSA instructions with non-sequential address found"); 32c29d4915SStanislav Mekhanoshin STATISTIC(NumNSAConverted, 33c29d4915SStanislav Mekhanoshin "Number of NSA instructions changed to sequential"); 34c29d4915SStanislav Mekhanoshin 35c29d4915SStanislav Mekhanoshin namespace { 36c29d4915SStanislav Mekhanoshin 37c29d4915SStanislav Mekhanoshin class GCNNSAReassign : public MachineFunctionPass { 38c29d4915SStanislav Mekhanoshin public: 39c29d4915SStanislav Mekhanoshin static char ID; 40c29d4915SStanislav Mekhanoshin 41c29d4915SStanislav Mekhanoshin GCNNSAReassign() : MachineFunctionPass(ID) { 42c29d4915SStanislav Mekhanoshin initializeGCNNSAReassignPass(*PassRegistry::getPassRegistry()); 43c29d4915SStanislav Mekhanoshin } 44c29d4915SStanislav Mekhanoshin 45c29d4915SStanislav Mekhanoshin bool runOnMachineFunction(MachineFunction &MF) override; 46c29d4915SStanislav Mekhanoshin 47c29d4915SStanislav Mekhanoshin StringRef getPassName() const override { return "GCN NSA Reassign"; } 48c29d4915SStanislav Mekhanoshin 49c29d4915SStanislav Mekhanoshin void getAnalysisUsage(AnalysisUsage &AU) const override { 50c29d4915SStanislav Mekhanoshin AU.addRequired<LiveIntervals>(); 51c29d4915SStanislav Mekhanoshin AU.addRequired<VirtRegMap>(); 52c29d4915SStanislav Mekhanoshin AU.addRequired<LiveRegMatrix>(); 53c29d4915SStanislav Mekhanoshin AU.setPreservesAll(); 54c29d4915SStanislav Mekhanoshin MachineFunctionPass::getAnalysisUsage(AU); 55c29d4915SStanislav Mekhanoshin } 56c29d4915SStanislav Mekhanoshin 57c29d4915SStanislav Mekhanoshin private: 58c29d4915SStanislav Mekhanoshin typedef enum { 59c29d4915SStanislav Mekhanoshin NOT_NSA, // Not an NSA instruction 60c29d4915SStanislav Mekhanoshin FIXED, // NSA which we cannot modify 61c29d4915SStanislav Mekhanoshin NON_CONTIGUOUS, // NSA with non-sequential address which we can try 62c29d4915SStanislav Mekhanoshin // to optimize. 63c29d4915SStanislav Mekhanoshin CONTIGUOUS // NSA with all sequential address registers 64c29d4915SStanislav Mekhanoshin } NSA_Status; 65c29d4915SStanislav Mekhanoshin 66c29d4915SStanislav Mekhanoshin const GCNSubtarget *ST; 67c29d4915SStanislav Mekhanoshin 68c29d4915SStanislav Mekhanoshin const MachineRegisterInfo *MRI; 69c29d4915SStanislav Mekhanoshin 70c29d4915SStanislav Mekhanoshin const SIRegisterInfo *TRI; 71c29d4915SStanislav Mekhanoshin 72c29d4915SStanislav Mekhanoshin VirtRegMap *VRM; 73c29d4915SStanislav Mekhanoshin 74c29d4915SStanislav Mekhanoshin LiveRegMatrix *LRM; 75c29d4915SStanislav Mekhanoshin 76c29d4915SStanislav Mekhanoshin LiveIntervals *LIS; 77c29d4915SStanislav Mekhanoshin 78c29d4915SStanislav Mekhanoshin unsigned MaxNumVGPRs; 79c29d4915SStanislav Mekhanoshin 80c29d4915SStanislav Mekhanoshin const MCPhysReg *CSRegs; 81c29d4915SStanislav Mekhanoshin 82c29d4915SStanislav Mekhanoshin NSA_Status CheckNSA(const MachineInstr &MI, bool Fast = false) const; 83c29d4915SStanislav Mekhanoshin 84c29d4915SStanislav Mekhanoshin bool tryAssignRegisters(SmallVectorImpl<LiveInterval *> &Intervals, 85c29d4915SStanislav Mekhanoshin unsigned StartReg) const; 86c29d4915SStanislav Mekhanoshin 87c29d4915SStanislav Mekhanoshin bool canAssign(unsigned StartReg, unsigned NumRegs) const; 88c29d4915SStanislav Mekhanoshin 89c29d4915SStanislav Mekhanoshin bool scavengeRegs(SmallVectorImpl<LiveInterval *> &Intervals) const; 90c29d4915SStanislav Mekhanoshin }; 91c29d4915SStanislav Mekhanoshin 92c29d4915SStanislav Mekhanoshin } // End anonymous namespace. 93c29d4915SStanislav Mekhanoshin 94c29d4915SStanislav Mekhanoshin INITIALIZE_PASS_BEGIN(GCNNSAReassign, DEBUG_TYPE, "GCN NSA Reassign", 95c29d4915SStanislav Mekhanoshin false, false) 96c29d4915SStanislav Mekhanoshin INITIALIZE_PASS_DEPENDENCY(LiveIntervals) 97c29d4915SStanislav Mekhanoshin INITIALIZE_PASS_DEPENDENCY(VirtRegMap) 98c29d4915SStanislav Mekhanoshin INITIALIZE_PASS_DEPENDENCY(LiveRegMatrix) 99c29d4915SStanislav Mekhanoshin INITIALIZE_PASS_END(GCNNSAReassign, DEBUG_TYPE, "GCN NSA Reassign", 100c29d4915SStanislav Mekhanoshin false, false) 101c29d4915SStanislav Mekhanoshin 102c29d4915SStanislav Mekhanoshin 103c29d4915SStanislav Mekhanoshin char GCNNSAReassign::ID = 0; 104c29d4915SStanislav Mekhanoshin 105c29d4915SStanislav Mekhanoshin char &llvm::GCNNSAReassignID = GCNNSAReassign::ID; 106c29d4915SStanislav Mekhanoshin 107c29d4915SStanislav Mekhanoshin bool 108c29d4915SStanislav Mekhanoshin GCNNSAReassign::tryAssignRegisters(SmallVectorImpl<LiveInterval *> &Intervals, 109c29d4915SStanislav Mekhanoshin unsigned StartReg) const { 110c29d4915SStanislav Mekhanoshin unsigned NumRegs = Intervals.size(); 111c29d4915SStanislav Mekhanoshin 112c29d4915SStanislav Mekhanoshin for (unsigned N = 0; N < NumRegs; ++N) 1136e85c3d5SMircea Trofin if (VRM->hasPhys(Intervals[N]->reg())) 114c29d4915SStanislav Mekhanoshin LRM->unassign(*Intervals[N]); 115c29d4915SStanislav Mekhanoshin 116c29d4915SStanislav Mekhanoshin for (unsigned N = 0; N < NumRegs; ++N) 11743d34799SMircea Trofin if (LRM->checkInterference(*Intervals[N], MCRegister::from(StartReg + N))) 118c29d4915SStanislav Mekhanoshin return false; 119c29d4915SStanislav Mekhanoshin 120c29d4915SStanislav Mekhanoshin for (unsigned N = 0; N < NumRegs; ++N) 12143d34799SMircea Trofin LRM->assign(*Intervals[N], MCRegister::from(StartReg + N)); 122c29d4915SStanislav Mekhanoshin 123c29d4915SStanislav Mekhanoshin return true; 124c29d4915SStanislav Mekhanoshin } 125c29d4915SStanislav Mekhanoshin 126c29d4915SStanislav Mekhanoshin bool GCNNSAReassign::canAssign(unsigned StartReg, unsigned NumRegs) const { 127c29d4915SStanislav Mekhanoshin for (unsigned N = 0; N < NumRegs; ++N) { 128c29d4915SStanislav Mekhanoshin unsigned Reg = StartReg + N; 129c29d4915SStanislav Mekhanoshin if (!MRI->isAllocatable(Reg)) 130c29d4915SStanislav Mekhanoshin return false; 131c29d4915SStanislav Mekhanoshin 132c29d4915SStanislav Mekhanoshin for (unsigned I = 0; CSRegs[I]; ++I) 133c29d4915SStanislav Mekhanoshin if (TRI->isSubRegisterEq(Reg, CSRegs[I]) && 134c29d4915SStanislav Mekhanoshin !LRM->isPhysRegUsed(CSRegs[I])) 135c29d4915SStanislav Mekhanoshin return false; 136c29d4915SStanislav Mekhanoshin } 137c29d4915SStanislav Mekhanoshin 138c29d4915SStanislav Mekhanoshin return true; 139c29d4915SStanislav Mekhanoshin } 140c29d4915SStanislav Mekhanoshin 141c29d4915SStanislav Mekhanoshin bool 142c29d4915SStanislav Mekhanoshin GCNNSAReassign::scavengeRegs(SmallVectorImpl<LiveInterval *> &Intervals) const { 143c29d4915SStanislav Mekhanoshin unsigned NumRegs = Intervals.size(); 144c29d4915SStanislav Mekhanoshin 145c29d4915SStanislav Mekhanoshin if (NumRegs > MaxNumVGPRs) 146c29d4915SStanislav Mekhanoshin return false; 147c29d4915SStanislav Mekhanoshin unsigned MaxReg = MaxNumVGPRs - NumRegs + AMDGPU::VGPR0; 148c29d4915SStanislav Mekhanoshin 149c29d4915SStanislav Mekhanoshin for (unsigned Reg = AMDGPU::VGPR0; Reg <= MaxReg; ++Reg) { 150c29d4915SStanislav Mekhanoshin if (!canAssign(Reg, NumRegs)) 151c29d4915SStanislav Mekhanoshin continue; 152c29d4915SStanislav Mekhanoshin 153c29d4915SStanislav Mekhanoshin if (tryAssignRegisters(Intervals, Reg)) 154c29d4915SStanislav Mekhanoshin return true; 155c29d4915SStanislav Mekhanoshin } 156c29d4915SStanislav Mekhanoshin 157c29d4915SStanislav Mekhanoshin return false; 158c29d4915SStanislav Mekhanoshin } 159c29d4915SStanislav Mekhanoshin 160c29d4915SStanislav Mekhanoshin GCNNSAReassign::NSA_Status 161c29d4915SStanislav Mekhanoshin GCNNSAReassign::CheckNSA(const MachineInstr &MI, bool Fast) const { 162c29d4915SStanislav Mekhanoshin const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(MI.getOpcode()); 163c29d4915SStanislav Mekhanoshin if (!Info || Info->MIMGEncoding != AMDGPU::MIMGEncGfx10NSA) 164c29d4915SStanislav Mekhanoshin return NSA_Status::NOT_NSA; 165c29d4915SStanislav Mekhanoshin 166c29d4915SStanislav Mekhanoshin int VAddr0Idx = 167c29d4915SStanislav Mekhanoshin AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vaddr0); 168c29d4915SStanislav Mekhanoshin 169c29d4915SStanislav Mekhanoshin unsigned VgprBase = 0; 170c29d4915SStanislav Mekhanoshin bool NSA = false; 171c29d4915SStanislav Mekhanoshin for (unsigned I = 0; I < Info->VAddrDwords; ++I) { 172c29d4915SStanislav Mekhanoshin const MachineOperand &Op = MI.getOperand(VAddr0Idx + I); 1730c476111SDaniel Sanders Register Reg = Op.getReg(); 17434978602SJay Foad if (Reg.isPhysical() || !VRM->isAssignedReg(Reg)) 175c29d4915SStanislav Mekhanoshin return NSA_Status::FIXED; 176c29d4915SStanislav Mekhanoshin 1770c476111SDaniel Sanders Register PhysReg = VRM->getPhys(Reg); 178c29d4915SStanislav Mekhanoshin 179c29d4915SStanislav Mekhanoshin if (!Fast) { 180c29d4915SStanislav Mekhanoshin if (!PhysReg) 181c29d4915SStanislav Mekhanoshin return NSA_Status::FIXED; 182c29d4915SStanislav Mekhanoshin 183c29d4915SStanislav Mekhanoshin // Bail if address is not a VGPR32. That should be possible to extend the 184c29d4915SStanislav Mekhanoshin // optimization to work with subregs of a wider register tuples, but the 185c29d4915SStanislav Mekhanoshin // logic to find free registers will be much more complicated with much 186c29d4915SStanislav Mekhanoshin // less chances for success. That seems reasonable to assume that in most 187c29d4915SStanislav Mekhanoshin // cases a tuple is used because a vector variable contains different 1885464fd36SJoe Nash // parts of an address and it is either already consecutive or cannot 189c29d4915SStanislav Mekhanoshin // be reassigned if not. If needed it is better to rely on register 190c29d4915SStanislav Mekhanoshin // coalescer to process such address tuples. 191c29d4915SStanislav Mekhanoshin if (MRI->getRegClass(Reg) != &AMDGPU::VGPR_32RegClass || Op.getSubReg()) 192c29d4915SStanislav Mekhanoshin return NSA_Status::FIXED; 193c29d4915SStanislav Mekhanoshin 194d91ee2f7SStanislav Mekhanoshin // InlineSpiller does not call LRM::assign() after an LI split leaving 195d91ee2f7SStanislav Mekhanoshin // it in an inconsistent state, so we cannot call LRM::unassign(). 196d91ee2f7SStanislav Mekhanoshin // See llvm bug #48911. 197d91ee2f7SStanislav Mekhanoshin // Skip reassign if a register has originated from such split. 198d91ee2f7SStanislav Mekhanoshin // FIXME: Remove the workaround when bug #48911 is fixed. 199d91ee2f7SStanislav Mekhanoshin if (VRM->getPreSplitReg(Reg)) 200d91ee2f7SStanislav Mekhanoshin return NSA_Status::FIXED; 201d91ee2f7SStanislav Mekhanoshin 202c29d4915SStanislav Mekhanoshin const MachineInstr *Def = MRI->getUniqueVRegDef(Reg); 203c29d4915SStanislav Mekhanoshin 204c29d4915SStanislav Mekhanoshin if (Def && Def->isCopy() && Def->getOperand(1).getReg() == PhysReg) 205c29d4915SStanislav Mekhanoshin return NSA_Status::FIXED; 206c29d4915SStanislav Mekhanoshin 207c29d4915SStanislav Mekhanoshin for (auto U : MRI->use_nodbg_operands(Reg)) { 208c29d4915SStanislav Mekhanoshin if (U.isImplicit()) 209c29d4915SStanislav Mekhanoshin return NSA_Status::FIXED; 210c29d4915SStanislav Mekhanoshin const MachineInstr *UseInst = U.getParent(); 211c29d4915SStanislav Mekhanoshin if (UseInst->isCopy() && UseInst->getOperand(0).getReg() == PhysReg) 212c29d4915SStanislav Mekhanoshin return NSA_Status::FIXED; 213c29d4915SStanislav Mekhanoshin } 214c29d4915SStanislav Mekhanoshin 215c29d4915SStanislav Mekhanoshin if (!LIS->hasInterval(Reg)) 216c29d4915SStanislav Mekhanoshin return NSA_Status::FIXED; 217c29d4915SStanislav Mekhanoshin } 218c29d4915SStanislav Mekhanoshin 219c29d4915SStanislav Mekhanoshin if (I == 0) 220c29d4915SStanislav Mekhanoshin VgprBase = PhysReg; 221c29d4915SStanislav Mekhanoshin else if (VgprBase + I != PhysReg) 222c29d4915SStanislav Mekhanoshin NSA = true; 223c29d4915SStanislav Mekhanoshin } 224c29d4915SStanislav Mekhanoshin 225c29d4915SStanislav Mekhanoshin return NSA ? NSA_Status::NON_CONTIGUOUS : NSA_Status::CONTIGUOUS; 226c29d4915SStanislav Mekhanoshin } 227c29d4915SStanislav Mekhanoshin 228c29d4915SStanislav Mekhanoshin bool GCNNSAReassign::runOnMachineFunction(MachineFunction &MF) { 229c29d4915SStanislav Mekhanoshin ST = &MF.getSubtarget<GCNSubtarget>(); 230c29d4915SStanislav Mekhanoshin if (ST->getGeneration() < GCNSubtarget::GFX10) 231c29d4915SStanislav Mekhanoshin return false; 232c29d4915SStanislav Mekhanoshin 233c29d4915SStanislav Mekhanoshin MRI = &MF.getRegInfo(); 234c29d4915SStanislav Mekhanoshin TRI = ST->getRegisterInfo(); 235c29d4915SStanislav Mekhanoshin VRM = &getAnalysis<VirtRegMap>(); 236c29d4915SStanislav Mekhanoshin LRM = &getAnalysis<LiveRegMatrix>(); 237c29d4915SStanislav Mekhanoshin LIS = &getAnalysis<LiveIntervals>(); 238c29d4915SStanislav Mekhanoshin 239c29d4915SStanislav Mekhanoshin const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>(); 240c29d4915SStanislav Mekhanoshin MaxNumVGPRs = ST->getMaxNumVGPRs(MF); 241c29d4915SStanislav Mekhanoshin MaxNumVGPRs = std::min(ST->getMaxNumVGPRs(MFI->getOccupancy()), MaxNumVGPRs); 242e0b84434SMatt Arsenault CSRegs = MRI->getCalleeSavedRegs(); 243c29d4915SStanislav Mekhanoshin 244c29d4915SStanislav Mekhanoshin using Candidate = std::pair<const MachineInstr*, bool>; 245c29d4915SStanislav Mekhanoshin SmallVector<Candidate, 32> Candidates; 246c29d4915SStanislav Mekhanoshin for (const MachineBasicBlock &MBB : MF) { 247c29d4915SStanislav Mekhanoshin for (const MachineInstr &MI : MBB) { 248c29d4915SStanislav Mekhanoshin switch (CheckNSA(MI)) { 249c29d4915SStanislav Mekhanoshin default: 250c29d4915SStanislav Mekhanoshin continue; 251c29d4915SStanislav Mekhanoshin case NSA_Status::CONTIGUOUS: 252c29d4915SStanislav Mekhanoshin Candidates.push_back(std::make_pair(&MI, true)); 253c29d4915SStanislav Mekhanoshin break; 254c29d4915SStanislav Mekhanoshin case NSA_Status::NON_CONTIGUOUS: 255c29d4915SStanislav Mekhanoshin Candidates.push_back(std::make_pair(&MI, false)); 256c29d4915SStanislav Mekhanoshin ++NumNSAInstructions; 257c29d4915SStanislav Mekhanoshin break; 258c29d4915SStanislav Mekhanoshin } 259c29d4915SStanislav Mekhanoshin } 260c29d4915SStanislav Mekhanoshin } 261c29d4915SStanislav Mekhanoshin 262c29d4915SStanislav Mekhanoshin bool Changed = false; 263c29d4915SStanislav Mekhanoshin for (auto &C : Candidates) { 264c29d4915SStanislav Mekhanoshin if (C.second) 265c29d4915SStanislav Mekhanoshin continue; 266c29d4915SStanislav Mekhanoshin 267c29d4915SStanislav Mekhanoshin const MachineInstr *MI = C.first; 268c29d4915SStanislav Mekhanoshin if (CheckNSA(*MI, true) == NSA_Status::CONTIGUOUS) { 269c29d4915SStanislav Mekhanoshin // Already happen to be fixed. 270c29d4915SStanislav Mekhanoshin C.second = true; 271c29d4915SStanislav Mekhanoshin ++NumNSAConverted; 272c29d4915SStanislav Mekhanoshin continue; 273c29d4915SStanislav Mekhanoshin } 274c29d4915SStanislav Mekhanoshin 275c29d4915SStanislav Mekhanoshin const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(MI->getOpcode()); 276c29d4915SStanislav Mekhanoshin int VAddr0Idx = 277c29d4915SStanislav Mekhanoshin AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::vaddr0); 278c29d4915SStanislav Mekhanoshin 279c29d4915SStanislav Mekhanoshin SmallVector<LiveInterval *, 16> Intervals; 28043d34799SMircea Trofin SmallVector<MCRegister, 16> OrigRegs; 281c29d4915SStanislav Mekhanoshin SlotIndex MinInd, MaxInd; 282c29d4915SStanislav Mekhanoshin for (unsigned I = 0; I < Info->VAddrDwords; ++I) { 283c29d4915SStanislav Mekhanoshin const MachineOperand &Op = MI->getOperand(VAddr0Idx + I); 2840c476111SDaniel Sanders Register Reg = Op.getReg(); 285c29d4915SStanislav Mekhanoshin LiveInterval *LI = &LIS->getInterval(Reg); 2862dc4a14eSKazu Hirata if (llvm::is_contained(Intervals, LI)) { 287c29d4915SStanislav Mekhanoshin // Same register used, unable to make sequential 288c29d4915SStanislav Mekhanoshin Intervals.clear(); 289c29d4915SStanislav Mekhanoshin break; 290c29d4915SStanislav Mekhanoshin } 291c29d4915SStanislav Mekhanoshin Intervals.push_back(LI); 292c29d4915SStanislav Mekhanoshin OrigRegs.push_back(VRM->getPhys(Reg)); 293ba811016SNicolai Hähnle if (LI->empty()) { 294ba811016SNicolai Hähnle // The address input is undef, so it doesn't contribute to the relevant 295ba811016SNicolai Hähnle // range. Seed a reasonable index range if required. 296ba811016SNicolai Hähnle if (I == 0) 297ba811016SNicolai Hähnle MinInd = MaxInd = LIS->getInstructionIndex(*MI); 298ba811016SNicolai Hähnle continue; 299ba811016SNicolai Hähnle } 300ba811016SNicolai Hähnle MinInd = I != 0 ? std::min(MinInd, LI->beginIndex()) : LI->beginIndex(); 301ba811016SNicolai Hähnle MaxInd = I != 0 ? std::max(MaxInd, LI->endIndex()) : LI->endIndex(); 302c29d4915SStanislav Mekhanoshin } 303c29d4915SStanislav Mekhanoshin 304c29d4915SStanislav Mekhanoshin if (Intervals.empty()) 305c29d4915SStanislav Mekhanoshin continue; 306c29d4915SStanislav Mekhanoshin 307c29d4915SStanislav Mekhanoshin LLVM_DEBUG(dbgs() << "Attempting to reassign NSA: " << *MI 308c29d4915SStanislav Mekhanoshin << "\tOriginal allocation:\t"; 3096e85c3d5SMircea Trofin for (auto *LI 3106e85c3d5SMircea Trofin : Intervals) dbgs() 3116e85c3d5SMircea Trofin << " " << llvm::printReg((VRM->getPhys(LI->reg())), TRI); 312c29d4915SStanislav Mekhanoshin dbgs() << '\n'); 313c29d4915SStanislav Mekhanoshin 314c29d4915SStanislav Mekhanoshin bool Success = scavengeRegs(Intervals); 315c29d4915SStanislav Mekhanoshin if (!Success) { 316c29d4915SStanislav Mekhanoshin LLVM_DEBUG(dbgs() << "\tCannot reallocate.\n"); 3176e85c3d5SMircea Trofin if (VRM->hasPhys(Intervals.back()->reg())) // Did not change allocation. 318c29d4915SStanislav Mekhanoshin continue; 319c29d4915SStanislav Mekhanoshin } else { 320c29d4915SStanislav Mekhanoshin // Check we did not make it worse for other instructions. 321c29d4915SStanislav Mekhanoshin auto I = std::lower_bound(Candidates.begin(), &C, MinInd, 322c29d4915SStanislav Mekhanoshin [this](const Candidate &C, SlotIndex I) { 323c29d4915SStanislav Mekhanoshin return LIS->getInstructionIndex(*C.first) < I; 324c29d4915SStanislav Mekhanoshin }); 325c29d4915SStanislav Mekhanoshin for (auto E = Candidates.end(); Success && I != E && 326c29d4915SStanislav Mekhanoshin LIS->getInstructionIndex(*I->first) < MaxInd; ++I) { 327c29d4915SStanislav Mekhanoshin if (I->second && CheckNSA(*I->first, true) < NSA_Status::CONTIGUOUS) { 328c29d4915SStanislav Mekhanoshin Success = false; 329c29d4915SStanislav Mekhanoshin LLVM_DEBUG(dbgs() << "\tNSA conversion conflict with " << *I->first); 330c29d4915SStanislav Mekhanoshin } 331c29d4915SStanislav Mekhanoshin } 332c29d4915SStanislav Mekhanoshin } 333c29d4915SStanislav Mekhanoshin 334c29d4915SStanislav Mekhanoshin if (!Success) { 335c29d4915SStanislav Mekhanoshin for (unsigned I = 0; I < Info->VAddrDwords; ++I) 3366e85c3d5SMircea Trofin if (VRM->hasPhys(Intervals[I]->reg())) 337c29d4915SStanislav Mekhanoshin LRM->unassign(*Intervals[I]); 338c29d4915SStanislav Mekhanoshin 339c29d4915SStanislav Mekhanoshin for (unsigned I = 0; I < Info->VAddrDwords; ++I) 340c29d4915SStanislav Mekhanoshin LRM->assign(*Intervals[I], OrigRegs[I]); 341c29d4915SStanislav Mekhanoshin 342c29d4915SStanislav Mekhanoshin continue; 343c29d4915SStanislav Mekhanoshin } 344c29d4915SStanislav Mekhanoshin 345c29d4915SStanislav Mekhanoshin C.second = true; 346c29d4915SStanislav Mekhanoshin ++NumNSAConverted; 3476e85c3d5SMircea Trofin LLVM_DEBUG( 3486e85c3d5SMircea Trofin dbgs() << "\tNew allocation:\t\t [" 3496e85c3d5SMircea Trofin << llvm::printReg((VRM->getPhys(Intervals.front()->reg())), TRI) 350c29d4915SStanislav Mekhanoshin << " : " 3516e85c3d5SMircea Trofin << llvm::printReg((VRM->getPhys(Intervals.back()->reg())), TRI) 352c29d4915SStanislav Mekhanoshin << "]\n"); 353c29d4915SStanislav Mekhanoshin Changed = true; 354c29d4915SStanislav Mekhanoshin } 355c29d4915SStanislav Mekhanoshin 356c29d4915SStanislav Mekhanoshin return Changed; 357c29d4915SStanislav Mekhanoshin } 358