181ad6265SDimitry Andric //===- SPIRVModuleAnalysis.h - analysis of global instrs & regs -*- C++ -*-===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric // 981ad6265SDimitry Andric // The analysis collects instructions that should be output at the module level 1081ad6265SDimitry Andric // and performs the global register numbering. 1181ad6265SDimitry Andric // 1281ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1381ad6265SDimitry Andric 1481ad6265SDimitry Andric #ifndef LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H 1581ad6265SDimitry Andric #define LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H 1681ad6265SDimitry Andric 1781ad6265SDimitry Andric #include "MCTargetDesc/SPIRVBaseInfo.h" 18753f127fSDimitry Andric #include "SPIRVDuplicatesTracker.h" 1981ad6265SDimitry Andric #include "SPIRVSubtarget.h" 2081ad6265SDimitry Andric #include "llvm/ADT/DenseMap.h" 2181ad6265SDimitry Andric #include "llvm/ADT/SmallVector.h" 2281ad6265SDimitry Andric #include "llvm/ADT/StringMap.h" 2381ad6265SDimitry Andric 2481ad6265SDimitry Andric namespace llvm { 2581ad6265SDimitry Andric class MachineFunction; 2681ad6265SDimitry Andric class MachineModuleInfo; 2781ad6265SDimitry Andric 2881ad6265SDimitry Andric namespace SPIRV { 2981ad6265SDimitry Andric // The enum contains logical module sections for the instruction collection. 3081ad6265SDimitry Andric enum ModuleSectionType { 3181ad6265SDimitry Andric // MB_Capabilities, MB_Extensions, MB_ExtInstImports, MB_MemoryModel, 3281ad6265SDimitry Andric MB_EntryPoints, // All OpEntryPoint instructions (if any). 3381ad6265SDimitry Andric // MB_ExecutionModes, MB_DebugSourceAndStrings, 3481ad6265SDimitry Andric MB_DebugNames, // All OpName and OpMemberName intrs. 3581ad6265SDimitry Andric MB_DebugModuleProcessed, // All OpModuleProcessed instructions. 3681ad6265SDimitry Andric MB_Annotations, // OpDecorate, OpMemberDecorate etc. 3781ad6265SDimitry Andric MB_TypeConstVars, // OpTypeXXX, OpConstantXXX, and global OpVariables. 3881ad6265SDimitry Andric MB_ExtFuncDecls, // OpFunction etc. to declare for external funcs. 3981ad6265SDimitry Andric NUM_MODULE_SECTIONS // Total number of sections requiring basic blocks. 4081ad6265SDimitry Andric }; 4181ad6265SDimitry Andric 4281ad6265SDimitry Andric using InstrList = SmallVector<MachineInstr *>; 4381ad6265SDimitry Andric // Maps a local register to the corresponding global alias. 4481ad6265SDimitry Andric using LocalToGlobalRegTable = std::map<Register, Register>; 4581ad6265SDimitry Andric using RegisterAliasMapTy = 4681ad6265SDimitry Andric std::map<const MachineFunction *, LocalToGlobalRegTable>; 4781ad6265SDimitry Andric 4881ad6265SDimitry Andric // The struct contains results of the module analysis and methods 4981ad6265SDimitry Andric // to access them. 5081ad6265SDimitry Andric struct ModuleAnalysisInfo { 5181ad6265SDimitry Andric SPIRV::MemoryModel Mem; 5281ad6265SDimitry Andric SPIRV::AddressingModel Addr; 5381ad6265SDimitry Andric SPIRV::SourceLanguage SrcLang; 5481ad6265SDimitry Andric unsigned SrcLangVersion; 55*fcaf7f86SDimitry Andric StringSet<> SrcExt; 56*fcaf7f86SDimitry Andric // Maps ExtInstSet to corresponding ID register. 57*fcaf7f86SDimitry Andric DenseMap<unsigned, Register> ExtInstSetMap; 5881ad6265SDimitry Andric // Contains the list of all global OpVariables in the module. 5981ad6265SDimitry Andric SmallVector<MachineInstr *, 4> GlobalVarList; 6081ad6265SDimitry Andric // Maps function names to coresponding function ID registers. 6181ad6265SDimitry Andric StringMap<Register> FuncNameMap; 6281ad6265SDimitry Andric // The set contains machine instructions which are necessary 6381ad6265SDimitry Andric // for correct MIR but will not be emitted in function bodies. 6481ad6265SDimitry Andric DenseSet<MachineInstr *> InstrsToDelete; 65*fcaf7f86SDimitry Andric // The set contains machine basic blocks which are necessary 66*fcaf7f86SDimitry Andric // for correct MIR but will not be emitted. 67*fcaf7f86SDimitry Andric DenseSet<MachineBasicBlock *> MBBsToSkip; 6881ad6265SDimitry Andric // The table contains global aliases of local registers for each machine 6981ad6265SDimitry Andric // function. The aliases are used to substitute local registers during 7081ad6265SDimitry Andric // code emission. 7181ad6265SDimitry Andric RegisterAliasMapTy RegisterAliasTable; 7281ad6265SDimitry Andric // The counter holds the maximum ID we have in the module. 7381ad6265SDimitry Andric unsigned MaxID; 7481ad6265SDimitry Andric // The array contains lists of MIs for each module section. 7581ad6265SDimitry Andric InstrList MS[NUM_MODULE_SECTIONS]; 7681ad6265SDimitry Andric // The table maps MBB number to SPIR-V unique ID register. 7781ad6265SDimitry Andric DenseMap<int, Register> BBNumToRegMap; 7881ad6265SDimitry Andric 7981ad6265SDimitry Andric Register getFuncReg(std::string FuncName) { 8081ad6265SDimitry Andric auto FuncReg = FuncNameMap.find(FuncName); 8181ad6265SDimitry Andric assert(FuncReg != FuncNameMap.end() && "Cannot find function Id"); 8281ad6265SDimitry Andric return FuncReg->second; 8381ad6265SDimitry Andric } 84*fcaf7f86SDimitry Andric Register getExtInstSetReg(unsigned SetNum) { return ExtInstSetMap[SetNum]; } 8581ad6265SDimitry Andric InstrList &getMSInstrs(unsigned MSType) { return MS[MSType]; } 8681ad6265SDimitry Andric void setSkipEmission(MachineInstr *MI) { InstrsToDelete.insert(MI); } 8781ad6265SDimitry Andric bool getSkipEmission(const MachineInstr *MI) { 8881ad6265SDimitry Andric return InstrsToDelete.contains(MI); 8981ad6265SDimitry Andric } 9081ad6265SDimitry Andric void setRegisterAlias(const MachineFunction *MF, Register Reg, 9181ad6265SDimitry Andric Register AliasReg) { 9281ad6265SDimitry Andric RegisterAliasTable[MF][Reg] = AliasReg; 9381ad6265SDimitry Andric } 9481ad6265SDimitry Andric Register getRegisterAlias(const MachineFunction *MF, Register Reg) { 9581ad6265SDimitry Andric auto RI = RegisterAliasTable[MF].find(Reg); 9681ad6265SDimitry Andric if (RI == RegisterAliasTable[MF].end()) { 9781ad6265SDimitry Andric return Register(0); 9881ad6265SDimitry Andric } 9981ad6265SDimitry Andric return RegisterAliasTable[MF][Reg]; 10081ad6265SDimitry Andric } 10181ad6265SDimitry Andric bool hasRegisterAlias(const MachineFunction *MF, Register Reg) { 10281ad6265SDimitry Andric return RegisterAliasTable.find(MF) != RegisterAliasTable.end() && 10381ad6265SDimitry Andric RegisterAliasTable[MF].find(Reg) != RegisterAliasTable[MF].end(); 10481ad6265SDimitry Andric } 10581ad6265SDimitry Andric unsigned getNextID() { return MaxID++; } 10681ad6265SDimitry Andric bool hasMBBRegister(const MachineBasicBlock &MBB) { 10781ad6265SDimitry Andric return BBNumToRegMap.find(MBB.getNumber()) != BBNumToRegMap.end(); 10881ad6265SDimitry Andric } 10981ad6265SDimitry Andric // Convert MBB's number to corresponding ID register. 11081ad6265SDimitry Andric Register getOrCreateMBBRegister(const MachineBasicBlock &MBB) { 11181ad6265SDimitry Andric auto f = BBNumToRegMap.find(MBB.getNumber()); 11281ad6265SDimitry Andric if (f != BBNumToRegMap.end()) 11381ad6265SDimitry Andric return f->second; 11481ad6265SDimitry Andric Register NewReg = Register::index2VirtReg(getNextID()); 11581ad6265SDimitry Andric BBNumToRegMap[MBB.getNumber()] = NewReg; 11681ad6265SDimitry Andric return NewReg; 11781ad6265SDimitry Andric } 11881ad6265SDimitry Andric }; 11981ad6265SDimitry Andric } // namespace SPIRV 12081ad6265SDimitry Andric 12181ad6265SDimitry Andric struct SPIRVModuleAnalysis : public ModulePass { 12281ad6265SDimitry Andric static char ID; 12381ad6265SDimitry Andric 12481ad6265SDimitry Andric public: 12581ad6265SDimitry Andric SPIRVModuleAnalysis() : ModulePass(ID) {} 12681ad6265SDimitry Andric 12781ad6265SDimitry Andric bool runOnModule(Module &M) override; 12881ad6265SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 12981ad6265SDimitry Andric static struct SPIRV::ModuleAnalysisInfo MAI; 13081ad6265SDimitry Andric 13181ad6265SDimitry Andric private: 13281ad6265SDimitry Andric void setBaseInfo(const Module &M); 133753f127fSDimitry Andric void collectGlobalEntities( 134753f127fSDimitry Andric const std::vector<SPIRV::DTSortableEntry *> &DepsGraph, 135753f127fSDimitry Andric SPIRV::ModuleSectionType MSType, 136753f127fSDimitry Andric std::function<bool(const SPIRV::DTSortableEntry *)> Pred, 137753f127fSDimitry Andric bool UsePreOrder); 13881ad6265SDimitry Andric void processDefInstrs(const Module &M); 13981ad6265SDimitry Andric void collectFuncNames(MachineInstr &MI, const Function &F); 14081ad6265SDimitry Andric void processOtherInstrs(const Module &M); 14181ad6265SDimitry Andric void numberRegistersGlobally(const Module &M); 14281ad6265SDimitry Andric 14381ad6265SDimitry Andric const SPIRVSubtarget *ST; 14481ad6265SDimitry Andric SPIRVGlobalRegistry *GR; 14581ad6265SDimitry Andric const SPIRVInstrInfo *TII; 14681ad6265SDimitry Andric MachineModuleInfo *MMI; 14781ad6265SDimitry Andric }; 14881ad6265SDimitry Andric } // namespace llvm 14981ad6265SDimitry Andric #endif // LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H 150