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