LLVM 17.0.0git
SPIRVModuleAnalysis.cpp
Go to the documentation of this file.
1//===- SPIRVModuleAnalysis.cpp - analysis of global instrs & regs - 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 analysis collects instructions that should be output at the module level
10// and performs the global register numbering.
11//
12// The results of this analysis are used in AsmPrinter to rename registers
13// globally and to output required instructions at the module level.
14//
15//===----------------------------------------------------------------------===//
16
17#include "SPIRVModuleAnalysis.h"
18#include "SPIRV.h"
19#include "SPIRVSubtarget.h"
20#include "SPIRVTargetMachine.h"
21#include "SPIRVUtils.h"
23#include "llvm/ADT/STLExtras.h"
26
27using namespace llvm;
28
29#define DEBUG_TYPE "spirv-module-analysis"
30
31static cl::opt<bool>
32 SPVDumpDeps("spv-dump-deps",
33 cl::desc("Dump MIR with SPIR-V dependencies info"),
34 cl::Optional, cl::init(false));
35
37
38namespace llvm {
40} // namespace llvm
41
42INITIALIZE_PASS(SPIRVModuleAnalysis, DEBUG_TYPE, "SPIRV module analysis", true,
43 true)
44
45// Retrieve an unsigned from an MDNode with a list of them as operands.
46static unsigned getMetadataUInt(MDNode *MdNode, unsigned OpIndex,
47 unsigned DefaultVal = 0) {
48 if (MdNode && OpIndex < MdNode->getNumOperands()) {
49 const auto &Op = MdNode->getOperand(OpIndex);
50 return mdconst::extract<ConstantInt>(Op)->getZExtValue();
51 }
52 return DefaultVal;
53}
54
56getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category,
57 unsigned i, const SPIRVSubtarget &ST,
59 unsigned ReqMinVer = getSymbolicOperandMinVersion(Category, i);
60 unsigned ReqMaxVer = getSymbolicOperandMaxVersion(Category, i);
61 unsigned TargetVer = ST.getSPIRVVersion();
62 bool MinVerOK = !ReqMinVer || !TargetVer || TargetVer >= ReqMinVer;
63 bool MaxVerOK = !ReqMaxVer || !TargetVer || TargetVer <= ReqMaxVer;
65 ExtensionList ReqExts = getSymbolicOperandExtensions(Category, i);
66 if (ReqCaps.empty()) {
67 if (ReqExts.empty()) {
68 if (MinVerOK && MaxVerOK)
69 return {true, {}, {}, ReqMinVer, ReqMaxVer};
70 return {false, {}, {}, 0, 0};
71 }
72 } else if (MinVerOK && MaxVerOK) {
73 for (auto Cap : ReqCaps) { // Only need 1 of the capabilities to work.
74 if (Reqs.isCapabilityAvailable(Cap))
75 return {true, {Cap}, {}, ReqMinVer, ReqMaxVer};
76 }
77 }
78 // If there are no capabilities, or we can't satisfy the version or
79 // capability requirements, use the list of extensions (if the subtarget
80 // can handle them all).
81 if (llvm::all_of(ReqExts, [&ST](const SPIRV::Extension::Extension &Ext) {
82 return ST.canUseExtension(Ext);
83 })) {
84 return {true, {}, ReqExts, 0, 0}; // TODO: add versions to extensions.
85 }
86 return {false, {}, {}, 0, 0};
87}
88
89void SPIRVModuleAnalysis::setBaseInfo(const Module &M) {
90 MAI.MaxID = 0;
91 for (int i = 0; i < SPIRV::NUM_MODULE_SECTIONS; i++)
92 MAI.MS[i].clear();
93 MAI.RegisterAliasTable.clear();
94 MAI.InstrsToDelete.clear();
95 MAI.FuncMap.clear();
97 MAI.ExtInstSetMap.clear();
98 MAI.Reqs.clear();
100
101 // TODO: determine memory model and source language from the configuratoin.
102 if (auto MemModel = M.getNamedMetadata("spirv.MemoryModel")) {
103 auto MemMD = MemModel->getOperand(0);
104 MAI.Addr = static_cast<SPIRV::AddressingModel::AddressingModel>(
105 getMetadataUInt(MemMD, 0));
106 MAI.Mem =
107 static_cast<SPIRV::MemoryModel::MemoryModel>(getMetadataUInt(MemMD, 1));
108 } else {
109 MAI.Mem = SPIRV::MemoryModel::OpenCL;
110 unsigned PtrSize = ST->getPointerSize();
111 MAI.Addr = PtrSize == 32 ? SPIRV::AddressingModel::Physical32
112 : PtrSize == 64 ? SPIRV::AddressingModel::Physical64
113 : SPIRV::AddressingModel::Logical;
114 }
115 // Get the OpenCL version number from metadata.
116 // TODO: support other source languages.
117 if (auto VerNode = M.getNamedMetadata("opencl.ocl.version")) {
118 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_C;
119 // Construct version literal in accordance with SPIRV-LLVM-Translator.
120 // TODO: support multiple OCL version metadata.
121 assert(VerNode->getNumOperands() > 0 && "Invalid SPIR");
122 auto VersionMD = VerNode->getOperand(0);
123 unsigned MajorNum = getMetadataUInt(VersionMD, 0, 2);
124 unsigned MinorNum = getMetadataUInt(VersionMD, 1);
125 unsigned RevNum = getMetadataUInt(VersionMD, 2);
126 MAI.SrcLangVersion = (MajorNum * 100 + MinorNum) * 1000 + RevNum;
127 } else {
128 MAI.SrcLang = SPIRV::SourceLanguage::Unknown;
130 }
131
132 if (auto ExtNode = M.getNamedMetadata("opencl.used.extensions")) {
133 for (unsigned I = 0, E = ExtNode->getNumOperands(); I != E; ++I) {
134 MDNode *MD = ExtNode->getOperand(I);
135 if (!MD || MD->getNumOperands() == 0)
136 continue;
137 for (unsigned J = 0, N = MD->getNumOperands(); J != N; ++J)
138 MAI.SrcExt.insert(cast<MDString>(MD->getOperand(J))->getString());
139 }
140 }
141
142 // Update required capabilities for this memory model, addressing model and
143 // source language.
144 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::MemoryModelOperand,
145 MAI.Mem, *ST);
146 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::SourceLanguageOperand,
147 MAI.SrcLang, *ST);
148 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::AddressingModelOperand,
149 MAI.Addr, *ST);
150
151 // TODO: check if it's required by default.
152 MAI.ExtInstSetMap[static_cast<unsigned>(SPIRV::InstructionSet::OpenCL_std)] =
154}
155
156// Collect MI which defines the register in the given machine function.
157static void collectDefInstr(Register Reg, const MachineFunction *MF,
160 bool DoInsert = true) {
161 assert(MAI->hasRegisterAlias(MF, Reg) && "Cannot find register alias");
163 assert(MI && "There should be an instruction that defines the register");
164 MAI->setSkipEmission(MI);
165 if (DoInsert)
166 MAI->MS[MSType].push_back(MI);
167}
168
169void SPIRVModuleAnalysis::collectGlobalEntities(
170 const std::vector<SPIRV::DTSortableEntry *> &DepsGraph,
172 std::function<bool(const SPIRV::DTSortableEntry *)> Pred,
173 bool UsePreOrder = false) {
175 for (const auto *E : DepsGraph) {
176 std::function<void(const SPIRV::DTSortableEntry *)> RecHoistUtil;
177 // NOTE: here we prefer recursive approach over iterative because
178 // we don't expect depchains long enough to cause SO.
179 RecHoistUtil = [MSType, UsePreOrder, &Visited, &Pred,
180 &RecHoistUtil](const SPIRV::DTSortableEntry *E) {
181 if (Visited.count(E) || !Pred(E))
182 return;
183 Visited.insert(E);
184
185 // Traversing deps graph in post-order allows us to get rid of
186 // register aliases preprocessing.
187 // But pre-order is required for correct processing of function
188 // declaration and arguments processing.
189 if (!UsePreOrder)
190 for (auto *S : E->getDeps())
191 RecHoistUtil(S);
192
194 bool IsFirst = true;
195 for (auto &U : *E) {
196 const MachineFunction *MF = U.first;
197 Register Reg = U.second;
198 MAI.setRegisterAlias(MF, Reg, GlobalReg);
199 if (!MF->getRegInfo().getUniqueVRegDef(Reg))
200 continue;
201 collectDefInstr(Reg, MF, &MAI, MSType, IsFirst);
202 IsFirst = false;
203 if (E->getIsGV())
205 }
206
207 if (UsePreOrder)
208 for (auto *S : E->getDeps())
209 RecHoistUtil(S);
210 };
211 RecHoistUtil(E);
212 }
213}
214
215// The function initializes global register alias table for types, consts,
216// global vars and func decls and collects these instruction for output
217// at module level. Also it collects explicit OpExtension/OpCapability
218// instructions.
219void SPIRVModuleAnalysis::processDefInstrs(const Module &M) {
220 std::vector<SPIRV::DTSortableEntry *> DepsGraph;
221
222 GR->buildDepsGraph(DepsGraph, SPVDumpDeps ? MMI : nullptr);
223
224 collectGlobalEntities(
225 DepsGraph, SPIRV::MB_TypeConstVars,
226 [](const SPIRV::DTSortableEntry *E) { return !E->getIsFunc(); });
227
228 for (auto F = M.begin(), E = M.end(); F != E; ++F) {
229 MachineFunction *MF = MMI->getMachineFunction(*F);
230 if (!MF)
231 continue;
232 // Iterate through and collect OpExtension/OpCapability instructions.
233 for (MachineBasicBlock &MBB : *MF) {
234 for (MachineInstr &MI : MBB) {
235 if (MI.getOpcode() == SPIRV::OpExtension) {
236 // Here, OpExtension just has a single enum operand, not a string.
237 auto Ext = SPIRV::Extension::Extension(MI.getOperand(0).getImm());
238 MAI.Reqs.addExtension(Ext);
240 } else if (MI.getOpcode() == SPIRV::OpCapability) {
241 auto Cap = SPIRV::Capability::Capability(MI.getOperand(0).getImm());
244 }
245 }
246 }
247 }
248
249 collectGlobalEntities(
250 DepsGraph, SPIRV::MB_ExtFuncDecls,
251 [](const SPIRV::DTSortableEntry *E) { return E->getIsFunc(); }, true);
252}
253
254// True if there is an instruction in the MS list with all the same operands as
255// the given instruction has (after the given starting index).
256// TODO: maybe it needs to check Opcodes too.
257static bool findSameInstrInMS(const MachineInstr &A,
260 unsigned StartOpIndex = 0) {
261 for (const auto *B : MAI.MS[MSType]) {
262 const unsigned NumAOps = A.getNumOperands();
263 if (NumAOps != B->getNumOperands() || A.getNumDefs() != B->getNumDefs())
264 continue;
265 bool AllOpsMatch = true;
266 for (unsigned i = StartOpIndex; i < NumAOps && AllOpsMatch; ++i) {
267 if (A.getOperand(i).isReg() && B->getOperand(i).isReg()) {
268 Register RegA = A.getOperand(i).getReg();
269 Register RegB = B->getOperand(i).getReg();
270 AllOpsMatch = MAI.getRegisterAlias(A.getMF(), RegA) ==
271 MAI.getRegisterAlias(B->getMF(), RegB);
272 } else {
273 AllOpsMatch = A.getOperand(i).isIdenticalTo(B->getOperand(i));
274 }
275 }
276 if (AllOpsMatch)
277 return true;
278 }
279 return false;
280}
281
282// Look for IDs declared with Import linkage, and map the corresponding function
283// to the register defining that variable (which will usually be the result of
284// an OpFunction). This lets us call externally imported functions using
285// the correct ID registers.
286void SPIRVModuleAnalysis::collectFuncNames(MachineInstr &MI,
287 const Function *F) {
288 if (MI.getOpcode() == SPIRV::OpDecorate) {
289 // If it's got Import linkage.
290 auto Dec = MI.getOperand(1).getImm();
291 if (Dec == static_cast<unsigned>(SPIRV::Decoration::LinkageAttributes)) {
292 auto Lnk = MI.getOperand(MI.getNumOperands() - 1).getImm();
293 if (Lnk == static_cast<unsigned>(SPIRV::LinkageType::Import)) {
294 // Map imported function name to function ID register.
295 const Function *ImportedFunc =
296 F->getParent()->getFunction(getStringImm(MI, 2));
297 Register Target = MI.getOperand(0).getReg();
298 MAI.FuncMap[ImportedFunc] = MAI.getRegisterAlias(MI.getMF(), Target);
299 }
300 }
301 } else if (MI.getOpcode() == SPIRV::OpFunction) {
302 // Record all internal OpFunction declarations.
303 Register Reg = MI.defs().begin()->getReg();
304 Register GlobalReg = MAI.getRegisterAlias(MI.getMF(), Reg);
305 assert(GlobalReg.isValid());
306 MAI.FuncMap[F] = GlobalReg;
307 }
308}
309
310// Collect the given instruction in the specified MS. We assume global register
311// numbering has already occurred by this point. We can directly compare reg
312// arguments when detecting duplicates.
313static void collectOtherInstr(MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI,
315 bool Append = true) {
316 MAI.setSkipEmission(&MI);
317 if (findSameInstrInMS(MI, MSType, MAI))
318 return; // Found a duplicate, so don't add it.
319 // No duplicates, so add it.
320 if (Append)
321 MAI.MS[MSType].push_back(&MI);
322 else
323 MAI.MS[MSType].insert(MAI.MS[MSType].begin(), &MI);
324}
325
326// Some global instructions make reference to function-local ID regs, so cannot
327// be correctly collected until these registers are globally numbered.
328void SPIRVModuleAnalysis::processOtherInstrs(const Module &M) {
329 for (auto F = M.begin(), E = M.end(); F != E; ++F) {
330 if ((*F).isDeclaration())
331 continue;
332 MachineFunction *MF = MMI->getMachineFunction(*F);
333 assert(MF);
334 for (MachineBasicBlock &MBB : *MF)
335 for (MachineInstr &MI : MBB) {
336 if (MAI.getSkipEmission(&MI))
337 continue;
338 const unsigned OpCode = MI.getOpcode();
339 if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
340 collectOtherInstr(MI, MAI, SPIRV::MB_DebugNames);
341 } else if (OpCode == SPIRV::OpEntryPoint) {
342 collectOtherInstr(MI, MAI, SPIRV::MB_EntryPoints);
343 } else if (TII->isDecorationInstr(MI)) {
344 collectOtherInstr(MI, MAI, SPIRV::MB_Annotations);
345 collectFuncNames(MI, &*F);
346 } else if (TII->isConstantInstr(MI)) {
347 // Now OpSpecConstant*s are not in DT,
348 // but they need to be collected anyway.
349 collectOtherInstr(MI, MAI, SPIRV::MB_TypeConstVars);
350 } else if (OpCode == SPIRV::OpFunction) {
351 collectFuncNames(MI, &*F);
352 } else if (OpCode == SPIRV::OpTypeForwardPointer) {
353 collectOtherInstr(MI, MAI, SPIRV::MB_TypeConstVars, false);
354 }
355 }
356 }
357}
358
359// Number registers in all functions globally from 0 onwards and store
360// the result in global register alias table. Some registers are already
361// numbered in collectGlobalEntities.
362void SPIRVModuleAnalysis::numberRegistersGlobally(const Module &M) {
363 for (auto F = M.begin(), E = M.end(); F != E; ++F) {
364 if ((*F).isDeclaration())
365 continue;
366 MachineFunction *MF = MMI->getMachineFunction(*F);
367 assert(MF);
368 for (MachineBasicBlock &MBB : *MF) {
369 for (MachineInstr &MI : MBB) {
370 for (MachineOperand &Op : MI.operands()) {
371 if (!Op.isReg())
372 continue;
373 Register Reg = Op.getReg();
374 if (MAI.hasRegisterAlias(MF, Reg))
375 continue;
377 MAI.setRegisterAlias(MF, Reg, NewReg);
378 }
379 if (MI.getOpcode() != SPIRV::OpExtInst)
380 continue;
381 auto Set = MI.getOperand(2).getImm();
382 if (MAI.ExtInstSetMap.find(Set) == MAI.ExtInstSetMap.end())
384 }
385 }
386 }
387}
388
389// Find OpIEqual and OpBranchConditional instructions originating from
390// OpSwitches, mark them skipped for emission. Also mark MBB skipped if it
391// contains only these instructions.
392static void processSwitches(const Module &M, SPIRV::ModuleAnalysisInfo &MAI,
393 MachineModuleInfo *MMI) {
394 DenseSet<Register> SwitchRegs;
395 for (auto F = M.begin(), E = M.end(); F != E; ++F) {
397 if (!MF)
398 continue;
399 for (MachineBasicBlock &MBB : *MF)
400 for (MachineInstr &MI : MBB) {
401 if (MAI.getSkipEmission(&MI))
402 continue;
403 if (MI.getOpcode() == SPIRV::OpSwitch) {
404 assert(MI.getOperand(0).isReg());
405 SwitchRegs.insert(MI.getOperand(0).getReg());
406 }
407 if (MI.getOpcode() == SPIRV::OpISubS &&
408 SwitchRegs.contains(MI.getOperand(2).getReg())) {
409 SwitchRegs.insert(MI.getOperand(0).getReg());
410 MAI.setSkipEmission(&MI);
411 }
412 if ((MI.getOpcode() != SPIRV::OpIEqual &&
413 MI.getOpcode() != SPIRV::OpULessThanEqual) ||
414 !MI.getOperand(2).isReg() ||
415 !SwitchRegs.contains(MI.getOperand(2).getReg()))
416 continue;
417 Register CmpReg = MI.getOperand(0).getReg();
418 MachineInstr *CBr = MI.getNextNode();
419 assert(CBr && CBr->getOpcode() == SPIRV::OpBranchConditional &&
420 CBr->getOperand(0).isReg() &&
421 CBr->getOperand(0).getReg() == CmpReg);
422 MAI.setSkipEmission(&MI);
423 MAI.setSkipEmission(CBr);
424 if (&MBB.front() == &MI && &MBB.back() == CBr)
425 MAI.MBBsToSkip.insert(&MBB);
426 }
427 }
428}
429
430// RequirementHandler implementations.
432 SPIRV::OperandCategory::OperandCategory Category, uint32_t i,
433 const SPIRVSubtarget &ST) {
434 addRequirements(getSymbolicOperandRequirements(Category, i, ST, *this));
435}
436
437void SPIRV::RequirementHandler::pruneCapabilities(
438 const CapabilityList &ToPrune) {
439 for (const auto &Cap : ToPrune) {
440 AllCaps.insert(Cap);
441 auto FoundIndex = std::find(MinimalCaps.begin(), MinimalCaps.end(), Cap);
442 if (FoundIndex != MinimalCaps.end())
443 MinimalCaps.erase(FoundIndex);
444 CapabilityList ImplicitDecls =
445 getSymbolicOperandCapabilities(OperandCategory::CapabilityOperand, Cap);
446 pruneCapabilities(ImplicitDecls);
447 }
448}
449
451 for (const auto &Cap : ToAdd) {
452 bool IsNewlyInserted = AllCaps.insert(Cap).second;
453 if (!IsNewlyInserted) // Don't re-add if it's already been declared.
454 continue;
455 CapabilityList ImplicitDecls =
456 getSymbolicOperandCapabilities(OperandCategory::CapabilityOperand, Cap);
457 pruneCapabilities(ImplicitDecls);
458 MinimalCaps.push_back(Cap);
459 }
460}
461
463 const SPIRV::Requirements &Req) {
464 if (!Req.IsSatisfiable)
465 report_fatal_error("Adding SPIR-V requirements this target can't satisfy.");
466
467 if (Req.Cap.has_value())
468 addCapabilities({Req.Cap.value()});
469
470 addExtensions(Req.Exts);
471
472 if (Req.MinVer) {
473 if (MaxVersion && Req.MinVer > MaxVersion) {
474 LLVM_DEBUG(dbgs() << "Conflicting version requirements: >= " << Req.MinVer
475 << " and <= " << MaxVersion << "\n");
476 report_fatal_error("Adding SPIR-V requirements that can't be satisfied.");
477 }
478
479 if (MinVersion == 0 || Req.MinVer > MinVersion)
480 MinVersion = Req.MinVer;
481 }
482
483 if (Req.MaxVer) {
484 if (MinVersion && Req.MaxVer < MinVersion) {
485 LLVM_DEBUG(dbgs() << "Conflicting version requirements: <= " << Req.MaxVer
486 << " and >= " << MinVersion << "\n");
487 report_fatal_error("Adding SPIR-V requirements that can't be satisfied.");
488 }
489
490 if (MaxVersion == 0 || Req.MaxVer < MaxVersion)
491 MaxVersion = Req.MaxVer;
492 }
493}
494
496 const SPIRVSubtarget &ST) const {
497 // Report as many errors as possible before aborting the compilation.
498 bool IsSatisfiable = true;
499 auto TargetVer = ST.getSPIRVVersion();
500
501 if (MaxVersion && TargetVer && MaxVersion < TargetVer) {
503 dbgs() << "Target SPIR-V version too high for required features\n"
504 << "Required max version: " << MaxVersion << " target version "
505 << TargetVer << "\n");
506 IsSatisfiable = false;
507 }
508
509 if (MinVersion && TargetVer && MinVersion > TargetVer) {
510 LLVM_DEBUG(dbgs() << "Target SPIR-V version too low for required features\n"
511 << "Required min version: " << MinVersion
512 << " target version " << TargetVer << "\n");
513 IsSatisfiable = false;
514 }
515
516 if (MinVersion && MaxVersion && MinVersion > MaxVersion) {
518 dbgs()
519 << "Version is too low for some features and too high for others.\n"
520 << "Required SPIR-V min version: " << MinVersion
521 << " required SPIR-V max version " << MaxVersion << "\n");
522 IsSatisfiable = false;
523 }
524
525 for (auto Cap : MinimalCaps) {
526 if (AvailableCaps.contains(Cap))
527 continue;
528 LLVM_DEBUG(dbgs() << "Capability not supported: "
530 OperandCategory::CapabilityOperand, Cap)
531 << "\n");
532 IsSatisfiable = false;
533 }
534
535 for (auto Ext : AllExtensions) {
536 if (ST.canUseExtension(Ext))
537 continue;
538 LLVM_DEBUG(dbgs() << "Extension not suported: "
540 OperandCategory::ExtensionOperand, Ext)
541 << "\n");
542 IsSatisfiable = false;
543 }
544
545 if (!IsSatisfiable)
546 report_fatal_error("Unable to meet SPIR-V requirements for this target.");
547}
548
549// Add the given capabilities and all their implicitly defined capabilities too.
551 for (const auto Cap : ToAdd)
552 if (AvailableCaps.insert(Cap).second)
553 addAvailableCaps(getSymbolicOperandCapabilities(
554 SPIRV::OperandCategory::CapabilityOperand, Cap));
555}
556
557namespace llvm {
558namespace SPIRV {
559void RequirementHandler::initAvailableCapabilities(const SPIRVSubtarget &ST) {
560 // TODO: Implemented for other targets other then OpenCL.
561 if (!ST.isOpenCLEnv())
562 return;
563 // Add the min requirements for different OpenCL and SPIR-V versions.
564 addAvailableCaps({Capability::Addresses, Capability::Float16Buffer,
565 Capability::Int16, Capability::Int8, Capability::Kernel,
566 Capability::Linkage, Capability::Vector16,
567 Capability::Groups, Capability::GenericPointer,
568 Capability::Shader});
569 if (ST.hasOpenCLFullProfile())
570 addAvailableCaps({Capability::Int64, Capability::Int64Atomics});
571 if (ST.hasOpenCLImageSupport()) {
572 addAvailableCaps({Capability::ImageBasic, Capability::LiteralSampler,
573 Capability::Image1D, Capability::SampledBuffer,
574 Capability::ImageBuffer});
575 if (ST.isAtLeastOpenCLVer(20))
576 addAvailableCaps({Capability::ImageReadWrite});
577 }
578 if (ST.isAtLeastSPIRVVer(11) && ST.isAtLeastOpenCLVer(22))
579 addAvailableCaps({Capability::SubgroupDispatch, Capability::PipeStorage});
580 if (ST.isAtLeastSPIRVVer(13))
581 addAvailableCaps({Capability::GroupNonUniform,
582 Capability::GroupNonUniformVote,
583 Capability::GroupNonUniformArithmetic,
584 Capability::GroupNonUniformBallot,
585 Capability::GroupNonUniformClustered,
586 Capability::GroupNonUniformShuffle,
587 Capability::GroupNonUniformShuffleRelative});
588 if (ST.isAtLeastSPIRVVer(14))
589 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
590 Capability::SignedZeroInfNanPreserve,
591 Capability::RoundingModeRTE,
592 Capability::RoundingModeRTZ});
593 // TODO: verify if this needs some checks.
594 addAvailableCaps({Capability::Float16, Capability::Float64});
595
596 // TODO: add OpenCL extensions.
597}
598} // namespace SPIRV
599} // namespace llvm
600
601// Add the required capabilities from a decoration instruction (including
602// BuiltIns).
603static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex,
605 const SPIRVSubtarget &ST) {
606 int64_t DecOp = MI.getOperand(DecIndex).getImm();
607 auto Dec = static_cast<SPIRV::Decoration::Decoration>(DecOp);
608 Reqs.addRequirements(getSymbolicOperandRequirements(
609 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
610
611 if (Dec == SPIRV::Decoration::BuiltIn) {
612 int64_t BuiltInOp = MI.getOperand(DecIndex + 1).getImm();
613 auto BuiltIn = static_cast<SPIRV::BuiltIn::BuiltIn>(BuiltInOp);
614 Reqs.addRequirements(getSymbolicOperandRequirements(
615 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
616 }
617}
618
619// Add requirements for image handling.
620static void addOpTypeImageReqs(const MachineInstr &MI,
622 const SPIRVSubtarget &ST) {
623 assert(MI.getNumOperands() >= 8 && "Insufficient operands for OpTypeImage");
624 // The operand indices used here are based on the OpTypeImage layout, which
625 // the MachineInstr follows as well.
626 int64_t ImgFormatOp = MI.getOperand(7).getImm();
627 auto ImgFormat = static_cast<SPIRV::ImageFormat::ImageFormat>(ImgFormatOp);
628 Reqs.getAndAddRequirements(SPIRV::OperandCategory::ImageFormatOperand,
629 ImgFormat, ST);
630
631 bool IsArrayed = MI.getOperand(4).getImm() == 1;
632 bool IsMultisampled = MI.getOperand(5).getImm() == 1;
633 bool NoSampler = MI.getOperand(6).getImm() == 2;
634 // Add dimension requirements.
635 assert(MI.getOperand(2).isImm());
636 switch (MI.getOperand(2).getImm()) {
637 case SPIRV::Dim::DIM_1D:
638 Reqs.addRequirements(NoSampler ? SPIRV::Capability::Image1D
639 : SPIRV::Capability::Sampled1D);
640 break;
641 case SPIRV::Dim::DIM_2D:
642 if (IsMultisampled && NoSampler)
643 Reqs.addRequirements(SPIRV::Capability::ImageMSArray);
644 break;
645 case SPIRV::Dim::DIM_Cube:
646 Reqs.addRequirements(SPIRV::Capability::Shader);
647 if (IsArrayed)
648 Reqs.addRequirements(NoSampler ? SPIRV::Capability::ImageCubeArray
649 : SPIRV::Capability::SampledCubeArray);
650 break;
651 case SPIRV::Dim::DIM_Rect:
652 Reqs.addRequirements(NoSampler ? SPIRV::Capability::ImageRect
653 : SPIRV::Capability::SampledRect);
654 break;
655 case SPIRV::Dim::DIM_Buffer:
656 Reqs.addRequirements(NoSampler ? SPIRV::Capability::ImageBuffer
657 : SPIRV::Capability::SampledBuffer);
658 break;
659 case SPIRV::Dim::DIM_SubpassData:
660 Reqs.addRequirements(SPIRV::Capability::InputAttachment);
661 break;
662 }
663
664 // Has optional access qualifier.
665 // TODO: check if it's OpenCL's kernel.
666 if (MI.getNumOperands() > 8 &&
667 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
668 Reqs.addRequirements(SPIRV::Capability::ImageReadWrite);
669 else
670 Reqs.addRequirements(SPIRV::Capability::ImageBasic);
671}
672
673void addInstrRequirements(const MachineInstr &MI,
675 const SPIRVSubtarget &ST) {
676 switch (MI.getOpcode()) {
677 case SPIRV::OpMemoryModel: {
678 int64_t Addr = MI.getOperand(0).getImm();
679 Reqs.getAndAddRequirements(SPIRV::OperandCategory::AddressingModelOperand,
680 Addr, ST);
681 int64_t Mem = MI.getOperand(1).getImm();
682 Reqs.getAndAddRequirements(SPIRV::OperandCategory::MemoryModelOperand, Mem,
683 ST);
684 break;
685 }
686 case SPIRV::OpEntryPoint: {
687 int64_t Exe = MI.getOperand(0).getImm();
688 Reqs.getAndAddRequirements(SPIRV::OperandCategory::ExecutionModelOperand,
689 Exe, ST);
690 break;
691 }
692 case SPIRV::OpExecutionMode:
693 case SPIRV::OpExecutionModeId: {
694 int64_t Exe = MI.getOperand(1).getImm();
695 Reqs.getAndAddRequirements(SPIRV::OperandCategory::ExecutionModeOperand,
696 Exe, ST);
697 break;
698 }
699 case SPIRV::OpTypeMatrix:
700 Reqs.addCapability(SPIRV::Capability::Matrix);
701 break;
702 case SPIRV::OpTypeInt: {
703 unsigned BitWidth = MI.getOperand(1).getImm();
704 if (BitWidth == 64)
705 Reqs.addCapability(SPIRV::Capability::Int64);
706 else if (BitWidth == 16)
707 Reqs.addCapability(SPIRV::Capability::Int16);
708 else if (BitWidth == 8)
709 Reqs.addCapability(SPIRV::Capability::Int8);
710 break;
711 }
712 case SPIRV::OpTypeFloat: {
713 unsigned BitWidth = MI.getOperand(1).getImm();
714 if (BitWidth == 64)
715 Reqs.addCapability(SPIRV::Capability::Float64);
716 else if (BitWidth == 16)
717 Reqs.addCapability(SPIRV::Capability::Float16);
718 break;
719 }
720 case SPIRV::OpTypeVector: {
721 unsigned NumComponents = MI.getOperand(2).getImm();
722 if (NumComponents == 8 || NumComponents == 16)
723 Reqs.addCapability(SPIRV::Capability::Vector16);
724 break;
725 }
726 case SPIRV::OpTypePointer: {
727 auto SC = MI.getOperand(1).getImm();
728 Reqs.getAndAddRequirements(SPIRV::OperandCategory::StorageClassOperand, SC,
729 ST);
730 // If it's a type of pointer to float16, add Float16Buffer capability.
731 assert(MI.getOperand(2).isReg());
732 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
733 SPIRVType *TypeDef = MRI.getVRegDef(MI.getOperand(2).getReg());
734 if (TypeDef->getOpcode() == SPIRV::OpTypeFloat &&
735 TypeDef->getOperand(1).getImm() == 16)
736 Reqs.addCapability(SPIRV::Capability::Float16Buffer);
737 break;
738 }
739 case SPIRV::OpBitReverse:
740 case SPIRV::OpTypeRuntimeArray:
741 Reqs.addCapability(SPIRV::Capability::Shader);
742 break;
743 case SPIRV::OpTypeOpaque:
744 case SPIRV::OpTypeEvent:
745 Reqs.addCapability(SPIRV::Capability::Kernel);
746 break;
747 case SPIRV::OpTypePipe:
748 case SPIRV::OpTypeReserveId:
749 Reqs.addCapability(SPIRV::Capability::Pipes);
750 break;
751 case SPIRV::OpTypeDeviceEvent:
752 case SPIRV::OpTypeQueue:
753 case SPIRV::OpBuildNDRange:
754 Reqs.addCapability(SPIRV::Capability::DeviceEnqueue);
755 break;
756 case SPIRV::OpDecorate:
757 case SPIRV::OpDecorateId:
758 case SPIRV::OpDecorateString:
759 addOpDecorateReqs(MI, 1, Reqs, ST);
760 break;
761 case SPIRV::OpMemberDecorate:
762 case SPIRV::OpMemberDecorateString:
763 addOpDecorateReqs(MI, 2, Reqs, ST);
764 break;
765 case SPIRV::OpInBoundsPtrAccessChain:
766 Reqs.addCapability(SPIRV::Capability::Addresses);
767 break;
768 case SPIRV::OpConstantSampler:
769 Reqs.addCapability(SPIRV::Capability::LiteralSampler);
770 break;
771 case SPIRV::OpTypeImage:
772 addOpTypeImageReqs(MI, Reqs, ST);
773 break;
774 case SPIRV::OpTypeSampler:
775 Reqs.addCapability(SPIRV::Capability::ImageBasic);
776 break;
777 case SPIRV::OpTypeForwardPointer:
778 // TODO: check if it's OpenCL's kernel.
779 Reqs.addCapability(SPIRV::Capability::Addresses);
780 break;
781 case SPIRV::OpAtomicFlagTestAndSet:
782 case SPIRV::OpAtomicLoad:
783 case SPIRV::OpAtomicStore:
784 case SPIRV::OpAtomicExchange:
785 case SPIRV::OpAtomicCompareExchange:
786 case SPIRV::OpAtomicIIncrement:
787 case SPIRV::OpAtomicIDecrement:
788 case SPIRV::OpAtomicIAdd:
789 case SPIRV::OpAtomicISub:
790 case SPIRV::OpAtomicUMin:
791 case SPIRV::OpAtomicUMax:
792 case SPIRV::OpAtomicSMin:
793 case SPIRV::OpAtomicSMax:
794 case SPIRV::OpAtomicAnd:
795 case SPIRV::OpAtomicOr:
796 case SPIRV::OpAtomicXor: {
797 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
798 const MachineInstr *InstrPtr = &MI;
799 if (MI.getOpcode() == SPIRV::OpAtomicStore) {
800 assert(MI.getOperand(3).isReg());
801 InstrPtr = MRI.getVRegDef(MI.getOperand(3).getReg());
802 assert(InstrPtr && "Unexpected type instruction for OpAtomicStore");
803 }
804 assert(InstrPtr->getOperand(1).isReg() && "Unexpected operand in atomic");
805 Register TypeReg = InstrPtr->getOperand(1).getReg();
806 SPIRVType *TypeDef = MRI.getVRegDef(TypeReg);
807 if (TypeDef->getOpcode() == SPIRV::OpTypeInt) {
808 unsigned BitWidth = TypeDef->getOperand(1).getImm();
809 if (BitWidth == 64)
810 Reqs.addCapability(SPIRV::Capability::Int64Atomics);
811 }
812 break;
813 }
814 case SPIRV::OpGroupNonUniformIAdd:
815 case SPIRV::OpGroupNonUniformFAdd:
816 case SPIRV::OpGroupNonUniformIMul:
817 case SPIRV::OpGroupNonUniformFMul:
818 case SPIRV::OpGroupNonUniformSMin:
819 case SPIRV::OpGroupNonUniformUMin:
820 case SPIRV::OpGroupNonUniformFMin:
821 case SPIRV::OpGroupNonUniformSMax:
822 case SPIRV::OpGroupNonUniformUMax:
823 case SPIRV::OpGroupNonUniformFMax:
824 case SPIRV::OpGroupNonUniformBitwiseAnd:
825 case SPIRV::OpGroupNonUniformBitwiseOr:
826 case SPIRV::OpGroupNonUniformBitwiseXor:
827 case SPIRV::OpGroupNonUniformLogicalAnd:
828 case SPIRV::OpGroupNonUniformLogicalOr:
829 case SPIRV::OpGroupNonUniformLogicalXor: {
830 assert(MI.getOperand(3).isImm());
831 int64_t GroupOp = MI.getOperand(3).getImm();
832 switch (GroupOp) {
833 case SPIRV::GroupOperation::Reduce:
834 case SPIRV::GroupOperation::InclusiveScan:
835 case SPIRV::GroupOperation::ExclusiveScan:
836 Reqs.addCapability(SPIRV::Capability::Kernel);
837 Reqs.addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
838 Reqs.addCapability(SPIRV::Capability::GroupNonUniformBallot);
839 break;
840 case SPIRV::GroupOperation::ClusteredReduce:
841 Reqs.addCapability(SPIRV::Capability::GroupNonUniformClustered);
842 break;
843 case SPIRV::GroupOperation::PartitionedReduceNV:
844 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
845 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
846 Reqs.addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
847 break;
848 }
849 break;
850 }
851 case SPIRV::OpGroupNonUniformShuffle:
852 case SPIRV::OpGroupNonUniformShuffleXor:
853 Reqs.addCapability(SPIRV::Capability::GroupNonUniformShuffle);
854 break;
855 case SPIRV::OpGroupNonUniformShuffleUp:
856 case SPIRV::OpGroupNonUniformShuffleDown:
857 Reqs.addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
858 break;
859 case SPIRV::OpGroupAll:
860 case SPIRV::OpGroupAny:
861 case SPIRV::OpGroupBroadcast:
862 case SPIRV::OpGroupIAdd:
863 case SPIRV::OpGroupFAdd:
864 case SPIRV::OpGroupFMin:
865 case SPIRV::OpGroupUMin:
866 case SPIRV::OpGroupSMin:
867 case SPIRV::OpGroupFMax:
868 case SPIRV::OpGroupUMax:
869 case SPIRV::OpGroupSMax:
870 Reqs.addCapability(SPIRV::Capability::Groups);
871 break;
872 case SPIRV::OpGroupNonUniformElect:
873 Reqs.addCapability(SPIRV::Capability::GroupNonUniform);
874 break;
875 case SPIRV::OpGroupNonUniformAll:
876 case SPIRV::OpGroupNonUniformAny:
877 case SPIRV::OpGroupNonUniformAllEqual:
878 Reqs.addCapability(SPIRV::Capability::GroupNonUniformVote);
879 break;
880 case SPIRV::OpGroupNonUniformBroadcast:
881 case SPIRV::OpGroupNonUniformBroadcastFirst:
882 case SPIRV::OpGroupNonUniformBallot:
883 case SPIRV::OpGroupNonUniformInverseBallot:
884 case SPIRV::OpGroupNonUniformBallotBitExtract:
885 case SPIRV::OpGroupNonUniformBallotBitCount:
886 case SPIRV::OpGroupNonUniformBallotFindLSB:
887 case SPIRV::OpGroupNonUniformBallotFindMSB:
888 Reqs.addCapability(SPIRV::Capability::GroupNonUniformBallot);
889 break;
890 default:
891 break;
892 }
893}
894
895static void collectReqs(const Module &M, SPIRV::ModuleAnalysisInfo &MAI,
896 MachineModuleInfo *MMI, const SPIRVSubtarget &ST) {
897 // Collect requirements for existing instructions.
898 for (auto F = M.begin(), E = M.end(); F != E; ++F) {
900 if (!MF)
901 continue;
902 for (const MachineBasicBlock &MBB : *MF)
903 for (const MachineInstr &MI : MBB)
904 addInstrRequirements(MI, MAI.Reqs, ST);
905 }
906 // Collect requirements for OpExecutionMode instructions.
907 auto Node = M.getNamedMetadata("spirv.ExecutionMode");
908 if (Node) {
909 for (unsigned i = 0; i < Node->getNumOperands(); i++) {
910 MDNode *MDN = cast<MDNode>(Node->getOperand(i));
911 const MDOperand &MDOp = MDN->getOperand(1);
912 if (auto *CMeta = dyn_cast<ConstantAsMetadata>(MDOp)) {
913 Constant *C = CMeta->getValue();
914 if (ConstantInt *Const = dyn_cast<ConstantInt>(C)) {
915 auto EM = Const->getZExtValue();
917 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
918 }
919 }
920 }
921 }
922 for (auto FI = M.begin(), E = M.end(); FI != E; ++FI) {
923 const Function &F = *FI;
924 if (F.isDeclaration())
925 continue;
926 if (F.getMetadata("reqd_work_group_size"))
928 SPIRV::OperandCategory::ExecutionModeOperand,
929 SPIRV::ExecutionMode::LocalSize, ST);
930 if (F.getMetadata("work_group_size_hint"))
932 SPIRV::OperandCategory::ExecutionModeOperand,
933 SPIRV::ExecutionMode::LocalSizeHint, ST);
934 if (F.getMetadata("intel_reqd_sub_group_size"))
936 SPIRV::OperandCategory::ExecutionModeOperand,
937 SPIRV::ExecutionMode::SubgroupSize, ST);
938 if (F.getMetadata("vec_type_hint"))
940 SPIRV::OperandCategory::ExecutionModeOperand,
941 SPIRV::ExecutionMode::VecTypeHint, ST);
942 }
943}
944
945static unsigned getFastMathFlags(const MachineInstr &I) {
946 unsigned Flags = SPIRV::FPFastMathMode::None;
948 Flags |= SPIRV::FPFastMathMode::NotNaN;
950 Flags |= SPIRV::FPFastMathMode::NotInf;
951 if (I.getFlag(MachineInstr::MIFlag::FmNsz))
952 Flags |= SPIRV::FPFastMathMode::NSZ;
953 if (I.getFlag(MachineInstr::MIFlag::FmArcp))
954 Flags |= SPIRV::FPFastMathMode::AllowRecip;
956 Flags |= SPIRV::FPFastMathMode::Fast;
957 return Flags;
958}
959
960static void handleMIFlagDecoration(MachineInstr &I, const SPIRVSubtarget &ST,
961 const SPIRVInstrInfo &TII,
963 if (I.getFlag(MachineInstr::MIFlag::NoSWrap) && TII.canUseNSW(I) &&
964 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
965 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
966 .IsSatisfiable) {
967 buildOpDecorate(I.getOperand(0).getReg(), I, TII,
968 SPIRV::Decoration::NoSignedWrap, {});
969 }
970 if (I.getFlag(MachineInstr::MIFlag::NoUWrap) && TII.canUseNUW(I) &&
971 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
972 SPIRV::Decoration::NoUnsignedWrap, ST,
973 Reqs)
974 .IsSatisfiable) {
975 buildOpDecorate(I.getOperand(0).getReg(), I, TII,
976 SPIRV::Decoration::NoUnsignedWrap, {});
977 }
978 if (!TII.canUseFastMathFlags(I))
979 return;
980 unsigned FMFlags = getFastMathFlags(I);
981 if (FMFlags == SPIRV::FPFastMathMode::None)
982 return;
983 Register DstReg = I.getOperand(0).getReg();
984 buildOpDecorate(DstReg, I, TII, SPIRV::Decoration::FPFastMathMode, {FMFlags});
985}
986
987// Walk all functions and add decorations related to MI flags.
988static void addDecorations(const Module &M, const SPIRVInstrInfo &TII,
989 MachineModuleInfo *MMI, const SPIRVSubtarget &ST,
991 for (auto F = M.begin(), E = M.end(); F != E; ++F) {
993 if (!MF)
994 continue;
995 for (auto &MBB : *MF)
996 for (auto &MI : MBB)
997 handleMIFlagDecoration(MI, ST, TII, MAI.Reqs);
998 }
999}
1000
1002
1004 AU.addRequired<TargetPassConfig>();
1005 AU.addRequired<MachineModuleInfoWrapperPass>();
1006}
1007
1010 getAnalysis<TargetPassConfig>().getTM<SPIRVTargetMachine>();
1011 ST = TM.getSubtargetImpl();
1012 GR = ST->getSPIRVGlobalRegistry();
1013 TII = ST->getInstrInfo();
1014
1015 MMI = &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
1016
1017 setBaseInfo(M);
1018
1019 addDecorations(M, *TII, MMI, *ST, MAI);
1020
1021 collectReqs(M, MAI, MMI, *ST);
1022
1023 processSwitches(M, MAI, MMI);
1024
1025 // Process type/const/global var/func decl instructions, number their
1026 // destination registers from 0 to N, collect Extensions and Capabilities.
1027 processDefInstrs(M);
1028
1029 // Number rest of registers from N+1 onwards.
1030 numberRegistersGlobally(M);
1031
1032 // Collect OpName, OpEntryPoint, OpDecorate etc, process other instructions.
1033 processOtherInstrs(M);
1034
1035 // If there are no entry points, we need the Linkage capability.
1036 if (MAI.MS[SPIRV::MB_EntryPoints].empty())
1037 MAI.Reqs.addCapability(SPIRV::Capability::Linkage);
1038
1039 return false;
1040}
unsigned const MachineRegisterInfo * MRI
aarch64 promote const
MachineBasicBlock & MBB
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_DEBUG(X)
Definition: Debug.h:101
uint64_t Addr
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static cl::opt< bool > SPVDumpDeps("spv-dump-deps", cl::desc("Dump MIR with SPIR-V dependencies info"), cl::Optional, cl::init(false))
unsigned unsigned DefaultVal
unsigned OpIndex
#define DEBUG_TYPE
static void processSwitches(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
This file contains some templates that are useful if you are working with the STL at all.
Target-Independent Code Generator Pass Configuration Options pass.
@ Flags
Definition: TextStubV5.cpp:93
This is the shared class of boolean and integer constants.
Definition: Constants.h:78
This is an important base class in LLVM.
Definition: Constant.h:41
Implements a dense probed hash-table based set.
Definition: DenseSet.h:271
Metadata node.
Definition: Metadata.h:943
const MDOperand & getOperand(unsigned I) const
Definition: Metadata.h:1291
unsigned getNumOperands() const
Return number of MDNode operands.
Definition: Metadata.h:1297
Tracking metadata reference owned by Metadata.
Definition: Metadata.h:772
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Representation of each machine instruction.
Definition: MachineInstr.h:68
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:516
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:526
This class contains meta information specific to a module.
MachineFunction * getMachineFunction(const Function &F) const
Returns the MachineFunction associated to IR function F if there is one, otherwise nullptr.
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:38
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
Definition: Register.h:84
bool isValid() const
Definition: Register.h:126
void buildDepsGraph(std::vector< SPIRV::DTSortableEntry * > &Graph, MachineModuleInfo *MMI=nullptr)
bool isConstantInstr(const MachineInstr &MI) const
bool isDecorationInstr(const MachineInstr &MI) const
bool empty() const
Definition: SmallVector.h:94
iterator insert(iterator I, T &&Elt)
Definition: SmallVector.h:809
void push_back(const T &Elt)
Definition: SmallVector.h:416
std::pair< typename Base::iterator, bool > insert(StringRef key)
Definition: StringSet.h:34
Target-Independent Code Generator Pass Configuration Options.
Target - Wrapper for Target specific information.
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:206
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
Definition: DenseSet.h:185
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
@ SC
CHAIN = SC CHAIN, Imm128 - System call.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:445
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
std::string getStringImm(const MachineInstr &MI, unsigned StartIndex)
Definition: SPIRVUtils.cpp:74
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1819
ExtensionList getSymbolicOperandExtensions(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
CapabilityList getSymbolicOperandCapabilities(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
void initializeSPIRVModuleAnalysisPass(PassRegistry &)
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
Definition: SPIRVUtils.cpp:112
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:145
std::string getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category, int32_t Value)
uint32_t getSymbolicOperandMinVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
constexpr unsigned BitWidth
Definition: BitmaskEnum.h:184
uint32_t getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
#define N
static struct SPIRV::ModuleAnalysisInfo MAI
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Register getRegisterAlias(const MachineFunction *MF, Register Reg)
SmallVector< MachineInstr *, 4 > GlobalVarList
DenseMap< const Function *, Register > FuncMap
DenseSet< MachineBasicBlock * > MBBsToSkip
void setRegisterAlias(const MachineFunction *MF, Register Reg, Register AliasReg)
bool hasRegisterAlias(const MachineFunction *MF, Register Reg)
bool getSkipEmission(const MachineInstr *MI)
InstrList MS[NUM_MODULE_SECTIONS]
AddressingModel::AddressingModel Addr
void setSkipEmission(MachineInstr *MI)
SourceLanguage::SourceLanguage SrcLang
DenseSet< MachineInstr * > InstrsToDelete
DenseMap< unsigned, Register > ExtInstSetMap
void addCapabilities(const CapabilityList &ToAdd)
bool isCapabilityAvailable(Capability::Capability Cap) const
void checkSatisfiable(const SPIRVSubtarget &ST) const
void getAndAddRequirements(SPIRV::OperandCategory::OperandCategory Category, uint32_t i, const SPIRVSubtarget &ST)
void addExtension(Extension::Extension ToAdd)
void initAvailableCapabilities(const SPIRVSubtarget &ST)
void addCapability(Capability::Capability ToAdd)
void addAvailableCaps(const CapabilityList &ToAdd)
void addRequirements(const Requirements &Req)
const std::optional< Capability::Capability > Cap