xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1*81ad6265SDimitry Andric //===- SPIRVModuleAnalysis.h - analysis of global instrs & regs -*- C++ -*-===//
2*81ad6265SDimitry Andric //
3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*81ad6265SDimitry Andric //
7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===//
8*81ad6265SDimitry Andric //
9*81ad6265SDimitry Andric // The analysis collects instructions that should be output at the module level
10*81ad6265SDimitry Andric // and performs the global register numbering.
11*81ad6265SDimitry Andric //
12*81ad6265SDimitry Andric //===----------------------------------------------------------------------===//
13*81ad6265SDimitry Andric 
14*81ad6265SDimitry Andric #ifndef LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H
15*81ad6265SDimitry Andric #define LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H
16*81ad6265SDimitry Andric 
17*81ad6265SDimitry Andric #include "MCTargetDesc/SPIRVBaseInfo.h"
18*81ad6265SDimitry Andric #include "SPIRVSubtarget.h"
19*81ad6265SDimitry Andric #include "llvm/ADT/DenseMap.h"
20*81ad6265SDimitry Andric #include "llvm/ADT/SmallVector.h"
21*81ad6265SDimitry Andric #include "llvm/ADT/StringMap.h"
22*81ad6265SDimitry Andric 
23*81ad6265SDimitry Andric namespace llvm {
24*81ad6265SDimitry Andric class MachineFunction;
25*81ad6265SDimitry Andric class MachineModuleInfo;
26*81ad6265SDimitry Andric 
27*81ad6265SDimitry Andric namespace SPIRV {
28*81ad6265SDimitry Andric // The enum contains logical module sections for the instruction collection.
29*81ad6265SDimitry Andric enum ModuleSectionType {
30*81ad6265SDimitry Andric   //  MB_Capabilities, MB_Extensions, MB_ExtInstImports, MB_MemoryModel,
31*81ad6265SDimitry Andric   MB_EntryPoints, // All OpEntryPoint instructions (if any).
32*81ad6265SDimitry Andric   //  MB_ExecutionModes, MB_DebugSourceAndStrings,
33*81ad6265SDimitry Andric   MB_DebugNames,           // All OpName and OpMemberName intrs.
34*81ad6265SDimitry Andric   MB_DebugModuleProcessed, // All OpModuleProcessed instructions.
35*81ad6265SDimitry Andric   MB_Annotations,          // OpDecorate, OpMemberDecorate etc.
36*81ad6265SDimitry Andric   MB_TypeConstVars,        // OpTypeXXX, OpConstantXXX, and global OpVariables.
37*81ad6265SDimitry Andric   MB_ExtFuncDecls,         // OpFunction etc. to declare for external funcs.
38*81ad6265SDimitry Andric   NUM_MODULE_SECTIONS      // Total number of sections requiring basic blocks.
39*81ad6265SDimitry Andric };
40*81ad6265SDimitry Andric 
41*81ad6265SDimitry Andric using InstrList = SmallVector<MachineInstr *>;
42*81ad6265SDimitry Andric // Maps a local register to the corresponding global alias.
43*81ad6265SDimitry Andric using LocalToGlobalRegTable = std::map<Register, Register>;
44*81ad6265SDimitry Andric using RegisterAliasMapTy =
45*81ad6265SDimitry Andric     std::map<const MachineFunction *, LocalToGlobalRegTable>;
46*81ad6265SDimitry Andric 
47*81ad6265SDimitry Andric // The struct contains results of the module analysis and methods
48*81ad6265SDimitry Andric // to access them.
49*81ad6265SDimitry Andric struct ModuleAnalysisInfo {
50*81ad6265SDimitry Andric   SPIRV::MemoryModel Mem;
51*81ad6265SDimitry Andric   SPIRV::AddressingModel Addr;
52*81ad6265SDimitry Andric   SPIRV::SourceLanguage SrcLang;
53*81ad6265SDimitry Andric   unsigned SrcLangVersion;
54*81ad6265SDimitry Andric   // Contains the list of all global OpVariables in the module.
55*81ad6265SDimitry Andric   SmallVector<MachineInstr *, 4> GlobalVarList;
56*81ad6265SDimitry Andric   // Maps function names to coresponding function ID registers.
57*81ad6265SDimitry Andric   StringMap<Register> FuncNameMap;
58*81ad6265SDimitry Andric   // The set contains machine instructions which are necessary
59*81ad6265SDimitry Andric   // for correct MIR but will not be emitted in function bodies.
60*81ad6265SDimitry Andric   DenseSet<MachineInstr *> InstrsToDelete;
61*81ad6265SDimitry Andric   // The table contains global aliases of local registers for each machine
62*81ad6265SDimitry Andric   // function. The aliases are used to substitute local registers during
63*81ad6265SDimitry Andric   // code emission.
64*81ad6265SDimitry Andric   RegisterAliasMapTy RegisterAliasTable;
65*81ad6265SDimitry Andric   // The counter holds the maximum ID we have in the module.
66*81ad6265SDimitry Andric   unsigned MaxID;
67*81ad6265SDimitry Andric   // The array contains lists of MIs for each module section.
68*81ad6265SDimitry Andric   InstrList MS[NUM_MODULE_SECTIONS];
69*81ad6265SDimitry Andric   // The table maps MBB number to SPIR-V unique ID register.
70*81ad6265SDimitry Andric   DenseMap<int, Register> BBNumToRegMap;
71*81ad6265SDimitry Andric 
72*81ad6265SDimitry Andric   Register getFuncReg(std::string FuncName) {
73*81ad6265SDimitry Andric     auto FuncReg = FuncNameMap.find(FuncName);
74*81ad6265SDimitry Andric     assert(FuncReg != FuncNameMap.end() && "Cannot find function Id");
75*81ad6265SDimitry Andric     return FuncReg->second;
76*81ad6265SDimitry Andric   }
77*81ad6265SDimitry Andric   InstrList &getMSInstrs(unsigned MSType) { return MS[MSType]; }
78*81ad6265SDimitry Andric   void setSkipEmission(MachineInstr *MI) { InstrsToDelete.insert(MI); }
79*81ad6265SDimitry Andric   bool getSkipEmission(const MachineInstr *MI) {
80*81ad6265SDimitry Andric     return InstrsToDelete.contains(MI);
81*81ad6265SDimitry Andric   }
82*81ad6265SDimitry Andric   void setRegisterAlias(const MachineFunction *MF, Register Reg,
83*81ad6265SDimitry Andric                         Register AliasReg) {
84*81ad6265SDimitry Andric     RegisterAliasTable[MF][Reg] = AliasReg;
85*81ad6265SDimitry Andric   }
86*81ad6265SDimitry Andric   Register getRegisterAlias(const MachineFunction *MF, Register Reg) {
87*81ad6265SDimitry Andric     auto RI = RegisterAliasTable[MF].find(Reg);
88*81ad6265SDimitry Andric     if (RI == RegisterAliasTable[MF].end()) {
89*81ad6265SDimitry Andric       return Register(0);
90*81ad6265SDimitry Andric     }
91*81ad6265SDimitry Andric     return RegisterAliasTable[MF][Reg];
92*81ad6265SDimitry Andric   }
93*81ad6265SDimitry Andric   bool hasRegisterAlias(const MachineFunction *MF, Register Reg) {
94*81ad6265SDimitry Andric     return RegisterAliasTable.find(MF) != RegisterAliasTable.end() &&
95*81ad6265SDimitry Andric            RegisterAliasTable[MF].find(Reg) != RegisterAliasTable[MF].end();
96*81ad6265SDimitry Andric   }
97*81ad6265SDimitry Andric   unsigned getNextID() { return MaxID++; }
98*81ad6265SDimitry Andric   bool hasMBBRegister(const MachineBasicBlock &MBB) {
99*81ad6265SDimitry Andric     return BBNumToRegMap.find(MBB.getNumber()) != BBNumToRegMap.end();
100*81ad6265SDimitry Andric   }
101*81ad6265SDimitry Andric   // Convert MBB's number to corresponding ID register.
102*81ad6265SDimitry Andric   Register getOrCreateMBBRegister(const MachineBasicBlock &MBB) {
103*81ad6265SDimitry Andric     auto f = BBNumToRegMap.find(MBB.getNumber());
104*81ad6265SDimitry Andric     if (f != BBNumToRegMap.end())
105*81ad6265SDimitry Andric       return f->second;
106*81ad6265SDimitry Andric     Register NewReg = Register::index2VirtReg(getNextID());
107*81ad6265SDimitry Andric     BBNumToRegMap[MBB.getNumber()] = NewReg;
108*81ad6265SDimitry Andric     return NewReg;
109*81ad6265SDimitry Andric   }
110*81ad6265SDimitry Andric };
111*81ad6265SDimitry Andric } // namespace SPIRV
112*81ad6265SDimitry Andric 
113*81ad6265SDimitry Andric struct SPIRVModuleAnalysis : public ModulePass {
114*81ad6265SDimitry Andric   static char ID;
115*81ad6265SDimitry Andric 
116*81ad6265SDimitry Andric public:
117*81ad6265SDimitry Andric   SPIRVModuleAnalysis() : ModulePass(ID) {}
118*81ad6265SDimitry Andric 
119*81ad6265SDimitry Andric   bool runOnModule(Module &M) override;
120*81ad6265SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override;
121*81ad6265SDimitry Andric   static struct SPIRV::ModuleAnalysisInfo MAI;
122*81ad6265SDimitry Andric 
123*81ad6265SDimitry Andric private:
124*81ad6265SDimitry Andric   void setBaseInfo(const Module &M);
125*81ad6265SDimitry Andric   template <typename T> void collectTypesConstsVars();
126*81ad6265SDimitry Andric   void processDefInstrs(const Module &M);
127*81ad6265SDimitry Andric   void collectFuncNames(MachineInstr &MI, const Function &F);
128*81ad6265SDimitry Andric   void processOtherInstrs(const Module &M);
129*81ad6265SDimitry Andric   void numberRegistersGlobally(const Module &M);
130*81ad6265SDimitry Andric 
131*81ad6265SDimitry Andric   const SPIRVSubtarget *ST;
132*81ad6265SDimitry Andric   SPIRVGlobalRegistry *GR;
133*81ad6265SDimitry Andric   const SPIRVInstrInfo *TII;
134*81ad6265SDimitry Andric   MachineModuleInfo *MMI;
135*81ad6265SDimitry Andric };
136*81ad6265SDimitry Andric } // namespace llvm
137*81ad6265SDimitry Andric #endif // LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H
138