1 //===- SPIRVModuleAnalysis.h - analysis of global instrs & regs -*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // The analysis collects instructions that should be output at the module level
10 // and performs the global register numbering.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H
15 #define LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H
17 #include "MCTargetDesc/SPIRVBaseInfo.h"
18 #include "SPIRVGlobalRegistry.h"
19 #include "SPIRVUtils.h"
20 #include "llvm/ADT/DenseMap.h"
21 #include "llvm/ADT/SmallSet.h"
22 #include "llvm/ADT/SmallVector.h"
23 #include "llvm/ADT/StringMap.h"
27 class MachineFunction
;
28 class MachineModuleInfo
;
31 // The enum contains logical module sections for the instruction collection.
32 enum ModuleSectionType
{
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_DebugModuleProcessed
, // All OpModuleProcessed instructions.
38 MB_Annotations
, // OpDecorate, OpMemberDecorate etc.
39 MB_TypeConstVars
, // OpTypeXXX, OpConstantXXX, and global OpVariables.
40 MB_ExtFuncDecls
, // OpFunction etc. to declare for external funcs.
41 NUM_MODULE_SECTIONS
// Total number of sections requiring basic blocks.
45 const bool IsSatisfiable
;
46 const std::optional
<Capability::Capability
> Cap
;
47 const ExtensionList Exts
;
48 const VersionTuple MinVer
; // 0 if no min version is required.
49 const VersionTuple MaxVer
; // 0 if no max version is required.
51 Requirements(bool IsSatisfiable
= false,
52 std::optional
<Capability::Capability
> Cap
= {},
53 ExtensionList Exts
= {}, VersionTuple MinVer
= VersionTuple(),
54 VersionTuple MaxVer
= VersionTuple())
55 : IsSatisfiable(IsSatisfiable
), Cap(Cap
), Exts(Exts
), MinVer(MinVer
),
57 Requirements(Capability::Capability Cap
) : Requirements(true, {Cap
}) {}
60 struct RequirementHandler
{
62 CapabilityList MinimalCaps
;
64 // AllCaps and AvailableCaps are related but different. AllCaps is a subset of
65 // AvailableCaps. AvailableCaps is the complete set of capabilities that are
66 // available to the current target. AllCaps is the set of capabilities that
67 // are required by the current module.
68 SmallSet
<Capability::Capability
, 8> AllCaps
;
69 DenseSet
<unsigned> AvailableCaps
;
71 SmallSet
<Extension::Extension
, 4> AllExtensions
;
72 VersionTuple MinVersion
; // 0 if no min version is defined.
73 VersionTuple MaxVersion
; // 0 if no max version is defined.
74 // Add capabilities to AllCaps, recursing through their implicitly declared
76 void recursiveAddCapabilities(const CapabilityList
&ToPrune
);
78 void initAvailableCapabilitiesForOpenCL(const SPIRVSubtarget
&ST
);
79 void initAvailableCapabilitiesForVulkan(const SPIRVSubtarget
&ST
);
82 RequirementHandler() {}
86 AvailableCaps
.clear();
87 AllExtensions
.clear();
88 MinVersion
= VersionTuple();
89 MaxVersion
= VersionTuple();
91 const CapabilityList
&getMinimalCapabilities() const { return MinimalCaps
; }
92 const SmallSet
<Extension::Extension
, 4> &getExtensions() const {
95 // Add a list of capabilities, ensuring AllCaps captures all the implicitly
96 // declared capabilities, and MinimalCaps has the minimal set of required
97 // capabilities (so all implicitly declared ones are removed).
98 void addCapabilities(const CapabilityList
&ToAdd
);
99 void addCapability(Capability::Capability ToAdd
) { addCapabilities({ToAdd
}); }
100 void addExtensions(const ExtensionList
&ToAdd
) {
101 AllExtensions
.insert(ToAdd
.begin(), ToAdd
.end());
103 void addExtension(Extension::Extension ToAdd
) { AllExtensions
.insert(ToAdd
); }
104 // Add the given requirements to the lists. If constraints conflict, or these
105 // requirements cannot be satisfied, then abort the compilation.
106 void addRequirements(const Requirements
&Req
);
107 // Get requirement and add it to the list.
108 void getAndAddRequirements(SPIRV::OperandCategory::OperandCategory Category
,
109 uint32_t i
, const SPIRVSubtarget
&ST
);
110 // Check if all the requirements can be satisfied for the given subtarget, and
111 // if not abort compilation.
112 void checkSatisfiable(const SPIRVSubtarget
&ST
) const;
113 void initAvailableCapabilities(const SPIRVSubtarget
&ST
);
114 // Add the given capabilities to available and all their implicitly defined
116 void addAvailableCaps(const CapabilityList
&ToAdd
);
117 bool isCapabilityAvailable(Capability::Capability Cap
) const {
118 return AvailableCaps
.contains(Cap
);
121 // Remove capability ToRemove, but only if IfPresent is present.
122 void removeCapabilityIf(const Capability::Capability ToRemove
,
123 const Capability::Capability IfPresent
);
126 using InstrList
= SmallVector
<MachineInstr
*>;
127 // Maps a local register to the corresponding global alias.
128 using LocalToGlobalRegTable
= std::map
<Register
, Register
>;
129 using RegisterAliasMapTy
=
130 std::map
<const MachineFunction
*, LocalToGlobalRegTable
>;
132 // The struct contains results of the module analysis and methods
134 struct ModuleAnalysisInfo
{
135 RequirementHandler Reqs
;
136 MemoryModel::MemoryModel Mem
;
137 AddressingModel::AddressingModel Addr
;
138 SourceLanguage::SourceLanguage SrcLang
;
139 unsigned SrcLangVersion
;
141 // Maps ExtInstSet to corresponding ID register.
142 DenseMap
<unsigned, Register
> ExtInstSetMap
;
143 // Contains the list of all global OpVariables in the module.
144 SmallVector
<MachineInstr
*, 4> GlobalVarList
;
145 // Maps functions to corresponding function ID registers.
146 DenseMap
<const Function
*, Register
> FuncMap
;
147 // The set contains machine instructions which are necessary
148 // for correct MIR but will not be emitted in function bodies.
149 DenseSet
<MachineInstr
*> InstrsToDelete
;
150 // The table contains global aliases of local registers for each machine
151 // function. The aliases are used to substitute local registers during
153 RegisterAliasMapTy RegisterAliasTable
;
154 // The counter holds the maximum ID we have in the module.
156 // The array contains lists of MIs for each module section.
157 InstrList MS
[NUM_MODULE_SECTIONS
];
158 // The table maps MBB number to SPIR-V unique ID register.
159 DenseMap
<int, Register
> BBNumToRegMap
;
161 Register
getFuncReg(const Function
*F
) {
162 assert(F
&& "Function is null");
163 auto FuncPtrRegPair
= FuncMap
.find(F
);
164 return FuncPtrRegPair
== FuncMap
.end() ? Register(0)
165 : FuncPtrRegPair
->second
;
167 Register
getExtInstSetReg(unsigned SetNum
) { return ExtInstSetMap
[SetNum
]; }
168 InstrList
&getMSInstrs(unsigned MSType
) { return MS
[MSType
]; }
169 void setSkipEmission(MachineInstr
*MI
) { InstrsToDelete
.insert(MI
); }
170 bool getSkipEmission(const MachineInstr
*MI
) {
171 return InstrsToDelete
.contains(MI
);
173 void setRegisterAlias(const MachineFunction
*MF
, Register Reg
,
175 RegisterAliasTable
[MF
][Reg
] = AliasReg
;
177 Register
getRegisterAlias(const MachineFunction
*MF
, Register Reg
) {
178 auto RI
= RegisterAliasTable
[MF
].find(Reg
);
179 if (RI
== RegisterAliasTable
[MF
].end()) {
182 return RegisterAliasTable
[MF
][Reg
];
184 bool hasRegisterAlias(const MachineFunction
*MF
, Register Reg
) {
185 return RegisterAliasTable
.find(MF
) != RegisterAliasTable
.end() &&
186 RegisterAliasTable
[MF
].find(Reg
) != RegisterAliasTable
[MF
].end();
188 unsigned getNextID() { return MaxID
++; }
189 bool hasMBBRegister(const MachineBasicBlock
&MBB
) {
190 return BBNumToRegMap
.contains(MBB
.getNumber());
192 // Convert MBB's number to corresponding ID register.
193 Register
getOrCreateMBBRegister(const MachineBasicBlock
&MBB
) {
194 auto f
= BBNumToRegMap
.find(MBB
.getNumber());
195 if (f
!= BBNumToRegMap
.end())
197 Register NewReg
= Register::index2VirtReg(getNextID());
198 BBNumToRegMap
[MBB
.getNumber()] = NewReg
;
204 struct SPIRVModuleAnalysis
: public ModulePass
{
208 SPIRVModuleAnalysis() : ModulePass(ID
) {}
210 bool runOnModule(Module
&M
) override
;
211 void getAnalysisUsage(AnalysisUsage
&AU
) const override
;
212 static struct SPIRV::ModuleAnalysisInfo MAI
;
215 void setBaseInfo(const Module
&M
);
216 void collectGlobalEntities(
217 const std::vector
<SPIRV::DTSortableEntry
*> &DepsGraph
,
218 SPIRV::ModuleSectionType MSType
,
219 std::function
<bool(const SPIRV::DTSortableEntry
*)> Pred
,
221 void processDefInstrs(const Module
&M
);
222 void collectFuncNames(MachineInstr
&MI
, const Function
*F
);
223 void processOtherInstrs(const Module
&M
);
224 void numberRegistersGlobally(const Module
&M
);
225 void collectFuncPtrs();
226 void collectFuncPtrs(MachineInstr
*MI
);
228 const SPIRVSubtarget
*ST
;
229 SPIRVGlobalRegistry
*GR
;
230 const SPIRVInstrInfo
*TII
;
231 MachineModuleInfo
*MMI
;
234 #endif // LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H