LLVM 22.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"
21#include "llvm/IR/Attributes.h"
22#include "llvm/IR/Constants.h"
23#include "llvm/IR/IntrinsicsSPIRV.h"
24
25#define DEBUG_TYPE "spirv-prelegalizer"
26
27using namespace llvm;
28
29namespace {
30class SPIRVPreLegalizer : public MachineFunctionPass {
31public:
32 static char ID;
33 SPIRVPreLegalizer() : MachineFunctionPass(ID) {}
34 bool runOnMachineFunction(MachineFunction &MF) override;
35 void getAnalysisUsage(AnalysisUsage &AU) const override;
36};
37} // namespace
38
39void SPIRVPreLegalizer::getAnalysisUsage(AnalysisUsage &AU) const {
40 AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
42}
43
44static void
46 const SPIRVSubtarget &STI,
47 DenseMap<MachineInstr *, Type *> &TargetExtConstTypes) {
49 DenseMap<MachineInstr *, Register> RegsAlreadyAddedToDT;
50 SmallVector<MachineInstr *, 10> ToErase, ToEraseComposites;
51 for (MachineBasicBlock &MBB : MF) {
52 for (MachineInstr &MI : MBB) {
53 if (!isSpvIntrinsic(MI, Intrinsic::spv_track_constant))
54 continue;
55 ToErase.push_back(&MI);
56 Register SrcReg = MI.getOperand(2).getReg();
57 auto *Const =
59 MI.getOperand(3).getMetadata()->getOperand(0))
60 ->getValue());
61 if (auto *GV = dyn_cast<GlobalValue>(Const)) {
62 Register Reg = GR->find(GV, &MF);
63 if (!Reg.isValid()) {
64 GR->add(GV, MRI.getVRegDef(SrcReg));
65 GR->addGlobalObject(GV, &MF, SrcReg);
66 } else
67 RegsAlreadyAddedToDT[&MI] = Reg;
68 } else {
69 Register Reg = GR->find(Const, &MF);
70 if (!Reg.isValid()) {
71 if (auto *ConstVec = dyn_cast<ConstantDataVector>(Const)) {
72 auto *BuildVec = MRI.getVRegDef(SrcReg);
73 assert(BuildVec &&
74 BuildVec->getOpcode() == TargetOpcode::G_BUILD_VECTOR);
75 GR->add(Const, BuildVec);
76 for (unsigned i = 0; i < ConstVec->getNumElements(); ++i) {
77 // Ensure that OpConstantComposite reuses a constant when it's
78 // already created and available in the same machine function.
79 Constant *ElemConst = ConstVec->getElementAsConstant(i);
80 Register ElemReg = GR->find(ElemConst, &MF);
81 if (!ElemReg.isValid())
82 GR->add(ElemConst,
83 MRI.getVRegDef(BuildVec->getOperand(1 + i).getReg()));
84 else
85 BuildVec->getOperand(1 + i).setReg(ElemReg);
86 }
87 }
88 if (Const->getType()->isTargetExtTy()) {
89 // remember association so that we can restore it when assign types
90 MachineInstr *SrcMI = MRI.getVRegDef(SrcReg);
91 if (SrcMI)
92 GR->add(Const, SrcMI);
93 if (SrcMI && (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT ||
94 SrcMI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF))
95 TargetExtConstTypes[SrcMI] = Const->getType();
96 if (Const->isNullValue()) {
97 MachineBasicBlock &DepMBB = MF.front();
98 MachineIRBuilder MIB(DepMBB, DepMBB.getFirstNonPHI());
99 SPIRVType *ExtType = GR->getOrCreateSPIRVType(
100 Const->getType(), MIB, SPIRV::AccessQualifier::ReadWrite,
101 true);
102 assert(SrcMI && "Expected source instruction to be valid");
103 SrcMI->setDesc(STI.getInstrInfo()->get(SPIRV::OpConstantNull));
105 GR->getSPIRVTypeID(ExtType), false));
106 }
107 }
108 } else {
109 RegsAlreadyAddedToDT[&MI] = Reg;
110 // This MI is unused and will be removed. If the MI uses
111 // const_composite, it will be unused and should be removed too.
112 assert(MI.getOperand(2).isReg() && "Reg operand is expected");
113 MachineInstr *SrcMI = MRI.getVRegDef(MI.getOperand(2).getReg());
114 if (SrcMI && isSpvIntrinsic(*SrcMI, Intrinsic::spv_const_composite))
115 ToEraseComposites.push_back(SrcMI);
116 }
117 }
118 }
119 }
120 for (MachineInstr *MI : ToErase) {
121 Register Reg = MI->getOperand(2).getReg();
122 auto It = RegsAlreadyAddedToDT.find(MI);
123 if (It != RegsAlreadyAddedToDT.end())
124 Reg = It->second;
125 auto *RC = MRI.getRegClassOrNull(MI->getOperand(0).getReg());
126 if (!MRI.getRegClassOrNull(Reg) && RC)
127 MRI.setRegClass(Reg, RC);
128 MRI.replaceRegWith(MI->getOperand(0).getReg(), Reg);
130 MI->eraseFromParent();
131 }
132 for (MachineInstr *MI : ToEraseComposites) {
134 MI->eraseFromParent();
135 }
136}
137
140 MachineIRBuilder MIB) {
142 for (MachineBasicBlock &MBB : MF) {
143 for (MachineInstr &MI : MBB) {
144 if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_name))
145 continue;
146 const MDNode *MD = MI.getOperand(2).getMetadata();
147 StringRef ValueName = cast<MDString>(MD->getOperand(0))->getString();
148 if (ValueName.size() > 0) {
149 MIB.setInsertPt(*MI.getParent(), MI);
150 buildOpName(MI.getOperand(1).getReg(), ValueName, MIB);
151 }
152 ToErase.push_back(&MI);
153 }
154 for (MachineInstr *MI : ToErase) {
156 MI->eraseFromParent();
157 }
158 ToErase.clear();
159 }
160}
161
164 for (MachineRegisterInfo::use_instr_iterator I = MRI->use_instr_begin(Reg),
165 IE = MRI->use_instr_end();
166 I != IE; ++I) {
167 MachineInstr *UseMI = &*I;
168 if ((isSpvIntrinsic(*UseMI, Intrinsic::spv_assign_ptr_type) ||
169 isSpvIntrinsic(*UseMI, Intrinsic::spv_assign_type)) &&
170 UseMI->getOperand(1).getReg() == Reg)
171 return UseMI;
172 }
173 return nullptr;
174}
175
177 Register ResVReg, Register OpReg) {
178 SPIRVType *ResType = GR->getSPIRVTypeForVReg(ResVReg);
179 SPIRVType *OpType = GR->getSPIRVTypeForVReg(OpReg);
180 assert(ResType && OpType && "Operand types are expected");
181 if (!GR->isBitcastCompatible(ResType, OpType))
182 report_fatal_error("incompatible result and operand types in a bitcast");
184 if (!MRI->getRegClassOrNull(ResVReg))
185 MRI->setRegClass(ResVReg, GR->getRegClass(ResType));
186 if (ResType == OpType)
187 MIB.buildInstr(TargetOpcode::COPY).addDef(ResVReg).addUse(OpReg);
188 else
189 MIB.buildInstr(SPIRV::OpBitcast)
190 .addDef(ResVReg)
191 .addUse(GR->getSPIRVTypeID(ResType))
192 .addUse(OpReg);
193}
194
195// We lower G_BITCAST to OpBitcast here to avoid a MachineVerifier error.
196// The verifier checks if the source and destination LLTs of a G_BITCAST are
197// different, but this check is too strict for SPIR-V's typed pointers, which
198// may have the same LLT but different SPIRVType (e.g. pointers to different
199// pointee types). By lowering to OpBitcast here, we bypass the verifier's
200// check. See discussion in https://github.com/llvm/llvm-project/pull/110270
201// for more context.
202//
203// We also handle the llvm.spv.bitcast intrinsic here. If the source and
204// destination SPIR-V types are the same, we lower it to a COPY to enable
205// further optimizations like copy propagation.
207 MachineIRBuilder MIB) {
209 for (MachineBasicBlock &MBB : MF) {
210 for (MachineInstr &MI : MBB) {
211 if (isSpvIntrinsic(MI, Intrinsic::spv_bitcast)) {
212 Register DstReg = MI.getOperand(0).getReg();
213 Register SrcReg = MI.getOperand(2).getReg();
214 SPIRVType *DstType = GR->getSPIRVTypeForVReg(DstReg);
215 assert(
216 DstType &&
217 "Expected destination SPIR-V type to have been assigned already.");
218 SPIRVType *SrcType = GR->getSPIRVTypeForVReg(SrcReg);
219 assert(SrcType &&
220 "Expected source SPIR-V type to have been assigned already.");
221 if (DstType == SrcType) {
222 MIB.setInsertPt(*MI.getParent(), MI);
223 MIB.buildCopy(DstReg, SrcReg);
224 ToErase.push_back(&MI);
225 continue;
226 }
227 }
228
229 if (MI.getOpcode() != TargetOpcode::G_BITCAST)
230 continue;
231
232 MIB.setInsertPt(*MI.getParent(), MI);
233 buildOpBitcast(GR, MIB, MI.getOperand(0).getReg(),
234 MI.getOperand(1).getReg());
235 ToErase.push_back(&MI);
236 }
237 }
238 for (MachineInstr *MI : ToErase) {
240 MI->eraseFromParent();
241 }
242}
243
245 MachineIRBuilder MIB) {
246 // Get access to information about available extensions
247 const SPIRVSubtarget *ST =
248 static_cast<const SPIRVSubtarget *>(&MIB.getMF().getSubtarget());
250 for (MachineBasicBlock &MBB : MF) {
251 for (MachineInstr &MI : MBB) {
252 if (!isSpvIntrinsic(MI, Intrinsic::spv_ptrcast))
253 continue;
254 assert(MI.getOperand(2).isReg());
255 MIB.setInsertPt(*MI.getParent(), MI);
256 ToErase.push_back(&MI);
257 Register Def = MI.getOperand(0).getReg();
258 Register Source = MI.getOperand(2).getReg();
259 Type *ElemTy = getMDOperandAsType(MI.getOperand(3).getMetadata(), 0);
260 auto SC =
261 isa<FunctionType>(ElemTy)
262 ? SPIRV::StorageClass::CodeSectionINTEL
263 : addressSpaceToStorageClass(MI.getOperand(4).getImm(), *ST);
264 SPIRVType *AssignedPtrType =
265 GR->getOrCreateSPIRVPointerType(ElemTy, MI, SC);
266
267 // If the ptrcast would be redundant, replace all uses with the source
268 // register.
270 if (GR->getSPIRVTypeForVReg(Source) == AssignedPtrType) {
271 // Erase Def's assign type instruction if we are going to replace Def.
272 if (MachineInstr *AssignMI = findAssignTypeInstr(Def, MRI))
273 ToErase.push_back(AssignMI);
274 MRI->replaceRegWith(Def, Source);
275 } else {
276 if (!GR->getSPIRVTypeForVReg(Def, &MF))
277 GR->assignSPIRVTypeToVReg(AssignedPtrType, Def, MF);
278 MIB.buildBitcast(Def, Source);
279 }
280 }
281 }
282 for (MachineInstr *MI : ToErase) {
284 MI->eraseFromParent();
285 }
286}
287
288// Translating GV, IRTranslator sometimes generates following IR:
289// %1 = G_GLOBAL_VALUE
290// %2 = COPY %1
291// %3 = G_ADDRSPACE_CAST %2
292//
293// or
294//
295// %1 = G_ZEXT %2
296// G_MEMCPY ... %2 ...
297//
298// New registers have no SPIRVType and no register class info.
299//
300// Set SPIRVType for GV, propagate it from GV to other instructions,
301// also set register classes.
304 MachineIRBuilder &MIB) {
305 SPIRVType *SpvType = nullptr;
306 assert(MI && "Machine instr is expected");
307 if (MI->getOperand(0).isReg()) {
308 Register Reg = MI->getOperand(0).getReg();
309 SpvType = GR->getSPIRVTypeForVReg(Reg);
310 if (!SpvType) {
311 switch (MI->getOpcode()) {
312 case TargetOpcode::G_FCONSTANT:
313 case TargetOpcode::G_CONSTANT: {
314 MIB.setInsertPt(*MI->getParent(), MI);
315 Type *Ty = MI->getOperand(1).getCImm()->getType();
316 SpvType = GR->getOrCreateSPIRVType(
317 Ty, MIB, SPIRV::AccessQualifier::ReadWrite, true);
318 break;
319 }
320 case TargetOpcode::G_GLOBAL_VALUE: {
321 MIB.setInsertPt(*MI->getParent(), MI);
322 const GlobalValue *Global = MI->getOperand(1).getGlobal();
324 auto *Ty = TypedPointerType::get(ElementTy,
325 Global->getType()->getAddressSpace());
326 SpvType = GR->getOrCreateSPIRVType(
327 Ty, MIB, SPIRV::AccessQualifier::ReadWrite, true);
328 break;
329 }
330 case TargetOpcode::G_ANYEXT:
331 case TargetOpcode::G_SEXT:
332 case TargetOpcode::G_ZEXT: {
333 if (MI->getOperand(1).isReg()) {
334 if (MachineInstr *DefInstr =
335 MRI.getVRegDef(MI->getOperand(1).getReg())) {
336 if (SPIRVType *Def = propagateSPIRVType(DefInstr, GR, MRI, MIB)) {
337 unsigned CurrentBW = GR->getScalarOrVectorBitWidth(Def);
338 unsigned ExpectedBW =
339 std::max(MRI.getType(Reg).getScalarSizeInBits(), CurrentBW);
340 unsigned NumElements = GR->getScalarOrVectorComponentCount(Def);
341 SpvType = GR->getOrCreateSPIRVIntegerType(ExpectedBW, MIB);
342 if (NumElements > 1)
343 SpvType = GR->getOrCreateSPIRVVectorType(SpvType, NumElements,
344 MIB, true);
345 }
346 }
347 }
348 break;
349 }
350 case TargetOpcode::G_PTRTOINT:
351 SpvType = GR->getOrCreateSPIRVIntegerType(
352 MRI.getType(Reg).getScalarSizeInBits(), MIB);
353 break;
354 case TargetOpcode::G_TRUNC:
355 case TargetOpcode::G_ADDRSPACE_CAST:
356 case TargetOpcode::G_PTR_ADD:
357 case TargetOpcode::COPY: {
358 MachineOperand &Op = MI->getOperand(1);
359 MachineInstr *Def = Op.isReg() ? MRI.getVRegDef(Op.getReg()) : nullptr;
360 if (Def)
361 SpvType = propagateSPIRVType(Def, GR, MRI, MIB);
362 break;
363 }
364 default:
365 break;
366 }
367 if (SpvType) {
368 // check if the address space needs correction
369 LLT RegType = MRI.getType(Reg);
370 if (SpvType->getOpcode() == SPIRV::OpTypePointer &&
371 RegType.isPointer() &&
373 RegType.getAddressSpace()) {
374 const SPIRVSubtarget &ST =
375 MI->getParent()->getParent()->getSubtarget<SPIRVSubtarget>();
376 auto TSC = addressSpaceToStorageClass(RegType.getAddressSpace(), ST);
377 SpvType = GR->changePointerStorageClass(SpvType, TSC, *MI);
378 }
379 GR->assignSPIRVTypeToVReg(SpvType, Reg, MIB.getMF());
380 }
381 if (!MRI.getRegClassOrNull(Reg))
382 MRI.setRegClass(Reg, SpvType ? GR->getRegClass(SpvType)
383 : &SPIRV::iIDRegClass);
384 }
385 }
386 return SpvType;
387}
388
389// To support current approach and limitations wrt. bit width here we widen a
390// scalar register with a bit width greater than 1 to valid sizes and cap it to
391// 64 width.
392static unsigned widenBitWidthToNextPow2(unsigned BitWidth) {
393 if (BitWidth == 1)
394 return 1; // No need to widen 1-bit values
395 return std::min(std::max(1u << Log2_32_Ceil(BitWidth), 8u), 64u);
396}
397
399 LLT RegType = MRI.getType(Reg);
400 if (!RegType.isScalar())
401 return;
402 unsigned CurrentWidth = RegType.getScalarSizeInBits();
403 unsigned NewWidth = widenBitWidthToNextPow2(CurrentWidth);
404 if (NewWidth != CurrentWidth)
405 MRI.setType(Reg, LLT::scalar(NewWidth));
406}
407
408static void widenCImmType(MachineOperand &MOP) {
409 const ConstantInt *CImmVal = MOP.getCImm();
410 unsigned CurrentWidth = CImmVal->getBitWidth();
411 unsigned NewWidth = widenBitWidthToNextPow2(CurrentWidth);
412 if (NewWidth != CurrentWidth) {
413 // Replace the immediate value with the widened version
414 MOP.setCImm(ConstantInt::get(CImmVal->getType()->getContext(),
415 CImmVal->getValue().zextOrTrunc(NewWidth)));
416 }
417}
418
420 MachineBasicBlock &MBB = *Def->getParent();
422 Def->getNextNode() ? Def->getNextNode()->getIterator() : MBB.end();
423 // Skip all the PHI and debug instructions.
424 while (DefIt != MBB.end() &&
425 (DefIt->isPHI() || DefIt->isDebugOrPseudoInstr()))
426 DefIt = std::next(DefIt);
427 MIB.setInsertPt(MBB, DefIt);
428}
429
430namespace llvm {
431void updateRegType(Register Reg, Type *Ty, SPIRVType *SpvType,
434 assert((Ty || SpvType) && "Either LLVM or SPIRV type is expected.");
435 MachineInstr *Def = MRI.getVRegDef(Reg);
436 setInsertPtAfterDef(MIB, Def);
437 if (!SpvType)
438 SpvType = GR->getOrCreateSPIRVType(Ty, MIB,
439 SPIRV::AccessQualifier::ReadWrite, true);
440 if (!MRI.getRegClassOrNull(Reg))
441 MRI.setRegClass(Reg, GR->getRegClass(SpvType));
442 if (!MRI.getType(Reg).isValid())
443 MRI.setType(Reg, GR->getRegType(SpvType));
444 GR->assignSPIRVTypeToVReg(SpvType, Reg, MIB.getMF());
445}
446
449 SPIRVType *KnownResType) {
450 MIB.setInsertPt(*MI.getParent(), MI.getIterator());
451 for (auto &Op : MI.operands()) {
452 if (!Op.isReg() || Op.isDef())
453 continue;
454 Register OpReg = Op.getReg();
455 SPIRVType *SpvType = GR->getSPIRVTypeForVReg(OpReg);
456 if (!SpvType && KnownResType) {
457 SpvType = KnownResType;
458 GR->assignSPIRVTypeToVReg(KnownResType, OpReg, *MI.getMF());
459 }
460 assert(SpvType);
461 if (!MRI.getRegClassOrNull(OpReg))
462 MRI.setRegClass(OpReg, GR->getRegClass(SpvType));
463 if (!MRI.getType(OpReg).isValid())
464 MRI.setType(OpReg, GR->getRegType(SpvType));
465 }
466}
467} // namespace llvm
468
469static void
472 DenseMap<MachineInstr *, Type *> &TargetExtConstTypes) {
473 // Get access to information about available extensions
474 const SPIRVSubtarget *ST =
475 static_cast<const SPIRVSubtarget *>(&MIB.getMF().getSubtarget());
476
479 DenseMap<MachineInstr *, Register> RegsAlreadyAddedToDT;
480
481 bool IsExtendedInts =
482 ST->canUseExtension(
483 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers) ||
484 ST->canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions) ||
485 ST->canUseExtension(SPIRV::Extension::SPV_INTEL_int4);
486
487 for (MachineBasicBlock *MBB : post_order(&MF)) {
488 if (MBB->empty())
489 continue;
490
491 bool ReachedBegin = false;
492 for (auto MII = std::prev(MBB->end()), Begin = MBB->begin();
493 !ReachedBegin;) {
494 MachineInstr &MI = *MII;
495 unsigned MIOp = MI.getOpcode();
496
497 if (!IsExtendedInts) {
498 // validate bit width of scalar registers and constant immediates
499 for (auto &MOP : MI.operands()) {
500 if (MOP.isReg())
501 widenScalarType(MOP.getReg(), MRI);
502 else if (MOP.isCImm())
503 widenCImmType(MOP);
504 }
505 }
506
507 if (isSpvIntrinsic(MI, Intrinsic::spv_assign_ptr_type)) {
508 Register Reg = MI.getOperand(1).getReg();
509 MIB.setInsertPt(*MI.getParent(), MI.getIterator());
510 Type *ElementTy = getMDOperandAsType(MI.getOperand(2).getMetadata(), 0);
511 SPIRVType *AssignedPtrType = GR->getOrCreateSPIRVPointerType(
512 ElementTy, MI,
513 addressSpaceToStorageClass(MI.getOperand(3).getImm(), *ST));
514 MachineInstr *Def = MRI.getVRegDef(Reg);
515 assert(Def && "Expecting an instruction that defines the register");
516 // G_GLOBAL_VALUE already has type info.
517 if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE)
518 updateRegType(Reg, nullptr, AssignedPtrType, GR, MIB,
519 MF.getRegInfo());
520 ToErase.push_back(&MI);
521 } else if (isSpvIntrinsic(MI, Intrinsic::spv_assign_type)) {
522 Register Reg = MI.getOperand(1).getReg();
523 Type *Ty = getMDOperandAsType(MI.getOperand(2).getMetadata(), 0);
524 MachineInstr *Def = MRI.getVRegDef(Reg);
525 assert(Def && "Expecting an instruction that defines the register");
526 // G_GLOBAL_VALUE already has type info.
527 if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE)
528 updateRegType(Reg, Ty, nullptr, GR, MIB, MF.getRegInfo());
529 ToErase.push_back(&MI);
530 } else if (MIOp == TargetOpcode::FAKE_USE && MI.getNumOperands() > 0) {
531 MachineInstr *MdMI = MI.getPrevNode();
532 if (MdMI && isSpvIntrinsic(*MdMI, Intrinsic::spv_value_md)) {
533 // It's an internal service info from before IRTranslator passes.
534 MachineInstr *Def = getVRegDef(MRI, MI.getOperand(0).getReg());
535 for (unsigned I = 1, E = MI.getNumOperands(); I != E && Def; ++I)
536 if (getVRegDef(MRI, MI.getOperand(I).getReg()) != Def)
537 Def = nullptr;
538 if (Def) {
539 const MDNode *MD = MdMI->getOperand(1).getMetadata();
541 cast<MDString>(MD->getOperand(1))->getString();
542 const MDNode *TypeMD = cast<MDNode>(MD->getOperand(0));
543 Type *ValueTy = getMDOperandAsType(TypeMD, 0);
544 GR->addValueAttrs(Def, std::make_pair(ValueTy, ValueName.str()));
545 }
546 ToErase.push_back(MdMI);
547 }
548 ToErase.push_back(&MI);
549 } else if (MIOp == TargetOpcode::G_CONSTANT ||
550 MIOp == TargetOpcode::G_FCONSTANT ||
551 MIOp == TargetOpcode::G_BUILD_VECTOR) {
552 // %rc = G_CONSTANT ty Val
553 // Ensure %rc has a valid SPIR-V type assigned in the Global Registry.
554 Register Reg = MI.getOperand(0).getReg();
555 bool NeedAssignType = GR->getSPIRVTypeForVReg(Reg) == nullptr;
556 Type *Ty = nullptr;
557 if (MIOp == TargetOpcode::G_CONSTANT) {
558 auto TargetExtIt = TargetExtConstTypes.find(&MI);
559 Ty = TargetExtIt == TargetExtConstTypes.end()
560 ? MI.getOperand(1).getCImm()->getType()
561 : TargetExtIt->second;
562 const ConstantInt *OpCI = MI.getOperand(1).getCImm();
563 // TODO: we may wish to analyze here if OpCI is zero and LLT RegType =
564 // MRI.getType(Reg); RegType.isPointer() is true, so that we observe
565 // at this point not i64/i32 constant but null pointer in the
566 // corresponding address space of RegType.getAddressSpace(). This may
567 // help to successfully validate the case when a OpConstantComposite's
568 // constituent has type that does not match Result Type of
569 // OpConstantComposite (see, for example,
570 // pointers/PtrCast-null-in-OpSpecConstantOp.ll).
571 Register PrimaryReg = GR->find(OpCI, &MF);
572 if (!PrimaryReg.isValid()) {
573 GR->add(OpCI, &MI);
574 } else if (PrimaryReg != Reg &&
575 MRI.getType(Reg) == MRI.getType(PrimaryReg)) {
576 auto *RCReg = MRI.getRegClassOrNull(Reg);
577 auto *RCPrimary = MRI.getRegClassOrNull(PrimaryReg);
578 if (!RCReg || RCPrimary == RCReg) {
579 RegsAlreadyAddedToDT[&MI] = PrimaryReg;
580 ToErase.push_back(&MI);
581 NeedAssignType = false;
582 }
583 }
584 } else if (MIOp == TargetOpcode::G_FCONSTANT) {
585 Ty = MI.getOperand(1).getFPImm()->getType();
586 } else {
587 assert(MIOp == TargetOpcode::G_BUILD_VECTOR);
588 Type *ElemTy = nullptr;
589 MachineInstr *ElemMI = MRI.getVRegDef(MI.getOperand(1).getReg());
590 assert(ElemMI);
591
592 if (ElemMI->getOpcode() == TargetOpcode::G_CONSTANT) {
593 ElemTy = ElemMI->getOperand(1).getCImm()->getType();
594 } else if (ElemMI->getOpcode() == TargetOpcode::G_FCONSTANT) {
595 ElemTy = ElemMI->getOperand(1).getFPImm()->getType();
596 } else {
597 if (const SPIRVType *ElemSpvType =
598 GR->getSPIRVTypeForVReg(MI.getOperand(1).getReg(), &MF))
599 ElemTy = const_cast<Type *>(GR->getTypeForSPIRVType(ElemSpvType));
600 }
601 if (ElemTy)
602 Ty = VectorType::get(
603 ElemTy, MI.getNumExplicitOperands() - MI.getNumExplicitDefs(),
604 false);
605 else
606 NeedAssignType = false;
607 }
608 if (NeedAssignType)
609 updateRegType(Reg, Ty, nullptr, GR, MIB, MRI);
610 } else if (MIOp == TargetOpcode::G_GLOBAL_VALUE) {
611 propagateSPIRVType(&MI, GR, MRI, MIB);
612 }
613
614 if (MII == Begin)
615 ReachedBegin = true;
616 else
617 --MII;
618 }
619 }
620 for (MachineInstr *MI : ToErase) {
621 auto It = RegsAlreadyAddedToDT.find(MI);
622 if (It != RegsAlreadyAddedToDT.end())
623 MRI.replaceRegWith(MI->getOperand(0).getReg(), It->second);
625 MI->eraseFromParent();
626 }
627
628 // Address the case when IRTranslator introduces instructions with new
629 // registers without SPIRVType associated.
630 for (MachineBasicBlock &MBB : MF) {
631 for (MachineInstr &MI : MBB) {
632 switch (MI.getOpcode()) {
633 case TargetOpcode::G_TRUNC:
634 case TargetOpcode::G_ANYEXT:
635 case TargetOpcode::G_SEXT:
636 case TargetOpcode::G_ZEXT:
637 case TargetOpcode::G_PTRTOINT:
638 case TargetOpcode::COPY:
639 case TargetOpcode::G_ADDRSPACE_CAST:
640 propagateSPIRVType(&MI, GR, MRI, MIB);
641 break;
642 }
643 }
644 }
645}
646
649 MachineIRBuilder MIB) {
651 for (MachineBasicBlock &MBB : MF)
652 for (MachineInstr &MI : MBB)
653 if (isTypeFoldingSupported(MI.getOpcode()))
654 processInstr(MI, MIB, MRI, GR, nullptr);
655}
656
657static Register
659 SmallVector<unsigned, 4> *Ops = nullptr) {
660 Register DefReg;
661 unsigned StartOp = InlineAsm::MIOp_FirstOperand,
663 for (unsigned Idx = StartOp, MISz = MI->getNumOperands(); Idx != MISz;
664 ++Idx) {
665 const MachineOperand &MO = MI->getOperand(Idx);
666 if (MO.isMetadata())
667 continue;
668 if (Idx == AsmDescOp && MO.isImm()) {
669 // compute the index of the next operand descriptor
670 const InlineAsm::Flag F(MO.getImm());
671 AsmDescOp += 1 + F.getNumOperandRegisters();
672 continue;
673 }
674 if (MO.isReg() && MO.isDef()) {
675 if (!Ops)
676 return MO.getReg();
677 else
678 DefReg = MO.getReg();
679 } else if (Ops) {
680 Ops->push_back(Idx);
681 }
682 }
683 return DefReg;
684}
685
686static void
688 const SPIRVSubtarget &ST, MachineIRBuilder MIRBuilder,
689 const SmallVector<MachineInstr *> &ToProcess) {
691 Register AsmTargetReg;
692 for (unsigned i = 0, Sz = ToProcess.size(); i + 1 < Sz; i += 2) {
693 MachineInstr *I1 = ToProcess[i], *I2 = ToProcess[i + 1];
694 assert(isSpvIntrinsic(*I1, Intrinsic::spv_inline_asm) && I2->isInlineAsm());
695 MIRBuilder.setInsertPt(*I2->getParent(), *I2);
696
697 if (!AsmTargetReg.isValid()) {
698 // define vendor specific assembly target or dialect
699 AsmTargetReg = MRI.createGenericVirtualRegister(LLT::scalar(32));
700 MRI.setRegClass(AsmTargetReg, &SPIRV::iIDRegClass);
701 auto AsmTargetMIB =
702 MIRBuilder.buildInstr(SPIRV::OpAsmTargetINTEL).addDef(AsmTargetReg);
703 addStringImm(ST.getTargetTripleAsStr(), AsmTargetMIB);
704 GR->add(AsmTargetMIB.getInstr(), AsmTargetMIB);
705 }
706
707 // create types
708 const MDNode *IAMD = I1->getOperand(1).getMetadata();
711 for (const auto &ArgTy : FTy->params())
712 ArgTypes.push_back(GR->getOrCreateSPIRVType(
713 ArgTy, MIRBuilder, SPIRV::AccessQualifier::ReadWrite, true));
714 SPIRVType *RetType =
715 GR->getOrCreateSPIRVType(FTy->getReturnType(), MIRBuilder,
716 SPIRV::AccessQualifier::ReadWrite, true);
718 FTy, RetType, ArgTypes, MIRBuilder);
719
720 // define vendor specific assembly instructions string
721 Register AsmReg = MRI.createGenericVirtualRegister(LLT::scalar(32));
722 MRI.setRegClass(AsmReg, &SPIRV::iIDRegClass);
723 auto AsmMIB = MIRBuilder.buildInstr(SPIRV::OpAsmINTEL)
724 .addDef(AsmReg)
725 .addUse(GR->getSPIRVTypeID(RetType))
726 .addUse(GR->getSPIRVTypeID(FuncType))
727 .addUse(AsmTargetReg);
728 // inline asm string:
729 addStringImm(I2->getOperand(InlineAsm::MIOp_AsmString).getSymbolName(),
730 AsmMIB);
731 // inline asm constraint string:
732 addStringImm(cast<MDString>(I1->getOperand(2).getMetadata()->getOperand(0))
733 ->getString(),
734 AsmMIB);
735 GR->add(AsmMIB.getInstr(), AsmMIB);
736
737 // calls the inline assembly instruction
738 unsigned ExtraInfo = I2->getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
739 if (ExtraInfo & InlineAsm::Extra_HasSideEffects)
740 MIRBuilder.buildInstr(SPIRV::OpDecorate)
741 .addUse(AsmReg)
742 .addImm(static_cast<uint32_t>(SPIRV::Decoration::SideEffectsINTEL));
743
745 if (!DefReg.isValid()) {
746 DefReg = MRI.createGenericVirtualRegister(LLT::scalar(32));
747 MRI.setRegClass(DefReg, &SPIRV::iIDRegClass);
748 SPIRVType *VoidType = GR->getOrCreateSPIRVType(
749 Type::getVoidTy(MF.getFunction().getContext()), MIRBuilder,
750 SPIRV::AccessQualifier::ReadWrite, true);
751 GR->assignSPIRVTypeToVReg(VoidType, DefReg, MF);
752 }
753
754 auto AsmCall = MIRBuilder.buildInstr(SPIRV::OpAsmCallINTEL)
755 .addDef(DefReg)
756 .addUse(GR->getSPIRVTypeID(RetType))
757 .addUse(AsmReg);
758 for (unsigned IntrIdx = 3; IntrIdx < I1->getNumOperands(); ++IntrIdx)
759 AsmCall.addUse(I1->getOperand(IntrIdx).getReg());
760 }
761 for (MachineInstr *MI : ToProcess) {
763 MI->eraseFromParent();
764 }
765}
766
768 const SPIRVSubtarget &ST,
769 MachineIRBuilder MIRBuilder) {
771 for (MachineBasicBlock &MBB : MF) {
772 for (MachineInstr &MI : MBB) {
773 if (isSpvIntrinsic(MI, Intrinsic::spv_inline_asm) ||
774 MI.getOpcode() == TargetOpcode::INLINEASM)
775 ToProcess.push_back(&MI);
776 }
777 }
778 if (ToProcess.size() == 0)
779 return;
780
781 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly))
782 report_fatal_error("Inline assembly instructions require the "
783 "following SPIR-V extension: SPV_INTEL_inline_assembly",
784 false);
785
786 insertInlineAsmProcess(MF, GR, ST, MIRBuilder, ToProcess);
787}
788
790 union {
791 float F;
792 uint32_t Spir;
793 } FPMaxError;
794 FPMaxError.F = F;
795 return FPMaxError.Spir;
796}
797
799 MachineIRBuilder MIB) {
802 for (MachineBasicBlock &MBB : MF) {
803 for (MachineInstr &MI : MBB) {
804 if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration) &&
805 !isSpvIntrinsic(MI, Intrinsic::spv_assign_aliasing_decoration) &&
806 !isSpvIntrinsic(MI, Intrinsic::spv_assign_fpmaxerror_decoration))
807 continue;
808 MIB.setInsertPt(*MI.getParent(), MI.getNextNode());
809 if (isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration)) {
810 buildOpSpirvDecorations(MI.getOperand(1).getReg(), MIB,
811 MI.getOperand(2).getMetadata(), ST);
812 } else if (isSpvIntrinsic(MI,
813 Intrinsic::spv_assign_fpmaxerror_decoration)) {
815 MI.getOperand(2).getMetadata()->getOperand(0));
816 uint32_t OpValue =
818
819 buildOpDecorate(MI.getOperand(1).getReg(), MIB,
820 SPIRV::Decoration::FPMaxErrorDecorationINTEL,
821 {OpValue});
822 } else {
823 GR->buildMemAliasingOpDecorate(MI.getOperand(1).getReg(), MIB,
824 MI.getOperand(2).getImm(),
825 MI.getOperand(3).getMetadata());
826 }
827
828 ToErase.push_back(&MI);
829 }
830 }
831 for (MachineInstr *MI : ToErase) {
833 MI->eraseFromParent();
834 }
835}
836
837// LLVM allows the switches to use registers as cases, while SPIR-V required
838// those to be immediate values. This function replaces such operands with the
839// equivalent immediate constant.
842 MachineIRBuilder MIB) {
844 for (MachineBasicBlock &MBB : MF) {
845 for (MachineInstr &MI : MBB) {
846 if (!isSpvIntrinsic(MI, Intrinsic::spv_switch))
847 continue;
848
850 NewOperands.push_back(MI.getOperand(0)); // Opcode
851 NewOperands.push_back(MI.getOperand(1)); // Condition
852 NewOperands.push_back(MI.getOperand(2)); // Default
853 for (unsigned i = 3; i < MI.getNumOperands(); i += 2) {
854 Register Reg = MI.getOperand(i).getReg();
856 NewOperands.push_back(
858
859 NewOperands.push_back(MI.getOperand(i + 1));
860 }
861
862 assert(MI.getNumOperands() == NewOperands.size());
863 while (MI.getNumOperands() > 0)
864 MI.removeOperand(0);
865 for (auto &MO : NewOperands)
866 MI.addOperand(MO);
867 }
868 }
869}
870
871// Some instructions are used during CodeGen but should never be emitted.
872// Cleaning up those.
876 for (MachineBasicBlock &MBB : MF) {
877 for (MachineInstr &MI : MBB) {
878 if (isSpvIntrinsic(MI, Intrinsic::spv_track_constant) ||
879 MI.getOpcode() == TargetOpcode::G_BRINDIRECT)
880 ToEraseMI.push_back(&MI);
881 }
882 }
883
884 for (MachineInstr *MI : ToEraseMI) {
886 MI->eraseFromParent();
887 }
888}
889
890// Find all usages of G_BLOCK_ADDR in our intrinsics and replace those
891// operands/registers by the actual MBB it references.
893 MachineIRBuilder MIB) {
894 // Gather the reverse-mapping BB -> MBB.
896 for (MachineBasicBlock &MBB : MF)
897 BB2MBB[MBB.getBasicBlock()] = &MBB;
898
899 // Gather instructions requiring patching. For now, only those can use
900 // G_BLOCK_ADDR.
901 SmallVector<MachineInstr *, 8> InstructionsToPatch;
902 for (MachineBasicBlock &MBB : MF) {
903 for (MachineInstr &MI : MBB) {
904 if (isSpvIntrinsic(MI, Intrinsic::spv_switch) ||
905 isSpvIntrinsic(MI, Intrinsic::spv_loop_merge) ||
906 isSpvIntrinsic(MI, Intrinsic::spv_selection_merge))
907 InstructionsToPatch.push_back(&MI);
908 }
909 }
910
911 // For each instruction to fix, we replace all the G_BLOCK_ADDR operands by
912 // the actual MBB it references. Once those references have been updated, we
913 // can cleanup remaining G_BLOCK_ADDR references.
914 SmallPtrSet<MachineBasicBlock *, 8> ClearAddressTaken;
917 for (MachineInstr *MI : InstructionsToPatch) {
919 for (unsigned i = 0; i < MI->getNumOperands(); ++i) {
920 // The operand is not a register, keep as-is.
921 if (!MI->getOperand(i).isReg()) {
922 NewOps.push_back(MI->getOperand(i));
923 continue;
924 }
925
926 Register Reg = MI->getOperand(i).getReg();
927 MachineInstr *BuildMBB = MRI.getVRegDef(Reg);
928 // The register is not the result of G_BLOCK_ADDR, keep as-is.
929 if (!BuildMBB || BuildMBB->getOpcode() != TargetOpcode::G_BLOCK_ADDR) {
930 NewOps.push_back(MI->getOperand(i));
931 continue;
932 }
933
934 assert(BuildMBB && BuildMBB->getOpcode() == TargetOpcode::G_BLOCK_ADDR &&
935 BuildMBB->getOperand(1).isBlockAddress() &&
936 BuildMBB->getOperand(1).getBlockAddress());
937 BasicBlock *BB =
938 BuildMBB->getOperand(1).getBlockAddress()->getBasicBlock();
939 auto It = BB2MBB.find(BB);
940 if (It == BB2MBB.end())
941 report_fatal_error("cannot find a machine basic block by a basic block "
942 "in a switch statement");
943 MachineBasicBlock *ReferencedBlock = It->second;
944 NewOps.push_back(MachineOperand::CreateMBB(ReferencedBlock));
945
946 ClearAddressTaken.insert(ReferencedBlock);
947 ToEraseMI.insert(BuildMBB);
948 }
949
950 // Replace the operands.
951 assert(MI->getNumOperands() == NewOps.size());
952 while (MI->getNumOperands() > 0)
953 MI->removeOperand(0);
954 for (auto &MO : NewOps)
955 MI->addOperand(MO);
956
957 if (MachineInstr *Next = MI->getNextNode()) {
958 if (isSpvIntrinsic(*Next, Intrinsic::spv_track_constant)) {
959 ToEraseMI.insert(Next);
960 Next = MI->getNextNode();
961 }
962 if (Next && Next->getOpcode() == TargetOpcode::G_BRINDIRECT)
963 ToEraseMI.insert(Next);
964 }
965 }
966
967 // BlockAddress operands were used to keep information between passes,
968 // let's undo the "address taken" status to reflect that Succ doesn't
969 // actually correspond to an IR-level basic block.
970 for (MachineBasicBlock *Succ : ClearAddressTaken)
971 Succ->setAddressTakenIRBlock(nullptr);
972
973 // If we just delete G_BLOCK_ADDR instructions with BlockAddress operands,
974 // this leaves their BasicBlock counterparts in a "address taken" status. This
975 // would make AsmPrinter to generate a series of unneeded labels of a "Address
976 // of block that was removed by CodeGen" kind. Let's first ensure that we
977 // don't have a dangling BlockAddress constants by zapping the BlockAddress
978 // nodes, and only after that proceed with erasing G_BLOCK_ADDR instructions.
979 Constant *Replacement =
980 ConstantInt::get(Type::getInt32Ty(MF.getFunction().getContext()), 1);
981 for (MachineInstr *BlockAddrI : ToEraseMI) {
982 if (BlockAddrI->getOpcode() == TargetOpcode::G_BLOCK_ADDR) {
983 BlockAddress *BA = const_cast<BlockAddress *>(
984 BlockAddrI->getOperand(1).getBlockAddress());
986 ConstantExpr::getIntToPtr(Replacement, BA->getType()));
987 BA->destroyConstant();
988 }
989 GR->invalidateMachineInstr(BlockAddrI);
990 BlockAddrI->eraseFromParent();
991 }
992}
993
995 if (MBB.empty())
996 return true;
997
998 // Branching SPIR-V intrinsics are not detected by this generic method.
999 // Thus, we can only trust negative result.
1000 if (!MBB.canFallThrough())
1001 return false;
1002
1003 // Otherwise, we must manually check if we have a SPIR-V intrinsic which
1004 // prevent an implicit fallthrough.
1005 for (MachineBasicBlock::reverse_iterator It = MBB.rbegin(), E = MBB.rend();
1006 It != E; ++It) {
1007 if (isSpvIntrinsic(*It, Intrinsic::spv_switch))
1008 return false;
1009 }
1010 return true;
1011}
1012
1014 MachineIRBuilder MIB) {
1015 // It is valid for MachineBasicBlocks to not finish with a branch instruction.
1016 // In such cases, they will simply fallthrough their immediate successor.
1017 for (MachineBasicBlock &MBB : MF) {
1019 continue;
1020
1021 assert(MBB.succ_size() == 1);
1022 MIB.setInsertPt(MBB, MBB.end());
1023 MIB.buildBr(**MBB.successors().begin());
1024 }
1025}
1026
1027bool SPIRVPreLegalizer::runOnMachineFunction(MachineFunction &MF) {
1028 // Initialize the type registry.
1029 const SPIRVSubtarget &ST = MF.getSubtarget<SPIRVSubtarget>();
1030 SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
1031 GR->setCurrentFunc(MF);
1032 MachineIRBuilder MIB(MF);
1033 // a registry of target extension constants
1034 DenseMap<MachineInstr *, Type *> TargetExtConstTypes;
1035 // to keep record of tracked constants
1036 addConstantsToTrack(MF, GR, ST, TargetExtConstTypes);
1037 foldConstantsIntoIntrinsics(MF, GR, MIB);
1038 insertBitcasts(MF, GR, MIB);
1039 generateAssignInstrs(MF, GR, MIB, TargetExtConstTypes);
1040
1041 processSwitchesConstants(MF, GR, MIB);
1042 processBlockAddr(MF, GR, MIB);
1044
1045 processInstrsWithTypeFolding(MF, GR, MIB);
1047 insertSpirvDecorations(MF, GR, MIB);
1048 insertInlineAsm(MF, GR, ST, MIB);
1049 lowerBitcasts(MF, GR, MIB);
1050
1051 return true;
1052}
1053
1054INITIALIZE_PASS(SPIRVPreLegalizer, DEBUG_TYPE, "SPIRV pre legalizer", false,
1055 false)
1056
1057char SPIRVPreLegalizer::ID = 0;
1058
1059FunctionPass *llvm::createSPIRVPreLegalizerPass() {
1060 return new SPIRVPreLegalizer();
1061}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Provides analysis for continuously CSEing during GISel passes.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Provides analysis for querying information about KnownBits during GISel passes.
#define DEBUG_TYPE
IRTranslator LLVM IR MI
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
static Register collectInlineAsmInstrOperands(MachineInstr *MI, SmallVector< unsigned, 4 > *Ops=nullptr)
static void insertInlineAsm(MachineFunction &MF, SPIRVGlobalRegistry *GR, const SPIRVSubtarget &ST, MachineIRBuilder MIRBuilder)
static void cleanupHelperInstructions(MachineFunction &MF, SPIRVGlobalRegistry *GR)
static void insertInlineAsmProcess(MachineFunction &MF, SPIRVGlobalRegistry *GR, const SPIRVSubtarget &ST, MachineIRBuilder MIRBuilder, const SmallVector< MachineInstr * > &ToProcess)
static void removeImplicitFallthroughs(MachineFunction &MF, MachineIRBuilder MIB)
static unsigned widenBitWidthToNextPow2(unsigned BitWidth)
static void setInsertPtAfterDef(MachineIRBuilder &MIB, MachineInstr *Def)
static bool isImplicitFallthrough(MachineBasicBlock &MBB)
static void insertSpirvDecorations(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void insertBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void processInstrsWithTypeFolding(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void processSwitchesConstants(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static SPIRVType * propagateSPIRVType(MachineInstr *MI, SPIRVGlobalRegistry *GR, MachineRegisterInfo &MRI, MachineIRBuilder &MIB)
static void lowerBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static MachineInstr * findAssignTypeInstr(Register Reg, MachineRegisterInfo *MRI)
static void widenCImmType(MachineOperand &MOP)
static void buildOpBitcast(SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, Register ResVReg, Register OpReg)
static void processBlockAddr(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void widenScalarType(Register Reg, MachineRegisterInfo &MRI)
static void foldConstantsIntoIntrinsics(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void addConstantsToTrack(MachineFunction &MF, SPIRVGlobalRegistry *GR, const SPIRVSubtarget &STI, DenseMap< MachineInstr *, Type * > &TargetExtConstTypes)
static uint32_t convertFloatToSPIRVWord(float F)
static void generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB, DenseMap< MachineInstr *, Type * > &TargetExtConstTypes)
LLVM_ABI float convertToFloat() const
Converts this APFloat to host float value.
Definition APFloat.cpp:6143
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
Definition APInt.cpp:1033
Represent the analysis usage information of a pass.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
The address of a basic block.
Definition Constants.h:904
BasicBlock * getBasicBlock() const
Definition Constants.h:939
static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
ConstantFP - Floating Point Values [float, double].
Definition Constants.h:282
const APFloat & getValueAPF() const
Definition Constants.h:325
This is the shared class of boolean and integer constants.
Definition Constants.h:87
unsigned getBitWidth() const
getBitWidth - Return the scalar bitwidth of this constant.
Definition Constants.h:162
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition Constants.h:159
This is an important base class in LLVM.
Definition Constant.h:43
LLVM_ABI void destroyConstant()
Called if some element of this constant is no longer valid.
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:178
iterator end()
Definition DenseMap.h:81
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:359
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isPointer() const
constexpr unsigned getAddressSpace() const
Metadata node.
Definition Metadata.h:1078
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1442
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
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.
const MachineBasicBlock & front() const
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.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
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 & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_ABI 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
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.
const MDNode * getMetadata() const
static MachineOperand CreateCImm(const ConstantInt *CI)
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
void setCImm(const ConstantInt *CI)
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)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
defusechain_instr_iterator< true, false, false, true > use_instr_iterator
use_instr_iterator/use_instr_begin/use_instr_end - Walk all uses of the specified register,...
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isValid() const
Definition Register.h:112
SPIRVType * getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, const MachineFunction &MF)
SPIRVType * changePointerStorageClass(SPIRVType *PtrType, SPIRV::StorageClass::StorageClass SC, MachineInstr &I)
const Type * getTypeForSPIRVType(const SPIRVType *Ty) const
bool isBitcastCompatible(const SPIRVType *Type1, const SPIRVType *Type2) const
unsigned getScalarOrVectorComponentCount(Register VReg) const
SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineInstr &I, SPIRV::AccessQualifier::AccessQualifier AQ, bool EmitIR)
SPIRVType * getOrCreateSPIRVPointerType(const Type *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC)
void invalidateMachineInstr(MachineInstr *MI)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
void addGlobalObject(const Value *V, const MachineFunction *MF, Register R)
SPIRVType * getOrCreateOpTypeFunctionWithArgs(const Type *Ty, SPIRVType *RetType, const SmallVectorImpl< SPIRVType * > &ArgTypes, MachineIRBuilder &MIRBuilder)
const TargetRegisterClass * getRegClass(SPIRVType *SpvType) const
SPIRVType * getOrCreateSPIRVVectorType(SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder, bool EmitIR)
SPIRVType * getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
Type * getDeducedGlobalValueType(const GlobalValue *Global)
LLT getRegType(SPIRVType *SpvType) const
void addValueAttrs(MachineInstr *Key, std::pair< Type *, std::string > Val)
void buildMemAliasingOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, uint32_t Dec, const MDNode *GVarMD)
SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const
unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const
bool add(SPIRV::IRHandle Handle, const MachineInstr *MI)
Register find(SPIRV::IRHandle Handle, const MachineFunction *MF)
const SPIRVInstrInfo * getInstrInfo() const override
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:296
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:280
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition Type.h:128
static LLVM_ABI 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:256
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:546
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract(Y &&MD)
Extract a Value from Metadata, if any.
Definition Metadata.h:695
This is an optimization pass for GlobalISel generic memory operations.
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
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:344
StringMapEntry< Value * > ValueName
Definition Value.h:56
bool isTypeFoldingSupported(unsigned Opcode)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
void updateRegType(Register Reg, Type *Ty, SPIRVType *SpirvTy, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, MachineRegisterInfo &MRI)
Helper external function for assigning SPIRVType to a register, ensuring the register class and type ...
FunctionPass * createSPIRVPreLegalizerPass()
iterator_range< po_iterator< T > > post_order(const T &G)
constexpr unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
Definition SPIRVUtils.h:244
void processInstr(MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR, SPIRVType *KnownResType)
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
Type * toTypedPointer(Type *Ty)
Definition SPIRVUtils.h:456
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
const MachineInstr SPIRVType
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
@ Global
Append to llvm.global_dtors.
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder, const MDNode *GVarMD, const SPIRVSubtarget &ST)
FunctionAddr VTableAddr Next
Definition InstrProf.h:141
DWARFExpression::Operation Op
MachineInstr * getDefInstrMaybeConstant(Register &ConstReg, const MachineRegisterInfo *MRI)
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
Type * getMDOperandAsType(const MDNode *N, unsigned I)
bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID)
void addStringImm(const StringRef &Str, MCInst &Inst)
MachineInstr * getVRegDef(MachineRegisterInfo &MRI, Register Reg)