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