blob: b6941c1cc759133803a9ff04bf40e92297acdd35 [file] [log] [blame]
Tom Stellard2f7cdda2013-08-06 23:08:28 +00001//===-- 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>
NAKAMURA Takumi78e80cd2013-11-14 04:05:22 +000026/// %vreg5 <vgpr> = VECTOR_INST %vreg4 <vsrc>
Tom Stellard2f7cdda2013-08-06 23:08:28 +000027///
NAKAMURA Takumi78e80cd2013-11-14 04:05:22 +000028///
Tom Stellard2f7cdda2013-08-06 23:08:28 +000029/// 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:
NAKAMURA Takumi78e80cd2013-11-14 04:05:22 +000046///
Tom Stellard2f7cdda2013-08-06 23:08:28 +000047/// 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///
NAKAMURA Takumi78e80cd2013-11-14 04:05:22 +000058/// Now this code contains an illegal copy from a VGPR to an SGPR.
Tom Stellard2f7cdda2013-08-06 23:08:28 +000059///
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 "AMDGPU.h"
Eric Christopherd9134482014-08-04 21:25:23 +000069#include "AMDGPUSubtarget.h"
Tom Stellard2f7cdda2013-08-06 23:08:28 +000070#include "SIInstrInfo.h"
71#include "llvm/CodeGen/MachineFunctionPass.h"
Tom Stellard82166022013-11-13 23:36:37 +000072#include "llvm/CodeGen/MachineInstrBuilder.h"
Tom Stellard2f7cdda2013-08-06 23:08:28 +000073#include "llvm/CodeGen/MachineRegisterInfo.h"
Tom Stellard82166022013-11-13 23:36:37 +000074#include "llvm/Support/Debug.h"
Hans Wennborga74fd702013-11-14 23:24:09 +000075#include "llvm/Support/raw_ostream.h"
Tom Stellard2f7cdda2013-08-06 23:08:28 +000076#include "llvm/Target/TargetMachine.h"
77
78using namespace llvm;
79
Chandler Carruth84e68b22014-04-22 02:41:26 +000080#define DEBUG_TYPE "sgpr-copies"
81
Tom Stellard2f7cdda2013-08-06 23:08:28 +000082namespace {
83
84class SIFixSGPRCopies : public MachineFunctionPass {
85
86private:
87 static char ID;
Matt Arsenaultf0d9e472015-10-13 00:07:54 +000088 std::pair<const TargetRegisterClass *, const TargetRegisterClass *>
89 getCopyRegClasses(const MachineInstr &Copy,
90 const SIRegisterInfo &TRI,
91 const MachineRegisterInfo &MRI) const;
92
93 bool isVGPRToSGPRCopy(const TargetRegisterClass *SrcRC,
94 const TargetRegisterClass *DstRC,
95 const SIRegisterInfo &TRI) const;
96
97 bool isSGPRToVGPRCopy(const TargetRegisterClass *SrcRC,
98 const TargetRegisterClass *DstRC,
99 const SIRegisterInfo &TRI) const;
Tom Stellard2f7cdda2013-08-06 23:08:28 +0000100
101public:
102 SIFixSGPRCopies(TargetMachine &tm) : MachineFunctionPass(ID) { }
103
Craig Topper5656db42014-04-29 07:57:24 +0000104 bool runOnMachineFunction(MachineFunction &MF) override;
Tom Stellard2f7cdda2013-08-06 23:08:28 +0000105
Craig Topper5656db42014-04-29 07:57:24 +0000106 const char *getPassName() const override {
Tom Stellard2f7cdda2013-08-06 23:08:28 +0000107 return "SI Fix SGPR copies";
108 }
109
Matt Arsenault0cb85172015-09-25 17:21:28 +0000110 void getAnalysisUsage(AnalysisUsage &AU) const override {
111 AU.setPreservesCFG();
112 MachineFunctionPass::getAnalysisUsage(AU);
113 }
Tom Stellard2f7cdda2013-08-06 23:08:28 +0000114};
115
116} // End anonymous namespace
117
118char SIFixSGPRCopies::ID = 0;
119
120FunctionPass *llvm::createSIFixSGPRCopiesPass(TargetMachine &tm) {
121 return new SIFixSGPRCopies(tm);
122}
123
Tom Stellard82166022013-11-13 23:36:37 +0000124static 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
Matt Arsenaultf0d9e472015-10-13 00:07:54 +0000137std::pair<const TargetRegisterClass *, const TargetRegisterClass *>
138SIFixSGPRCopies::getCopyRegClasses(const MachineInstr &Copy,
139 const SIRegisterInfo &TRI,
140 const MachineRegisterInfo &MRI) const {
Tom Stellard82166022013-11-13 23:36:37 +0000141 unsigned DstReg = Copy.getOperand(0).getReg();
142 unsigned SrcReg = Copy.getOperand(1).getReg();
Matt Arsenault120a0c92014-12-03 05:22:39 +0000143
Matt Arsenaultf0d9e472015-10-13 00:07:54 +0000144 const TargetRegisterClass *SrcRC =
145 TargetRegisterInfo::isVirtualRegister(SrcReg) ?
146 MRI.getRegClass(SrcReg) :
147 TRI.getPhysRegClass(SrcReg);
Tom Stellardd33d7f12015-05-12 14:18:11 +0000148
Matt Arsenaultf0d9e472015-10-13 00:07:54 +0000149 // We don't really care about the subregister here.
150 // SrcRC = TRI.getSubRegClass(SrcRC, Copy.getOperand(1).getSubReg());
Tom Stellard82166022013-11-13 23:36:37 +0000151
Matt Arsenaultf0d9e472015-10-13 00:07:54 +0000152 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
160bool SIFixSGPRCopies::isVGPRToSGPRCopy(const TargetRegisterClass *SrcRC,
161 const TargetRegisterClass *DstRC,
162 const SIRegisterInfo &TRI) const {
163 return TRI.isSGPRClass(DstRC) && TRI.hasVGPRs(SrcRC);
164}
165
166bool SIFixSGPRCopies::isSGPRToVGPRCopy(const TargetRegisterClass *SrcRC,
167 const TargetRegisterClass *DstRC,
168 const SIRegisterInfo &TRI) const {
169 return TRI.isSGPRClass(SrcRC) && TRI.hasVGPRs(DstRC);
Tom Stellard82166022013-11-13 23:36:37 +0000170}
171
Tom Stellard2f7cdda2013-08-06 23:08:28 +0000172bool SIFixSGPRCopies::runOnMachineFunction(MachineFunction &MF) {
173 MachineRegisterInfo &MRI = MF.getRegInfo();
Eric Christopherfc6de422014-08-05 02:39:49 +0000174 const SIRegisterInfo *TRI =
175 static_cast<const SIRegisterInfo *>(MF.getSubtarget().getRegisterInfo());
176 const SIInstrInfo *TII =
177 static_cast<const SIInstrInfo *>(MF.getSubtarget().getInstrInfo());
Tom Stellard2f7cdda2013-08-06 23:08:28 +0000178 for (MachineFunction::iterator BI = MF.begin(), BE = MF.end();
179 BI != BE; ++BI) {
180
181 MachineBasicBlock &MBB = *BI;
182 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
183 I != E; ++I) {
184 MachineInstr &MI = *I;
Tom Stellard82166022013-11-13 23:36:37 +0000185
186 switch (MI.getOpcode()) {
Matt Arsenault85441dd2015-09-21 16:27:22 +0000187 default:
188 continue;
189 case AMDGPU::COPY: {
Matt Arsenaultf0d9e472015-10-13 00:07:54 +0000190 // If the destination register is a physical register there isn't really
191 // much we can do to fix this.
192 if (!TargetRegisterInfo::isVirtualRegister(MI.getOperand(0).getReg()))
193 continue;
194
195 const TargetRegisterClass *SrcRC, *DstRC;
196 std::tie(SrcRC, DstRC) = getCopyRegClasses(MI, *TRI, MRI);
197 if (isVGPRToSGPRCopy(SrcRC, DstRC, *TRI)) {
Matt Arsenault85441dd2015-09-21 16:27:22 +0000198 DEBUG(dbgs() << "Fixing VGPR -> SGPR copy: " << MI);
199 TII->moveToVALU(MI);
200 }
201
202 break;
203 }
Tom Stellard82166022013-11-13 23:36:37 +0000204 case AMDGPU::PHI: {
Matt Arsenault3896a0a2014-11-25 21:03:22 +0000205 DEBUG(dbgs() << "Fixing PHI: " << MI);
Tom Stellard82166022013-11-13 23:36:37 +0000206 unsigned Reg = MI.getOperand(0).getReg();
Tom Stellard82166022013-11-13 23:36:37 +0000207 if (!TRI->isSGPRClass(MRI.getRegClass(Reg)))
208 break;
209
210 // If a PHI node defines an SGPR and any of its operands are VGPRs,
211 // then we need to move it to the VALU.
Tom Stellarddeb3f9e2014-09-24 01:33:26 +0000212 //
213 // Also, if a PHI node defines an SGPR and has all SGPR operands
214 // we must move it to the VALU, because the SGPR operands will
215 // all end up being assigned the same register, which means
216 // there is a potential for a conflict if different threads take
Matt Arsenaultbfaab762014-10-17 00:36:20 +0000217 // different control flow paths.
Tom Stellarddeb3f9e2014-09-24 01:33:26 +0000218 //
219 // For Example:
220 //
221 // sgpr0 = def;
222 // ...
223 // sgpr1 = def;
224 // ...
225 // sgpr2 = PHI sgpr0, sgpr1
226 // use sgpr2;
227 //
228 // Will Become:
229 //
230 // sgpr2 = def;
231 // ...
232 // sgpr2 = def;
233 // ...
234 // use sgpr2
235 //
236 // FIXME: This is OK if the branching decision is made based on an
237 // SGPR value.
238 bool SGPRBranch = false;
239
240 // The one exception to this rule is when one of the operands
241 // is defined by a SI_BREAK, SI_IF_BREAK, or SI_ELSE_BREAK
242 // instruction. In this case, there we know the program will
243 // never enter the second block (the loop) without entering
244 // the first block (where the condition is computed), so there
245 // is no chance for values to be over-written.
246
247 bool HasBreakDef = false;
Tom Stellard82166022013-11-13 23:36:37 +0000248 for (unsigned i = 1; i < MI.getNumOperands(); i+=2) {
249 unsigned Reg = MI.getOperand(i).getReg();
250 if (TRI->hasVGPRs(MRI.getRegClass(Reg))) {
251 TII->moveToVALU(MI);
252 break;
253 }
Tom Stellarddeb3f9e2014-09-24 01:33:26 +0000254 MachineInstr *DefInstr = MRI.getUniqueVRegDef(Reg);
255 assert(DefInstr);
256 switch(DefInstr->getOpcode()) {
257
258 case AMDGPU::SI_BREAK:
259 case AMDGPU::SI_IF_BREAK:
260 case AMDGPU::SI_ELSE_BREAK:
261 // If we see a PHI instruction that defines an SGPR, then that PHI
262 // instruction has already been considered and should have
263 // a *_BREAK as an operand.
264 case AMDGPU::PHI:
265 HasBreakDef = true;
266 break;
267 }
Tom Stellard82166022013-11-13 23:36:37 +0000268 }
269
Tom Stellarddeb3f9e2014-09-24 01:33:26 +0000270 if (!SGPRBranch && !HasBreakDef)
271 TII->moveToVALU(MI);
Tom Stellard82166022013-11-13 23:36:37 +0000272 break;
273 }
274 case AMDGPU::REG_SEQUENCE: {
275 if (TRI->hasVGPRs(TII->getOpRegClass(MI, 0)) ||
276 !hasVGPROperands(MI, TRI))
277 continue;
278
Matt Arsenaultbfaab762014-10-17 00:36:20 +0000279 DEBUG(dbgs() << "Fixing REG_SEQUENCE: " << MI);
Tom Stellard82166022013-11-13 23:36:37 +0000280
281 TII->moveToVALU(MI);
Tom Stellard82166022013-11-13 23:36:37 +0000282 break;
283 }
Tom Stellard204e61b2014-04-07 19:45:45 +0000284 case AMDGPU::INSERT_SUBREG: {
Tom Stellarda5687382014-05-15 14:41:55 +0000285 const TargetRegisterClass *DstRC, *Src0RC, *Src1RC;
Tom Stellard204e61b2014-04-07 19:45:45 +0000286 DstRC = MRI.getRegClass(MI.getOperand(0).getReg());
Tom Stellarda5687382014-05-15 14:41:55 +0000287 Src0RC = MRI.getRegClass(MI.getOperand(1).getReg());
288 Src1RC = MRI.getRegClass(MI.getOperand(2).getReg());
289 if (TRI->isSGPRClass(DstRC) &&
290 (TRI->hasVGPRs(Src0RC) || TRI->hasVGPRs(Src1RC))) {
Matt Arsenaultbfaab762014-10-17 00:36:20 +0000291 DEBUG(dbgs() << " Fixing INSERT_SUBREG: " << MI);
Tom Stellarda5687382014-05-15 14:41:55 +0000292 TII->moveToVALU(MI);
293 }
294 break;
Tom Stellard204e61b2014-04-07 19:45:45 +0000295 }
Tom Stellard2f7cdda2013-08-06 23:08:28 +0000296 }
297 }
298 }
Matt Arsenault6f679782014-11-17 21:11:34 +0000299
300 return true;
Tom Stellard2f7cdda2013-08-06 23:08:28 +0000301}