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 // Contains the list of all global OpVariables in the module. 56 SmallVector<MachineInstr *, 4> GlobalVarList; 57 // Maps function names to coresponding function ID registers. 58 StringMap<Register> FuncNameMap; 59 // The set contains machine instructions which are necessary 60 // for correct MIR but will not be emitted in function bodies. 61 DenseSet<MachineInstr *> InstrsToDelete; 62 // The table contains global aliases of local registers for each machine 63 // function. The aliases are used to substitute local registers during 64 // code emission. 65 RegisterAliasMapTy RegisterAliasTable; 66 // The counter holds the maximum ID we have in the module. 67 unsigned MaxID; 68 // The array contains lists of MIs for each module section. 69 InstrList MS[NUM_MODULE_SECTIONS]; 70 // The table maps MBB number to SPIR-V unique ID register. 71 DenseMap<int, Register> BBNumToRegMap; 72 73 Register getFuncReg(std::string FuncName) { 74 auto FuncReg = FuncNameMap.find(FuncName); 75 assert(FuncReg != FuncNameMap.end() && "Cannot find function Id"); 76 return FuncReg->second; 77 } 78 InstrList &getMSInstrs(unsigned MSType) { return MS[MSType]; } 79 void setSkipEmission(MachineInstr *MI) { InstrsToDelete.insert(MI); } 80 bool getSkipEmission(const MachineInstr *MI) { 81 return InstrsToDelete.contains(MI); 82 } 83 void setRegisterAlias(const MachineFunction *MF, Register Reg, 84 Register AliasReg) { 85 RegisterAliasTable[MF][Reg] = AliasReg; 86 } 87 Register getRegisterAlias(const MachineFunction *MF, Register Reg) { 88 auto RI = RegisterAliasTable[MF].find(Reg); 89 if (RI == RegisterAliasTable[MF].end()) { 90 return Register(0); 91 } 92 return RegisterAliasTable[MF][Reg]; 93 } 94 bool hasRegisterAlias(const MachineFunction *MF, Register Reg) { 95 return RegisterAliasTable.find(MF) != RegisterAliasTable.end() && 96 RegisterAliasTable[MF].find(Reg) != RegisterAliasTable[MF].end(); 97 } 98 unsigned getNextID() { return MaxID++; } 99 bool hasMBBRegister(const MachineBasicBlock &MBB) { 100 return BBNumToRegMap.find(MBB.getNumber()) != BBNumToRegMap.end(); 101 } 102 // Convert MBB's number to corresponding ID register. 103 Register getOrCreateMBBRegister(const MachineBasicBlock &MBB) { 104 auto f = BBNumToRegMap.find(MBB.getNumber()); 105 if (f != BBNumToRegMap.end()) 106 return f->second; 107 Register NewReg = Register::index2VirtReg(getNextID()); 108 BBNumToRegMap[MBB.getNumber()] = NewReg; 109 return NewReg; 110 } 111 }; 112 } // namespace SPIRV 113 114 struct SPIRVModuleAnalysis : public ModulePass { 115 static char ID; 116 117 public: 118 SPIRVModuleAnalysis() : ModulePass(ID) {} 119 120 bool runOnModule(Module &M) override; 121 void getAnalysisUsage(AnalysisUsage &AU) const override; 122 static struct SPIRV::ModuleAnalysisInfo MAI; 123 124 private: 125 void setBaseInfo(const Module &M); 126 template <typename T> void collectTypesConstsVars(); 127 void collectGlobalEntities( 128 const std::vector<SPIRV::DTSortableEntry *> &DepsGraph, 129 SPIRV::ModuleSectionType MSType, 130 std::function<bool(const SPIRV::DTSortableEntry *)> Pred, 131 bool UsePreOrder); 132 void processDefInstrs(const Module &M); 133 void collectFuncNames(MachineInstr &MI, const Function &F); 134 void processOtherInstrs(const Module &M); 135 void numberRegistersGlobally(const Module &M); 136 137 const SPIRVSubtarget *ST; 138 SPIRVGlobalRegistry *GR; 139 const SPIRVInstrInfo *TII; 140 MachineModuleInfo *MMI; 141 }; 142 } // namespace llvm 143 #endif // LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H 144