LLVM 20.0.0git
SPIRVPreLegalizer.cpp
Go to the documentation of this file.
1//===-- SPIRVPreLegalizer.cpp - prepare IR for legalization -----*- 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// The pass prepares IR for legalization: it assigns SPIR-V types to registers
10// and removes intrinsics which holded these types during IR translation.
11// Also it processes constants and registers them in GR to avoid duplication.
12//
13//===----------------------------------------------------------------------===//
14
15#include "SPIRV.h"
16#include "SPIRVSubtarget.h"
17#include "SPIRVUtils.h"
20#include "llvm/IR/Attributes.h"
21#include "llvm/IR/Constants.h"
23#include "llvm/IR/IntrinsicsSPIRV.h"
25
26#define DEBUG_TYPE "spirv-prelegalizer"
27
28using namespace llvm;
29
30namespace {
31class SPIRVPreLegalizer : public MachineFunctionPass {
32public:
33 static char ID;
34 SPIRVPreLegalizer() : MachineFunctionPass(ID) {
36 }
37 bool runOnMachineFunction(MachineFunction &MF) override;
38};
39} // namespace
40
41static void
43 const SPIRVSubtarget &STI,
44 DenseMap<MachineInstr *, Type *> &TargetExtConstTypes,
45 SmallSet<Register, 4> &TrackedConstRegs) {
47 DenseMap<MachineInstr *, Register> RegsAlreadyAddedToDT;
48 SmallVector<MachineInstr *, 10> ToErase, ToEraseComposites;
49 for (MachineBasicBlock &MBB : MF) {
50 for (MachineInstr &MI : MBB) {
51 if (!isSpvIntrinsic(MI, Intrinsic::spv_track_constant))
52 continue;
53 ToErase.push_back(&MI);
54 Register SrcReg = MI.getOperand(2).getReg();
55 auto *Const =
56 cast<Constant>(cast<ConstantAsMetadata>(
57 MI.getOperand(3).getMetadata()->getOperand(0))
58 ->getValue());
59 if (auto *GV = dyn_cast<GlobalValue>(Const)) {
60 Register Reg = GR->find(GV, &MF);
61 if (!Reg.isValid())
62 GR->add(GV, &MF, SrcReg);
63 else
64 RegsAlreadyAddedToDT[&MI] = Reg;
65 } else {
66 Register Reg = GR->find(Const, &MF);
67 if (!Reg.isValid()) {
68 if (auto *ConstVec = dyn_cast<ConstantDataVector>(Const)) {
69 auto *BuildVec = MRI.getVRegDef(SrcReg);
70 assert(BuildVec &&
71 BuildVec->getOpcode() == TargetOpcode::G_BUILD_VECTOR);
72 for (unsigned i = 0; i < ConstVec->getNumElements(); ++i) {
73 // Ensure that OpConstantComposite reuses a constant when it's
74 // already created and available in the same machine function.
75 Constant *ElemConst = ConstVec->getElementAsConstant(i);
76 Register ElemReg = GR->find(ElemConst, &MF);
77 if (!ElemReg.isValid())
78 GR->add(ElemConst, &MF, BuildVec->getOperand(1 + i).getReg());
79 else
80 BuildVec->getOperand(1 + i).setReg(ElemReg);
81 }
82 }
83 GR->add(Const, &MF, SrcReg);
84 TrackedConstRegs.insert(SrcReg);
85 if (Const->getType()->isTargetExtTy()) {
86 // remember association so that we can restore it when assign types
87 MachineInstr *SrcMI = MRI.getVRegDef(SrcReg);
88 if (SrcMI && (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT ||
89 SrcMI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF))
90 TargetExtConstTypes[SrcMI] = Const->getType();
91 if (Const->isNullValue()) {
92 MachineIRBuilder MIB(MF);
93 SPIRVType *ExtType =
94 GR->getOrCreateSPIRVType(Const->getType(), MIB);
95 SrcMI->setDesc(STI.getInstrInfo()->get(SPIRV::OpConstantNull));
97 GR->getSPIRVTypeID(ExtType), false));
98 }
99 }
100 } else {
101 RegsAlreadyAddedToDT[&MI] = Reg;
102 // This MI is unused and will be removed. If the MI uses
103 // const_composite, it will be unused and should be removed too.
104 assert(MI.getOperand(2).isReg() && "Reg operand is expected");
105 MachineInstr *SrcMI = MRI.getVRegDef(MI.getOperand(2).getReg());
106 if (SrcMI && isSpvIntrinsic(*SrcMI, Intrinsic::spv_const_composite))
107 ToEraseComposites.push_back(SrcMI);
108 }
109 }
110 }
111 }
112 for (MachineInstr *MI : ToErase) {
113 Register Reg = MI->getOperand(2).getReg();
114 if (RegsAlreadyAddedToDT.contains(MI))
115 Reg = RegsAlreadyAddedToDT[MI];
116 auto *RC = MRI.getRegClassOrNull(MI->getOperand(0).getReg());
117 if (!MRI.getRegClassOrNull(Reg) && RC)
118 MRI.setRegClass(Reg, RC);
119 MRI.replaceRegWith(MI->getOperand(0).getReg(), Reg);
120 MI->eraseFromParent();
121 }
122 for (MachineInstr *MI : ToEraseComposites)
123 MI->eraseFromParent();
124}
125
126static void
128 const SmallSet<Register, 4> &TrackedConstRegs) {
131 const unsigned AssignNameOperandShift = 2;
132 for (MachineBasicBlock &MBB : MF) {
133 for (MachineInstr &MI : MBB) {
134 if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_name))
135 continue;
136 unsigned NumOp = MI.getNumExplicitDefs() + AssignNameOperandShift;
137 while (MI.getOperand(NumOp).isReg()) {
138 MachineOperand &MOp = MI.getOperand(NumOp);
139 MachineInstr *ConstMI = MRI.getVRegDef(MOp.getReg());
140 assert(ConstMI->getOpcode() == TargetOpcode::G_CONSTANT);
141 MI.removeOperand(NumOp);
142 MI.addOperand(MachineOperand::CreateImm(
143 ConstMI->getOperand(1).getCImm()->getZExtValue()));
144 Register DefReg = ConstMI->getOperand(0).getReg();
145 if (MRI.use_empty(DefReg) && !TrackedConstRegs.contains(DefReg))
146 ToErase.push_back(ConstMI);
147 }
148 }
149 }
150 for (MachineInstr *MI : ToErase)
151 MI->eraseFromParent();
152}
153
156 for (MachineRegisterInfo::use_instr_iterator I = MRI->use_instr_begin(Reg),
157 IE = MRI->use_instr_end();
158 I != IE; ++I) {
159 MachineInstr *UseMI = &*I;
160 if ((isSpvIntrinsic(*UseMI, Intrinsic::spv_assign_ptr_type) ||
161 isSpvIntrinsic(*UseMI, Intrinsic::spv_assign_type)) &&
162 UseMI->getOperand(1).getReg() == Reg)
163 return UseMI;
164 }
165 return nullptr;
166}
167
169 MachineIRBuilder MIB) {
170 // Get access to information about available extensions
171 const SPIRVSubtarget *ST =
172 static_cast<const SPIRVSubtarget *>(&MIB.getMF().getSubtarget());
174 for (MachineBasicBlock &MBB : MF) {
175 for (MachineInstr &MI : MBB) {
176 if (!isSpvIntrinsic(MI, Intrinsic::spv_bitcast) &&
177 !isSpvIntrinsic(MI, Intrinsic::spv_ptrcast))
178 continue;
179 assert(MI.getOperand(2).isReg());
180 MIB.setInsertPt(*MI.getParent(), MI);
181 ToErase.push_back(&MI);
182 if (isSpvIntrinsic(MI, Intrinsic::spv_bitcast)) {
183 MIB.buildBitcast(MI.getOperand(0).getReg(), MI.getOperand(2).getReg());
184 continue;
185 }
186 Register Def = MI.getOperand(0).getReg();
187 Register Source = MI.getOperand(2).getReg();
188 Type *ElemTy = getMDOperandAsType(MI.getOperand(3).getMetadata(), 0);
189 SPIRVType *BaseTy = GR->getOrCreateSPIRVType(ElemTy, MIB);
190 SPIRVType *AssignedPtrType = GR->getOrCreateSPIRVPointerType(
192 addressSpaceToStorageClass(MI.getOperand(4).getImm(), *ST));
193
194 // If the ptrcast would be redundant, replace all uses with the source
195 // register.
197 if (GR->getSPIRVTypeForVReg(Source) == AssignedPtrType) {
198 // Erase Def's assign type instruction if we are going to replace Def.
199 if (MachineInstr *AssignMI = findAssignTypeInstr(Def, MRI))
200 ToErase.push_back(AssignMI);
201 MRI->replaceRegWith(Def, Source);
202 } else {
203 GR->assignSPIRVTypeToVReg(AssignedPtrType, Def, MF);
204 MIB.buildBitcast(Def, Source);
205 // MachineVerifier requires that bitcast must change the type.
206 // Change AddressSpace if needed to hint that Def and Source points to
207 // different types: this doesn't change actual code generation.
208 LLT DefType = MRI->getType(Def);
209 if (DefType == MRI->getType(Source))
210 MRI->setType(Def,
211 LLT::pointer((DefType.getAddressSpace() + 1) %
213 GR->getPointerSize()));
214 }
215 }
216 }
217 for (MachineInstr *MI : ToErase)
218 MI->eraseFromParent();
219}
220
221// Translating GV, IRTranslator sometimes generates following IR:
222// %1 = G_GLOBAL_VALUE
223// %2 = COPY %1
224// %3 = G_ADDRSPACE_CAST %2
225//
226// or
227//
228// %1 = G_ZEXT %2
229// G_MEMCPY ... %2 ...
230//
231// New registers have no SPIRVType and no register class info.
232//
233// Set SPIRVType for GV, propagate it from GV to other instructions,
234// also set register classes.
237 MachineIRBuilder &MIB) {
238 SPIRVType *SpvType = nullptr;
239 assert(MI && "Machine instr is expected");
240 if (MI->getOperand(0).isReg()) {
241 Register Reg = MI->getOperand(0).getReg();
242 SpvType = GR->getSPIRVTypeForVReg(Reg);
243 if (!SpvType) {
244 switch (MI->getOpcode()) {
245 case TargetOpcode::G_CONSTANT: {
246 MIB.setInsertPt(*MI->getParent(), MI);
247 Type *Ty = MI->getOperand(1).getCImm()->getType();
248 SpvType = GR->getOrCreateSPIRVType(Ty, MIB);
249 break;
250 }
251 case TargetOpcode::G_GLOBAL_VALUE: {
252 MIB.setInsertPt(*MI->getParent(), MI);
253 const GlobalValue *Global = MI->getOperand(1).getGlobal();
255 auto *Ty = TypedPointerType::get(ElementTy,
256 Global->getType()->getAddressSpace());
257 SpvType = GR->getOrCreateSPIRVType(Ty, MIB);
258 break;
259 }
260 case TargetOpcode::G_ANYEXT:
261 case TargetOpcode::G_SEXT:
262 case TargetOpcode::G_ZEXT: {
263 if (MI->getOperand(1).isReg()) {
264 if (MachineInstr *DefInstr =
265 MRI.getVRegDef(MI->getOperand(1).getReg())) {
266 if (SPIRVType *Def = propagateSPIRVType(DefInstr, GR, MRI, MIB)) {
267 unsigned CurrentBW = GR->getScalarOrVectorBitWidth(Def);
268 unsigned ExpectedBW =
269 std::max(MRI.getType(Reg).getScalarSizeInBits(), CurrentBW);
270 unsigned NumElements = GR->getScalarOrVectorComponentCount(Def);
271 SpvType = GR->getOrCreateSPIRVIntegerType(ExpectedBW, MIB);
272 if (NumElements > 1)
273 SpvType =
274 GR->getOrCreateSPIRVVectorType(SpvType, NumElements, MIB);
275 }
276 }
277 }
278 break;
279 }
280 case TargetOpcode::G_PTRTOINT:
281 SpvType = GR->getOrCreateSPIRVIntegerType(
282 MRI.getType(Reg).getScalarSizeInBits(), MIB);
283 break;
284 case TargetOpcode::G_TRUNC:
285 case TargetOpcode::G_ADDRSPACE_CAST:
286 case TargetOpcode::G_PTR_ADD:
287 case TargetOpcode::COPY: {
288 MachineOperand &Op = MI->getOperand(1);
289 MachineInstr *Def = Op.isReg() ? MRI.getVRegDef(Op.getReg()) : nullptr;
290 if (Def)
291 SpvType = propagateSPIRVType(Def, GR, MRI, MIB);
292 break;
293 }
294 default:
295 break;
296 }
297 if (SpvType)
298 GR->assignSPIRVTypeToVReg(SpvType, Reg, MIB.getMF());
299 if (!MRI.getRegClassOrNull(Reg))
300 MRI.setRegClass(Reg, SpvType ? GR->getRegClass(SpvType)
301 : &SPIRV::iIDRegClass);
302 }
303 }
304 return SpvType;
305}
306
307// To support current approach and limitations wrt. bit width here we widen a
308// scalar register with a bit width greater than 1 to valid sizes and cap it to
309// 64 width.
311 LLT RegType = MRI.getType(Reg);
312 if (!RegType.isScalar())
313 return;
314 unsigned Sz = RegType.getScalarSizeInBits();
315 if (Sz == 1)
316 return;
317 unsigned NewSz = std::min(std::max(1u << Log2_32_Ceil(Sz), 8u), 64u);
318 if (NewSz != Sz)
319 MRI.setType(Reg, LLT::scalar(NewSz));
320}
321
322static std::pair<Register, unsigned>
324 const SPIRVGlobalRegistry &GR) {
325 if (!SpvType)
326 SpvType = GR.getSPIRVTypeForVReg(SrcReg);
327 const TargetRegisterClass *RC = GR.getRegClass(SpvType);
328 Register Reg = MRI.createGenericVirtualRegister(GR.getRegType(SpvType));
329 MRI.setRegClass(Reg, RC);
330 unsigned GetIdOp = SPIRV::GET_ID;
331 if (RC == &SPIRV::fIDRegClass)
332 GetIdOp = SPIRV::GET_fID;
333 else if (RC == &SPIRV::pIDRegClass)
334 GetIdOp = SPIRV::GET_pID;
335 else if (RC == &SPIRV::vfIDRegClass)
336 GetIdOp = SPIRV::GET_vfID;
337 else if (RC == &SPIRV::vpIDRegClass)
338 GetIdOp = SPIRV::GET_vpID;
339 else if (RC == &SPIRV::vIDRegClass)
340 GetIdOp = SPIRV::GET_vID;
341 return {Reg, GetIdOp};
342}
343
344// Insert ASSIGN_TYPE instuction between Reg and its definition, set NewReg as
345// a dst of the definition, assign SPIRVType to both registers. If SpvType is
346// provided, use it as SPIRVType in ASSIGN_TYPE, otherwise create it from Ty.
347// It's used also in SPIRVBuiltins.cpp.
348// TODO: maybe move to SPIRVUtils.
349namespace llvm {
353 MachineInstr *Def = MRI.getVRegDef(Reg);
354 assert((Ty || SpvType) && "Either LLVM or SPIRV type is expected.");
355 MIB.setInsertPt(*Def->getParent(),
356 (Def->getNextNode() ? Def->getNextNode()->getIterator()
357 : Def->getParent()->end()));
358 SpvType = SpvType ? SpvType : GR->getOrCreateSPIRVType(Ty, MIB);
359 Register NewReg = MRI.createGenericVirtualRegister(MRI.getType(Reg));
360 if (auto *RC = MRI.getRegClassOrNull(Reg)) {
361 MRI.setRegClass(NewReg, RC);
362 } else {
363 auto RegClass = GR->getRegClass(SpvType);
364 MRI.setRegClass(NewReg, RegClass);
365 MRI.setRegClass(Reg, RegClass);
366 }
367 GR->assignSPIRVTypeToVReg(SpvType, Reg, MIB.getMF());
368 // This is to make it convenient for Legalizer to get the SPIRVType
369 // when processing the actual MI (i.e. not pseudo one).
370 GR->assignSPIRVTypeToVReg(SpvType, NewReg, MIB.getMF());
371 // Copy MIFlags from Def to ASSIGN_TYPE instruction. It's required to keep
372 // the flags after instruction selection.
373 const uint32_t Flags = Def->getFlags();
374 MIB.buildInstr(SPIRV::ASSIGN_TYPE)
375 .addDef(Reg)
376 .addUse(NewReg)
377 .addUse(GR->getSPIRVTypeID(SpvType))
378 .setMIFlags(Flags);
379 Def->getOperand(0).setReg(NewReg);
380 return NewReg;
381}
382
385 assert(MI.getNumDefs() > 0 && MRI.hasOneUse(MI.getOperand(0).getReg()));
386 MachineInstr &AssignTypeInst =
387 *(MRI.use_instr_begin(MI.getOperand(0).getReg()));
388 auto NewReg =
389 createNewIdReg(nullptr, MI.getOperand(0).getReg(), MRI, *GR).first;
390 AssignTypeInst.getOperand(1).setReg(NewReg);
391 MI.getOperand(0).setReg(NewReg);
392 MIB.setInsertPt(*MI.getParent(),
393 (MI.getNextNode() ? MI.getNextNode()->getIterator()
394 : MI.getParent()->end()));
395 for (auto &Op : MI.operands()) {
396 if (!Op.isReg() || Op.isDef())
397 continue;
398 auto IdOpInfo = createNewIdReg(nullptr, Op.getReg(), MRI, *GR);
399 MIB.buildInstr(IdOpInfo.second).addDef(IdOpInfo.first).addUse(Op.getReg());
400 Op.setReg(IdOpInfo.first);
401 }
402}
403} // namespace llvm
404
405static void
408 DenseMap<MachineInstr *, Type *> &TargetExtConstTypes) {
409 // Get access to information about available extensions
410 const SPIRVSubtarget *ST =
411 static_cast<const SPIRVSubtarget *>(&MIB.getMF().getSubtarget());
412
415 DenseMap<MachineInstr *, Register> RegsAlreadyAddedToDT;
416
417 bool IsExtendedInts =
418 ST->canUseExtension(
419 SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers) ||
420 ST->canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
421
422 for (MachineBasicBlock *MBB : post_order(&MF)) {
423 if (MBB->empty())
424 continue;
425
426 bool ReachedBegin = false;
427 for (auto MII = std::prev(MBB->end()), Begin = MBB->begin();
428 !ReachedBegin;) {
429 MachineInstr &MI = *MII;
430 unsigned MIOp = MI.getOpcode();
431
432 if (!IsExtendedInts) {
433 // validate bit width of scalar registers
434 for (const auto &MOP : MI.operands())
435 if (MOP.isReg())
436 widenScalarLLTNextPow2(MOP.getReg(), MRI);
437 }
438
439 if (isSpvIntrinsic(MI, Intrinsic::spv_assign_ptr_type)) {
440 Register Reg = MI.getOperand(1).getReg();
441 MIB.setInsertPt(*MI.getParent(), MI.getIterator());
442 Type *ElementTy = getMDOperandAsType(MI.getOperand(2).getMetadata(), 0);
443 SPIRVType *BaseTy = GR->getOrCreateSPIRVType(ElementTy, MIB);
444 SPIRVType *AssignedPtrType = GR->getOrCreateSPIRVPointerType(
446 addressSpaceToStorageClass(MI.getOperand(3).getImm(), *ST));
447 MachineInstr *Def = MRI.getVRegDef(Reg);
448 assert(Def && "Expecting an instruction that defines the register");
449 // G_GLOBAL_VALUE already has type info.
450 if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE &&
451 Def->getOpcode() != SPIRV::ASSIGN_TYPE)
452 insertAssignInstr(Reg, nullptr, AssignedPtrType, GR, MIB,
453 MF.getRegInfo());
454 ToErase.push_back(&MI);
455 } else if (isSpvIntrinsic(MI, Intrinsic::spv_assign_type)) {
456 Register Reg = MI.getOperand(1).getReg();
457 Type *Ty = getMDOperandAsType(MI.getOperand(2).getMetadata(), 0);
458 MachineInstr *Def = MRI.getVRegDef(Reg);
459 assert(Def && "Expecting an instruction that defines the register");
460 // G_GLOBAL_VALUE already has type info.
461 if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE &&
462 Def->getOpcode() != SPIRV::ASSIGN_TYPE)
463 insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MF.getRegInfo());
464 ToErase.push_back(&MI);
465 } else if (MIOp == TargetOpcode::G_CONSTANT ||
466 MIOp == TargetOpcode::G_FCONSTANT ||
467 MIOp == TargetOpcode::G_BUILD_VECTOR) {
468 // %rc = G_CONSTANT ty Val
469 // ===>
470 // %cty = OpType* ty
471 // %rctmp = G_CONSTANT ty Val
472 // %rc = ASSIGN_TYPE %rctmp, %cty
473 Register Reg = MI.getOperand(0).getReg();
474 bool NeedAssignType = true;
475 if (MRI.hasOneUse(Reg)) {
476 MachineInstr &UseMI = *MRI.use_instr_begin(Reg);
477 if (isSpvIntrinsic(UseMI, Intrinsic::spv_assign_type) ||
478 isSpvIntrinsic(UseMI, Intrinsic::spv_assign_name))
479 continue;
480 if (UseMI.getOpcode() == SPIRV::ASSIGN_TYPE)
481 NeedAssignType = false;
482 }
483 Type *Ty = nullptr;
484 if (MIOp == TargetOpcode::G_CONSTANT) {
485 auto TargetExtIt = TargetExtConstTypes.find(&MI);
486 Ty = TargetExtIt == TargetExtConstTypes.end()
487 ? MI.getOperand(1).getCImm()->getType()
488 : TargetExtIt->second;
489 const ConstantInt *OpCI = MI.getOperand(1).getCImm();
490 Register PrimaryReg = GR->find(OpCI, &MF);
491 if (!PrimaryReg.isValid()) {
492 GR->add(OpCI, &MF, Reg);
493 } else if (PrimaryReg != Reg &&
494 MRI.getType(Reg) == MRI.getType(PrimaryReg)) {
495 auto *RCReg = MRI.getRegClassOrNull(Reg);
496 auto *RCPrimary = MRI.getRegClassOrNull(PrimaryReg);
497 if (!RCReg || RCPrimary == RCReg) {
498 RegsAlreadyAddedToDT[&MI] = PrimaryReg;
499 ToErase.push_back(&MI);
500 NeedAssignType = false;
501 }
502 }
503 } else if (MIOp == TargetOpcode::G_FCONSTANT) {
504 Ty = MI.getOperand(1).getFPImm()->getType();
505 } else {
506 assert(MIOp == TargetOpcode::G_BUILD_VECTOR);
507 Type *ElemTy = nullptr;
508 MachineInstr *ElemMI = MRI.getVRegDef(MI.getOperand(1).getReg());
509 assert(ElemMI);
510
511 if (ElemMI->getOpcode() == TargetOpcode::G_CONSTANT) {
512 ElemTy = ElemMI->getOperand(1).getCImm()->getType();
513 } else if (ElemMI->getOpcode() == TargetOpcode::G_FCONSTANT) {
514 ElemTy = ElemMI->getOperand(1).getFPImm()->getType();
515 } else {
516 // There may be a case when we already know Reg's type.
517 MachineInstr *NextMI = MI.getNextNode();
518 if (!NextMI || NextMI->getOpcode() != SPIRV::ASSIGN_TYPE ||
519 NextMI->getOperand(1).getReg() != Reg)
520 llvm_unreachable("Unexpected opcode");
521 }
522 if (ElemTy)
523 Ty = VectorType::get(
524 ElemTy, MI.getNumExplicitOperands() - MI.getNumExplicitDefs(),
525 false);
526 else
527 NeedAssignType = false;
528 }
529 if (NeedAssignType)
530 insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MRI);
531 } else if (MIOp == TargetOpcode::G_GLOBAL_VALUE) {
532 propagateSPIRVType(&MI, GR, MRI, MIB);
533 }
534
535 if (MII == Begin)
536 ReachedBegin = true;
537 else
538 --MII;
539 }
540 }
541 for (MachineInstr *MI : ToErase) {
542 auto It = RegsAlreadyAddedToDT.find(MI);
543 if (RegsAlreadyAddedToDT.contains(MI))
544 MRI.replaceRegWith(MI->getOperand(0).getReg(), It->second);
545 MI->eraseFromParent();
546 }
547
548 // Address the case when IRTranslator introduces instructions with new
549 // registers without SPIRVType associated.
550 for (MachineBasicBlock &MBB : MF) {
551 for (MachineInstr &MI : MBB) {
552 switch (MI.getOpcode()) {
553 case TargetOpcode::G_TRUNC:
554 case TargetOpcode::G_ANYEXT:
555 case TargetOpcode::G_SEXT:
556 case TargetOpcode::G_ZEXT:
557 case TargetOpcode::G_PTRTOINT:
558 case TargetOpcode::COPY:
559 case TargetOpcode::G_ADDRSPACE_CAST:
560 propagateSPIRVType(&MI, GR, MRI, MIB);
561 break;
562 }
563 }
564 }
565}
566
567// Defined in SPIRVLegalizerInfo.cpp.
568extern bool isTypeFoldingSupported(unsigned Opcode);
569
572 MachineIRBuilder MIB) {
574 for (MachineBasicBlock &MBB : MF) {
575 for (MachineInstr &MI : MBB) {
576 if (isTypeFoldingSupported(MI.getOpcode()))
577 processInstr(MI, MIB, MRI, GR);
578 }
579 }
580
581 for (MachineBasicBlock &MBB : MF) {
582 for (MachineInstr &MI : MBB) {
583 // We need to rewrite dst types for ASSIGN_TYPE instrs to be able
584 // to perform tblgen'erated selection and we can't do that on Legalizer
585 // as it operates on gMIR only.
586 if (MI.getOpcode() != SPIRV::ASSIGN_TYPE)
587 continue;
588 Register SrcReg = MI.getOperand(1).getReg();
589 unsigned Opcode = MRI.getVRegDef(SrcReg)->getOpcode();
590 if (!isTypeFoldingSupported(Opcode))
591 continue;
592 Register DstReg = MI.getOperand(0).getReg();
593 // Don't need to reset type of register holding constant and used in
594 // G_ADDRSPACE_CAST, since it breaks legalizer.
595 if (Opcode == TargetOpcode::G_CONSTANT && MRI.hasOneUse(DstReg)) {
596 MachineInstr &UseMI = *MRI.use_instr_begin(DstReg);
597 if (UseMI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST)
598 continue;
599 }
600 }
601 }
602}
603
604static Register
606 SmallVector<unsigned, 4> *Ops = nullptr) {
607 Register DefReg;
608 unsigned StartOp = InlineAsm::MIOp_FirstOperand,
610 for (unsigned Idx = StartOp, MISz = MI->getNumOperands(); Idx != MISz;
611 ++Idx) {
612 const MachineOperand &MO = MI->getOperand(Idx);
613 if (MO.isMetadata())
614 continue;
615 if (Idx == AsmDescOp && MO.isImm()) {
616 // compute the index of the next operand descriptor
617 const InlineAsm::Flag F(MO.getImm());
618 AsmDescOp += 1 + F.getNumOperandRegisters();
619 continue;
620 }
621 if (MO.isReg() && MO.isDef()) {
622 if (!Ops)
623 return MO.getReg();
624 else
625 DefReg = MO.getReg();
626 } else if (Ops) {
627 Ops->push_back(Idx);
628 }
629 }
630 return DefReg;
631}
632
633static void
635 const SPIRVSubtarget &ST, MachineIRBuilder MIRBuilder,
636 const SmallVector<MachineInstr *> &ToProcess) {
638 Register AsmTargetReg;
639 for (unsigned i = 0, Sz = ToProcess.size(); i + 1 < Sz; i += 2) {
640 MachineInstr *I1 = ToProcess[i], *I2 = ToProcess[i + 1];
641 assert(isSpvIntrinsic(*I1, Intrinsic::spv_inline_asm) && I2->isInlineAsm());
642 MIRBuilder.setInsertPt(*I2->getParent(), *I2);
643
644 if (!AsmTargetReg.isValid()) {
645 // define vendor specific assembly target or dialect
646 AsmTargetReg = MRI.createGenericVirtualRegister(LLT::scalar(32));
647 MRI.setRegClass(AsmTargetReg, &SPIRV::iIDRegClass);
648 auto AsmTargetMIB =
649 MIRBuilder.buildInstr(SPIRV::OpAsmTargetINTEL).addDef(AsmTargetReg);
650 addStringImm(ST.getTargetTripleAsStr(), AsmTargetMIB);
651 GR->add(AsmTargetMIB.getInstr(), &MF, AsmTargetReg);
652 }
653
654 // create types
655 const MDNode *IAMD = I1->getOperand(1).getMetadata();
656 FunctionType *FTy = cast<FunctionType>(getMDOperandAsType(IAMD, 0));
658 for (const auto &ArgTy : FTy->params())
659 ArgTypes.push_back(GR->getOrCreateSPIRVType(ArgTy, MIRBuilder));
660 SPIRVType *RetType =
661 GR->getOrCreateSPIRVType(FTy->getReturnType(), MIRBuilder);
663 FTy, RetType, ArgTypes, MIRBuilder);
664
665 // define vendor specific assembly instructions string
666 Register AsmReg = MRI.createGenericVirtualRegister(LLT::scalar(32));
667 MRI.setRegClass(AsmReg, &SPIRV::iIDRegClass);
668 auto AsmMIB = MIRBuilder.buildInstr(SPIRV::OpAsmINTEL)
669 .addDef(AsmReg)
670 .addUse(GR->getSPIRVTypeID(RetType))
671 .addUse(GR->getSPIRVTypeID(FuncType))
672 .addUse(AsmTargetReg);
673 // inline asm string:
674 addStringImm(I2->getOperand(InlineAsm::MIOp_AsmString).getSymbolName(),
675 AsmMIB);
676 // inline asm constraint string:
677 addStringImm(cast<MDString>(I1->getOperand(2).getMetadata()->getOperand(0))
678 ->getString(),
679 AsmMIB);
680 GR->add(AsmMIB.getInstr(), &MF, AsmReg);
681
682 // calls the inline assembly instruction
683 unsigned ExtraInfo = I2->getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
684 if (ExtraInfo & InlineAsm::Extra_HasSideEffects)
685 MIRBuilder.buildInstr(SPIRV::OpDecorate)
686 .addUse(AsmReg)
687 .addImm(static_cast<uint32_t>(SPIRV::Decoration::SideEffectsINTEL));
688
690 if (!DefReg.isValid()) {
691 DefReg = MRI.createGenericVirtualRegister(LLT::scalar(32));
692 MRI.setRegClass(DefReg, &SPIRV::iIDRegClass);
693 SPIRVType *VoidType = GR->getOrCreateSPIRVType(
694 Type::getVoidTy(MF.getFunction().getContext()), MIRBuilder);
695 GR->assignSPIRVTypeToVReg(VoidType, DefReg, MF);
696 }
697
698 auto AsmCall = MIRBuilder.buildInstr(SPIRV::OpAsmCallINTEL)
699 .addDef(DefReg)
700 .addUse(GR->getSPIRVTypeID(RetType))
701 .addUse(AsmReg);
702 for (unsigned IntrIdx = 3; IntrIdx < I1->getNumOperands(); ++IntrIdx)
703 AsmCall.addUse(I1->getOperand(IntrIdx).getReg());
704 }
705 for (MachineInstr *MI : ToProcess)
706 MI->eraseFromParent();
707}
708
710 const SPIRVSubtarget &ST,
711 MachineIRBuilder MIRBuilder) {
713 for (MachineBasicBlock &MBB : MF) {
714 for (MachineInstr &MI : MBB) {
715 if (isSpvIntrinsic(MI, Intrinsic::spv_inline_asm) ||
716 MI.getOpcode() == TargetOpcode::INLINEASM)
717 ToProcess.push_back(&MI);
718 }
719 }
720 if (ToProcess.size() == 0)
721 return;
722
723 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly))
724 report_fatal_error("Inline assembly instructions require the "
725 "following SPIR-V extension: SPV_INTEL_inline_assembly",
726 false);
727
728 insertInlineAsmProcess(MF, GR, ST, MIRBuilder, ToProcess);
729}
730
733 for (MachineBasicBlock &MBB : MF) {
734 for (MachineInstr &MI : MBB) {
735 if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration))
736 continue;
737 MIB.setInsertPt(*MI.getParent(), MI);
738 buildOpSpirvDecorations(MI.getOperand(1).getReg(), MIB,
739 MI.getOperand(2).getMetadata());
740 ToErase.push_back(&MI);
741 }
742 }
743 for (MachineInstr *MI : ToErase)
744 MI->eraseFromParent();
745}
746
747// Find basic blocks of the switch and replace registers in spv_switch() by its
748// MBB equivalent.
750 MachineIRBuilder MIB) {
753 Switches;
754 for (MachineBasicBlock &MBB : MF) {
756 BB2MBB[MBB.getBasicBlock()] = &MBB;
757 for (MachineInstr &MI : MBB) {
758 if (!isSpvIntrinsic(MI, Intrinsic::spv_switch))
759 continue;
760 // Calls to spv_switch intrinsics representing IR switches.
762 for (unsigned i = 2; i < MI.getNumOperands(); ++i) {
763 Register Reg = MI.getOperand(i).getReg();
764 if (i % 2 == 1) {
765 MachineInstr *ConstInstr = getDefInstrMaybeConstant(Reg, &MRI);
766 NewOps.push_back(ConstInstr);
767 } else {
768 MachineInstr *BuildMBB = MRI.getVRegDef(Reg);
769 assert(BuildMBB &&
770 BuildMBB->getOpcode() == TargetOpcode::G_BLOCK_ADDR &&
771 BuildMBB->getOperand(1).isBlockAddress() &&
772 BuildMBB->getOperand(1).getBlockAddress());
773 NewOps.push_back(BuildMBB);
774 }
775 }
776 Switches.push_back(std::make_pair(&MI, NewOps));
777 }
778 }
779
781 for (auto &SwIt : Switches) {
782 MachineInstr &MI = *SwIt.first;
783 SmallVector<MachineInstr *, 8> &Ins = SwIt.second;
785 for (unsigned i = 0; i < Ins.size(); ++i) {
786 if (Ins[i]->getOpcode() == TargetOpcode::G_BLOCK_ADDR) {
787 BasicBlock *CaseBB =
788 Ins[i]->getOperand(1).getBlockAddress()->getBasicBlock();
789 auto It = BB2MBB.find(CaseBB);
790 if (It == BB2MBB.end())
791 report_fatal_error("cannot find a machine basic block by a basic "
792 "block in a switch statement");
793 NewOps.push_back(MachineOperand::CreateMBB(It->second));
794 MI.getParent()->addSuccessor(It->second);
795 ToEraseMI.insert(Ins[i]);
796 } else {
797 NewOps.push_back(
798 MachineOperand::CreateCImm(Ins[i]->getOperand(1).getCImm()));
799 }
800 }
801 for (unsigned i = MI.getNumOperands() - 1; i > 1; --i)
802 MI.removeOperand(i);
803 for (auto &MO : NewOps)
804 MI.addOperand(MO);
805 if (MachineInstr *Next = MI.getNextNode()) {
806 if (isSpvIntrinsic(*Next, Intrinsic::spv_track_constant)) {
807 ToEraseMI.insert(Next);
808 Next = MI.getNextNode();
809 }
810 if (Next && Next->getOpcode() == TargetOpcode::G_BRINDIRECT)
811 ToEraseMI.insert(Next);
812 }
813 }
814
815 // If we just delete G_BLOCK_ADDR instructions with BlockAddress operands,
816 // this leaves their BasicBlock counterparts in a "address taken" status. This
817 // would make AsmPrinter to generate a series of unneeded labels of a "Address
818 // of block that was removed by CodeGen" kind. Let's first ensure that we
819 // don't have a dangling BlockAddress constants by zapping the BlockAddress
820 // nodes, and only after that proceed with erasing G_BLOCK_ADDR instructions.
821 Constant *Replacement =
822 ConstantInt::get(Type::getInt32Ty(MF.getFunction().getContext()), 1);
823 for (MachineInstr *BlockAddrI : ToEraseMI) {
824 if (BlockAddrI->getOpcode() == TargetOpcode::G_BLOCK_ADDR) {
825 BlockAddress *BA = const_cast<BlockAddress *>(
826 BlockAddrI->getOperand(1).getBlockAddress());
828 ConstantExpr::getIntToPtr(Replacement, BA->getType()));
829 BA->destroyConstant();
830 }
831 BlockAddrI->eraseFromParent();
832 }
833}
834
836 if (MBB.empty())
837 return true;
838
839 // Branching SPIR-V intrinsics are not detected by this generic method.
840 // Thus, we can only trust negative result.
841 if (!MBB.canFallThrough())
842 return false;
843
844 // Otherwise, we must manually check if we have a SPIR-V intrinsic which
845 // prevent an implicit fallthrough.
847 It != E; ++It) {
848 if (isSpvIntrinsic(*It, Intrinsic::spv_switch))
849 return false;
850 }
851 return true;
852}
853
855 MachineIRBuilder MIB) {
856 // It is valid for MachineBasicBlocks to not finish with a branch instruction.
857 // In such cases, they will simply fallthrough their immediate successor.
858 for (MachineBasicBlock &MBB : MF) {
860 continue;
861
862 assert(std::distance(MBB.successors().begin(), MBB.successors().end()) ==
863 1);
864 MIB.setInsertPt(MBB, MBB.end());
865 MIB.buildBr(**MBB.successors().begin());
866 }
867}
868
869bool SPIRVPreLegalizer::runOnMachineFunction(MachineFunction &MF) {
870 // Initialize the type registry.
872 SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
873 GR->setCurrentFunc(MF);
874 MachineIRBuilder MIB(MF);
875 // a registry of target extension constants
876 DenseMap<MachineInstr *, Type *> TargetExtConstTypes;
877 // to keep record of tracked constants
878 SmallSet<Register, 4> TrackedConstRegs;
879 addConstantsToTrack(MF, GR, ST, TargetExtConstTypes, TrackedConstRegs);
880 foldConstantsIntoIntrinsics(MF, TrackedConstRegs);
881 insertBitcasts(MF, GR, MIB);
882 generateAssignInstrs(MF, GR, MIB, TargetExtConstTypes);
883 processSwitches(MF, GR, MIB);
884 processInstrsWithTypeFolding(MF, GR, MIB);
886 insertSpirvDecorations(MF, MIB);
887 insertInlineAsm(MF, GR, ST, MIB);
888
889 return true;
890}
891
892INITIALIZE_PASS(SPIRVPreLegalizer, DEBUG_TYPE, "SPIRV pre legalizer", false,
893 false)
894
895char SPIRVPreLegalizer::ID = 0;
896
898 return new SPIRVPreLegalizer();
899}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineBasicBlock & MBB
This file contains the simple types necessary to represent the attributes associated with functions a...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static Register collectInlineAsmInstrOperands(MachineInstr *MI, SmallVector< unsigned, 4 > *Ops=nullptr)
static void insertInlineAsm(MachineFunction &MF, SPIRVGlobalRegistry *GR, const SPIRVSubtarget &ST, MachineIRBuilder MIRBuilder)
static void insertInlineAsmProcess(MachineFunction &MF, SPIRVGlobalRegistry *GR, const SPIRVSubtarget &ST, MachineIRBuilder MIRBuilder, const SmallVector< MachineInstr * > &ToProcess)
static void removeImplicitFallthroughs(MachineFunction &MF, MachineIRBuilder MIB)
static bool isImplicitFallthrough(MachineBasicBlock &MBB)
bool isTypeFoldingSupported(unsigned Opcode)
static void insertBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void processInstrsWithTypeFolding(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void widenScalarLLTNextPow2(Register Reg, MachineRegisterInfo &MRI)
static SPIRVType * propagateSPIRVType(MachineInstr *MI, SPIRVGlobalRegistry *GR, MachineRegisterInfo &MRI, MachineIRBuilder &MIB)
static MachineInstr * findAssignTypeInstr(Register Reg, MachineRegisterInfo *MRI)
static void processSwitches(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void addConstantsToTrack(MachineFunction &MF, SPIRVGlobalRegistry *GR, const SPIRVSubtarget &STI, DenseMap< MachineInstr *, Type * > &TargetExtConstTypes, SmallSet< Register, 4 > &TrackedConstRegs)
#define DEBUG_TYPE
static void foldConstantsIntoIntrinsics(MachineFunction &MF, const SmallSet< Register, 4 > &TrackedConstRegs)
static void insertSpirvDecorations(MachineFunction &MF, MachineIRBuilder MIB)
static std::pair< Register, unsigned > createNewIdReg(SPIRVType *SpvType, Register SrcReg, MachineRegisterInfo &MRI, const SPIRVGlobalRegistry &GR)
static void generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB, DenseMap< MachineInstr *, Type * > &TargetExtConstTypes)
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
Definition: VPlanSLP.cpp:191
LLVM Basic Block Representation.
Definition: BasicBlock.h:61
The address of a basic block.
Definition: Constants.h:890
static Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
Definition: Constants.cpp:2281
This is the shared class of boolean and integer constants.
Definition: Constants.h:81
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition: Constants.h:155
This is an important base class in LLVM.
Definition: Constant.h:42
void destroyConstant()
Called if some element of this constant is no longer valid.
Definition: Constants.cpp:472
This class represents an Operation in the Expression.
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:155
iterator end()
Definition: DenseMap.h:84
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Definition: DenseMap.h:146
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:380
constexpr unsigned getScalarSizeInBits() const
Definition: LowLevelType.h:267
constexpr bool isScalar() const
Definition: LowLevelType.h:146
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Definition: LowLevelType.h:42
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
Definition: LowLevelType.h:57
constexpr unsigned getAddressSpace() const
Definition: LowLevelType.h:280
Metadata node.
Definition: Metadata.h:1069
reverse_iterator rend()
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
bool canFallThrough()
Return true if the block can implicitly transfer control to the block after it by falling off the end...
iterator_range< succ_iterator > successors()
reverse_iterator rbegin()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Helper class to build MachineInstr.
MachineInstrBuilder buildBr(MachineBasicBlock &Dest)
Build and insert G_BR Dest.
void setInsertPt(MachineBasicBlock &MBB, MachineBasicBlock::iterator II)
Set the insertion point before the specified position.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildBitcast(const DstOp &Dst, const SrcOp &Src)
Build and insert Dst = G_BITCAST Src.
MachineRegisterInfo * getMRI()
Getter for MRI.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
Definition: MachineInstr.h:69
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:569
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:579
MachineOperand class - Representation of each machine instruction operand.
const ConstantInt * getCImm() const
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static MachineOperand CreateCImm(const ConstantInt *CI)
void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isMetadata() const
isMetadata - Tests if this is a MO_Metadata operand.
const BlockAddress * getBlockAddress() const
static MachineOperand CreateImm(int64_t Val)
bool isBlockAddress() const
isBlockAddress - Tests if this is a MO_BlockAddress operand.
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
static MachineOperand CreateMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0)
defusechain_iterator - This class provides iterator support for machine operands in the function that...
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
constexpr bool isValid() const
Definition: Register.h:116
SPIRVType * getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
void add(const Constant *C, MachineFunction *MF, Register R)
unsigned getScalarOrVectorComponentCount(Register VReg) const
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite, bool EmitIR=true)
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, MachineFunction &MF)
SPIRVType * getOrCreateOpTypeFunctionWithArgs(const Type *Ty, SPIRVType *RetType, const SmallVectorImpl< SPIRVType * > &ArgTypes, MachineIRBuilder &MIRBuilder)
const TargetRegisterClass * getRegClass(SPIRVType *SpvType) const
Register find(const MachineInstr *MI, MachineFunction *MF)
SPIRVType * getOrCreateSPIRVPointerType(SPIRVType *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SClass=SPIRV::StorageClass::Function)
SPIRVType * getOrCreateSPIRVVectorType(SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
Type * getDeducedGlobalValueType(const GlobalValue *Global)
LLT getRegType(SPIRVType *SpvType) const
unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const
const SPIRVInstrInfo * getInstrInfo() const override
static constexpr unsigned MaxLegalAddressSpace
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition: SmallPtrSet.h:367
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:502
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:135
bool contains(const T &V) const
Check if the SmallSet contains the given element.
Definition: SmallSet.h:236
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition: SmallSet.h:179
size_t size() const
Definition: SmallVector.h:91
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
static Type * getVoidTy(LLVMContext &C)
static IntegerType * getInt32Ty(LLVMContext &C)
static TypedPointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:534
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
Definition: MathExtras.h:353
FunctionPass * createSPIRVPreLegalizerPass()
Register insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpirvTy, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, MachineRegisterInfo &MRI)
Helper external function for inserting ASSIGN_TYPE instuction between Reg and its definition,...
iterator_range< po_iterator< T > > post_order(const T &G)
Type * toTypedPointer(Type *Ty)
Definition: SPIRVUtils.h:208
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
@ Global
Append to llvm.global_dtors.
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
Definition: SPIRVUtils.cpp:190
void processInstr(MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR)
MachineInstr * getDefInstrMaybeConstant(Register &ConstReg, const MachineRegisterInfo *MRI)
Definition: SPIRVUtils.cpp:254
Type * getMDOperandAsType(const MDNode *N, unsigned I)
Definition: SPIRVUtils.cpp:285
void initializeSPIRVPreLegalizerPass(PassRegistry &)
bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID)
Definition: SPIRVUtils.cpp:279
void addStringImm(const StringRef &Str, MCInst &Inst)
Definition: SPIRVUtils.cpp:51
void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder, const MDNode *GVarMD)
Definition: SPIRVUtils.cpp:136