xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h (revision fcaf7f8644a9988098ac6be2165bce3ea4786e91)
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