xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/GCNNSAReassign.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
181ad6265SDimitry Andric //===-- GCNNSAReassign.cpp - Reassign registers in NSA instructions -------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// \brief Try to reassign registers on GFX10+ from non-sequential to sequential
1181ad6265SDimitry Andric /// in NSA image instructions. Later SIShrinkInstructions pass will replace NSA
120b57cec5SDimitry Andric /// with sequential versions where possible.
130b57cec5SDimitry Andric ///
140b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "AMDGPU.h"
17e8d8bef9SDimitry Andric #include "GCNSubtarget.h"
180b57cec5SDimitry Andric #include "SIMachineFunctionInfo.h"
1981ad6265SDimitry Andric #include "SIRegisterInfo.h"
200b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/LiveRegMatrix.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
2481ad6265SDimitry Andric #include "llvm/CodeGen/VirtRegMap.h"
25480093f4SDimitry Andric #include "llvm/InitializePasses.h"
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric using namespace llvm;
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric #define DEBUG_TYPE "amdgpu-nsa-reassign"
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric STATISTIC(NumNSAInstructions,
320b57cec5SDimitry Andric           "Number of NSA instructions with non-sequential address found");
330b57cec5SDimitry Andric STATISTIC(NumNSAConverted,
340b57cec5SDimitry Andric           "Number of NSA instructions changed to sequential");
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric namespace {
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric class GCNNSAReassign : public MachineFunctionPass {
390b57cec5SDimitry Andric public:
400b57cec5SDimitry Andric   static char ID;
410b57cec5SDimitry Andric 
GCNNSAReassign()420b57cec5SDimitry Andric   GCNNSAReassign() : MachineFunctionPass(ID) {
430b57cec5SDimitry Andric     initializeGCNNSAReassignPass(*PassRegistry::getPassRegistry());
440b57cec5SDimitry Andric   }
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
470b57cec5SDimitry Andric 
getPassName() const480b57cec5SDimitry Andric   StringRef getPassName() const override { return "GCN NSA Reassign"; }
490b57cec5SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const500b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
51*0fca6ea1SDimitry Andric     AU.addRequired<LiveIntervalsWrapperPass>();
520b57cec5SDimitry Andric     AU.addRequired<VirtRegMap>();
530b57cec5SDimitry Andric     AU.addRequired<LiveRegMatrix>();
540b57cec5SDimitry Andric     AU.setPreservesAll();
550b57cec5SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
560b57cec5SDimitry Andric   }
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric private:
59*0fca6ea1SDimitry Andric   using NSA_Status = enum {
600b57cec5SDimitry Andric     NOT_NSA,        // Not an NSA instruction
610b57cec5SDimitry Andric     FIXED,          // NSA which we cannot modify
620b57cec5SDimitry Andric     NON_CONTIGUOUS, // NSA with non-sequential address which we can try
630b57cec5SDimitry Andric                     // to optimize.
640b57cec5SDimitry Andric     CONTIGUOUS      // NSA with all sequential address registers
65*0fca6ea1SDimitry Andric   };
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric   const GCNSubtarget *ST;
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   const MachineRegisterInfo *MRI;
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   const SIRegisterInfo *TRI;
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   VirtRegMap *VRM;
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   LiveRegMatrix *LRM;
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   LiveIntervals *LIS;
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   unsigned MaxNumVGPRs;
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   const MCPhysReg *CSRegs;
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   NSA_Status CheckNSA(const MachineInstr &MI, bool Fast = false) const;
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   bool tryAssignRegisters(SmallVectorImpl<LiveInterval *> &Intervals,
860b57cec5SDimitry Andric                           unsigned StartReg) const;
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   bool canAssign(unsigned StartReg, unsigned NumRegs) const;
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   bool scavengeRegs(SmallVectorImpl<LiveInterval *> &Intervals) const;
910b57cec5SDimitry Andric };
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric } // End anonymous namespace.
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(GCNNSAReassign, DEBUG_TYPE, "GCN NSA Reassign",
960b57cec5SDimitry Andric                       false, false)
97*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LiveIntervalsWrapperPass)
980b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(VirtRegMap)
990b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LiveRegMatrix)
1000b57cec5SDimitry Andric INITIALIZE_PASS_END(GCNNSAReassign, DEBUG_TYPE, "GCN NSA Reassign",
1010b57cec5SDimitry Andric                     false, false)
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric char GCNNSAReassign::ID = 0;
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric char &llvm::GCNNSAReassignID = GCNNSAReassign::ID;
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric bool
tryAssignRegisters(SmallVectorImpl<LiveInterval * > & Intervals,unsigned StartReg) const1090b57cec5SDimitry Andric GCNNSAReassign::tryAssignRegisters(SmallVectorImpl<LiveInterval *> &Intervals,
1100b57cec5SDimitry Andric                                    unsigned StartReg) const {
1110b57cec5SDimitry Andric   unsigned NumRegs = Intervals.size();
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   for (unsigned N = 0; N < NumRegs; ++N)
114e8d8bef9SDimitry Andric     if (VRM->hasPhys(Intervals[N]->reg()))
1150b57cec5SDimitry Andric       LRM->unassign(*Intervals[N]);
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   for (unsigned N = 0; N < NumRegs; ++N)
118e8d8bef9SDimitry Andric     if (LRM->checkInterference(*Intervals[N], MCRegister::from(StartReg + N)))
1190b57cec5SDimitry Andric       return false;
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   for (unsigned N = 0; N < NumRegs; ++N)
122e8d8bef9SDimitry Andric     LRM->assign(*Intervals[N], MCRegister::from(StartReg + N));
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   return true;
1250b57cec5SDimitry Andric }
1260b57cec5SDimitry Andric 
canAssign(unsigned StartReg,unsigned NumRegs) const1270b57cec5SDimitry Andric bool GCNNSAReassign::canAssign(unsigned StartReg, unsigned NumRegs) const {
1280b57cec5SDimitry Andric   for (unsigned N = 0; N < NumRegs; ++N) {
1290b57cec5SDimitry Andric     unsigned Reg = StartReg + N;
1300b57cec5SDimitry Andric     if (!MRI->isAllocatable(Reg))
1310b57cec5SDimitry Andric       return false;
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric     for (unsigned I = 0; CSRegs[I]; ++I)
1340b57cec5SDimitry Andric       if (TRI->isSubRegisterEq(Reg, CSRegs[I]) &&
1350b57cec5SDimitry Andric           !LRM->isPhysRegUsed(CSRegs[I]))
1360b57cec5SDimitry Andric       return false;
1370b57cec5SDimitry Andric   }
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   return true;
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric bool
scavengeRegs(SmallVectorImpl<LiveInterval * > & Intervals) const1430b57cec5SDimitry Andric GCNNSAReassign::scavengeRegs(SmallVectorImpl<LiveInterval *> &Intervals) const {
1440b57cec5SDimitry Andric   unsigned NumRegs = Intervals.size();
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric   if (NumRegs > MaxNumVGPRs)
1470b57cec5SDimitry Andric     return false;
1480b57cec5SDimitry Andric   unsigned MaxReg = MaxNumVGPRs - NumRegs + AMDGPU::VGPR0;
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric   for (unsigned Reg = AMDGPU::VGPR0; Reg <= MaxReg; ++Reg) {
1510b57cec5SDimitry Andric     if (!canAssign(Reg, NumRegs))
1520b57cec5SDimitry Andric       continue;
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric     if (tryAssignRegisters(Intervals, Reg))
1550b57cec5SDimitry Andric       return true;
1560b57cec5SDimitry Andric   }
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   return false;
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric GCNNSAReassign::NSA_Status
CheckNSA(const MachineInstr & MI,bool Fast) const1620b57cec5SDimitry Andric GCNNSAReassign::CheckNSA(const MachineInstr &MI, bool Fast) const {
1630b57cec5SDimitry Andric   const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(MI.getOpcode());
16481ad6265SDimitry Andric   if (!Info)
1650b57cec5SDimitry Andric     return NSA_Status::NOT_NSA;
1660b57cec5SDimitry Andric 
16781ad6265SDimitry Andric   switch (Info->MIMGEncoding) {
16881ad6265SDimitry Andric   case AMDGPU::MIMGEncGfx10NSA:
16981ad6265SDimitry Andric   case AMDGPU::MIMGEncGfx11NSA:
17081ad6265SDimitry Andric     break;
17181ad6265SDimitry Andric   default:
17281ad6265SDimitry Andric     return NSA_Status::NOT_NSA;
17381ad6265SDimitry Andric   }
17481ad6265SDimitry Andric 
1750b57cec5SDimitry Andric   int VAddr0Idx =
1760b57cec5SDimitry Andric     AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vaddr0);
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric   unsigned VgprBase = 0;
1790b57cec5SDimitry Andric   bool NSA = false;
18081ad6265SDimitry Andric   for (unsigned I = 0; I < Info->VAddrOperands; ++I) {
1810b57cec5SDimitry Andric     const MachineOperand &Op = MI.getOperand(VAddr0Idx + I);
1828bcb0991SDimitry Andric     Register Reg = Op.getReg();
183e8d8bef9SDimitry Andric     if (Reg.isPhysical() || !VRM->isAssignedReg(Reg))
1840b57cec5SDimitry Andric       return NSA_Status::FIXED;
1850b57cec5SDimitry Andric 
1868bcb0991SDimitry Andric     Register PhysReg = VRM->getPhys(Reg);
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric     if (!Fast) {
1890b57cec5SDimitry Andric       if (!PhysReg)
1900b57cec5SDimitry Andric         return NSA_Status::FIXED;
1910b57cec5SDimitry Andric 
19281ad6265SDimitry Andric       // TODO: address the below limitation to handle GFX11 BVH instructions
1930b57cec5SDimitry Andric       // Bail if address is not a VGPR32. That should be possible to extend the
1940b57cec5SDimitry Andric       // optimization to work with subregs of a wider register tuples, but the
1950b57cec5SDimitry Andric       // logic to find free registers will be much more complicated with much
1960b57cec5SDimitry Andric       // less chances for success. That seems reasonable to assume that in most
1970b57cec5SDimitry Andric       // cases a tuple is used because a vector variable contains different
19881ad6265SDimitry Andric       // parts of an address and it is either already consecutive or cannot
1990b57cec5SDimitry Andric       // be reassigned if not. If needed it is better to rely on register
2000b57cec5SDimitry Andric       // coalescer to process such address tuples.
20181ad6265SDimitry Andric       if (TRI->getRegSizeInBits(*MRI->getRegClass(Reg)) != 32 || Op.getSubReg())
2020b57cec5SDimitry Andric         return NSA_Status::FIXED;
2030b57cec5SDimitry Andric 
204fe6060f1SDimitry Andric       // InlineSpiller does not call LRM::assign() after an LI split leaving
205fe6060f1SDimitry Andric       // it in an inconsistent state, so we cannot call LRM::unassign().
206fe6060f1SDimitry Andric       // See llvm bug #48911.
207fe6060f1SDimitry Andric       // Skip reassign if a register has originated from such split.
208fe6060f1SDimitry Andric       // FIXME: Remove the workaround when bug #48911 is fixed.
209fe6060f1SDimitry Andric       if (VRM->getPreSplitReg(Reg))
210fe6060f1SDimitry Andric         return NSA_Status::FIXED;
211fe6060f1SDimitry Andric 
2120b57cec5SDimitry Andric       const MachineInstr *Def = MRI->getUniqueVRegDef(Reg);
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric       if (Def && Def->isCopy() && Def->getOperand(1).getReg() == PhysReg)
2150b57cec5SDimitry Andric         return NSA_Status::FIXED;
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric       for (auto U : MRI->use_nodbg_operands(Reg)) {
2180b57cec5SDimitry Andric         if (U.isImplicit())
2190b57cec5SDimitry Andric           return NSA_Status::FIXED;
2200b57cec5SDimitry Andric         const MachineInstr *UseInst = U.getParent();
2210b57cec5SDimitry Andric         if (UseInst->isCopy() && UseInst->getOperand(0).getReg() == PhysReg)
2220b57cec5SDimitry Andric           return NSA_Status::FIXED;
2230b57cec5SDimitry Andric       }
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric       if (!LIS->hasInterval(Reg))
2260b57cec5SDimitry Andric         return NSA_Status::FIXED;
2270b57cec5SDimitry Andric     }
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric     if (I == 0)
2300b57cec5SDimitry Andric       VgprBase = PhysReg;
2310b57cec5SDimitry Andric     else if (VgprBase + I != PhysReg)
2320b57cec5SDimitry Andric       NSA = true;
2330b57cec5SDimitry Andric   }
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   return NSA ? NSA_Status::NON_CONTIGUOUS : NSA_Status::CONTIGUOUS;
2360b57cec5SDimitry Andric }
2370b57cec5SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)2380b57cec5SDimitry Andric bool GCNNSAReassign::runOnMachineFunction(MachineFunction &MF) {
2390b57cec5SDimitry Andric   ST = &MF.getSubtarget<GCNSubtarget>();
2407a6dacacSDimitry Andric   if (!ST->hasNSAEncoding() || !ST->hasNonNSAEncoding())
2410b57cec5SDimitry Andric     return false;
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
2440b57cec5SDimitry Andric   TRI = ST->getRegisterInfo();
2450b57cec5SDimitry Andric   VRM = &getAnalysis<VirtRegMap>();
2460b57cec5SDimitry Andric   LRM = &getAnalysis<LiveRegMatrix>();
247*0fca6ea1SDimitry Andric   LIS = &getAnalysis<LiveIntervalsWrapperPass>().getLIS();
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric   const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
2500b57cec5SDimitry Andric   MaxNumVGPRs = ST->getMaxNumVGPRs(MF);
2510b57cec5SDimitry Andric   MaxNumVGPRs = std::min(ST->getMaxNumVGPRs(MFI->getOccupancy()), MaxNumVGPRs);
2520b57cec5SDimitry Andric   CSRegs = MRI->getCalleeSavedRegs();
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric   using Candidate = std::pair<const MachineInstr*, bool>;
2550b57cec5SDimitry Andric   SmallVector<Candidate, 32> Candidates;
2560b57cec5SDimitry Andric   for (const MachineBasicBlock &MBB : MF) {
2570b57cec5SDimitry Andric     for (const MachineInstr &MI : MBB) {
2580b57cec5SDimitry Andric       switch (CheckNSA(MI)) {
2590b57cec5SDimitry Andric       default:
2600b57cec5SDimitry Andric         continue;
2610b57cec5SDimitry Andric       case NSA_Status::CONTIGUOUS:
262bdd1243dSDimitry Andric         Candidates.push_back(std::pair(&MI, true));
2630b57cec5SDimitry Andric         break;
2640b57cec5SDimitry Andric       case NSA_Status::NON_CONTIGUOUS:
265bdd1243dSDimitry Andric         Candidates.push_back(std::pair(&MI, false));
2660b57cec5SDimitry Andric         ++NumNSAInstructions;
2670b57cec5SDimitry Andric         break;
2680b57cec5SDimitry Andric       }
2690b57cec5SDimitry Andric     }
2700b57cec5SDimitry Andric   }
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric   bool Changed = false;
2730b57cec5SDimitry Andric   for (auto &C : Candidates) {
2740b57cec5SDimitry Andric     if (C.second)
2750b57cec5SDimitry Andric       continue;
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric     const MachineInstr *MI = C.first;
2780b57cec5SDimitry Andric     if (CheckNSA(*MI, true) == NSA_Status::CONTIGUOUS) {
2790b57cec5SDimitry Andric       // Already happen to be fixed.
2800b57cec5SDimitry Andric       C.second = true;
2810b57cec5SDimitry Andric       ++NumNSAConverted;
2820b57cec5SDimitry Andric       continue;
2830b57cec5SDimitry Andric     }
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric     const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(MI->getOpcode());
2860b57cec5SDimitry Andric     int VAddr0Idx =
2870b57cec5SDimitry Andric       AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::vaddr0);
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric     SmallVector<LiveInterval *, 16> Intervals;
290e8d8bef9SDimitry Andric     SmallVector<MCRegister, 16> OrigRegs;
2910b57cec5SDimitry Andric     SlotIndex MinInd, MaxInd;
29281ad6265SDimitry Andric     for (unsigned I = 0; I < Info->VAddrOperands; ++I) {
2930b57cec5SDimitry Andric       const MachineOperand &Op = MI->getOperand(VAddr0Idx + I);
2948bcb0991SDimitry Andric       Register Reg = Op.getReg();
2950b57cec5SDimitry Andric       LiveInterval *LI = &LIS->getInterval(Reg);
296e8d8bef9SDimitry Andric       if (llvm::is_contained(Intervals, LI)) {
2970b57cec5SDimitry Andric         // Same register used, unable to make sequential
2980b57cec5SDimitry Andric         Intervals.clear();
2990b57cec5SDimitry Andric         break;
3000b57cec5SDimitry Andric       }
3010b57cec5SDimitry Andric       Intervals.push_back(LI);
3020b57cec5SDimitry Andric       OrigRegs.push_back(VRM->getPhys(Reg));
3035ffd83dbSDimitry Andric       if (LI->empty()) {
3045ffd83dbSDimitry Andric         // The address input is undef, so it doesn't contribute to the relevant
3055ffd83dbSDimitry Andric         // range. Seed a reasonable index range if required.
3065ffd83dbSDimitry Andric         if (I == 0)
3075ffd83dbSDimitry Andric           MinInd = MaxInd = LIS->getInstructionIndex(*MI);
3085ffd83dbSDimitry Andric         continue;
3095ffd83dbSDimitry Andric       }
3105ffd83dbSDimitry Andric       MinInd = I != 0 ? std::min(MinInd, LI->beginIndex()) : LI->beginIndex();
3115ffd83dbSDimitry Andric       MaxInd = I != 0 ? std::max(MaxInd, LI->endIndex()) : LI->endIndex();
3120b57cec5SDimitry Andric     }
3130b57cec5SDimitry Andric 
3140b57cec5SDimitry Andric     if (Intervals.empty())
3150b57cec5SDimitry Andric       continue;
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Attempting to reassign NSA: " << *MI
3180b57cec5SDimitry Andric                       << "\tOriginal allocation:\t";
319e8d8bef9SDimitry Andric                for (auto *LI
320e8d8bef9SDimitry Andric                     : Intervals) dbgs()
321e8d8bef9SDimitry Andric                << " " << llvm::printReg((VRM->getPhys(LI->reg())), TRI);
3220b57cec5SDimitry Andric                dbgs() << '\n');
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric     bool Success = scavengeRegs(Intervals);
3250b57cec5SDimitry Andric     if (!Success) {
3260b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "\tCannot reallocate.\n");
327e8d8bef9SDimitry Andric       if (VRM->hasPhys(Intervals.back()->reg())) // Did not change allocation.
3280b57cec5SDimitry Andric         continue;
3290b57cec5SDimitry Andric     } else {
3300b57cec5SDimitry Andric       // Check we did not make it worse for other instructions.
3310b57cec5SDimitry Andric       auto I = std::lower_bound(Candidates.begin(), &C, MinInd,
3320b57cec5SDimitry Andric                                 [this](const Candidate &C, SlotIndex I) {
3330b57cec5SDimitry Andric                                   return LIS->getInstructionIndex(*C.first) < I;
3340b57cec5SDimitry Andric                                 });
3350b57cec5SDimitry Andric       for (auto E = Candidates.end(); Success && I != E &&
3360b57cec5SDimitry Andric               LIS->getInstructionIndex(*I->first) < MaxInd; ++I) {
3370b57cec5SDimitry Andric         if (I->second && CheckNSA(*I->first, true) < NSA_Status::CONTIGUOUS) {
3380b57cec5SDimitry Andric           Success = false;
3390b57cec5SDimitry Andric           LLVM_DEBUG(dbgs() << "\tNSA conversion conflict with " << *I->first);
3400b57cec5SDimitry Andric         }
3410b57cec5SDimitry Andric       }
3420b57cec5SDimitry Andric     }
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric     if (!Success) {
34581ad6265SDimitry Andric       for (unsigned I = 0; I < Info->VAddrOperands; ++I)
346e8d8bef9SDimitry Andric         if (VRM->hasPhys(Intervals[I]->reg()))
3470b57cec5SDimitry Andric           LRM->unassign(*Intervals[I]);
3480b57cec5SDimitry Andric 
34981ad6265SDimitry Andric       for (unsigned I = 0; I < Info->VAddrOperands; ++I)
3500b57cec5SDimitry Andric         LRM->assign(*Intervals[I], OrigRegs[I]);
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric       continue;
3530b57cec5SDimitry Andric     }
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric     C.second = true;
3560b57cec5SDimitry Andric     ++NumNSAConverted;
357e8d8bef9SDimitry Andric     LLVM_DEBUG(
358e8d8bef9SDimitry Andric         dbgs() << "\tNew allocation:\t\t ["
359e8d8bef9SDimitry Andric                << llvm::printReg((VRM->getPhys(Intervals.front()->reg())), TRI)
3600b57cec5SDimitry Andric                << " : "
361e8d8bef9SDimitry Andric                << llvm::printReg((VRM->getPhys(Intervals.back()->reg())), TRI)
3620b57cec5SDimitry Andric                << "]\n");
3630b57cec5SDimitry Andric     Changed = true;
3640b57cec5SDimitry Andric   }
3650b57cec5SDimitry Andric 
3660b57cec5SDimitry Andric   return Changed;
3670b57cec5SDimitry Andric }
368