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