Line data Source code
1 : //===- AMDGPUInstructionSelector.cpp ----------------------------*- C++ -*-==//
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 : /// \file
10 : /// This file implements the targeting of the InstructionSelector class for
11 : /// AMDGPU.
12 : /// \todo This should be generated by TableGen.
13 : //===----------------------------------------------------------------------===//
14 :
15 : #include "AMDGPUInstructionSelector.h"
16 : #include "AMDGPUInstrInfo.h"
17 : #include "AMDGPURegisterBankInfo.h"
18 : #include "AMDGPURegisterInfo.h"
19 : #include "AMDGPUSubtarget.h"
20 : #include "AMDGPUTargetMachine.h"
21 : #include "SIMachineFunctionInfo.h"
22 : #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
23 : #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
24 : #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
25 : #include "llvm/CodeGen/GlobalISel/Utils.h"
26 : #include "llvm/CodeGen/MachineBasicBlock.h"
27 : #include "llvm/CodeGen/MachineFunction.h"
28 : #include "llvm/CodeGen/MachineInstr.h"
29 : #include "llvm/CodeGen/MachineInstrBuilder.h"
30 : #include "llvm/CodeGen/MachineRegisterInfo.h"
31 : #include "llvm/IR/Type.h"
32 : #include "llvm/Support/Debug.h"
33 : #include "llvm/Support/raw_ostream.h"
34 :
35 : #define DEBUG_TYPE "amdgpu-isel"
36 :
37 : using namespace llvm;
38 :
39 : #define GET_GLOBALISEL_IMPL
40 : #define AMDGPUSubtarget GCNSubtarget
41 : #include "AMDGPUGenGlobalISel.inc"
42 : #undef GET_GLOBALISEL_IMPL
43 : #undef AMDGPUSubtarget
44 :
45 2492 : AMDGPUInstructionSelector::AMDGPUInstructionSelector(
46 : const GCNSubtarget &STI, const AMDGPURegisterBankInfo &RBI,
47 2492 : const AMDGPUTargetMachine &TM)
48 2492 : : InstructionSelector(), TII(*STI.getInstrInfo()),
49 2492 : TRI(*STI.getRegisterInfo()), RBI(RBI), TM(TM),
50 : STI(STI),
51 : EnableLateStructurizeCFG(AMDGPUTargetMachine::EnableLateStructurizeCFG),
52 : #define GET_GLOBALISEL_PREDICATES_INIT
53 : #include "AMDGPUGenGlobalISel.inc"
54 : #undef GET_GLOBALISEL_PREDICATES_INIT
55 : #define GET_GLOBALISEL_TEMPORARIES_INIT
56 : #include "AMDGPUGenGlobalISel.inc"
57 : #undef GET_GLOBALISEL_TEMPORARIES_INIT
58 : {
59 2492 : }
60 :
61 0 : const char *AMDGPUInstructionSelector::getName() { return DEBUG_TYPE; }
62 :
63 151 : bool AMDGPUInstructionSelector::selectCOPY(MachineInstr &I) const {
64 151 : MachineBasicBlock *BB = I.getParent();
65 151 : MachineFunction *MF = BB->getParent();
66 151 : MachineRegisterInfo &MRI = MF->getRegInfo();
67 151 : I.setDesc(TII.get(TargetOpcode::COPY));
68 453 : for (const MachineOperand &MO : I.operands()) {
69 604 : if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
70 : continue;
71 :
72 : const TargetRegisterClass *RC =
73 188 : TRI.getConstrainedRegClassForOperand(MO, MRI);
74 188 : if (!RC)
75 : continue;
76 78 : RBI.constrainGenericRegister(MO.getReg(), *RC, MRI);
77 : }
78 151 : return true;
79 : }
80 :
81 : MachineOperand
82 36 : AMDGPUInstructionSelector::getSubOperand64(MachineOperand &MO,
83 : unsigned SubIdx) const {
84 :
85 36 : MachineInstr *MI = MO.getParent();
86 36 : MachineBasicBlock *BB = MO.getParent()->getParent();
87 36 : MachineFunction *MF = BB->getParent();
88 36 : MachineRegisterInfo &MRI = MF->getRegInfo();
89 36 : unsigned DstReg = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
90 :
91 36 : if (MO.isReg()) {
92 36 : unsigned ComposedSubIdx = TRI.composeSubRegIndices(MO.getSubReg(), SubIdx);
93 36 : unsigned Reg = MO.getReg();
94 72 : BuildMI(*BB, MI, MI->getDebugLoc(), TII.get(AMDGPU::COPY), DstReg)
95 36 : .addReg(Reg, 0, ComposedSubIdx);
96 :
97 : return MachineOperand::CreateReg(DstReg, MO.isDef(), MO.isImplicit(),
98 : MO.isKill(), MO.isDead(), MO.isUndef(),
99 : MO.isEarlyClobber(), 0, MO.isDebug(),
100 : MO.isInternalRead());
101 : }
102 :
103 : assert(MO.isImm());
104 :
105 0 : APInt Imm(64, MO.getImm());
106 :
107 0 : switch (SubIdx) {
108 0 : default:
109 0 : llvm_unreachable("do not know to split immediate with this sub index.");
110 0 : case AMDGPU::sub0:
111 0 : return MachineOperand::CreateImm(Imm.getLoBits(32).getSExtValue());
112 0 : case AMDGPU::sub1:
113 0 : return MachineOperand::CreateImm(Imm.getHiBits(32).getSExtValue());
114 : }
115 : }
116 :
117 : static int64_t getConstant(const MachineInstr *MI) {
118 16 : return MI->getOperand(1).getCImm()->getSExtValue();
119 : }
120 :
121 9 : bool AMDGPUInstructionSelector::selectG_ADD(MachineInstr &I) const {
122 9 : MachineBasicBlock *BB = I.getParent();
123 9 : MachineFunction *MF = BB->getParent();
124 9 : MachineRegisterInfo &MRI = MF->getRegInfo();
125 9 : unsigned Size = RBI.getSizeInBits(I.getOperand(0).getReg(), MRI, TRI);
126 9 : unsigned DstLo = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
127 9 : unsigned DstHi = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
128 :
129 9 : if (Size != 64)
130 : return false;
131 :
132 : DebugLoc DL = I.getDebugLoc();
133 :
134 18 : MachineOperand Lo1(getSubOperand64(I.getOperand(1), AMDGPU::sub0));
135 18 : MachineOperand Lo2(getSubOperand64(I.getOperand(2), AMDGPU::sub0));
136 :
137 9 : BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_ADD_U32), DstLo)
138 : .add(Lo1)
139 : .add(Lo2);
140 :
141 18 : MachineOperand Hi1(getSubOperand64(I.getOperand(1), AMDGPU::sub1));
142 18 : MachineOperand Hi2(getSubOperand64(I.getOperand(2), AMDGPU::sub1));
143 :
144 9 : BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_ADDC_U32), DstHi)
145 : .add(Hi1)
146 : .add(Hi2);
147 :
148 18 : BuildMI(*BB, &I, DL, TII.get(AMDGPU::REG_SEQUENCE), I.getOperand(0).getReg())
149 9 : .addReg(DstLo)
150 : .addImm(AMDGPU::sub0)
151 9 : .addReg(DstHi)
152 : .addImm(AMDGPU::sub1);
153 :
154 36 : for (MachineOperand &MO : I.explicit_operands()) {
155 27 : if (!MO.isReg() || TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
156 : continue;
157 27 : RBI.constrainGenericRegister(MO.getReg(), AMDGPU::SReg_64RegClass, MRI);
158 : }
159 :
160 9 : I.eraseFromParent();
161 : return true;
162 : }
163 :
164 9 : bool AMDGPUInstructionSelector::selectG_GEP(MachineInstr &I) const {
165 9 : return selectG_ADD(I);
166 : }
167 :
168 20 : bool AMDGPUInstructionSelector::selectG_IMPLICIT_DEF(MachineInstr &I) const {
169 20 : MachineBasicBlock *BB = I.getParent();
170 20 : MachineFunction *MF = BB->getParent();
171 20 : MachineRegisterInfo &MRI = MF->getRegInfo();
172 20 : const MachineOperand &MO = I.getOperand(0);
173 : const TargetRegisterClass *RC =
174 20 : TRI.getConstrainedRegClassForOperand(MO, MRI);
175 20 : if (RC)
176 0 : RBI.constrainGenericRegister(MO.getReg(), *RC, MRI);
177 20 : I.setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
178 20 : return true;
179 : }
180 :
181 31 : bool AMDGPUInstructionSelector::selectG_INTRINSIC(MachineInstr &I,
182 : CodeGenCoverage &CoverageInfo) const {
183 31 : unsigned IntrinsicID = I.getOperand(1).getIntrinsicID();
184 :
185 31 : switch (IntrinsicID) {
186 : default:
187 : break;
188 18 : case Intrinsic::maxnum:
189 : case Intrinsic::minnum:
190 : case Intrinsic::amdgcn_cvt_pkrtz:
191 18 : return selectImpl(I, CoverageInfo);
192 :
193 13 : case Intrinsic::amdgcn_kernarg_segment_ptr: {
194 13 : MachineFunction *MF = I.getParent()->getParent();
195 13 : MachineRegisterInfo &MRI = MF->getRegInfo();
196 13 : const SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>();
197 : const ArgDescriptor *InputPtrReg;
198 : const TargetRegisterClass *RC;
199 : const DebugLoc &DL = I.getDebugLoc();
200 :
201 : std::tie(InputPtrReg, RC)
202 : = MFI->getPreloadedValue(AMDGPUFunctionArgInfo::KERNARG_SEGMENT_PTR);
203 13 : if (!InputPtrReg)
204 1 : report_fatal_error("missing kernarg segment ptr");
205 :
206 24 : BuildMI(*I.getParent(), &I, DL, TII.get(AMDGPU::COPY))
207 12 : .add(I.getOperand(0))
208 12 : .addReg(MRI.getLiveInVirtReg(InputPtrReg->getRegister()));
209 12 : I.eraseFromParent();
210 : return true;
211 : }
212 : }
213 : return false;
214 : }
215 :
216 : static MachineInstr *
217 4 : buildEXP(const TargetInstrInfo &TII, MachineInstr *Insert, unsigned Tgt,
218 : unsigned Reg0, unsigned Reg1, unsigned Reg2, unsigned Reg3,
219 : unsigned VM, bool Compr, unsigned Enabled, bool Done) {
220 : const DebugLoc &DL = Insert->getDebugLoc();
221 4 : MachineBasicBlock &BB = *Insert->getParent();
222 4 : unsigned Opcode = Done ? AMDGPU::EXP_DONE : AMDGPU::EXP;
223 4 : return BuildMI(BB, Insert, DL, TII.get(Opcode))
224 4 : .addImm(Tgt)
225 4 : .addReg(Reg0)
226 4 : .addReg(Reg1)
227 4 : .addReg(Reg2)
228 4 : .addReg(Reg3)
229 4 : .addImm(VM)
230 4 : .addImm(Compr)
231 4 : .addImm(Enabled);
232 : }
233 :
234 4 : bool AMDGPUInstructionSelector::selectG_INTRINSIC_W_SIDE_EFFECTS(
235 : MachineInstr &I,
236 : CodeGenCoverage &CoverageInfo) const {
237 4 : MachineBasicBlock *BB = I.getParent();
238 4 : MachineFunction *MF = BB->getParent();
239 4 : MachineRegisterInfo &MRI = MF->getRegInfo();
240 :
241 4 : unsigned IntrinsicID = I.getOperand(0).getIntrinsicID();
242 4 : switch (IntrinsicID) {
243 2 : case Intrinsic::amdgcn_exp: {
244 2 : int64_t Tgt = getConstant(MRI.getVRegDef(I.getOperand(1).getReg()));
245 2 : int64_t Enabled = getConstant(MRI.getVRegDef(I.getOperand(2).getReg()));
246 2 : int64_t Done = getConstant(MRI.getVRegDef(I.getOperand(7).getReg()));
247 2 : int64_t VM = getConstant(MRI.getVRegDef(I.getOperand(8).getReg()));
248 :
249 4 : MachineInstr *Exp = buildEXP(TII, &I, Tgt, I.getOperand(3).getReg(),
250 : I.getOperand(4).getReg(),
251 : I.getOperand(5).getReg(),
252 2 : I.getOperand(6).getReg(),
253 : VM, false, Enabled, Done);
254 :
255 2 : I.eraseFromParent();
256 2 : return constrainSelectedInstRegOperands(*Exp, TII, TRI, RBI);
257 : }
258 : case Intrinsic::amdgcn_exp_compr: {
259 : const DebugLoc &DL = I.getDebugLoc();
260 2 : int64_t Tgt = getConstant(MRI.getVRegDef(I.getOperand(1).getReg()));
261 2 : int64_t Enabled = getConstant(MRI.getVRegDef(I.getOperand(2).getReg()));
262 2 : unsigned Reg0 = I.getOperand(3).getReg();
263 2 : unsigned Reg1 = I.getOperand(4).getReg();
264 2 : unsigned Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
265 2 : int64_t Done = getConstant(MRI.getVRegDef(I.getOperand(5).getReg()));
266 2 : int64_t VM = getConstant(MRI.getVRegDef(I.getOperand(6).getReg()));
267 :
268 2 : BuildMI(*BB, &I, DL, TII.get(AMDGPU::IMPLICIT_DEF), Undef);
269 2 : MachineInstr *Exp = buildEXP(TII, &I, Tgt, Reg0, Reg1, Undef, Undef, VM,
270 : true, Enabled, Done);
271 :
272 2 : I.eraseFromParent();
273 2 : return constrainSelectedInstRegOperands(*Exp, TII, TRI, RBI);
274 : }
275 : }
276 : return false;
277 : }
278 :
279 69 : bool AMDGPUInstructionSelector::selectG_STORE(MachineInstr &I) const {
280 69 : MachineBasicBlock *BB = I.getParent();
281 69 : MachineFunction *MF = BB->getParent();
282 69 : MachineRegisterInfo &MRI = MF->getRegInfo();
283 : DebugLoc DL = I.getDebugLoc();
284 69 : unsigned StoreSize = RBI.getSizeInBits(I.getOperand(0).getReg(), MRI, TRI);
285 : unsigned Opcode;
286 :
287 : // FIXME: Select store instruction based on address space
288 69 : switch (StoreSize) {
289 : default:
290 : return false;
291 : case 32:
292 : Opcode = AMDGPU::FLAT_STORE_DWORD;
293 : break;
294 13 : case 64:
295 : Opcode = AMDGPU::FLAT_STORE_DWORDX2;
296 13 : break;
297 2 : case 96:
298 : Opcode = AMDGPU::FLAT_STORE_DWORDX3;
299 2 : break;
300 2 : case 128:
301 : Opcode = AMDGPU::FLAT_STORE_DWORDX4;
302 2 : break;
303 : }
304 :
305 69 : MachineInstr *Flat = BuildMI(*BB, &I, DL, TII.get(Opcode))
306 69 : .add(I.getOperand(1))
307 69 : .add(I.getOperand(0))
308 : .addImm(0) // offset
309 : .addImm(0) // glc
310 : .addImm(0); // slc
311 :
312 :
313 : // Now that we selected an opcode, we need to constrain the register
314 : // operands to use appropriate classes.
315 69 : bool Ret = constrainSelectedInstRegOperands(*Flat, TII, TRI, RBI);
316 :
317 69 : I.eraseFromParent();
318 69 : return Ret;
319 : }
320 :
321 25 : bool AMDGPUInstructionSelector::selectG_CONSTANT(MachineInstr &I) const {
322 25 : MachineBasicBlock *BB = I.getParent();
323 25 : MachineFunction *MF = BB->getParent();
324 25 : MachineRegisterInfo &MRI = MF->getRegInfo();
325 25 : MachineOperand &ImmOp = I.getOperand(1);
326 :
327 : // The AMDGPU backend only supports Imm operands and not CImm or FPImm.
328 25 : if (ImmOp.isFPImm()) {
329 8 : const APInt &Imm = ImmOp.getFPImm()->getValueAPF().bitcastToAPInt();
330 4 : ImmOp.ChangeToImmediate(Imm.getZExtValue());
331 21 : } else if (ImmOp.isCImm()) {
332 34 : ImmOp.ChangeToImmediate(ImmOp.getCImm()->getZExtValue());
333 : }
334 :
335 25 : unsigned DstReg = I.getOperand(0).getReg();
336 : unsigned Size;
337 : bool IsSgpr;
338 : const RegisterBank *RB = MRI.getRegBankOrNull(I.getOperand(0).getReg());
339 3 : if (RB) {
340 3 : IsSgpr = RB->getID() == AMDGPU::SGPRRegBankID;
341 3 : Size = MRI.getType(DstReg).getSizeInBits();
342 : } else {
343 22 : const TargetRegisterClass *RC = TRI.getRegClassForReg(MRI, DstReg);
344 22 : IsSgpr = TRI.isSGPRClass(RC);
345 22 : Size = TRI.getRegSizeInBits(*RC);
346 : }
347 :
348 25 : if (Size != 32 && Size != 64)
349 : return false;
350 :
351 25 : unsigned Opcode = IsSgpr ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
352 25 : if (Size == 32) {
353 12 : I.setDesc(TII.get(Opcode));
354 12 : I.addImplicitDefUseOperands(*MF);
355 12 : return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
356 : }
357 :
358 : DebugLoc DL = I.getDebugLoc();
359 13 : const TargetRegisterClass *RC = IsSgpr ? &AMDGPU::SReg_32_XM0RegClass :
360 : &AMDGPU::VGPR_32RegClass;
361 13 : unsigned LoReg = MRI.createVirtualRegister(RC);
362 13 : unsigned HiReg = MRI.createVirtualRegister(RC);
363 13 : const APInt &Imm = APInt(Size, I.getOperand(1).getImm());
364 :
365 13 : BuildMI(*BB, &I, DL, TII.get(Opcode), LoReg)
366 26 : .addImm(Imm.trunc(32).getZExtValue());
367 :
368 13 : BuildMI(*BB, &I, DL, TII.get(Opcode), HiReg)
369 26 : .addImm(Imm.ashr(32).getZExtValue());
370 :
371 : const MachineInstr *RS =
372 13 : BuildMI(*BB, &I, DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
373 13 : .addReg(LoReg)
374 : .addImm(AMDGPU::sub0)
375 13 : .addReg(HiReg)
376 13 : .addImm(AMDGPU::sub1);
377 :
378 : // We can't call constrainSelectedInstRegOperands here, because it doesn't
379 : // work for target independent opcodes
380 13 : I.eraseFromParent();
381 : const TargetRegisterClass *DstRC =
382 13 : TRI.getConstrainedRegClassForOperand(RS->getOperand(0), MRI);
383 13 : if (!DstRC)
384 : return true;
385 2 : return RBI.constrainGenericRegister(DstReg, *DstRC, MRI);
386 : }
387 :
388 : static bool isConstant(const MachineInstr &MI) {
389 102 : return MI.getOpcode() == TargetOpcode::G_CONSTANT;
390 : }
391 :
392 106 : void AMDGPUInstructionSelector::getAddrModeInfo(const MachineInstr &Load,
393 : const MachineRegisterInfo &MRI, SmallVectorImpl<GEPInfo> &AddrInfo) const {
394 :
395 106 : const MachineInstr *PtrMI = MRI.getUniqueVRegDef(Load.getOperand(1).getReg());
396 :
397 : assert(PtrMI);
398 :
399 212 : if (PtrMI->getOpcode() != TargetOpcode::G_GEP)
400 55 : return;
401 :
402 51 : GEPInfo GEPInfo(*PtrMI);
403 :
404 153 : for (unsigned i = 1, e = 3; i < e; ++i) {
405 102 : const MachineOperand &GEPOp = PtrMI->getOperand(i);
406 102 : const MachineInstr *OpDef = MRI.getUniqueVRegDef(GEPOp.getReg());
407 : assert(OpDef);
408 102 : if (isConstant(*OpDef)) {
409 : // FIXME: Is it possible to have multiple Imm parts? Maybe if we
410 : // are lacking other optimizations.
411 : assert(GEPInfo.Imm == 0);
412 51 : GEPInfo.Imm = OpDef->getOperand(1).getCImm()->getSExtValue();
413 51 : continue;
414 : }
415 51 : const RegisterBank *OpBank = RBI.getRegBank(GEPOp.getReg(), MRI, TRI);
416 51 : if (OpBank->getID() == AMDGPU::SGPRRegBankID)
417 51 : GEPInfo.SgprParts.push_back(GEPOp.getReg());
418 : else
419 0 : GEPInfo.VgprParts.push_back(GEPOp.getReg());
420 : }
421 :
422 51 : AddrInfo.push_back(GEPInfo);
423 51 : getAddrModeInfo(*PtrMI, MRI, AddrInfo);
424 : }
425 :
426 52 : static bool isInstrUniform(const MachineInstr &MI) {
427 52 : if (!MI.hasOneMemOperand())
428 : return false;
429 :
430 52 : const MachineMemOperand *MMO = *MI.memoperands_begin();
431 : const Value *Ptr = MMO->getValue();
432 :
433 : // UndefValue means this is a load of a kernel input. These are uniform.
434 : // Sometimes LDS instructions have constant pointers.
435 : // If Ptr is null, then that means this mem operand contains a
436 : // PseudoSourceValue like GOT.
437 52 : if (!Ptr || isa<UndefValue>(Ptr) || isa<Argument>(Ptr) ||
438 52 : isa<Constant>(Ptr) || isa<GlobalValue>(Ptr))
439 : return true;
440 :
441 24 : if (MMO->getAddrSpace() == AMDGPUAS::CONSTANT_ADDRESS_32BIT)
442 : return true;
443 :
444 : const Instruction *I = dyn_cast<Instruction>(Ptr);
445 24 : return I && I->getMetadata("amdgpu.uniform");
446 : }
447 :
448 : static unsigned getSmrdOpcode(unsigned BaseOpcode, unsigned LoadSize) {
449 :
450 42 : if (LoadSize == 32)
451 : return BaseOpcode;
452 :
453 : switch (BaseOpcode) {
454 12 : case AMDGPU::S_LOAD_DWORD_IMM:
455 : switch (LoadSize) {
456 : case 64:
457 : return AMDGPU::S_LOAD_DWORDX2_IMM;
458 0 : case 128:
459 : return AMDGPU::S_LOAD_DWORDX4_IMM;
460 0 : case 256:
461 : return AMDGPU::S_LOAD_DWORDX8_IMM;
462 0 : case 512:
463 : return AMDGPU::S_LOAD_DWORDX16_IMM;
464 : }
465 : break;
466 0 : case AMDGPU::S_LOAD_DWORD_IMM_ci:
467 : switch (LoadSize) {
468 : case 64:
469 : return AMDGPU::S_LOAD_DWORDX2_IMM_ci;
470 0 : case 128:
471 : return AMDGPU::S_LOAD_DWORDX4_IMM_ci;
472 0 : case 256:
473 : return AMDGPU::S_LOAD_DWORDX8_IMM_ci;
474 0 : case 512:
475 : return AMDGPU::S_LOAD_DWORDX16_IMM_ci;
476 : }
477 : break;
478 0 : case AMDGPU::S_LOAD_DWORD_SGPR:
479 : switch (LoadSize) {
480 : case 64:
481 : return AMDGPU::S_LOAD_DWORDX2_SGPR;
482 0 : case 128:
483 : return AMDGPU::S_LOAD_DWORDX4_SGPR;
484 0 : case 256:
485 : return AMDGPU::S_LOAD_DWORDX8_SGPR;
486 0 : case 512:
487 : return AMDGPU::S_LOAD_DWORDX16_SGPR;
488 : }
489 : break;
490 : }
491 0 : llvm_unreachable("Invalid base smrd opcode or size");
492 : }
493 :
494 52 : bool AMDGPUInstructionSelector::hasVgprParts(ArrayRef<GEPInfo> AddrInfo) const {
495 103 : for (const GEPInfo &GEPInfo : AddrInfo) {
496 51 : if (!GEPInfo.VgprParts.empty())
497 : return true;
498 : }
499 : return false;
500 : }
501 :
502 55 : bool AMDGPUInstructionSelector::selectSMRD(MachineInstr &I,
503 : ArrayRef<GEPInfo> AddrInfo) const {
504 :
505 55 : if (!I.hasOneMemOperand())
506 : return false;
507 :
508 58 : if ((*I.memoperands_begin())->getAddrSpace() != AMDGPUAS::CONSTANT_ADDRESS &&
509 3 : (*I.memoperands_begin())->getAddrSpace() != AMDGPUAS::CONSTANT_ADDRESS_32BIT)
510 : return false;
511 :
512 52 : if (!isInstrUniform(I))
513 : return false;
514 :
515 52 : if (hasVgprParts(AddrInfo))
516 : return false;
517 :
518 52 : MachineBasicBlock *BB = I.getParent();
519 52 : MachineFunction *MF = BB->getParent();
520 52 : const GCNSubtarget &Subtarget = MF->getSubtarget<GCNSubtarget>();
521 52 : MachineRegisterInfo &MRI = MF->getRegInfo();
522 52 : unsigned DstReg = I.getOperand(0).getReg();
523 : const DebugLoc &DL = I.getDebugLoc();
524 : unsigned Opcode;
525 52 : unsigned LoadSize = RBI.getSizeInBits(DstReg, MRI, TRI);
526 :
527 52 : if (!AddrInfo.empty() && AddrInfo[0].SgprParts.size() == 1) {
528 :
529 : const GEPInfo &GEPInfo = AddrInfo[0];
530 :
531 51 : unsigned PtrReg = GEPInfo.SgprParts[0];
532 51 : int64_t EncodedImm = AMDGPU::getSMRDEncodedOffset(Subtarget, GEPInfo.Imm);
533 51 : if (AMDGPU::isLegalSMRDImmOffset(Subtarget, GEPInfo.Imm)) {
534 : Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_IMM, LoadSize);
535 :
536 26 : MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg)
537 26 : .addReg(PtrReg)
538 : .addImm(EncodedImm)
539 26 : .addImm(0); // glc
540 26 : return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI);
541 : }
542 :
543 25 : if (Subtarget.getGeneration() == AMDGPUSubtarget::SEA_ISLANDS &&
544 11 : isUInt<32>(EncodedImm)) {
545 : Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_IMM_ci, LoadSize);
546 9 : MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg)
547 9 : .addReg(PtrReg)
548 : .addImm(EncodedImm)
549 9 : .addImm(0); // glc
550 9 : return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI);
551 : }
552 :
553 16 : if (isUInt<32>(GEPInfo.Imm)) {
554 : Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_SGPR, LoadSize);
555 7 : unsigned OffsetReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
556 7 : BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_MOV_B32), OffsetReg)
557 7 : .addImm(GEPInfo.Imm);
558 :
559 7 : MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg)
560 7 : .addReg(PtrReg)
561 7 : .addReg(OffsetReg)
562 7 : .addImm(0); // glc
563 7 : return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI);
564 : }
565 : }
566 :
567 10 : unsigned PtrReg = I.getOperand(1).getReg();
568 : Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_IMM, LoadSize);
569 10 : MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg)
570 10 : .addReg(PtrReg)
571 : .addImm(0)
572 10 : .addImm(0); // glc
573 10 : return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI);
574 : }
575 :
576 :
577 55 : bool AMDGPUInstructionSelector::selectG_LOAD(MachineInstr &I) const {
578 55 : MachineBasicBlock *BB = I.getParent();
579 55 : MachineFunction *MF = BB->getParent();
580 55 : MachineRegisterInfo &MRI = MF->getRegInfo();
581 : DebugLoc DL = I.getDebugLoc();
582 55 : unsigned DstReg = I.getOperand(0).getReg();
583 55 : unsigned PtrReg = I.getOperand(1).getReg();
584 55 : unsigned LoadSize = RBI.getSizeInBits(DstReg, MRI, TRI);
585 : unsigned Opcode;
586 :
587 55 : SmallVector<GEPInfo, 4> AddrInfo;
588 :
589 55 : getAddrModeInfo(I, MRI, AddrInfo);
590 :
591 55 : if (selectSMRD(I, AddrInfo)) {
592 52 : I.eraseFromParent();
593 52 : return true;
594 : }
595 :
596 3 : switch (LoadSize) {
597 0 : default:
598 0 : llvm_unreachable("Load size not supported\n");
599 : case 32:
600 : Opcode = AMDGPU::FLAT_LOAD_DWORD;
601 : break;
602 0 : case 64:
603 : Opcode = AMDGPU::FLAT_LOAD_DWORDX2;
604 0 : break;
605 : }
606 :
607 3 : MachineInstr *Flat = BuildMI(*BB, &I, DL, TII.get(Opcode))
608 3 : .add(I.getOperand(0))
609 3 : .addReg(PtrReg)
610 : .addImm(0) // offset
611 : .addImm(0) // glc
612 3 : .addImm(0); // slc
613 :
614 3 : bool Ret = constrainSelectedInstRegOperands(*Flat, TII, TRI, RBI);
615 3 : I.eraseFromParent();
616 3 : return Ret;
617 : }
618 :
619 415 : bool AMDGPUInstructionSelector::select(MachineInstr &I,
620 : CodeGenCoverage &CoverageInfo) const {
621 :
622 830 : if (!isPreISelGenericOpcode(I.getOpcode())) {
623 153 : if (I.isCopy())
624 140 : return selectCOPY(I);
625 : return true;
626 : }
627 :
628 262 : switch (I.getOpcode()) {
629 38 : default:
630 38 : return selectImpl(I, CoverageInfo);
631 0 : case TargetOpcode::G_ADD:
632 0 : return selectG_ADD(I);
633 11 : case TargetOpcode::G_INTTOPTR:
634 : case TargetOpcode::G_BITCAST:
635 11 : return selectCOPY(I);
636 25 : case TargetOpcode::G_CONSTANT:
637 : case TargetOpcode::G_FCONSTANT:
638 25 : return selectG_CONSTANT(I);
639 9 : case TargetOpcode::G_GEP:
640 9 : return selectG_GEP(I);
641 20 : case TargetOpcode::G_IMPLICIT_DEF:
642 20 : return selectG_IMPLICIT_DEF(I);
643 31 : case TargetOpcode::G_INTRINSIC:
644 31 : return selectG_INTRINSIC(I, CoverageInfo);
645 4 : case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
646 4 : return selectG_INTRINSIC_W_SIDE_EFFECTS(I, CoverageInfo);
647 55 : case TargetOpcode::G_LOAD:
648 55 : return selectG_LOAD(I);
649 69 : case TargetOpcode::G_STORE:
650 69 : return selectG_STORE(I);
651 : }
652 : return false;
653 : }
654 :
655 : InstructionSelector::ComplexRendererFns
656 6 : AMDGPUInstructionSelector::selectVCSRC(MachineOperand &Root) const {
657 : return {{
658 6 : [=](MachineInstrBuilder &MIB) { MIB.add(Root); }
659 18 : }};
660 :
661 : }
662 :
663 : ///
664 : /// This will select either an SGPR or VGPR operand and will save us from
665 : /// having to write an extra tablegen pattern.
666 : InstructionSelector::ComplexRendererFns
667 20 : AMDGPUInstructionSelector::selectVSRC0(MachineOperand &Root) const {
668 : return {{
669 20 : [=](MachineInstrBuilder &MIB) { MIB.add(Root); }
670 60 : }};
671 : }
672 :
673 : InstructionSelector::ComplexRendererFns
674 20 : AMDGPUInstructionSelector::selectVOP3Mods0(MachineOperand &Root) const {
675 : return {{
676 20 : [=](MachineInstrBuilder &MIB) { MIB.add(Root); },
677 : [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }, // src0_mods
678 : [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }, // clamp
679 : [=](MachineInstrBuilder &MIB) { MIB.addImm(0); } // omod
680 120 : }};
681 : }
682 : InstructionSelector::ComplexRendererFns
683 2 : AMDGPUInstructionSelector::selectVOP3OMods(MachineOperand &Root) const {
684 : return {{
685 2 : [=](MachineInstrBuilder &MIB) { MIB.add(Root); },
686 : [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }, // clamp
687 : [=](MachineInstrBuilder &MIB) { MIB.addImm(0); } // omod
688 10 : }};
689 : }
690 :
691 : InstructionSelector::ComplexRendererFns
692 18 : AMDGPUInstructionSelector::selectVOP3Mods(MachineOperand &Root) const {
693 : return {{
694 18 : [=](MachineInstrBuilder &MIB) { MIB.add(Root); },
695 : [=](MachineInstrBuilder &MIB) { MIB.addImm(0); } // src_mods
696 72 : }};
697 : }
|