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