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