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