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