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