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