1 //===- SPIRVInstructionSelector.cpp ------------------------------*- C++ -*-==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the targeting of the InstructionSelector class for
10 // SPIRV.
11 // TODO: This should be generated by TableGen.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "SPIRV.h"
16 #include "SPIRVGlobalRegistry.h"
17 #include "SPIRVInstrInfo.h"
18 #include "SPIRVRegisterBankInfo.h"
19 #include "SPIRVRegisterInfo.h"
20 #include "SPIRVTargetMachine.h"
21 #include "SPIRVUtils.h"
22 #include "llvm/ADT/APFloat.h"
23 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
24 #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
25 #include "llvm/CodeGen/MachineInstrBuilder.h"
26 #include "llvm/CodeGen/MachineRegisterInfo.h"
27 #include "llvm/Support/Debug.h"
28 
29 #define DEBUG_TYPE "spirv-isel"
30 
31 using namespace llvm;
32 
33 namespace {
34 
35 #define GET_GLOBALISEL_PREDICATE_BITSET
36 #include "SPIRVGenGlobalISel.inc"
37 #undef GET_GLOBALISEL_PREDICATE_BITSET
38 
39 class SPIRVInstructionSelector : public InstructionSelector {
40   const SPIRVSubtarget &STI;
41   const SPIRVInstrInfo &TII;
42   const SPIRVRegisterInfo &TRI;
43   const RegisterBankInfo &RBI;
44   SPIRVGlobalRegistry &GR;
45   MachineRegisterInfo *MRI;
46 
47 public:
48   SPIRVInstructionSelector(const SPIRVTargetMachine &TM,
49                            const SPIRVSubtarget &ST,
50                            const RegisterBankInfo &RBI);
51   void setupMF(MachineFunction &MF, GISelKnownBits *KB,
52                CodeGenCoverage &CoverageInfo, ProfileSummaryInfo *PSI,
53                BlockFrequencyInfo *BFI) override;
54   // Common selection code. Instruction-specific selection occurs in spvSelect.
55   bool select(MachineInstr &I) override;
56   static const char *getName() { return DEBUG_TYPE; }
57 
58 #define GET_GLOBALISEL_PREDICATES_DECL
59 #include "SPIRVGenGlobalISel.inc"
60 #undef GET_GLOBALISEL_PREDICATES_DECL
61 
62 #define GET_GLOBALISEL_TEMPORARIES_DECL
63 #include "SPIRVGenGlobalISel.inc"
64 #undef GET_GLOBALISEL_TEMPORARIES_DECL
65 
66 private:
67   // tblgen-erated 'select' implementation, used as the initial selector for
68   // the patterns that don't require complex C++.
69   bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
70 
71   // All instruction-specific selection that didn't happen in "select()".
72   // Is basically a large Switch/Case delegating to all other select method.
73   bool spvSelect(Register ResVReg, const SPIRVType *ResType,
74                  MachineInstr &I) const;
75 
76   bool selectGlobalValue(Register ResVReg, MachineInstr &I,
77                          const MachineInstr *Init = nullptr) const;
78 
79   bool selectUnOpWithSrc(Register ResVReg, const SPIRVType *ResType,
80                          MachineInstr &I, Register SrcReg,
81                          unsigned Opcode) const;
82   bool selectUnOp(Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
83                   unsigned Opcode) const;
84 
85   bool selectLoad(Register ResVReg, const SPIRVType *ResType,
86                   MachineInstr &I) const;
87   bool selectStore(MachineInstr &I) const;
88 
89   bool selectMemOperation(Register ResVReg, MachineInstr &I) const;
90 
91   bool selectAtomicRMW(Register ResVReg, const SPIRVType *ResType,
92                        MachineInstr &I, unsigned NewOpcode) const;
93 
94   bool selectAtomicCmpXchg(Register ResVReg, const SPIRVType *ResType,
95                            MachineInstr &I) const;
96 
97   bool selectFence(MachineInstr &I) const;
98 
99   bool selectAddrSpaceCast(Register ResVReg, const SPIRVType *ResType,
100                            MachineInstr &I) const;
101 
102   bool selectBitreverse(Register ResVReg, const SPIRVType *ResType,
103                         MachineInstr &I) const;
104 
105   bool selectConstVector(Register ResVReg, const SPIRVType *ResType,
106                          MachineInstr &I) const;
107 
108   bool selectCmp(Register ResVReg, const SPIRVType *ResType,
109                  unsigned comparisonOpcode, MachineInstr &I) const;
110 
111   bool selectICmp(Register ResVReg, const SPIRVType *ResType,
112                   MachineInstr &I) const;
113   bool selectFCmp(Register ResVReg, const SPIRVType *ResType,
114                   MachineInstr &I) const;
115 
116   void renderImm32(MachineInstrBuilder &MIB, const MachineInstr &I,
117                    int OpIdx) const;
118   void renderFImm32(MachineInstrBuilder &MIB, const MachineInstr &I,
119                     int OpIdx) const;
120 
121   bool selectConst(Register ResVReg, const SPIRVType *ResType, const APInt &Imm,
122                    MachineInstr &I) const;
123 
124   bool selectSelect(Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
125                     bool IsSigned) const;
126   bool selectIToF(Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
127                   bool IsSigned, unsigned Opcode) const;
128   bool selectExt(Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
129                  bool IsSigned) const;
130 
131   bool selectTrunc(Register ResVReg, const SPIRVType *ResType,
132                    MachineInstr &I) const;
133 
134   bool selectIntToBool(Register IntReg, Register ResVReg,
135                        const SPIRVType *intTy, const SPIRVType *boolTy,
136                        MachineInstr &I) const;
137 
138   bool selectOpUndef(Register ResVReg, const SPIRVType *ResType,
139                      MachineInstr &I) const;
140   bool selectIntrinsic(Register ResVReg, const SPIRVType *ResType,
141                        MachineInstr &I) const;
142 
143   bool selectFrameIndex(Register ResVReg, const SPIRVType *ResType,
144                         MachineInstr &I) const;
145 
146   bool selectBranch(MachineInstr &I) const;
147   bool selectBranchCond(MachineInstr &I) const;
148 
149   bool selectPhi(Register ResVReg, const SPIRVType *ResType,
150                  MachineInstr &I) const;
151 
152   Register buildI32Constant(uint32_t Val, MachineInstr &I,
153                             const SPIRVType *ResType = nullptr) const;
154 
155   Register buildZerosVal(const SPIRVType *ResType, MachineInstr &I) const;
156   Register buildOnesVal(bool AllOnes, const SPIRVType *ResType,
157                         MachineInstr &I) const;
158 };
159 
160 } // end anonymous namespace
161 
162 #define GET_GLOBALISEL_IMPL
163 #include "SPIRVGenGlobalISel.inc"
164 #undef GET_GLOBALISEL_IMPL
165 
166 SPIRVInstructionSelector::SPIRVInstructionSelector(const SPIRVTargetMachine &TM,
167                                                    const SPIRVSubtarget &ST,
168                                                    const RegisterBankInfo &RBI)
169     : InstructionSelector(), STI(ST), TII(*ST.getInstrInfo()),
170       TRI(*ST.getRegisterInfo()), RBI(RBI), GR(*ST.getSPIRVGlobalRegistry()),
171 #define GET_GLOBALISEL_PREDICATES_INIT
172 #include "SPIRVGenGlobalISel.inc"
173 #undef GET_GLOBALISEL_PREDICATES_INIT
174 #define GET_GLOBALISEL_TEMPORARIES_INIT
175 #include "SPIRVGenGlobalISel.inc"
176 #undef GET_GLOBALISEL_TEMPORARIES_INIT
177 {
178 }
179 
180 void SPIRVInstructionSelector::setupMF(MachineFunction &MF, GISelKnownBits *KB,
181                                        CodeGenCoverage &CoverageInfo,
182                                        ProfileSummaryInfo *PSI,
183                                        BlockFrequencyInfo *BFI) {
184   MRI = &MF.getRegInfo();
185   GR.setCurrentFunc(MF);
186   InstructionSelector::setupMF(MF, KB, CoverageInfo, PSI, BFI);
187 }
188 
189 // Defined in SPIRVLegalizerInfo.cpp.
190 extern bool isTypeFoldingSupported(unsigned Opcode);
191 
192 bool SPIRVInstructionSelector::select(MachineInstr &I) {
193   assert(I.getParent() && "Instruction should be in a basic block!");
194   assert(I.getParent()->getParent() && "Instruction should be in a function!");
195 
196   Register Opcode = I.getOpcode();
197   // If it's not a GMIR instruction, we've selected it already.
198   if (!isPreISelGenericOpcode(Opcode)) {
199     if (Opcode == SPIRV::ASSIGN_TYPE) { // These pseudos aren't needed any more.
200       auto *Def = MRI->getVRegDef(I.getOperand(1).getReg());
201       if (isTypeFoldingSupported(Def->getOpcode())) {
202         auto Res = selectImpl(I, *CoverageInfo);
203         assert(Res || Def->getOpcode() == TargetOpcode::G_CONSTANT);
204         if (Res)
205           return Res;
206       }
207       MRI->replaceRegWith(I.getOperand(1).getReg(), I.getOperand(0).getReg());
208       I.removeFromParent();
209     } else if (I.getNumDefs() == 1) {
210       // Make all vregs 32 bits (for SPIR-V IDs).
211       MRI->setType(I.getOperand(0).getReg(), LLT::scalar(32));
212     }
213     return true;
214   }
215 
216   if (I.getNumOperands() != I.getNumExplicitOperands()) {
217     LLVM_DEBUG(errs() << "Generic instr has unexpected implicit operands\n");
218     return false;
219   }
220 
221   // Common code for getting return reg+type, and removing selected instr
222   // from parent occurs here. Instr-specific selection happens in spvSelect().
223   bool HasDefs = I.getNumDefs() > 0;
224   Register ResVReg = HasDefs ? I.getOperand(0).getReg() : Register(0);
225   SPIRVType *ResType = HasDefs ? GR.getSPIRVTypeForVReg(ResVReg) : nullptr;
226   assert(!HasDefs || ResType || I.getOpcode() == TargetOpcode::G_GLOBAL_VALUE);
227   if (spvSelect(ResVReg, ResType, I)) {
228     if (HasDefs) // Make all vregs 32 bits (for SPIR-V IDs).
229       MRI->setType(ResVReg, LLT::scalar(32));
230     I.removeFromParent();
231     return true;
232   }
233   return false;
234 }
235 
236 bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
237                                          const SPIRVType *ResType,
238                                          MachineInstr &I) const {
239   assert(!isTypeFoldingSupported(I.getOpcode()) ||
240          I.getOpcode() == TargetOpcode::G_CONSTANT);
241   const unsigned Opcode = I.getOpcode();
242   switch (Opcode) {
243   case TargetOpcode::G_CONSTANT:
244     return selectConst(ResVReg, ResType, I.getOperand(1).getCImm()->getValue(),
245                        I);
246   case TargetOpcode::G_GLOBAL_VALUE:
247     return selectGlobalValue(ResVReg, I);
248   case TargetOpcode::G_IMPLICIT_DEF:
249     return selectOpUndef(ResVReg, ResType, I);
250 
251   case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
252     return selectIntrinsic(ResVReg, ResType, I);
253   case TargetOpcode::G_BITREVERSE:
254     return selectBitreverse(ResVReg, ResType, I);
255 
256   case TargetOpcode::G_BUILD_VECTOR:
257     return selectConstVector(ResVReg, ResType, I);
258 
259   case TargetOpcode::G_SHUFFLE_VECTOR: {
260     MachineBasicBlock &BB = *I.getParent();
261     auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpVectorShuffle))
262                    .addDef(ResVReg)
263                    .addUse(GR.getSPIRVTypeID(ResType))
264                    .addUse(I.getOperand(1).getReg())
265                    .addUse(I.getOperand(2).getReg());
266     for (auto V : I.getOperand(3).getShuffleMask())
267       MIB.addImm(V);
268     return MIB.constrainAllUses(TII, TRI, RBI);
269   }
270   case TargetOpcode::G_MEMMOVE:
271   case TargetOpcode::G_MEMCPY:
272     return selectMemOperation(ResVReg, I);
273 
274   case TargetOpcode::G_ICMP:
275     return selectICmp(ResVReg, ResType, I);
276   case TargetOpcode::G_FCMP:
277     return selectFCmp(ResVReg, ResType, I);
278 
279   case TargetOpcode::G_FRAME_INDEX:
280     return selectFrameIndex(ResVReg, ResType, I);
281 
282   case TargetOpcode::G_LOAD:
283     return selectLoad(ResVReg, ResType, I);
284   case TargetOpcode::G_STORE:
285     return selectStore(I);
286 
287   case TargetOpcode::G_BR:
288     return selectBranch(I);
289   case TargetOpcode::G_BRCOND:
290     return selectBranchCond(I);
291 
292   case TargetOpcode::G_PHI:
293     return selectPhi(ResVReg, ResType, I);
294 
295   case TargetOpcode::G_FPTOSI:
296     return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertFToS);
297   case TargetOpcode::G_FPTOUI:
298     return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertFToU);
299 
300   case TargetOpcode::G_SITOFP:
301     return selectIToF(ResVReg, ResType, I, true, SPIRV::OpConvertSToF);
302   case TargetOpcode::G_UITOFP:
303     return selectIToF(ResVReg, ResType, I, false, SPIRV::OpConvertUToF);
304 
305   case TargetOpcode::G_CTPOP:
306     return selectUnOp(ResVReg, ResType, I, SPIRV::OpBitCount);
307 
308   case TargetOpcode::G_SEXT:
309     return selectExt(ResVReg, ResType, I, true);
310   case TargetOpcode::G_ANYEXT:
311   case TargetOpcode::G_ZEXT:
312     return selectExt(ResVReg, ResType, I, false);
313   case TargetOpcode::G_TRUNC:
314     return selectTrunc(ResVReg, ResType, I);
315   case TargetOpcode::G_FPTRUNC:
316   case TargetOpcode::G_FPEXT:
317     return selectUnOp(ResVReg, ResType, I, SPIRV::OpFConvert);
318 
319   case TargetOpcode::G_PTRTOINT:
320     return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertPtrToU);
321   case TargetOpcode::G_INTTOPTR:
322     return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertUToPtr);
323   case TargetOpcode::G_BITCAST:
324     return selectUnOp(ResVReg, ResType, I, SPIRV::OpBitcast);
325   case TargetOpcode::G_ADDRSPACE_CAST:
326     return selectAddrSpaceCast(ResVReg, ResType, I);
327 
328   case TargetOpcode::G_ATOMICRMW_OR:
329     return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicOr);
330   case TargetOpcode::G_ATOMICRMW_ADD:
331     return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicIAdd);
332   case TargetOpcode::G_ATOMICRMW_AND:
333     return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicAnd);
334   case TargetOpcode::G_ATOMICRMW_MAX:
335     return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicSMax);
336   case TargetOpcode::G_ATOMICRMW_MIN:
337     return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicSMin);
338   case TargetOpcode::G_ATOMICRMW_SUB:
339     return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicISub);
340   case TargetOpcode::G_ATOMICRMW_XOR:
341     return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicXor);
342   case TargetOpcode::G_ATOMICRMW_UMAX:
343     return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicUMax);
344   case TargetOpcode::G_ATOMICRMW_UMIN:
345     return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicUMin);
346   case TargetOpcode::G_ATOMICRMW_XCHG:
347     return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicExchange);
348   case TargetOpcode::G_ATOMIC_CMPXCHG:
349     return selectAtomicCmpXchg(ResVReg, ResType, I);
350 
351   case TargetOpcode::G_FENCE:
352     return selectFence(I);
353 
354   default:
355     return false;
356   }
357 }
358 
359 bool SPIRVInstructionSelector::selectUnOpWithSrc(Register ResVReg,
360                                                  const SPIRVType *ResType,
361                                                  MachineInstr &I,
362                                                  Register SrcReg,
363                                                  unsigned Opcode) const {
364   return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode))
365       .addDef(ResVReg)
366       .addUse(GR.getSPIRVTypeID(ResType))
367       .addUse(SrcReg)
368       .constrainAllUses(TII, TRI, RBI);
369 }
370 
371 bool SPIRVInstructionSelector::selectUnOp(Register ResVReg,
372                                           const SPIRVType *ResType,
373                                           MachineInstr &I,
374                                           unsigned Opcode) const {
375   return selectUnOpWithSrc(ResVReg, ResType, I, I.getOperand(1).getReg(),
376                            Opcode);
377 }
378 
379 static SPIRV::MemorySemantics getMemSemantics(AtomicOrdering Ord) {
380   switch (Ord) {
381   case AtomicOrdering::Acquire:
382     return SPIRV::MemorySemantics::Acquire;
383   case AtomicOrdering::Release:
384     return SPIRV::MemorySemantics::Release;
385   case AtomicOrdering::AcquireRelease:
386     return SPIRV::MemorySemantics::AcquireRelease;
387   case AtomicOrdering::SequentiallyConsistent:
388     return SPIRV::MemorySemantics::SequentiallyConsistent;
389   case AtomicOrdering::Unordered:
390   case AtomicOrdering::Monotonic:
391   case AtomicOrdering::NotAtomic:
392   default:
393     return SPIRV::MemorySemantics::None;
394   }
395 }
396 
397 static SPIRV::Scope getScope(SyncScope::ID Ord) {
398   switch (Ord) {
399   case SyncScope::SingleThread:
400     return SPIRV::Scope::Invocation;
401   case SyncScope::System:
402     return SPIRV::Scope::Device;
403   default:
404     llvm_unreachable("Unsupported synchronization Scope ID.");
405   }
406 }
407 
408 static void addMemoryOperands(MachineMemOperand *MemOp,
409                               MachineInstrBuilder &MIB) {
410   uint32_t SpvMemOp = static_cast<uint32_t>(SPIRV::MemoryOperand::None);
411   if (MemOp->isVolatile())
412     SpvMemOp |= static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
413   if (MemOp->isNonTemporal())
414     SpvMemOp |= static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);
415   if (MemOp->getAlign().value())
416     SpvMemOp |= static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned);
417 
418   if (SpvMemOp != static_cast<uint32_t>(SPIRV::MemoryOperand::None)) {
419     MIB.addImm(SpvMemOp);
420     if (SpvMemOp & static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned))
421       MIB.addImm(MemOp->getAlign().value());
422   }
423 }
424 
425 static void addMemoryOperands(uint64_t Flags, MachineInstrBuilder &MIB) {
426   uint32_t SpvMemOp = static_cast<uint32_t>(SPIRV::MemoryOperand::None);
427   if (Flags & MachineMemOperand::Flags::MOVolatile)
428     SpvMemOp |= static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
429   if (Flags & MachineMemOperand::Flags::MONonTemporal)
430     SpvMemOp |= static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);
431 
432   if (SpvMemOp != static_cast<uint32_t>(SPIRV::MemoryOperand::None))
433     MIB.addImm(SpvMemOp);
434 }
435 
436 bool SPIRVInstructionSelector::selectLoad(Register ResVReg,
437                                           const SPIRVType *ResType,
438                                           MachineInstr &I) const {
439   unsigned OpOffset =
440       I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ? 1 : 0;
441   Register Ptr = I.getOperand(1 + OpOffset).getReg();
442   auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpLoad))
443                  .addDef(ResVReg)
444                  .addUse(GR.getSPIRVTypeID(ResType))
445                  .addUse(Ptr);
446   if (!I.getNumMemOperands()) {
447     assert(I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS);
448     addMemoryOperands(I.getOperand(2 + OpOffset).getImm(), MIB);
449   } else {
450     addMemoryOperands(*I.memoperands_begin(), MIB);
451   }
452   return MIB.constrainAllUses(TII, TRI, RBI);
453 }
454 
455 bool SPIRVInstructionSelector::selectStore(MachineInstr &I) const {
456   unsigned OpOffset =
457       I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ? 1 : 0;
458   Register StoreVal = I.getOperand(0 + OpOffset).getReg();
459   Register Ptr = I.getOperand(1 + OpOffset).getReg();
460   MachineBasicBlock &BB = *I.getParent();
461   auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpStore))
462                  .addUse(Ptr)
463                  .addUse(StoreVal);
464   if (!I.getNumMemOperands()) {
465     assert(I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS);
466     addMemoryOperands(I.getOperand(2 + OpOffset).getImm(), MIB);
467   } else {
468     addMemoryOperands(*I.memoperands_begin(), MIB);
469   }
470   return MIB.constrainAllUses(TII, TRI, RBI);
471 }
472 
473 bool SPIRVInstructionSelector::selectMemOperation(Register ResVReg,
474                                                   MachineInstr &I) const {
475   MachineBasicBlock &BB = *I.getParent();
476   auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpCopyMemorySized))
477                  .addDef(I.getOperand(0).getReg())
478                  .addUse(I.getOperand(1).getReg())
479                  .addUse(I.getOperand(2).getReg());
480   if (I.getNumMemOperands())
481     addMemoryOperands(*I.memoperands_begin(), MIB);
482   bool Result = MIB.constrainAllUses(TII, TRI, RBI);
483   if (ResVReg.isValid() && ResVReg != MIB->getOperand(0).getReg()) {
484     BuildMI(BB, I, I.getDebugLoc(), TII.get(TargetOpcode::COPY), ResVReg)
485         .addUse(MIB->getOperand(0).getReg());
486   }
487   return Result;
488 }
489 
490 bool SPIRVInstructionSelector::selectAtomicRMW(Register ResVReg,
491                                                const SPIRVType *ResType,
492                                                MachineInstr &I,
493                                                unsigned NewOpcode) const {
494   assert(I.hasOneMemOperand());
495   const MachineMemOperand *MemOp = *I.memoperands_begin();
496   uint32_t Scope = static_cast<uint32_t>(getScope(MemOp->getSyncScopeID()));
497   Register ScopeReg = buildI32Constant(Scope, I);
498 
499   Register Ptr = I.getOperand(1).getReg();
500   // TODO: Changed as it's implemented in the translator. See test/atomicrmw.ll
501   // auto ScSem =
502   // getMemSemanticsForStorageClass(GR.getPointerStorageClass(Ptr));
503   AtomicOrdering AO = MemOp->getSuccessOrdering();
504   uint32_t MemSem = static_cast<uint32_t>(getMemSemantics(AO));
505   Register MemSemReg = buildI32Constant(MemSem /*| ScSem*/, I);
506 
507   return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(NewOpcode))
508       .addDef(ResVReg)
509       .addUse(GR.getSPIRVTypeID(ResType))
510       .addUse(Ptr)
511       .addUse(ScopeReg)
512       .addUse(MemSemReg)
513       .addUse(I.getOperand(2).getReg())
514       .constrainAllUses(TII, TRI, RBI);
515 }
516 
517 bool SPIRVInstructionSelector::selectFence(MachineInstr &I) const {
518   AtomicOrdering AO = AtomicOrdering(I.getOperand(0).getImm());
519   uint32_t MemSem = static_cast<uint32_t>(getMemSemantics(AO));
520   Register MemSemReg = buildI32Constant(MemSem, I);
521   SyncScope::ID Ord = SyncScope::ID(I.getOperand(1).getImm());
522   uint32_t Scope = static_cast<uint32_t>(getScope(Ord));
523   Register ScopeReg = buildI32Constant(Scope, I);
524   MachineBasicBlock &BB = *I.getParent();
525   return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpMemoryBarrier))
526       .addUse(ScopeReg)
527       .addUse(MemSemReg)
528       .constrainAllUses(TII, TRI, RBI);
529 }
530 
531 bool SPIRVInstructionSelector::selectAtomicCmpXchg(Register ResVReg,
532                                                    const SPIRVType *ResType,
533                                                    MachineInstr &I) const {
534   assert(I.hasOneMemOperand());
535   const MachineMemOperand *MemOp = *I.memoperands_begin();
536   uint32_t Scope = static_cast<uint32_t>(getScope(MemOp->getSyncScopeID()));
537   Register ScopeReg = buildI32Constant(Scope, I);
538 
539   Register Ptr = I.getOperand(2).getReg();
540   Register Cmp = I.getOperand(3).getReg();
541   Register Val = I.getOperand(4).getReg();
542 
543   SPIRVType *SpvValTy = GR.getSPIRVTypeForVReg(Val);
544   SPIRV::StorageClass SC = GR.getPointerStorageClass(Ptr);
545   uint32_t ScSem = static_cast<uint32_t>(getMemSemanticsForStorageClass(SC));
546   AtomicOrdering AO = MemOp->getSuccessOrdering();
547   uint32_t MemSemEq = static_cast<uint32_t>(getMemSemantics(AO)) | ScSem;
548   Register MemSemEqReg = buildI32Constant(MemSemEq, I);
549   AtomicOrdering FO = MemOp->getFailureOrdering();
550   uint32_t MemSemNeq = static_cast<uint32_t>(getMemSemantics(FO)) | ScSem;
551   Register MemSemNeqReg =
552       MemSemEq == MemSemNeq ? MemSemEqReg : buildI32Constant(MemSemNeq, I);
553   const DebugLoc &DL = I.getDebugLoc();
554   return BuildMI(*I.getParent(), I, DL, TII.get(SPIRV::OpAtomicCompareExchange))
555       .addDef(ResVReg)
556       .addUse(GR.getSPIRVTypeID(SpvValTy))
557       .addUse(Ptr)
558       .addUse(ScopeReg)
559       .addUse(MemSemEqReg)
560       .addUse(MemSemNeqReg)
561       .addUse(Val)
562       .addUse(Cmp)
563       .constrainAllUses(TII, TRI, RBI);
564 }
565 
566 static bool isGenericCastablePtr(SPIRV::StorageClass SC) {
567   switch (SC) {
568   case SPIRV::StorageClass::Workgroup:
569   case SPIRV::StorageClass::CrossWorkgroup:
570   case SPIRV::StorageClass::Function:
571     return true;
572   default:
573     return false;
574   }
575 }
576 
577 // In SPIR-V address space casting can only happen to and from the Generic
578 // storage class. We can also only case Workgroup, CrossWorkgroup, or Function
579 // pointers to and from Generic pointers. As such, we can convert e.g. from
580 // Workgroup to Function by going via a Generic pointer as an intermediary. All
581 // other combinations can only be done by a bitcast, and are probably not safe.
582 bool SPIRVInstructionSelector::selectAddrSpaceCast(Register ResVReg,
583                                                    const SPIRVType *ResType,
584                                                    MachineInstr &I) const {
585   Register SrcPtr = I.getOperand(1).getReg();
586   SPIRVType *SrcPtrTy = GR.getSPIRVTypeForVReg(SrcPtr);
587   SPIRV::StorageClass SrcSC = GR.getPointerStorageClass(SrcPtr);
588   SPIRV::StorageClass DstSC = GR.getPointerStorageClass(ResVReg);
589 
590   // Casting from an eligable pointer to Generic.
591   if (DstSC == SPIRV::StorageClass::Generic && isGenericCastablePtr(SrcSC))
592     return selectUnOp(ResVReg, ResType, I, SPIRV::OpPtrCastToGeneric);
593   // Casting from Generic to an eligable pointer.
594   if (SrcSC == SPIRV::StorageClass::Generic && isGenericCastablePtr(DstSC))
595     return selectUnOp(ResVReg, ResType, I, SPIRV::OpGenericCastToPtr);
596   // Casting between 2 eligable pointers using Generic as an intermediary.
597   if (isGenericCastablePtr(SrcSC) && isGenericCastablePtr(DstSC)) {
598     Register Tmp = MRI->createVirtualRegister(&SPIRV::IDRegClass);
599     SPIRVType *GenericPtrTy = GR.getOrCreateSPIRVPointerType(
600         SrcPtrTy, I, TII, SPIRV::StorageClass::Generic);
601     MachineBasicBlock &BB = *I.getParent();
602     const DebugLoc &DL = I.getDebugLoc();
603     bool Success = BuildMI(BB, I, DL, TII.get(SPIRV::OpPtrCastToGeneric))
604                        .addDef(Tmp)
605                        .addUse(GR.getSPIRVTypeID(GenericPtrTy))
606                        .addUse(SrcPtr)
607                        .constrainAllUses(TII, TRI, RBI);
608     return Success && BuildMI(BB, I, DL, TII.get(SPIRV::OpGenericCastToPtr))
609                           .addDef(ResVReg)
610                           .addUse(GR.getSPIRVTypeID(ResType))
611                           .addUse(Tmp)
612                           .constrainAllUses(TII, TRI, RBI);
613   }
614   // TODO Should this case just be disallowed completely?
615   // We're casting 2 other arbitrary address spaces, so have to bitcast.
616   return selectUnOp(ResVReg, ResType, I, SPIRV::OpBitcast);
617 }
618 
619 static unsigned getFCmpOpcode(unsigned PredNum) {
620   auto Pred = static_cast<CmpInst::Predicate>(PredNum);
621   switch (Pred) {
622   case CmpInst::FCMP_OEQ:
623     return SPIRV::OpFOrdEqual;
624   case CmpInst::FCMP_OGE:
625     return SPIRV::OpFOrdGreaterThanEqual;
626   case CmpInst::FCMP_OGT:
627     return SPIRV::OpFOrdGreaterThan;
628   case CmpInst::FCMP_OLE:
629     return SPIRV::OpFOrdLessThanEqual;
630   case CmpInst::FCMP_OLT:
631     return SPIRV::OpFOrdLessThan;
632   case CmpInst::FCMP_ONE:
633     return SPIRV::OpFOrdNotEqual;
634   case CmpInst::FCMP_ORD:
635     return SPIRV::OpOrdered;
636   case CmpInst::FCMP_UEQ:
637     return SPIRV::OpFUnordEqual;
638   case CmpInst::FCMP_UGE:
639     return SPIRV::OpFUnordGreaterThanEqual;
640   case CmpInst::FCMP_UGT:
641     return SPIRV::OpFUnordGreaterThan;
642   case CmpInst::FCMP_ULE:
643     return SPIRV::OpFUnordLessThanEqual;
644   case CmpInst::FCMP_ULT:
645     return SPIRV::OpFUnordLessThan;
646   case CmpInst::FCMP_UNE:
647     return SPIRV::OpFUnordNotEqual;
648   case CmpInst::FCMP_UNO:
649     return SPIRV::OpUnordered;
650   default:
651     llvm_unreachable("Unknown predicate type for FCmp");
652   }
653 }
654 
655 static unsigned getICmpOpcode(unsigned PredNum) {
656   auto Pred = static_cast<CmpInst::Predicate>(PredNum);
657   switch (Pred) {
658   case CmpInst::ICMP_EQ:
659     return SPIRV::OpIEqual;
660   case CmpInst::ICMP_NE:
661     return SPIRV::OpINotEqual;
662   case CmpInst::ICMP_SGE:
663     return SPIRV::OpSGreaterThanEqual;
664   case CmpInst::ICMP_SGT:
665     return SPIRV::OpSGreaterThan;
666   case CmpInst::ICMP_SLE:
667     return SPIRV::OpSLessThanEqual;
668   case CmpInst::ICMP_SLT:
669     return SPIRV::OpSLessThan;
670   case CmpInst::ICMP_UGE:
671     return SPIRV::OpUGreaterThanEqual;
672   case CmpInst::ICMP_UGT:
673     return SPIRV::OpUGreaterThan;
674   case CmpInst::ICMP_ULE:
675     return SPIRV::OpULessThanEqual;
676   case CmpInst::ICMP_ULT:
677     return SPIRV::OpULessThan;
678   default:
679     llvm_unreachable("Unknown predicate type for ICmp");
680   }
681 }
682 
683 static unsigned getPtrCmpOpcode(unsigned Pred) {
684   switch (static_cast<CmpInst::Predicate>(Pred)) {
685   case CmpInst::ICMP_EQ:
686     return SPIRV::OpPtrEqual;
687   case CmpInst::ICMP_NE:
688     return SPIRV::OpPtrNotEqual;
689   default:
690     llvm_unreachable("Unknown predicate type for pointer comparison");
691   }
692 }
693 
694 // Return the logical operation, or abort if none exists.
695 static unsigned getBoolCmpOpcode(unsigned PredNum) {
696   auto Pred = static_cast<CmpInst::Predicate>(PredNum);
697   switch (Pred) {
698   case CmpInst::ICMP_EQ:
699     return SPIRV::OpLogicalEqual;
700   case CmpInst::ICMP_NE:
701     return SPIRV::OpLogicalNotEqual;
702   default:
703     llvm_unreachable("Unknown predicate type for Bool comparison");
704   }
705 }
706 
707 bool SPIRVInstructionSelector::selectBitreverse(Register ResVReg,
708                                                 const SPIRVType *ResType,
709                                                 MachineInstr &I) const {
710   MachineBasicBlock &BB = *I.getParent();
711   return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpBitReverse))
712       .addDef(ResVReg)
713       .addUse(GR.getSPIRVTypeID(ResType))
714       .addUse(I.getOperand(1).getReg())
715       .constrainAllUses(TII, TRI, RBI);
716 }
717 
718 bool SPIRVInstructionSelector::selectConstVector(Register ResVReg,
719                                                  const SPIRVType *ResType,
720                                                  MachineInstr &I) const {
721   // TODO: only const case is supported for now.
722   assert(std::all_of(
723       I.operands_begin(), I.operands_end(), [this](const MachineOperand &MO) {
724         if (MO.isDef())
725           return true;
726         if (!MO.isReg())
727           return false;
728         SPIRVType *ConstTy = this->MRI->getVRegDef(MO.getReg());
729         assert(ConstTy && ConstTy->getOpcode() == SPIRV::ASSIGN_TYPE &&
730                ConstTy->getOperand(1).isReg());
731         Register ConstReg = ConstTy->getOperand(1).getReg();
732         const MachineInstr *Const = this->MRI->getVRegDef(ConstReg);
733         assert(Const);
734         return (Const->getOpcode() == TargetOpcode::G_CONSTANT ||
735                 Const->getOpcode() == TargetOpcode::G_FCONSTANT);
736       }));
737 
738   auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
739                      TII.get(SPIRV::OpConstantComposite))
740                  .addDef(ResVReg)
741                  .addUse(GR.getSPIRVTypeID(ResType));
742   for (unsigned i = I.getNumExplicitDefs(); i < I.getNumExplicitOperands(); ++i)
743     MIB.addUse(I.getOperand(i).getReg());
744   return MIB.constrainAllUses(TII, TRI, RBI);
745 }
746 
747 bool SPIRVInstructionSelector::selectCmp(Register ResVReg,
748                                          const SPIRVType *ResType,
749                                          unsigned CmpOpc,
750                                          MachineInstr &I) const {
751   Register Cmp0 = I.getOperand(2).getReg();
752   Register Cmp1 = I.getOperand(3).getReg();
753   assert(GR.getSPIRVTypeForVReg(Cmp0)->getOpcode() ==
754              GR.getSPIRVTypeForVReg(Cmp1)->getOpcode() &&
755          "CMP operands should have the same type");
756   return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(CmpOpc))
757       .addDef(ResVReg)
758       .addUse(GR.getSPIRVTypeID(ResType))
759       .addUse(Cmp0)
760       .addUse(Cmp1)
761       .constrainAllUses(TII, TRI, RBI);
762 }
763 
764 bool SPIRVInstructionSelector::selectICmp(Register ResVReg,
765                                           const SPIRVType *ResType,
766                                           MachineInstr &I) const {
767   auto Pred = I.getOperand(1).getPredicate();
768   unsigned CmpOpc;
769 
770   Register CmpOperand = I.getOperand(2).getReg();
771   if (GR.isScalarOfType(CmpOperand, SPIRV::OpTypePointer))
772     CmpOpc = getPtrCmpOpcode(Pred);
773   else if (GR.isScalarOrVectorOfType(CmpOperand, SPIRV::OpTypeBool))
774     CmpOpc = getBoolCmpOpcode(Pred);
775   else
776     CmpOpc = getICmpOpcode(Pred);
777   return selectCmp(ResVReg, ResType, CmpOpc, I);
778 }
779 
780 void SPIRVInstructionSelector::renderFImm32(MachineInstrBuilder &MIB,
781                                             const MachineInstr &I,
782                                             int OpIdx) const {
783   assert(I.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 &&
784          "Expected G_FCONSTANT");
785   const ConstantFP *FPImm = I.getOperand(1).getFPImm();
786   addNumImm(FPImm->getValueAPF().bitcastToAPInt(), MIB);
787 }
788 
789 void SPIRVInstructionSelector::renderImm32(MachineInstrBuilder &MIB,
790                                            const MachineInstr &I,
791                                            int OpIdx) const {
792   assert(I.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
793          "Expected G_CONSTANT");
794   addNumImm(I.getOperand(1).getCImm()->getValue(), MIB);
795 }
796 
797 Register
798 SPIRVInstructionSelector::buildI32Constant(uint32_t Val, MachineInstr &I,
799                                            const SPIRVType *ResType) const {
800   const SPIRVType *SpvI32Ty =
801       ResType ? ResType : GR.getOrCreateSPIRVIntegerType(32, I, TII);
802   Register NewReg;
803   NewReg = MRI->createGenericVirtualRegister(LLT::scalar(32));
804   MachineInstr *MI;
805   MachineBasicBlock &BB = *I.getParent();
806   if (Val == 0) {
807     MI = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
808              .addDef(NewReg)
809              .addUse(GR.getSPIRVTypeID(SpvI32Ty));
810   } else {
811     MI = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantI))
812              .addDef(NewReg)
813              .addUse(GR.getSPIRVTypeID(SpvI32Ty))
814              .addImm(APInt(32, Val).getZExtValue());
815   }
816   constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
817   return NewReg;
818 }
819 
820 bool SPIRVInstructionSelector::selectFCmp(Register ResVReg,
821                                           const SPIRVType *ResType,
822                                           MachineInstr &I) const {
823   unsigned CmpOp = getFCmpOpcode(I.getOperand(1).getPredicate());
824   return selectCmp(ResVReg, ResType, CmpOp, I);
825 }
826 
827 Register SPIRVInstructionSelector::buildZerosVal(const SPIRVType *ResType,
828                                                  MachineInstr &I) const {
829   return buildI32Constant(0, I, ResType);
830 }
831 
832 Register SPIRVInstructionSelector::buildOnesVal(bool AllOnes,
833                                                 const SPIRVType *ResType,
834                                                 MachineInstr &I) const {
835   unsigned BitWidth = GR.getScalarOrVectorBitWidth(ResType);
836   APInt One = AllOnes ? APInt::getAllOnesValue(BitWidth)
837                       : APInt::getOneBitSet(BitWidth, 0);
838   Register OneReg = buildI32Constant(One.getZExtValue(), I, ResType);
839   if (ResType->getOpcode() == SPIRV::OpTypeVector) {
840     const unsigned NumEles = ResType->getOperand(2).getImm();
841     Register OneVec = MRI->createVirtualRegister(&SPIRV::IDRegClass);
842     unsigned Opcode = SPIRV::OpConstantComposite;
843     auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode))
844                    .addDef(OneVec)
845                    .addUse(GR.getSPIRVTypeID(ResType));
846     for (unsigned i = 0; i < NumEles; ++i)
847       MIB.addUse(OneReg);
848     constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
849     return OneVec;
850   }
851   return OneReg;
852 }
853 
854 bool SPIRVInstructionSelector::selectSelect(Register ResVReg,
855                                             const SPIRVType *ResType,
856                                             MachineInstr &I,
857                                             bool IsSigned) const {
858   // To extend a bool, we need to use OpSelect between constants.
859   Register ZeroReg = buildZerosVal(ResType, I);
860   Register OneReg = buildOnesVal(IsSigned, ResType, I);
861   bool IsScalarBool =
862       GR.isScalarOfType(I.getOperand(1).getReg(), SPIRV::OpTypeBool);
863   unsigned Opcode =
864       IsScalarBool ? SPIRV::OpSelectSISCond : SPIRV::OpSelectSIVCond;
865   return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode))
866       .addDef(ResVReg)
867       .addUse(GR.getSPIRVTypeID(ResType))
868       .addUse(I.getOperand(1).getReg())
869       .addUse(OneReg)
870       .addUse(ZeroReg)
871       .constrainAllUses(TII, TRI, RBI);
872 }
873 
874 bool SPIRVInstructionSelector::selectIToF(Register ResVReg,
875                                           const SPIRVType *ResType,
876                                           MachineInstr &I, bool IsSigned,
877                                           unsigned Opcode) const {
878   Register SrcReg = I.getOperand(1).getReg();
879   // We can convert bool value directly to float type without OpConvert*ToF,
880   // however the translator generates OpSelect+OpConvert*ToF, so we do the same.
881   if (GR.isScalarOrVectorOfType(I.getOperand(1).getReg(), SPIRV::OpTypeBool)) {
882     unsigned BitWidth = GR.getScalarOrVectorBitWidth(ResType);
883     SPIRVType *TmpType = GR.getOrCreateSPIRVIntegerType(BitWidth, I, TII);
884     if (ResType->getOpcode() == SPIRV::OpTypeVector) {
885       const unsigned NumElts = ResType->getOperand(2).getImm();
886       TmpType = GR.getOrCreateSPIRVVectorType(TmpType, NumElts, I, TII);
887     }
888     SrcReg = MRI->createVirtualRegister(&SPIRV::IDRegClass);
889     selectSelect(SrcReg, TmpType, I, false);
890   }
891   return selectUnOpWithSrc(ResVReg, ResType, I, SrcReg, Opcode);
892 }
893 
894 bool SPIRVInstructionSelector::selectExt(Register ResVReg,
895                                          const SPIRVType *ResType,
896                                          MachineInstr &I, bool IsSigned) const {
897   if (GR.isScalarOrVectorOfType(I.getOperand(1).getReg(), SPIRV::OpTypeBool))
898     return selectSelect(ResVReg, ResType, I, IsSigned);
899   unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
900   return selectUnOp(ResVReg, ResType, I, Opcode);
901 }
902 
903 bool SPIRVInstructionSelector::selectIntToBool(Register IntReg,
904                                                Register ResVReg,
905                                                const SPIRVType *IntTy,
906                                                const SPIRVType *BoolTy,
907                                                MachineInstr &I) const {
908   // To truncate to a bool, we use OpBitwiseAnd 1 and OpINotEqual to zero.
909   Register BitIntReg = MRI->createVirtualRegister(&SPIRV::IDRegClass);
910   bool IsVectorTy = IntTy->getOpcode() == SPIRV::OpTypeVector;
911   unsigned Opcode = IsVectorTy ? SPIRV::OpBitwiseAndV : SPIRV::OpBitwiseAndS;
912   Register Zero = buildZerosVal(IntTy, I);
913   Register One = buildOnesVal(false, IntTy, I);
914   MachineBasicBlock &BB = *I.getParent();
915   BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
916       .addDef(BitIntReg)
917       .addUse(GR.getSPIRVTypeID(IntTy))
918       .addUse(IntReg)
919       .addUse(One)
920       .constrainAllUses(TII, TRI, RBI);
921   return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpINotEqual))
922       .addDef(ResVReg)
923       .addUse(GR.getSPIRVTypeID(BoolTy))
924       .addUse(BitIntReg)
925       .addUse(Zero)
926       .constrainAllUses(TII, TRI, RBI);
927 }
928 
929 bool SPIRVInstructionSelector::selectTrunc(Register ResVReg,
930                                            const SPIRVType *ResType,
931                                            MachineInstr &I) const {
932   if (GR.isScalarOrVectorOfType(ResVReg, SPIRV::OpTypeBool)) {
933     Register IntReg = I.getOperand(1).getReg();
934     const SPIRVType *ArgType = GR.getSPIRVTypeForVReg(IntReg);
935     return selectIntToBool(IntReg, ResVReg, ArgType, ResType, I);
936   }
937   bool IsSigned = GR.isScalarOrVectorSigned(ResType);
938   unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
939   return selectUnOp(ResVReg, ResType, I, Opcode);
940 }
941 
942 bool SPIRVInstructionSelector::selectConst(Register ResVReg,
943                                            const SPIRVType *ResType,
944                                            const APInt &Imm,
945                                            MachineInstr &I) const {
946   assert(ResType->getOpcode() != SPIRV::OpTypePointer || Imm.isNullValue());
947   MachineBasicBlock &BB = *I.getParent();
948   if (ResType->getOpcode() == SPIRV::OpTypePointer && Imm.isNullValue()) {
949     return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
950         .addDef(ResVReg)
951         .addUse(GR.getSPIRVTypeID(ResType))
952         .constrainAllUses(TII, TRI, RBI);
953   }
954   auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantI))
955                  .addDef(ResVReg)
956                  .addUse(GR.getSPIRVTypeID(ResType));
957   // <=32-bit integers should be caught by the sdag pattern.
958   assert(Imm.getBitWidth() > 32);
959   addNumImm(Imm, MIB);
960   return MIB.constrainAllUses(TII, TRI, RBI);
961 }
962 
963 bool SPIRVInstructionSelector::selectOpUndef(Register ResVReg,
964                                              const SPIRVType *ResType,
965                                              MachineInstr &I) const {
966   return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpUndef))
967       .addDef(ResVReg)
968       .addUse(GR.getSPIRVTypeID(ResType))
969       .constrainAllUses(TII, TRI, RBI);
970 }
971 
972 bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
973                                                const SPIRVType *ResType,
974                                                MachineInstr &I) const {
975   llvm_unreachable("Intrinsic selection not implemented");
976 }
977 
978 bool SPIRVInstructionSelector::selectFrameIndex(Register ResVReg,
979                                                 const SPIRVType *ResType,
980                                                 MachineInstr &I) const {
981   return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpVariable))
982       .addDef(ResVReg)
983       .addUse(GR.getSPIRVTypeID(ResType))
984       .addImm(static_cast<uint32_t>(SPIRV::StorageClass::Function))
985       .constrainAllUses(TII, TRI, RBI);
986 }
987 
988 bool SPIRVInstructionSelector::selectBranch(MachineInstr &I) const {
989   // InstructionSelector walks backwards through the instructions. We can use
990   // both a G_BR and a G_BRCOND to create an OpBranchConditional. We hit G_BR
991   // first, so can generate an OpBranchConditional here. If there is no
992   // G_BRCOND, we just use OpBranch for a regular unconditional branch.
993   const MachineInstr *PrevI = I.getPrevNode();
994   MachineBasicBlock &MBB = *I.getParent();
995   if (PrevI != nullptr && PrevI->getOpcode() == TargetOpcode::G_BRCOND) {
996     return BuildMI(MBB, I, I.getDebugLoc(), TII.get(SPIRV::OpBranchConditional))
997         .addUse(PrevI->getOperand(0).getReg())
998         .addMBB(PrevI->getOperand(1).getMBB())
999         .addMBB(I.getOperand(0).getMBB())
1000         .constrainAllUses(TII, TRI, RBI);
1001   }
1002   return BuildMI(MBB, I, I.getDebugLoc(), TII.get(SPIRV::OpBranch))
1003       .addMBB(I.getOperand(0).getMBB())
1004       .constrainAllUses(TII, TRI, RBI);
1005 }
1006 
1007 bool SPIRVInstructionSelector::selectBranchCond(MachineInstr &I) const {
1008   // InstructionSelector walks backwards through the instructions. For an
1009   // explicit conditional branch with no fallthrough, we use both a G_BR and a
1010   // G_BRCOND to create an OpBranchConditional. We should hit G_BR first, and
1011   // generate the OpBranchConditional in selectBranch above.
1012   //
1013   // If an OpBranchConditional has been generated, we simply return, as the work
1014   // is alread done. If there is no OpBranchConditional, LLVM must be relying on
1015   // implicit fallthrough to the next basic block, so we need to create an
1016   // OpBranchConditional with an explicit "false" argument pointing to the next
1017   // basic block that LLVM would fall through to.
1018   const MachineInstr *NextI = I.getNextNode();
1019   // Check if this has already been successfully selected.
1020   if (NextI != nullptr && NextI->getOpcode() == SPIRV::OpBranchConditional)
1021     return true;
1022   // Must be relying on implicit block fallthrough, so generate an
1023   // OpBranchConditional with the "next" basic block as the "false" target.
1024   MachineBasicBlock &MBB = *I.getParent();
1025   unsigned NextMBBNum = MBB.getNextNode()->getNumber();
1026   MachineBasicBlock *NextMBB = I.getMF()->getBlockNumbered(NextMBBNum);
1027   return BuildMI(MBB, I, I.getDebugLoc(), TII.get(SPIRV::OpBranchConditional))
1028       .addUse(I.getOperand(0).getReg())
1029       .addMBB(I.getOperand(1).getMBB())
1030       .addMBB(NextMBB)
1031       .constrainAllUses(TII, TRI, RBI);
1032 }
1033 
1034 bool SPIRVInstructionSelector::selectPhi(Register ResVReg,
1035                                          const SPIRVType *ResType,
1036                                          MachineInstr &I) const {
1037   auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpPhi))
1038                  .addDef(ResVReg)
1039                  .addUse(GR.getSPIRVTypeID(ResType));
1040   const unsigned NumOps = I.getNumOperands();
1041   for (unsigned i = 1; i < NumOps; i += 2) {
1042     MIB.addUse(I.getOperand(i + 0).getReg());
1043     MIB.addMBB(I.getOperand(i + 1).getMBB());
1044   }
1045   return MIB.constrainAllUses(TII, TRI, RBI);
1046 }
1047 
1048 bool SPIRVInstructionSelector::selectGlobalValue(
1049     Register ResVReg, MachineInstr &I, const MachineInstr *Init) const {
1050   // FIXME: don't use MachineIRBuilder here, replace it with BuildMI.
1051   MachineIRBuilder MIRBuilder(I);
1052   const GlobalValue *GV = I.getOperand(1).getGlobal();
1053   SPIRVType *ResType = GR.getOrCreateSPIRVType(
1054       GV->getType(), MIRBuilder, SPIRV::AccessQualifier::ReadWrite, false);
1055 
1056   std::string GlobalIdent = GV->getGlobalIdentifier();
1057   // TODO: suport @llvm.global.annotations.
1058   auto GlobalVar = cast<GlobalVariable>(GV);
1059 
1060   bool HasInit = GlobalVar->hasInitializer() &&
1061                  !isa<UndefValue>(GlobalVar->getInitializer());
1062   // Skip empty declaration for GVs with initilaizers till we get the decl with
1063   // passed initializer.
1064   if (HasInit && !Init)
1065     return true;
1066 
1067   unsigned AddrSpace = GV->getAddressSpace();
1068   SPIRV::StorageClass Storage = addressSpaceToStorageClass(AddrSpace);
1069   bool HasLnkTy = GV->getLinkage() != GlobalValue::InternalLinkage &&
1070                   Storage != SPIRV::StorageClass::Function;
1071   SPIRV::LinkageType LnkType =
1072       (GV->isDeclaration() || GV->hasAvailableExternallyLinkage())
1073           ? SPIRV::LinkageType::Import
1074           : SPIRV::LinkageType::Export;
1075 
1076   Register Reg = GR.buildGlobalVariable(ResVReg, ResType, GlobalIdent, GV,
1077                                         Storage, Init, GlobalVar->isConstant(),
1078                                         HasLnkTy, LnkType, MIRBuilder, true);
1079   return Reg.isValid();
1080 }
1081 
1082 namespace llvm {
1083 InstructionSelector *
1084 createSPIRVInstructionSelector(const SPIRVTargetMachine &TM,
1085                                const SPIRVSubtarget &Subtarget,
1086                                const RegisterBankInfo &RBI) {
1087   return new SPIRVInstructionSelector(TM, Subtarget, RBI);
1088 }
1089 } // namespace llvm
1090