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