LLVM 24.0.0git
SPIRVModuleAnalysis.h
Go to the documentation of this file.
1//===- SPIRVModuleAnalysis.h - 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//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H
15#define LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H
16
18#include "SPIRVGlobalRegistry.h"
19#include "SPIRVUtils.h"
20#include "llvm/ADT/DenseMap.h"
21#include "llvm/ADT/MapVector.h"
22#include "llvm/ADT/SmallSet.h"
24#include "llvm/IR/PassManager.h"
25
26namespace llvm {
27class SPIRVSubtarget;
28class MachineFunction;
29
30namespace SPIRV {
31// The enum contains logical module sections for the instruction collection.
33 // MB_Capabilities, MB_Extensions, MB_ExtInstImports, MB_MemoryModel,
34 MB_EntryPoints, // All OpEntryPoint instructions (if any).
35 // MB_ExecutionModes, MB_DebugSourceAndStrings,
36 MB_DebugNames, // All OpName and OpMemberName intrs.
37 MB_DebugStrings, // All OpString intrs.
38 MB_DebugModuleProcessed, // All OpModuleProcessed instructions.
39 MB_AliasingInsts, // SPV_INTEL_memory_access_aliasing instructions.
40 MB_Annotations, // OpDecorate, OpMemberDecorate etc.
41 MB_TypeConstVars, // OpTypeXXX, OpConstantXXX, and global OpVariables.
42 MB_NonSemanticGlobalDI, // OpExtInst with e.g. DebugSource, DebugTypeBasic.
43 MB_ExtFuncDecls, // OpFunction etc. to declare for external funcs.
44 NUM_MODULE_SECTIONS // Total number of sections requiring basic blocks.
45};
46
48 const bool IsSatisfiable;
49 const std::optional<Capability::Capability> Cap;
51 const VersionTuple MinVer; // 0 if no min version is required.
52 const VersionTuple MaxVer; // 0 if no max version is required.
53
55 std::optional<Capability::Capability> Cap = {},
60 Requirements(Capability::Capability Cap) : Requirements(true, {Cap}) {}
61};
62
64private:
65 CapabilityList MinimalCaps;
66
67 // AllCaps and AvailableCaps are related but different. AllCaps is a subset of
68 // AvailableCaps. AvailableCaps is the complete set of capabilities that are
69 // available to the current target. AllCaps is the set of capabilities that
70 // are required by the current module.
72 DenseSet<unsigned> AvailableCaps;
73
75 VersionTuple MinVersion; // 0 if no min version is defined.
76 VersionTuple MaxVersion; // 0 if no max version is defined.
77 // Add capabilities to AllCaps, recursing through their implicitly declared
78 // capabilities too.
79 void recursiveAddCapabilities(const CapabilityList &ToPrune);
80
81 void initAvailableCapabilitiesForOpenCL(const SPIRVSubtarget &ST);
82 void initAvailableCapabilitiesForVulkan(const SPIRVSubtarget &ST);
83
84public:
85 RequirementHandler() = default;
86 void clear() {
87 MinimalCaps.clear();
88 AllCaps.clear();
89 AvailableCaps.clear();
90 AllExtensions.clear();
91 MinVersion = VersionTuple();
92 MaxVersion = VersionTuple();
93 }
94 const CapabilityList &getMinimalCapabilities() const { return MinimalCaps; }
96 return AllExtensions;
97 }
98 // Add a list of capabilities, ensuring AllCaps captures all the implicitly
99 // declared capabilities, and MinimalCaps has the minimal set of required
100 // capabilities (so all implicitly declared ones are removed).
101 void addCapabilities(const CapabilityList &ToAdd);
102 void addCapability(Capability::Capability ToAdd) { addCapabilities({ToAdd}); }
103 void addExtensions(const ExtensionList &ToAdd) {
104 AllExtensions.insert_range(ToAdd);
105 }
106 void addExtension(Extension::Extension ToAdd) { AllExtensions.insert(ToAdd); }
107 // Add the given requirements to the lists. If constraints conflict, or these
108 // requirements cannot be satisfied, then abort the compilation.
109 void addRequirements(const Requirements &Req);
110 // Get requirement and add it to the list.
111 void getAndAddRequirements(SPIRV::OperandCategory::OperandCategory Category,
112 uint32_t i, const SPIRVSubtarget &ST);
113 // Check if all the requirements can be satisfied for the given subtarget, and
114 // if not abort compilation.
115 void checkSatisfiable(const SPIRVSubtarget &ST) const;
117 // Add the given capabilities to available and all their implicitly defined
118 // capabilities too.
119 void addAvailableCaps(const CapabilityList &ToAdd);
120 bool isCapabilityAvailable(Capability::Capability Cap) const {
121 return AvailableCaps.contains(Cap);
122 }
123
124 // Remove capability ToRemove, but only if IfPresent is present.
125 void removeCapabilityIf(const Capability::Capability ToRemove,
126 const Capability::Capability IfPresent);
127};
128
130// Maps a local register to the corresponding global alias.
131using LocalToGlobalRegTable = std::map<Register, MCRegister>;
133 std::map<const MachineFunction *, LocalToGlobalRegTable>;
136
137// The struct contains results of the module analysis and methods
138// to access them.
141 MemoryModel::MemoryModel Mem;
142 AddressingModel::AddressingModel Addr;
143 SourceLanguage::SourceLanguage SrcLang;
146 // Maps ExtInstSet to corresponding ID register.
148 // Contains the list of all global OpVariables in the module.
150 // Maps functions and global variables to corresponding ID registers.
152 // The set contains machine instructions which are necessary
153 // for correct MIR but will not be emitted in function bodies.
155 // The table contains global aliases of local registers for each machine
156 // function. The aliases are used to substitute local registers during
157 // code emission.
159 // The counter holds the maximum ID we have in the module.
160 unsigned MaxID;
161 // The array contains lists of MIs for each module section.
163 // The table maps MBB number to SPIR-V unique ID register.
165 // Basic block IDs and names to emit as OpName.
167 // The table maps function pointers to their default FP fast math info. It can
168 // be assumed that the SmallVector is sorted by the bit width of the type. The
169 // first element is the smallest bit width, and the last element is the
170 // largest bit width, therefore, we will have {half, float, double} in
171 // the order of their bit widths.
173
188
190 assert(GO && "GlobalObject is null");
191 return GlobalObjMap.lookup(GO);
192 }
193 MCRegister getExtInstSetReg(unsigned SetNum) { return ExtInstSetMap[SetNum]; }
194 InstrList &getMSInstrs(unsigned MSType) { return MS[MSType]; }
197 return InstrsToDelete.contains(MI);
198 }
200 MCRegister AliasReg) {
201 RegisterAliasTable[MF][Reg] = AliasReg;
202 }
204 auto &RegTable = RegisterAliasTable[MF];
205 auto RI = RegTable.find(Reg);
206 if (RI == RegTable.end()) {
207 return MCRegister();
208 }
209 return RI->second;
210 }
212 auto RI = RegisterAliasTable.find(MF);
213 if (RI == RegisterAliasTable.end())
214 return false;
215 return RI->second.find(Reg) != RI->second.end();
216 }
217 unsigned getNextID() { return MaxID++; }
219 return MCRegister((1U << 31) | getNextID());
220 }
221 // Convert MBB's number to corresponding ID register.
223 auto Key = std::make_pair(MBB.getParent(), MBB.getNumber());
224 auto [It, Inserted] = BBNumToRegMap.try_emplace(Key);
225 if (Inserted)
226 It->second = getNextIDRegister();
227 return It->second;
228 }
230 switch (Kind) {
232 return "amdgpu.no.fine.grained.memory";
234 return "amdgpu.no.remote.memory";
236 return "atomic.ignore.denormal.mode";
237 }
238 llvm_unreachable("unknown AMDGPUAtomicMDKind");
239 }
240 // Must stay alive until the AsmPrinter consumes it.
242 ModuleAnalysisManager::Invalidator &) {
243 return false;
244 }
245};
246} // namespace SPIRV
247
249using InstrTraces = std::set<InstrSignature>;
250using InstrGRegsMap = std::map<SmallVector<size_t>, unsigned>;
252
254public:
258
259 void run(const Module &M);
260
261private:
262 void setBaseInfo(const Module &M);
263 void collectFuncNames(MachineInstr &MI, const Function *F);
264 void processOtherInstrs(const Module &M);
265 void numberRegistersGlobally(const Module &M);
266
267 // analyze dependencies to collect module scope definitions
268 void collectDeclarations(const Module &M);
269 void visitDecl(const MachineRegisterInfo &MRI, InstrGRegsMap &SignatureToGReg,
270 std::map<const Value *, unsigned> &GlobalToGReg,
271 const MachineFunction *MF, const MachineInstr &MI);
272 MCRegister handleVariable(const MachineFunction *MF, const MachineInstr &MI,
273 std::map<const Value *, unsigned> &GlobalToGReg);
274 MCRegister handleTypeDeclOrConstant(const MachineInstr &MI,
275 InstrGRegsMap &SignatureToGReg);
277 handleFunctionOrParameter(const MachineFunction *MF, const MachineInstr &MI,
278 std::map<const Value *, unsigned> &GlobalToGReg,
279 bool &IsFunDef);
280 void visitFunPtrUse(Register OpReg, const MachineOperand *FunPtrOp,
281 InstrGRegsMap &SignatureToGReg,
282 std::map<const Value *, unsigned> &GlobalToGReg,
283 const MachineFunction *MF);
284 bool isDeclSection(const MachineRegisterInfo &MRI, const MachineInstr &MI);
285
286 const SPIRVSubtarget *ST;
288 const SPIRVInstrInfo *TII;
291};
292
294 static char ID;
295
296public:
298
299 bool runOnModule(Module &M) override;
300 void getAnalysisUsage(AnalysisUsage &AU) const override;
302};
303
304class SPIRVModuleAnalysis : public AnalysisInfoMixin<SPIRVModuleAnalysis> {
306 static AnalysisKey Key;
307
308public:
310
312};
313} // namespace llvm
314#endif // LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet & ToRemove
MachineBasicBlock & MBB
This file defines the DenseMap class.
IRTranslator LLVM IR MI
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition MD5.cpp:54
Register Reg
This file implements a map that provides insertion order iteration.
ModuleAnalysisManager MAM
MachineRegisterInfo & MRI
This file defines the SmallSet class.
This file defines the SmallVector class.
Represent the analysis usage information of a pass.
Implements a dense probed hash-table based set.
Definition DenseSet.h:283
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:39
ModulePass(char &pid)
Definition Pass.h:255
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
Wrapper class representing virtual and physical registers.
Definition Register.h:20
SPIRVModuleAnalysisImpl(const SPIRVSubtarget &ST, SPIRV::ModuleAnalysisInfo &MAI, MachineFunctionGetter GetMF)
SPIRV::ModuleAnalysisInfo Result
Result run(Module &M, ModuleAnalysisManager &MAM)
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition SmallSet.h:134
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
StringSet - A wrapper for StringMap that provides set-like functionality.
Definition StringSet.h:27
Represents a version number in the form major[.minor[.subminor[.build]]].
An efficient, type-erasing, non-owning reference to a callable.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
MapVector< const Function *, FPFastMathDefaultInfoVector > FPFastMathDefaultInfoMapTy
std::map< Register, MCRegister > LocalToGlobalRegTable
SmallVector< const MachineInstr * > InstrList
std::map< const MachineFunction *, LocalToGlobalRegTable > RegisterAliasMapTy
This is an optimization pass for GlobalISel generic memory operations.
SmallVector< SPIRV::Extension::Extension, 8 > ExtensionList
SmallVector< size_t > InstrSignature
function_ref< MachineFunction *(const Function &)> MachineFunctionGetter
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1933
SmallVector< SPIRV::Capability::Capability, 8 > CapabilityList
std::set< InstrSignature > InstrTraces
std::map< SmallVector< size_t >, unsigned > InstrGRegsMap
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
A CRTP mix-in that provides informational APIs needed for analysis passes.
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition Analysis.h:29
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
FPFastMathDefaultInfoMapTy FPFastMathDefaultInfoMap
SmallVector< const MachineInstr *, 4 > GlobalVarList
MCRegister getExtInstSetReg(unsigned SetNum)
DenseMap< std::pair< const MachineFunction *, int >, MCRegister > BBNumToRegMap
DenseMap< unsigned, MCRegister > ExtInstSetMap
void setSkipEmission(const MachineInstr *MI)
DenseSet< const MachineInstr * > InstrsToDelete
bool hasRegisterAlias(const MachineFunction *MF, Register Reg)
InstrList & getMSInstrs(unsigned MSType)
MCRegister getRegisterAlias(const MachineFunction *MF, Register Reg)
bool getSkipEmission(const MachineInstr *MI)
MCRegister getOrCreateMBBRegister(const MachineBasicBlock &MBB)
SmallVector< InstrAuxDataRecord > InstrAuxDataRecords
InstrList MS[NUM_MODULE_SECTIONS]
AddressingModel::AddressingModel Addr
void setRegisterAlias(const MachineFunction *MF, Register Reg, MCRegister AliasReg)
static StringRef getAMDGPUAtomicMDName(AMDGPUAtomicMDKind Kind)
bool invalidate(Module &, const PreservedAnalyses &, ModuleAnalysisManager::Invalidator &)
SmallVector< std::pair< MCRegister, StringRef > > MBBNames
SourceLanguage::SourceLanguage SrcLang
MCRegister getGlobalObjReg(const GlobalObject *GO)
SmallVector< const MachineInstr * > DebugValueMIs
DenseMap< const GlobalObject *, MCRegister > GlobalObjMap
void checkSatisfiable(const SPIRVSubtarget &ST) const
void getAndAddRequirements(SPIRV::OperandCategory::OperandCategory Category, uint32_t i, const SPIRVSubtarget &ST)
void addRequirements(const Requirements &Req)
bool isCapabilityAvailable(Capability::Capability Cap) const
void removeCapabilityIf(const Capability::Capability ToRemove, const Capability::Capability IfPresent)
void addExtensions(const ExtensionList &ToAdd)
void addAvailableCaps(const CapabilityList &ToAdd)
void addExtension(Extension::Extension ToAdd)
void initAvailableCapabilities(const SPIRVSubtarget &ST)
void addCapability(Capability::Capability ToAdd)
void addCapabilities(const CapabilityList &ToAdd)
const CapabilityList & getMinimalCapabilities() const
const SmallSet< Extension::Extension, 4 > & getExtensions() const
Requirements(bool IsSatisfiable=false, std::optional< Capability::Capability > Cap={}, ExtensionList Exts={}, VersionTuple MinVer=VersionTuple(), VersionTuple MaxVer=VersionTuple())
const std::optional< Capability::Capability > Cap
Requirements(Capability::Capability Cap)