1 //===-- SIFixSGPRCopies.cpp - Remove potential VGPR => SGPR copies --------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 /// \file
11 /// Copies from VGPR to SGPR registers are illegal and the register coalescer
12 /// will sometimes generate these illegal copies in situations like this:
13 ///
14 ///  Register Class <vsrc> is the union of <vgpr> and <sgpr>
15 ///
16 /// BB0:
17 ///   %vreg0 <sgpr> = SCALAR_INST
18 ///   %vreg1 <vsrc> = COPY %vreg0 <sgpr>
19 ///    ...
20 ///    BRANCH %cond BB1, BB2
21 ///  BB1:
22 ///    %vreg2 <vgpr> = VECTOR_INST
23 ///    %vreg3 <vsrc> = COPY %vreg2 <vgpr>
24 ///  BB2:
25 ///    %vreg4 <vsrc> = PHI %vreg1 <vsrc>, <BB#0>, %vreg3 <vrsc>, <BB#1>
26 ///    %vreg5 <vgpr> = VECTOR_INST %vreg4 <vsrc>
27 ///
28 ///
29 /// The coalescer will begin at BB0 and eliminate its copy, then the resulting
30 /// code will look like this:
31 ///
32 /// BB0:
33 ///   %vreg0 <sgpr> = SCALAR_INST
34 ///    ...
35 ///    BRANCH %cond BB1, BB2
36 /// BB1:
37 ///   %vreg2 <vgpr> = VECTOR_INST
38 ///   %vreg3 <vsrc> = COPY %vreg2 <vgpr>
39 /// BB2:
40 ///   %vreg4 <sgpr> = PHI %vreg0 <sgpr>, <BB#0>, %vreg3 <vsrc>, <BB#1>
41 ///   %vreg5 <vgpr> = VECTOR_INST %vreg4 <sgpr>
42 ///
43 /// Now that the result of the PHI instruction is an SGPR, the register
44 /// allocator is now forced to constrain the register class of %vreg3 to
45 /// <sgpr> so we end up with final code like this:
46 ///
47 /// BB0:
48 ///   %vreg0 <sgpr> = SCALAR_INST
49 ///    ...
50 ///    BRANCH %cond BB1, BB2
51 /// BB1:
52 ///   %vreg2 <vgpr> = VECTOR_INST
53 ///   %vreg3 <sgpr> = COPY %vreg2 <vgpr>
54 /// BB2:
55 ///   %vreg4 <sgpr> = PHI %vreg0 <sgpr>, <BB#0>, %vreg3 <sgpr>, <BB#1>
56 ///   %vreg5 <vgpr> = VECTOR_INST %vreg4 <sgpr>
57 ///
58 /// Now this code contains an illegal copy from a VGPR to an SGPR.
59 ///
60 /// In order to avoid this problem, this pass searches for PHI instructions
61 /// which define a <vsrc> register and constrains its definition class to
62 /// <vgpr> if the user of the PHI's definition register is a vector instruction.
63 /// If the PHI's definition class is constrained to <vgpr> then the coalescer
64 /// will be unable to perform the COPY removal from the above example  which
65 /// ultimately led to the creation of an illegal COPY.
66 //===----------------------------------------------------------------------===//
67 
68 #include "llvm/ADT/DenseSet.h"
69 #include "AMDGPU.h"
70 #include "AMDGPUSubtarget.h"
71 #include "SIInstrInfo.h"
72 #include "llvm/CodeGen/MachineDominators.h"
73 #include "llvm/CodeGen/MachineFunctionPass.h"
74 #include "llvm/CodeGen/MachineInstrBuilder.h"
75 #include "llvm/CodeGen/MachineRegisterInfo.h"
76 #include "llvm/Support/Debug.h"
77 #include "llvm/Support/raw_ostream.h"
78 #include "llvm/Target/TargetMachine.h"
79 
80 using namespace llvm;
81 
82 #define DEBUG_TYPE "si-fix-sgpr-copies"
83 
84 namespace {
85 
86 class SIFixSGPRCopies : public MachineFunctionPass {
87 
88   MachineDominatorTree *MDT;
89 
90 public:
91   static char ID;
92 
93   SIFixSGPRCopies() : MachineFunctionPass(ID) { }
94 
95   bool runOnMachineFunction(MachineFunction &MF) override;
96 
97   StringRef getPassName() const override { return "SI Fix SGPR copies"; }
98 
99   void getAnalysisUsage(AnalysisUsage &AU) const override {
100     AU.addRequired<MachineDominatorTree>();
101     AU.addPreserved<MachineDominatorTree>();
102     AU.setPreservesCFG();
103     MachineFunctionPass::getAnalysisUsage(AU);
104   }
105 };
106 
107 } // End anonymous namespace
108 
109 INITIALIZE_PASS_BEGIN(SIFixSGPRCopies, DEBUG_TYPE,
110                      "SI Fix SGPR copies", false, false)
111 INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTree)
112 INITIALIZE_PASS_END(SIFixSGPRCopies, DEBUG_TYPE,
113                      "SI Fix SGPR copies", false, false)
114 
115 
116 char SIFixSGPRCopies::ID = 0;
117 
118 char &llvm::SIFixSGPRCopiesID = SIFixSGPRCopies::ID;
119 
120 FunctionPass *llvm::createSIFixSGPRCopiesPass() {
121   return new SIFixSGPRCopies();
122 }
123 
124 static bool hasVGPROperands(const MachineInstr &MI, const SIRegisterInfo *TRI) {
125   const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
126   for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
127     if (!MI.getOperand(i).isReg() ||
128         !TargetRegisterInfo::isVirtualRegister(MI.getOperand(i).getReg()))
129       continue;
130 
131     if (TRI->hasVGPRs(MRI.getRegClass(MI.getOperand(i).getReg())))
132       return true;
133   }
134   return false;
135 }
136 
137 static std::pair<const TargetRegisterClass *, const TargetRegisterClass *>
138 getCopyRegClasses(const MachineInstr &Copy,
139                   const SIRegisterInfo &TRI,
140                   const MachineRegisterInfo &MRI) {
141   unsigned DstReg = Copy.getOperand(0).getReg();
142   unsigned SrcReg = Copy.getOperand(1).getReg();
143 
144   const TargetRegisterClass *SrcRC =
145     TargetRegisterInfo::isVirtualRegister(SrcReg) ?
146     MRI.getRegClass(SrcReg) :
147     TRI.getPhysRegClass(SrcReg);
148 
149   // We don't really care about the subregister here.
150   // SrcRC = TRI.getSubRegClass(SrcRC, Copy.getOperand(1).getSubReg());
151 
152   const TargetRegisterClass *DstRC =
153     TargetRegisterInfo::isVirtualRegister(DstReg) ?
154     MRI.getRegClass(DstReg) :
155     TRI.getPhysRegClass(DstReg);
156 
157   return std::make_pair(SrcRC, DstRC);
158 }
159 
160 static bool isVGPRToSGPRCopy(const TargetRegisterClass *SrcRC,
161                              const TargetRegisterClass *DstRC,
162                              const SIRegisterInfo &TRI) {
163   return TRI.isSGPRClass(DstRC) && TRI.hasVGPRs(SrcRC);
164 }
165 
166 static bool isSGPRToVGPRCopy(const TargetRegisterClass *SrcRC,
167                              const TargetRegisterClass *DstRC,
168                              const SIRegisterInfo &TRI) {
169   return TRI.isSGPRClass(SrcRC) && TRI.hasVGPRs(DstRC);
170 }
171 
172 // Distribute an SGPR->VGPR copy of a REG_SEQUENCE into a VGPR REG_SEQUENCE.
173 //
174 // SGPRx = ...
175 // SGPRy = REG_SEQUENCE SGPRx, sub0 ...
176 // VGPRz = COPY SGPRy
177 //
178 // ==>
179 //
180 // VGPRx = COPY SGPRx
181 // VGPRz = REG_SEQUENCE VGPRx, sub0
182 //
183 // This exposes immediate folding opportunities when materializing 64-bit
184 // immediates.
185 static bool foldVGPRCopyIntoRegSequence(MachineInstr &MI,
186                                         const SIRegisterInfo *TRI,
187                                         const SIInstrInfo *TII,
188                                         MachineRegisterInfo &MRI) {
189   assert(MI.isRegSequence());
190 
191   unsigned DstReg = MI.getOperand(0).getReg();
192   if (!TRI->isSGPRClass(MRI.getRegClass(DstReg)))
193     return false;
194 
195   if (!MRI.hasOneUse(DstReg))
196     return false;
197 
198   MachineInstr &CopyUse = *MRI.use_instr_begin(DstReg);
199   if (!CopyUse.isCopy())
200     return false;
201 
202   // It is illegal to have vreg inputs to a physreg defining reg_sequence.
203   if (TargetRegisterInfo::isPhysicalRegister(CopyUse.getOperand(0).getReg()))
204     return false;
205 
206   const TargetRegisterClass *SrcRC, *DstRC;
207   std::tie(SrcRC, DstRC) = getCopyRegClasses(CopyUse, *TRI, MRI);
208 
209   if (!isSGPRToVGPRCopy(SrcRC, DstRC, *TRI))
210     return false;
211 
212   // TODO: Could have multiple extracts?
213   unsigned SubReg = CopyUse.getOperand(1).getSubReg();
214   if (SubReg != AMDGPU::NoSubRegister)
215     return false;
216 
217   MRI.setRegClass(DstReg, DstRC);
218 
219   // SGPRx = ...
220   // SGPRy = REG_SEQUENCE SGPRx, sub0 ...
221   // VGPRz = COPY SGPRy
222 
223   // =>
224   // VGPRx = COPY SGPRx
225   // VGPRz = REG_SEQUENCE VGPRx, sub0
226 
227   MI.getOperand(0).setReg(CopyUse.getOperand(0).getReg());
228 
229   for (unsigned I = 1, N = MI.getNumOperands(); I != N; I += 2) {
230     unsigned SrcReg = MI.getOperand(I).getReg();
231     unsigned SrcSubReg = MI.getOperand(I).getSubReg();
232 
233     const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg);
234     assert(TRI->isSGPRClass(SrcRC) &&
235            "Expected SGPR REG_SEQUENCE to only have SGPR inputs");
236 
237     SrcRC = TRI->getSubRegClass(SrcRC, SrcSubReg);
238     const TargetRegisterClass *NewSrcRC = TRI->getEquivalentVGPRClass(SrcRC);
239 
240     unsigned TmpReg = MRI.createVirtualRegister(NewSrcRC);
241 
242     BuildMI(*MI.getParent(), &MI, MI.getDebugLoc(), TII->get(AMDGPU::COPY),
243             TmpReg)
244         .add(MI.getOperand(I));
245 
246     MI.getOperand(I).setReg(TmpReg);
247   }
248 
249   CopyUse.eraseFromParent();
250   return true;
251 }
252 
253 static bool phiHasVGPROperands(const MachineInstr &PHI,
254                                const MachineRegisterInfo &MRI,
255                                const SIRegisterInfo *TRI,
256                                const SIInstrInfo *TII) {
257 
258   for (unsigned i = 1; i < PHI.getNumOperands(); i += 2) {
259     unsigned Reg = PHI.getOperand(i).getReg();
260     if (TRI->hasVGPRs(MRI.getRegClass(Reg)))
261       return true;
262   }
263   return false;
264 }
265 static bool phiHasBreakDef(const MachineInstr &PHI,
266                            const MachineRegisterInfo &MRI,
267                            SmallSet<unsigned, 8> &Visited) {
268 
269   for (unsigned i = 1; i < PHI.getNumOperands(); i += 2) {
270     unsigned Reg = PHI.getOperand(i).getReg();
271     if (Visited.count(Reg))
272       continue;
273 
274     Visited.insert(Reg);
275 
276     MachineInstr *DefInstr = MRI.getUniqueVRegDef(Reg);
277     assert(DefInstr);
278     switch (DefInstr->getOpcode()) {
279     default:
280       break;
281     case AMDGPU::SI_BREAK:
282     case AMDGPU::SI_IF_BREAK:
283     case AMDGPU::SI_ELSE_BREAK:
284       return true;
285     case AMDGPU::PHI:
286       if (phiHasBreakDef(*DefInstr, MRI, Visited))
287         return true;
288     }
289   }
290   return false;
291 }
292 
293 static bool hasTerminatorThatModifiesExec(const MachineBasicBlock &MBB,
294                                           const TargetRegisterInfo &TRI) {
295   for (MachineBasicBlock::const_iterator I = MBB.getFirstTerminator(),
296        E = MBB.end(); I != E; ++I) {
297     if (I->modifiesRegister(AMDGPU::EXEC, &TRI))
298       return true;
299   }
300   return false;
301 }
302 
303 static bool isSafeToFoldImmIntoCopy(const MachineInstr *Copy,
304                                     const MachineInstr *MoveImm,
305                                     const SIInstrInfo *TII,
306                                     unsigned &SMovOp,
307                                     int64_t &Imm) {
308 
309   if (!MoveImm->isMoveImmediate())
310     return false;
311 
312   const MachineOperand *ImmOp =
313       TII->getNamedOperand(*MoveImm, AMDGPU::OpName::src0);
314   if (!ImmOp->isImm())
315     return false;
316 
317   // FIXME: Handle copies with sub-regs.
318   if (Copy->getOperand(0).getSubReg())
319     return false;
320 
321   switch (MoveImm->getOpcode()) {
322   default:
323     return false;
324   case AMDGPU::V_MOV_B32_e32:
325     SMovOp = AMDGPU::S_MOV_B32;
326     break;
327   case AMDGPU::V_MOV_B64_PSEUDO:
328     SMovOp = AMDGPU::S_MOV_B64;
329     break;
330   }
331   Imm = ImmOp->getImm();
332   return true;
333 }
334 
335 static bool predsHasDivergentTerminator(MachineBasicBlock *MBB,
336                                const TargetRegisterInfo *TRI) {
337   DenseSet<MachineBasicBlock*> Visited;
338   SmallVector<MachineBasicBlock*, 4> Worklist(MBB->pred_begin(),
339                                               MBB->pred_end());
340 
341   while (!Worklist.empty()) {
342     MachineBasicBlock *mbb = Worklist.back();
343     Worklist.pop_back();
344 
345     if (!Visited.insert(mbb).second)
346       continue;
347     if (hasTerminatorThatModifiesExec(*mbb, *TRI))
348       return true;
349 
350     Worklist.insert(Worklist.end(), mbb->pred_begin(), mbb->pred_end());
351   }
352 
353   return false;
354 }
355 
356 bool SIFixSGPRCopies::runOnMachineFunction(MachineFunction &MF) {
357   const SISubtarget &ST = MF.getSubtarget<SISubtarget>();
358   MachineRegisterInfo &MRI = MF.getRegInfo();
359   const SIRegisterInfo *TRI = ST.getRegisterInfo();
360   const SIInstrInfo *TII = ST.getInstrInfo();
361   MDT = &getAnalysis<MachineDominatorTree>();
362 
363   SmallVector<MachineInstr *, 16> Worklist;
364 
365   for (MachineFunction::iterator BI = MF.begin(), BE = MF.end();
366                                                   BI != BE; ++BI) {
367 
368     MachineBasicBlock &MBB = *BI;
369     for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
370          I != E; ++I) {
371       MachineInstr &MI = *I;
372 
373       switch (MI.getOpcode()) {
374       default:
375         continue;
376       case AMDGPU::COPY: {
377         // If the destination register is a physical register there isn't really
378         // much we can do to fix this.
379         if (!TargetRegisterInfo::isVirtualRegister(MI.getOperand(0).getReg()))
380           continue;
381 
382         const TargetRegisterClass *SrcRC, *DstRC;
383         std::tie(SrcRC, DstRC) = getCopyRegClasses(MI, *TRI, MRI);
384         if (isVGPRToSGPRCopy(SrcRC, DstRC, *TRI)) {
385           MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(1).getReg());
386           unsigned SMovOp;
387           int64_t Imm;
388           // If we are just copying an immediate, we can replace the copy with
389           // s_mov_b32.
390           if (isSafeToFoldImmIntoCopy(&MI, DefMI, TII, SMovOp, Imm)) {
391             MI.getOperand(1).ChangeToImmediate(Imm);
392             MI.addImplicitDefUseOperands(MF);
393             MI.setDesc(TII->get(SMovOp));
394             break;
395           }
396           TII->moveToVALU(MI);
397         }
398 
399         break;
400       }
401       case AMDGPU::PHI: {
402         unsigned Reg = MI.getOperand(0).getReg();
403         if (!TRI->isSGPRClass(MRI.getRegClass(Reg)))
404           break;
405 
406         // We don't need to fix the PHI if the common dominator of the
407         // two incoming blocks terminates with a uniform branch.
408         if (MI.getNumExplicitOperands() == 5) {
409           MachineBasicBlock *MBB0 = MI.getOperand(2).getMBB();
410           MachineBasicBlock *MBB1 = MI.getOperand(4).getMBB();
411 
412           if (!predsHasDivergentTerminator(MBB0, TRI) &&
413               !predsHasDivergentTerminator(MBB1, TRI)) {
414             DEBUG(dbgs() << "Not fixing PHI for uniform branch: " << MI << '\n');
415             break;
416           }
417         }
418 
419         // If a PHI node defines an SGPR and any of its operands are VGPRs,
420         // then we need to move it to the VALU.
421         //
422         // Also, if a PHI node defines an SGPR and has all SGPR operands
423         // we must move it to the VALU, because the SGPR operands will
424         // all end up being assigned the same register, which means
425         // there is a potential for a conflict if different threads take
426         // different control flow paths.
427         //
428         // For Example:
429         //
430         // sgpr0 = def;
431         // ...
432         // sgpr1 = def;
433         // ...
434         // sgpr2 = PHI sgpr0, sgpr1
435         // use sgpr2;
436         //
437         // Will Become:
438         //
439         // sgpr2 = def;
440         // ...
441         // sgpr2 = def;
442         // ...
443         // use sgpr2
444         //
445         // The one exception to this rule is when one of the operands
446         // is defined by a SI_BREAK, SI_IF_BREAK, or SI_ELSE_BREAK
447         // instruction.  In this case, there we know the program will
448         // never enter the second block (the loop) without entering
449         // the first block (where the condition is computed), so there
450         // is no chance for values to be over-written.
451 
452         SmallSet<unsigned, 8> Visited;
453         if (phiHasVGPROperands(MI, MRI, TRI, TII) ||
454             !phiHasBreakDef(MI, MRI, Visited)) {
455           DEBUG(dbgs() << "Fixing PHI: " << MI);
456           TII->moveToVALU(MI);
457         }
458         break;
459       }
460       case AMDGPU::REG_SEQUENCE: {
461         if (TRI->hasVGPRs(TII->getOpRegClass(MI, 0)) ||
462             !hasVGPROperands(MI, TRI)) {
463           foldVGPRCopyIntoRegSequence(MI, TRI, TII, MRI);
464           continue;
465         }
466 
467         DEBUG(dbgs() << "Fixing REG_SEQUENCE: " << MI);
468 
469         TII->moveToVALU(MI);
470         break;
471       }
472       case AMDGPU::INSERT_SUBREG: {
473         const TargetRegisterClass *DstRC, *Src0RC, *Src1RC;
474         DstRC = MRI.getRegClass(MI.getOperand(0).getReg());
475         Src0RC = MRI.getRegClass(MI.getOperand(1).getReg());
476         Src1RC = MRI.getRegClass(MI.getOperand(2).getReg());
477         if (TRI->isSGPRClass(DstRC) &&
478             (TRI->hasVGPRs(Src0RC) || TRI->hasVGPRs(Src1RC))) {
479           DEBUG(dbgs() << " Fixing INSERT_SUBREG: " << MI);
480           TII->moveToVALU(MI);
481         }
482         break;
483       }
484       }
485     }
486   }
487 
488   return true;
489 }
490