xref: /aosp_15_r20/external/llvm/lib/Target/AMDGPU/SIFixSGPRCopies.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- SIFixSGPRCopies.cpp - Remove potential VGPR => SGPR copies --------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker /// \file
11*9880d681SAndroid Build Coastguard Worker /// Copies from VGPR to SGPR registers are illegal and the register coalescer
12*9880d681SAndroid Build Coastguard Worker /// will sometimes generate these illegal copies in situations like this:
13*9880d681SAndroid Build Coastguard Worker ///
14*9880d681SAndroid Build Coastguard Worker ///  Register Class <vsrc> is the union of <vgpr> and <sgpr>
15*9880d681SAndroid Build Coastguard Worker ///
16*9880d681SAndroid Build Coastguard Worker /// BB0:
17*9880d681SAndroid Build Coastguard Worker ///   %vreg0 <sgpr> = SCALAR_INST
18*9880d681SAndroid Build Coastguard Worker ///   %vreg1 <vsrc> = COPY %vreg0 <sgpr>
19*9880d681SAndroid Build Coastguard Worker ///    ...
20*9880d681SAndroid Build Coastguard Worker ///    BRANCH %cond BB1, BB2
21*9880d681SAndroid Build Coastguard Worker ///  BB1:
22*9880d681SAndroid Build Coastguard Worker ///    %vreg2 <vgpr> = VECTOR_INST
23*9880d681SAndroid Build Coastguard Worker ///    %vreg3 <vsrc> = COPY %vreg2 <vgpr>
24*9880d681SAndroid Build Coastguard Worker ///  BB2:
25*9880d681SAndroid Build Coastguard Worker ///    %vreg4 <vsrc> = PHI %vreg1 <vsrc>, <BB#0>, %vreg3 <vrsc>, <BB#1>
26*9880d681SAndroid Build Coastguard Worker ///    %vreg5 <vgpr> = VECTOR_INST %vreg4 <vsrc>
27*9880d681SAndroid Build Coastguard Worker ///
28*9880d681SAndroid Build Coastguard Worker ///
29*9880d681SAndroid Build Coastguard Worker /// The coalescer will begin at BB0 and eliminate its copy, then the resulting
30*9880d681SAndroid Build Coastguard Worker /// code will look like this:
31*9880d681SAndroid Build Coastguard Worker ///
32*9880d681SAndroid Build Coastguard Worker /// BB0:
33*9880d681SAndroid Build Coastguard Worker ///   %vreg0 <sgpr> = SCALAR_INST
34*9880d681SAndroid Build Coastguard Worker ///    ...
35*9880d681SAndroid Build Coastguard Worker ///    BRANCH %cond BB1, BB2
36*9880d681SAndroid Build Coastguard Worker /// BB1:
37*9880d681SAndroid Build Coastguard Worker ///   %vreg2 <vgpr> = VECTOR_INST
38*9880d681SAndroid Build Coastguard Worker ///   %vreg3 <vsrc> = COPY %vreg2 <vgpr>
39*9880d681SAndroid Build Coastguard Worker /// BB2:
40*9880d681SAndroid Build Coastguard Worker ///   %vreg4 <sgpr> = PHI %vreg0 <sgpr>, <BB#0>, %vreg3 <vsrc>, <BB#1>
41*9880d681SAndroid Build Coastguard Worker ///   %vreg5 <vgpr> = VECTOR_INST %vreg4 <sgpr>
42*9880d681SAndroid Build Coastguard Worker ///
43*9880d681SAndroid Build Coastguard Worker /// Now that the result of the PHI instruction is an SGPR, the register
44*9880d681SAndroid Build Coastguard Worker /// allocator is now forced to constrain the register class of %vreg3 to
45*9880d681SAndroid Build Coastguard Worker /// <sgpr> so we end up with final code like this:
46*9880d681SAndroid Build Coastguard Worker ///
47*9880d681SAndroid Build Coastguard Worker /// BB0:
48*9880d681SAndroid Build Coastguard Worker ///   %vreg0 <sgpr> = SCALAR_INST
49*9880d681SAndroid Build Coastguard Worker ///    ...
50*9880d681SAndroid Build Coastguard Worker ///    BRANCH %cond BB1, BB2
51*9880d681SAndroid Build Coastguard Worker /// BB1:
52*9880d681SAndroid Build Coastguard Worker ///   %vreg2 <vgpr> = VECTOR_INST
53*9880d681SAndroid Build Coastguard Worker ///   %vreg3 <sgpr> = COPY %vreg2 <vgpr>
54*9880d681SAndroid Build Coastguard Worker /// BB2:
55*9880d681SAndroid Build Coastguard Worker ///   %vreg4 <sgpr> = PHI %vreg0 <sgpr>, <BB#0>, %vreg3 <sgpr>, <BB#1>
56*9880d681SAndroid Build Coastguard Worker ///   %vreg5 <vgpr> = VECTOR_INST %vreg4 <sgpr>
57*9880d681SAndroid Build Coastguard Worker ///
58*9880d681SAndroid Build Coastguard Worker /// Now this code contains an illegal copy from a VGPR to an SGPR.
59*9880d681SAndroid Build Coastguard Worker ///
60*9880d681SAndroid Build Coastguard Worker /// In order to avoid this problem, this pass searches for PHI instructions
61*9880d681SAndroid Build Coastguard Worker /// which define a <vsrc> register and constrains its definition class to
62*9880d681SAndroid Build Coastguard Worker /// <vgpr> if the user of the PHI's definition register is a vector instruction.
63*9880d681SAndroid Build Coastguard Worker /// If the PHI's definition class is constrained to <vgpr> then the coalescer
64*9880d681SAndroid Build Coastguard Worker /// will be unable to perform the COPY removal from the above example  which
65*9880d681SAndroid Build Coastguard Worker /// ultimately led to the creation of an illegal COPY.
66*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
67*9880d681SAndroid Build Coastguard Worker 
68*9880d681SAndroid Build Coastguard Worker #include "AMDGPU.h"
69*9880d681SAndroid Build Coastguard Worker #include "AMDGPUSubtarget.h"
70*9880d681SAndroid Build Coastguard Worker #include "SIInstrInfo.h"
71*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
72*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
73*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
74*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
75*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
76*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetMachine.h"
77*9880d681SAndroid Build Coastguard Worker 
78*9880d681SAndroid Build Coastguard Worker using namespace llvm;
79*9880d681SAndroid Build Coastguard Worker 
80*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "si-fix-sgpr-copies"
81*9880d681SAndroid Build Coastguard Worker 
82*9880d681SAndroid Build Coastguard Worker namespace {
83*9880d681SAndroid Build Coastguard Worker 
84*9880d681SAndroid Build Coastguard Worker class SIFixSGPRCopies : public MachineFunctionPass {
85*9880d681SAndroid Build Coastguard Worker public:
86*9880d681SAndroid Build Coastguard Worker   static char ID;
87*9880d681SAndroid Build Coastguard Worker 
SIFixSGPRCopies()88*9880d681SAndroid Build Coastguard Worker   SIFixSGPRCopies() : MachineFunctionPass(ID) { }
89*9880d681SAndroid Build Coastguard Worker 
90*9880d681SAndroid Build Coastguard Worker   bool runOnMachineFunction(MachineFunction &MF) override;
91*9880d681SAndroid Build Coastguard Worker 
getPassName() const92*9880d681SAndroid Build Coastguard Worker   const char *getPassName() const override {
93*9880d681SAndroid Build Coastguard Worker     return "SI Fix SGPR copies";
94*9880d681SAndroid Build Coastguard Worker   }
95*9880d681SAndroid Build Coastguard Worker 
getAnalysisUsage(AnalysisUsage & AU) const96*9880d681SAndroid Build Coastguard Worker   void getAnalysisUsage(AnalysisUsage &AU) const override {
97*9880d681SAndroid Build Coastguard Worker     AU.setPreservesCFG();
98*9880d681SAndroid Build Coastguard Worker     MachineFunctionPass::getAnalysisUsage(AU);
99*9880d681SAndroid Build Coastguard Worker   }
100*9880d681SAndroid Build Coastguard Worker };
101*9880d681SAndroid Build Coastguard Worker 
102*9880d681SAndroid Build Coastguard Worker } // End anonymous namespace
103*9880d681SAndroid Build Coastguard Worker 
104*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(SIFixSGPRCopies, DEBUG_TYPE,
105*9880d681SAndroid Build Coastguard Worker                 "SI Fix SGPR copies", false, false)
106*9880d681SAndroid Build Coastguard Worker 
107*9880d681SAndroid Build Coastguard Worker char SIFixSGPRCopies::ID = 0;
108*9880d681SAndroid Build Coastguard Worker 
109*9880d681SAndroid Build Coastguard Worker char &llvm::SIFixSGPRCopiesID = SIFixSGPRCopies::ID;
110*9880d681SAndroid Build Coastguard Worker 
createSIFixSGPRCopiesPass()111*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createSIFixSGPRCopiesPass() {
112*9880d681SAndroid Build Coastguard Worker   return new SIFixSGPRCopies();
113*9880d681SAndroid Build Coastguard Worker }
114*9880d681SAndroid Build Coastguard Worker 
hasVGPROperands(const MachineInstr & MI,const SIRegisterInfo * TRI)115*9880d681SAndroid Build Coastguard Worker static bool hasVGPROperands(const MachineInstr &MI, const SIRegisterInfo *TRI) {
116*9880d681SAndroid Build Coastguard Worker   const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
117*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
118*9880d681SAndroid Build Coastguard Worker     if (!MI.getOperand(i).isReg() ||
119*9880d681SAndroid Build Coastguard Worker         !TargetRegisterInfo::isVirtualRegister(MI.getOperand(i).getReg()))
120*9880d681SAndroid Build Coastguard Worker       continue;
121*9880d681SAndroid Build Coastguard Worker 
122*9880d681SAndroid Build Coastguard Worker     if (TRI->hasVGPRs(MRI.getRegClass(MI.getOperand(i).getReg())))
123*9880d681SAndroid Build Coastguard Worker       return true;
124*9880d681SAndroid Build Coastguard Worker   }
125*9880d681SAndroid Build Coastguard Worker   return false;
126*9880d681SAndroid Build Coastguard Worker }
127*9880d681SAndroid Build Coastguard Worker 
128*9880d681SAndroid Build Coastguard Worker static std::pair<const TargetRegisterClass *, const TargetRegisterClass *>
getCopyRegClasses(const MachineInstr & Copy,const SIRegisterInfo & TRI,const MachineRegisterInfo & MRI)129*9880d681SAndroid Build Coastguard Worker getCopyRegClasses(const MachineInstr &Copy,
130*9880d681SAndroid Build Coastguard Worker                   const SIRegisterInfo &TRI,
131*9880d681SAndroid Build Coastguard Worker                   const MachineRegisterInfo &MRI) {
132*9880d681SAndroid Build Coastguard Worker   unsigned DstReg = Copy.getOperand(0).getReg();
133*9880d681SAndroid Build Coastguard Worker   unsigned SrcReg = Copy.getOperand(1).getReg();
134*9880d681SAndroid Build Coastguard Worker 
135*9880d681SAndroid Build Coastguard Worker   const TargetRegisterClass *SrcRC =
136*9880d681SAndroid Build Coastguard Worker     TargetRegisterInfo::isVirtualRegister(SrcReg) ?
137*9880d681SAndroid Build Coastguard Worker     MRI.getRegClass(SrcReg) :
138*9880d681SAndroid Build Coastguard Worker     TRI.getPhysRegClass(SrcReg);
139*9880d681SAndroid Build Coastguard Worker 
140*9880d681SAndroid Build Coastguard Worker   // We don't really care about the subregister here.
141*9880d681SAndroid Build Coastguard Worker   // SrcRC = TRI.getSubRegClass(SrcRC, Copy.getOperand(1).getSubReg());
142*9880d681SAndroid Build Coastguard Worker 
143*9880d681SAndroid Build Coastguard Worker   const TargetRegisterClass *DstRC =
144*9880d681SAndroid Build Coastguard Worker     TargetRegisterInfo::isVirtualRegister(DstReg) ?
145*9880d681SAndroid Build Coastguard Worker     MRI.getRegClass(DstReg) :
146*9880d681SAndroid Build Coastguard Worker     TRI.getPhysRegClass(DstReg);
147*9880d681SAndroid Build Coastguard Worker 
148*9880d681SAndroid Build Coastguard Worker   return std::make_pair(SrcRC, DstRC);
149*9880d681SAndroid Build Coastguard Worker }
150*9880d681SAndroid Build Coastguard Worker 
isVGPRToSGPRCopy(const TargetRegisterClass * SrcRC,const TargetRegisterClass * DstRC,const SIRegisterInfo & TRI)151*9880d681SAndroid Build Coastguard Worker static bool isVGPRToSGPRCopy(const TargetRegisterClass *SrcRC,
152*9880d681SAndroid Build Coastguard Worker                              const TargetRegisterClass *DstRC,
153*9880d681SAndroid Build Coastguard Worker                              const SIRegisterInfo &TRI) {
154*9880d681SAndroid Build Coastguard Worker   return TRI.isSGPRClass(DstRC) && TRI.hasVGPRs(SrcRC);
155*9880d681SAndroid Build Coastguard Worker }
156*9880d681SAndroid Build Coastguard Worker 
isSGPRToVGPRCopy(const TargetRegisterClass * SrcRC,const TargetRegisterClass * DstRC,const SIRegisterInfo & TRI)157*9880d681SAndroid Build Coastguard Worker static bool isSGPRToVGPRCopy(const TargetRegisterClass *SrcRC,
158*9880d681SAndroid Build Coastguard Worker                              const TargetRegisterClass *DstRC,
159*9880d681SAndroid Build Coastguard Worker                              const SIRegisterInfo &TRI) {
160*9880d681SAndroid Build Coastguard Worker   return TRI.isSGPRClass(SrcRC) && TRI.hasVGPRs(DstRC);
161*9880d681SAndroid Build Coastguard Worker }
162*9880d681SAndroid Build Coastguard Worker 
163*9880d681SAndroid Build Coastguard Worker // Distribute an SGPR->VGPR copy of a REG_SEQUENCE into a VGPR REG_SEQUENCE.
164*9880d681SAndroid Build Coastguard Worker //
165*9880d681SAndroid Build Coastguard Worker // SGPRx = ...
166*9880d681SAndroid Build Coastguard Worker // SGPRy = REG_SEQUENCE SGPRx, sub0 ...
167*9880d681SAndroid Build Coastguard Worker // VGPRz = COPY SGPRy
168*9880d681SAndroid Build Coastguard Worker //
169*9880d681SAndroid Build Coastguard Worker // ==>
170*9880d681SAndroid Build Coastguard Worker //
171*9880d681SAndroid Build Coastguard Worker // VGPRx = COPY SGPRx
172*9880d681SAndroid Build Coastguard Worker // VGPRz = REG_SEQUENCE VGPRx, sub0
173*9880d681SAndroid Build Coastguard Worker //
174*9880d681SAndroid Build Coastguard Worker // This exposes immediate folding opportunities when materializing 64-bit
175*9880d681SAndroid Build Coastguard Worker // immediates.
foldVGPRCopyIntoRegSequence(MachineInstr & MI,const SIRegisterInfo * TRI,const SIInstrInfo * TII,MachineRegisterInfo & MRI)176*9880d681SAndroid Build Coastguard Worker static bool foldVGPRCopyIntoRegSequence(MachineInstr &MI,
177*9880d681SAndroid Build Coastguard Worker                                         const SIRegisterInfo *TRI,
178*9880d681SAndroid Build Coastguard Worker                                         const SIInstrInfo *TII,
179*9880d681SAndroid Build Coastguard Worker                                         MachineRegisterInfo &MRI) {
180*9880d681SAndroid Build Coastguard Worker   assert(MI.isRegSequence());
181*9880d681SAndroid Build Coastguard Worker 
182*9880d681SAndroid Build Coastguard Worker   unsigned DstReg = MI.getOperand(0).getReg();
183*9880d681SAndroid Build Coastguard Worker   if (!TRI->isSGPRClass(MRI.getRegClass(DstReg)))
184*9880d681SAndroid Build Coastguard Worker     return false;
185*9880d681SAndroid Build Coastguard Worker 
186*9880d681SAndroid Build Coastguard Worker   if (!MRI.hasOneUse(DstReg))
187*9880d681SAndroid Build Coastguard Worker     return false;
188*9880d681SAndroid Build Coastguard Worker 
189*9880d681SAndroid Build Coastguard Worker   MachineInstr &CopyUse = *MRI.use_instr_begin(DstReg);
190*9880d681SAndroid Build Coastguard Worker   if (!CopyUse.isCopy())
191*9880d681SAndroid Build Coastguard Worker     return false;
192*9880d681SAndroid Build Coastguard Worker 
193*9880d681SAndroid Build Coastguard Worker   const TargetRegisterClass *SrcRC, *DstRC;
194*9880d681SAndroid Build Coastguard Worker   std::tie(SrcRC, DstRC) = getCopyRegClasses(CopyUse, *TRI, MRI);
195*9880d681SAndroid Build Coastguard Worker 
196*9880d681SAndroid Build Coastguard Worker   if (!isSGPRToVGPRCopy(SrcRC, DstRC, *TRI))
197*9880d681SAndroid Build Coastguard Worker     return false;
198*9880d681SAndroid Build Coastguard Worker 
199*9880d681SAndroid Build Coastguard Worker   // TODO: Could have multiple extracts?
200*9880d681SAndroid Build Coastguard Worker   unsigned SubReg = CopyUse.getOperand(1).getSubReg();
201*9880d681SAndroid Build Coastguard Worker   if (SubReg != AMDGPU::NoSubRegister)
202*9880d681SAndroid Build Coastguard Worker     return false;
203*9880d681SAndroid Build Coastguard Worker 
204*9880d681SAndroid Build Coastguard Worker   MRI.setRegClass(DstReg, DstRC);
205*9880d681SAndroid Build Coastguard Worker 
206*9880d681SAndroid Build Coastguard Worker   // SGPRx = ...
207*9880d681SAndroid Build Coastguard Worker   // SGPRy = REG_SEQUENCE SGPRx, sub0 ...
208*9880d681SAndroid Build Coastguard Worker   // VGPRz = COPY SGPRy
209*9880d681SAndroid Build Coastguard Worker 
210*9880d681SAndroid Build Coastguard Worker   // =>
211*9880d681SAndroid Build Coastguard Worker   // VGPRx = COPY SGPRx
212*9880d681SAndroid Build Coastguard Worker   // VGPRz = REG_SEQUENCE VGPRx, sub0
213*9880d681SAndroid Build Coastguard Worker 
214*9880d681SAndroid Build Coastguard Worker   MI.getOperand(0).setReg(CopyUse.getOperand(0).getReg());
215*9880d681SAndroid Build Coastguard Worker 
216*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 1, N = MI.getNumOperands(); I != N; I += 2) {
217*9880d681SAndroid Build Coastguard Worker     unsigned SrcReg = MI.getOperand(I).getReg();
218*9880d681SAndroid Build Coastguard Worker     unsigned SrcSubReg = MI.getOperand(I).getSubReg();
219*9880d681SAndroid Build Coastguard Worker 
220*9880d681SAndroid Build Coastguard Worker     const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg);
221*9880d681SAndroid Build Coastguard Worker     assert(TRI->isSGPRClass(SrcRC) &&
222*9880d681SAndroid Build Coastguard Worker            "Expected SGPR REG_SEQUENCE to only have SGPR inputs");
223*9880d681SAndroid Build Coastguard Worker 
224*9880d681SAndroid Build Coastguard Worker     SrcRC = TRI->getSubRegClass(SrcRC, SrcSubReg);
225*9880d681SAndroid Build Coastguard Worker     const TargetRegisterClass *NewSrcRC = TRI->getEquivalentVGPRClass(SrcRC);
226*9880d681SAndroid Build Coastguard Worker 
227*9880d681SAndroid Build Coastguard Worker     unsigned TmpReg = MRI.createVirtualRegister(NewSrcRC);
228*9880d681SAndroid Build Coastguard Worker 
229*9880d681SAndroid Build Coastguard Worker     BuildMI(*MI.getParent(), &MI, MI.getDebugLoc(), TII->get(AMDGPU::COPY), TmpReg)
230*9880d681SAndroid Build Coastguard Worker       .addOperand(MI.getOperand(I));
231*9880d681SAndroid Build Coastguard Worker 
232*9880d681SAndroid Build Coastguard Worker     MI.getOperand(I).setReg(TmpReg);
233*9880d681SAndroid Build Coastguard Worker   }
234*9880d681SAndroid Build Coastguard Worker 
235*9880d681SAndroid Build Coastguard Worker   CopyUse.eraseFromParent();
236*9880d681SAndroid Build Coastguard Worker   return true;
237*9880d681SAndroid Build Coastguard Worker }
238*9880d681SAndroid Build Coastguard Worker 
runOnMachineFunction(MachineFunction & MF)239*9880d681SAndroid Build Coastguard Worker bool SIFixSGPRCopies::runOnMachineFunction(MachineFunction &MF) {
240*9880d681SAndroid Build Coastguard Worker   const SISubtarget &ST = MF.getSubtarget<SISubtarget>();
241*9880d681SAndroid Build Coastguard Worker   MachineRegisterInfo &MRI = MF.getRegInfo();
242*9880d681SAndroid Build Coastguard Worker   const SIRegisterInfo *TRI = ST.getRegisterInfo();
243*9880d681SAndroid Build Coastguard Worker   const SIInstrInfo *TII = ST.getInstrInfo();
244*9880d681SAndroid Build Coastguard Worker 
245*9880d681SAndroid Build Coastguard Worker   SmallVector<MachineInstr *, 16> Worklist;
246*9880d681SAndroid Build Coastguard Worker 
247*9880d681SAndroid Build Coastguard Worker   for (MachineFunction::iterator BI = MF.begin(), BE = MF.end();
248*9880d681SAndroid Build Coastguard Worker                                                   BI != BE; ++BI) {
249*9880d681SAndroid Build Coastguard Worker 
250*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock &MBB = *BI;
251*9880d681SAndroid Build Coastguard Worker     for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
252*9880d681SAndroid Build Coastguard Worker          I != E; ++I) {
253*9880d681SAndroid Build Coastguard Worker       MachineInstr &MI = *I;
254*9880d681SAndroid Build Coastguard Worker 
255*9880d681SAndroid Build Coastguard Worker       switch (MI.getOpcode()) {
256*9880d681SAndroid Build Coastguard Worker       default:
257*9880d681SAndroid Build Coastguard Worker         continue;
258*9880d681SAndroid Build Coastguard Worker       case AMDGPU::COPY: {
259*9880d681SAndroid Build Coastguard Worker         // If the destination register is a physical register there isn't really
260*9880d681SAndroid Build Coastguard Worker         // much we can do to fix this.
261*9880d681SAndroid Build Coastguard Worker         if (!TargetRegisterInfo::isVirtualRegister(MI.getOperand(0).getReg()))
262*9880d681SAndroid Build Coastguard Worker           continue;
263*9880d681SAndroid Build Coastguard Worker 
264*9880d681SAndroid Build Coastguard Worker         const TargetRegisterClass *SrcRC, *DstRC;
265*9880d681SAndroid Build Coastguard Worker         std::tie(SrcRC, DstRC) = getCopyRegClasses(MI, *TRI, MRI);
266*9880d681SAndroid Build Coastguard Worker         if (isVGPRToSGPRCopy(SrcRC, DstRC, *TRI)) {
267*9880d681SAndroid Build Coastguard Worker           DEBUG(dbgs() << "Fixing VGPR -> SGPR copy: " << MI);
268*9880d681SAndroid Build Coastguard Worker           TII->moveToVALU(MI);
269*9880d681SAndroid Build Coastguard Worker         }
270*9880d681SAndroid Build Coastguard Worker 
271*9880d681SAndroid Build Coastguard Worker         break;
272*9880d681SAndroid Build Coastguard Worker       }
273*9880d681SAndroid Build Coastguard Worker       case AMDGPU::PHI: {
274*9880d681SAndroid Build Coastguard Worker         DEBUG(dbgs() << "Fixing PHI: " << MI);
275*9880d681SAndroid Build Coastguard Worker         unsigned Reg = MI.getOperand(0).getReg();
276*9880d681SAndroid Build Coastguard Worker         if (!TRI->isSGPRClass(MRI.getRegClass(Reg)))
277*9880d681SAndroid Build Coastguard Worker           break;
278*9880d681SAndroid Build Coastguard Worker 
279*9880d681SAndroid Build Coastguard Worker         // If a PHI node defines an SGPR and any of its operands are VGPRs,
280*9880d681SAndroid Build Coastguard Worker         // then we need to move it to the VALU.
281*9880d681SAndroid Build Coastguard Worker         //
282*9880d681SAndroid Build Coastguard Worker         // Also, if a PHI node defines an SGPR and has all SGPR operands
283*9880d681SAndroid Build Coastguard Worker         // we must move it to the VALU, because the SGPR operands will
284*9880d681SAndroid Build Coastguard Worker         // all end up being assigned the same register, which means
285*9880d681SAndroid Build Coastguard Worker         // there is a potential for a conflict if different threads take
286*9880d681SAndroid Build Coastguard Worker         // different control flow paths.
287*9880d681SAndroid Build Coastguard Worker         //
288*9880d681SAndroid Build Coastguard Worker         // For Example:
289*9880d681SAndroid Build Coastguard Worker         //
290*9880d681SAndroid Build Coastguard Worker         // sgpr0 = def;
291*9880d681SAndroid Build Coastguard Worker         // ...
292*9880d681SAndroid Build Coastguard Worker         // sgpr1 = def;
293*9880d681SAndroid Build Coastguard Worker         // ...
294*9880d681SAndroid Build Coastguard Worker         // sgpr2 = PHI sgpr0, sgpr1
295*9880d681SAndroid Build Coastguard Worker         // use sgpr2;
296*9880d681SAndroid Build Coastguard Worker         //
297*9880d681SAndroid Build Coastguard Worker         // Will Become:
298*9880d681SAndroid Build Coastguard Worker         //
299*9880d681SAndroid Build Coastguard Worker         // sgpr2 = def;
300*9880d681SAndroid Build Coastguard Worker         // ...
301*9880d681SAndroid Build Coastguard Worker         // sgpr2 = def;
302*9880d681SAndroid Build Coastguard Worker         // ...
303*9880d681SAndroid Build Coastguard Worker         // use sgpr2
304*9880d681SAndroid Build Coastguard Worker         //
305*9880d681SAndroid Build Coastguard Worker         // FIXME: This is OK if the branching decision is made based on an
306*9880d681SAndroid Build Coastguard Worker         // SGPR value.
307*9880d681SAndroid Build Coastguard Worker         bool SGPRBranch = false;
308*9880d681SAndroid Build Coastguard Worker 
309*9880d681SAndroid Build Coastguard Worker         // The one exception to this rule is when one of the operands
310*9880d681SAndroid Build Coastguard Worker         // is defined by a SI_BREAK, SI_IF_BREAK, or SI_ELSE_BREAK
311*9880d681SAndroid Build Coastguard Worker         // instruction.  In this case, there we know the program will
312*9880d681SAndroid Build Coastguard Worker         // never enter the second block (the loop) without entering
313*9880d681SAndroid Build Coastguard Worker         // the first block (where the condition is computed), so there
314*9880d681SAndroid Build Coastguard Worker         // is no chance for values to be over-written.
315*9880d681SAndroid Build Coastguard Worker 
316*9880d681SAndroid Build Coastguard Worker         bool HasBreakDef = false;
317*9880d681SAndroid Build Coastguard Worker         for (unsigned i = 1; i < MI.getNumOperands(); i+=2) {
318*9880d681SAndroid Build Coastguard Worker           unsigned Reg = MI.getOperand(i).getReg();
319*9880d681SAndroid Build Coastguard Worker           if (TRI->hasVGPRs(MRI.getRegClass(Reg))) {
320*9880d681SAndroid Build Coastguard Worker             TII->moveToVALU(MI);
321*9880d681SAndroid Build Coastguard Worker             break;
322*9880d681SAndroid Build Coastguard Worker           }
323*9880d681SAndroid Build Coastguard Worker           MachineInstr *DefInstr = MRI.getUniqueVRegDef(Reg);
324*9880d681SAndroid Build Coastguard Worker           assert(DefInstr);
325*9880d681SAndroid Build Coastguard Worker           switch(DefInstr->getOpcode()) {
326*9880d681SAndroid Build Coastguard Worker 
327*9880d681SAndroid Build Coastguard Worker           case AMDGPU::SI_BREAK:
328*9880d681SAndroid Build Coastguard Worker           case AMDGPU::SI_IF_BREAK:
329*9880d681SAndroid Build Coastguard Worker           case AMDGPU::SI_ELSE_BREAK:
330*9880d681SAndroid Build Coastguard Worker           // If we see a PHI instruction that defines an SGPR, then that PHI
331*9880d681SAndroid Build Coastguard Worker           // instruction has already been considered and should have
332*9880d681SAndroid Build Coastguard Worker           // a *_BREAK as an operand.
333*9880d681SAndroid Build Coastguard Worker           case AMDGPU::PHI:
334*9880d681SAndroid Build Coastguard Worker             HasBreakDef = true;
335*9880d681SAndroid Build Coastguard Worker             break;
336*9880d681SAndroid Build Coastguard Worker           }
337*9880d681SAndroid Build Coastguard Worker         }
338*9880d681SAndroid Build Coastguard Worker 
339*9880d681SAndroid Build Coastguard Worker         if (!SGPRBranch && !HasBreakDef)
340*9880d681SAndroid Build Coastguard Worker           TII->moveToVALU(MI);
341*9880d681SAndroid Build Coastguard Worker         break;
342*9880d681SAndroid Build Coastguard Worker       }
343*9880d681SAndroid Build Coastguard Worker       case AMDGPU::REG_SEQUENCE: {
344*9880d681SAndroid Build Coastguard Worker         if (TRI->hasVGPRs(TII->getOpRegClass(MI, 0)) ||
345*9880d681SAndroid Build Coastguard Worker             !hasVGPROperands(MI, TRI)) {
346*9880d681SAndroid Build Coastguard Worker           foldVGPRCopyIntoRegSequence(MI, TRI, TII, MRI);
347*9880d681SAndroid Build Coastguard Worker           continue;
348*9880d681SAndroid Build Coastguard Worker         }
349*9880d681SAndroid Build Coastguard Worker 
350*9880d681SAndroid Build Coastguard Worker         DEBUG(dbgs() << "Fixing REG_SEQUENCE: " << MI);
351*9880d681SAndroid Build Coastguard Worker 
352*9880d681SAndroid Build Coastguard Worker         TII->moveToVALU(MI);
353*9880d681SAndroid Build Coastguard Worker         break;
354*9880d681SAndroid Build Coastguard Worker       }
355*9880d681SAndroid Build Coastguard Worker       case AMDGPU::INSERT_SUBREG: {
356*9880d681SAndroid Build Coastguard Worker         const TargetRegisterClass *DstRC, *Src0RC, *Src1RC;
357*9880d681SAndroid Build Coastguard Worker         DstRC = MRI.getRegClass(MI.getOperand(0).getReg());
358*9880d681SAndroid Build Coastguard Worker         Src0RC = MRI.getRegClass(MI.getOperand(1).getReg());
359*9880d681SAndroid Build Coastguard Worker         Src1RC = MRI.getRegClass(MI.getOperand(2).getReg());
360*9880d681SAndroid Build Coastguard Worker         if (TRI->isSGPRClass(DstRC) &&
361*9880d681SAndroid Build Coastguard Worker             (TRI->hasVGPRs(Src0RC) || TRI->hasVGPRs(Src1RC))) {
362*9880d681SAndroid Build Coastguard Worker           DEBUG(dbgs() << " Fixing INSERT_SUBREG: " << MI);
363*9880d681SAndroid Build Coastguard Worker           TII->moveToVALU(MI);
364*9880d681SAndroid Build Coastguard Worker         }
365*9880d681SAndroid Build Coastguard Worker         break;
366*9880d681SAndroid Build Coastguard Worker       }
367*9880d681SAndroid Build Coastguard Worker       }
368*9880d681SAndroid Build Coastguard Worker     }
369*9880d681SAndroid Build Coastguard Worker   }
370*9880d681SAndroid Build Coastguard Worker 
371*9880d681SAndroid Build Coastguard Worker   return true;
372*9880d681SAndroid Build Coastguard Worker }
373