Path: blob/main/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h
35294 views
//===- SPIRVModuleAnalysis.h - analysis of global instrs & regs -*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// The analysis collects instructions that should be output at the module level9// and performs the global register numbering.10//11//===----------------------------------------------------------------------===//1213#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H14#define LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H1516#include "MCTargetDesc/SPIRVBaseInfo.h"17#include "SPIRVGlobalRegistry.h"18#include "SPIRVUtils.h"19#include "llvm/ADT/DenseMap.h"20#include "llvm/ADT/SmallSet.h"21#include "llvm/ADT/SmallVector.h"22#include "llvm/ADT/StringMap.h"2324namespace llvm {25class SPIRVSubtarget;26class MachineFunction;27class MachineModuleInfo;2829namespace SPIRV {30// The enum contains logical module sections for the instruction collection.31enum ModuleSectionType {32// MB_Capabilities, MB_Extensions, MB_ExtInstImports, MB_MemoryModel,33MB_EntryPoints, // All OpEntryPoint instructions (if any).34// MB_ExecutionModes, MB_DebugSourceAndStrings,35MB_DebugNames, // All OpName and OpMemberName intrs.36MB_DebugModuleProcessed, // All OpModuleProcessed instructions.37MB_Annotations, // OpDecorate, OpMemberDecorate etc.38MB_TypeConstVars, // OpTypeXXX, OpConstantXXX, and global OpVariables.39MB_ExtFuncDecls, // OpFunction etc. to declare for external funcs.40NUM_MODULE_SECTIONS // Total number of sections requiring basic blocks.41};4243struct Requirements {44const bool IsSatisfiable;45const std::optional<Capability::Capability> Cap;46const ExtensionList Exts;47const VersionTuple MinVer; // 0 if no min version is required.48const VersionTuple MaxVer; // 0 if no max version is required.4950Requirements(bool IsSatisfiable = false,51std::optional<Capability::Capability> Cap = {},52ExtensionList Exts = {}, VersionTuple MinVer = VersionTuple(),53VersionTuple MaxVer = VersionTuple())54: IsSatisfiable(IsSatisfiable), Cap(Cap), Exts(Exts), MinVer(MinVer),55MaxVer(MaxVer) {}56Requirements(Capability::Capability Cap) : Requirements(true, {Cap}) {}57};5859struct RequirementHandler {60private:61CapabilityList MinimalCaps;6263// AllCaps and AvailableCaps are related but different. AllCaps is a subset of64// AvailableCaps. AvailableCaps is the complete set of capabilities that are65// available to the current target. AllCaps is the set of capabilities that66// are required by the current module.67SmallSet<Capability::Capability, 8> AllCaps;68DenseSet<unsigned> AvailableCaps;6970SmallSet<Extension::Extension, 4> AllExtensions;71VersionTuple MinVersion; // 0 if no min version is defined.72VersionTuple MaxVersion; // 0 if no max version is defined.73// Add capabilities to AllCaps, recursing through their implicitly declared74// capabilities too.75void recursiveAddCapabilities(const CapabilityList &ToPrune);7677void initAvailableCapabilitiesForOpenCL(const SPIRVSubtarget &ST);78void initAvailableCapabilitiesForVulkan(const SPIRVSubtarget &ST);7980public:81RequirementHandler() {}82void clear() {83MinimalCaps.clear();84AllCaps.clear();85AvailableCaps.clear();86AllExtensions.clear();87MinVersion = VersionTuple();88MaxVersion = VersionTuple();89}90const CapabilityList &getMinimalCapabilities() const { return MinimalCaps; }91const SmallSet<Extension::Extension, 4> &getExtensions() const {92return AllExtensions;93}94// Add a list of capabilities, ensuring AllCaps captures all the implicitly95// declared capabilities, and MinimalCaps has the minimal set of required96// capabilities (so all implicitly declared ones are removed).97void addCapabilities(const CapabilityList &ToAdd);98void addCapability(Capability::Capability ToAdd) { addCapabilities({ToAdd}); }99void addExtensions(const ExtensionList &ToAdd) {100AllExtensions.insert(ToAdd.begin(), ToAdd.end());101}102void addExtension(Extension::Extension ToAdd) { AllExtensions.insert(ToAdd); }103// Add the given requirements to the lists. If constraints conflict, or these104// requirements cannot be satisfied, then abort the compilation.105void addRequirements(const Requirements &Req);106// Get requirement and add it to the list.107void getAndAddRequirements(SPIRV::OperandCategory::OperandCategory Category,108uint32_t i, const SPIRVSubtarget &ST);109// Check if all the requirements can be satisfied for the given subtarget, and110// if not abort compilation.111void checkSatisfiable(const SPIRVSubtarget &ST) const;112void initAvailableCapabilities(const SPIRVSubtarget &ST);113// Add the given capabilities to available and all their implicitly defined114// capabilities too.115void addAvailableCaps(const CapabilityList &ToAdd);116bool isCapabilityAvailable(Capability::Capability Cap) const {117return AvailableCaps.contains(Cap);118}119120// Remove capability ToRemove, but only if IfPresent is present.121void removeCapabilityIf(const Capability::Capability ToRemove,122const Capability::Capability IfPresent);123};124125using InstrList = SmallVector<MachineInstr *>;126// Maps a local register to the corresponding global alias.127using LocalToGlobalRegTable = std::map<Register, Register>;128using RegisterAliasMapTy =129std::map<const MachineFunction *, LocalToGlobalRegTable>;130131// The struct contains results of the module analysis and methods132// to access them.133struct ModuleAnalysisInfo {134RequirementHandler Reqs;135MemoryModel::MemoryModel Mem;136AddressingModel::AddressingModel Addr;137SourceLanguage::SourceLanguage SrcLang;138unsigned SrcLangVersion;139StringSet<> SrcExt;140// Maps ExtInstSet to corresponding ID register.141DenseMap<unsigned, Register> ExtInstSetMap;142// Contains the list of all global OpVariables in the module.143SmallVector<MachineInstr *, 4> GlobalVarList;144// Maps functions to corresponding function ID registers.145DenseMap<const Function *, Register> FuncMap;146// The set contains machine instructions which are necessary147// for correct MIR but will not be emitted in function bodies.148DenseSet<MachineInstr *> InstrsToDelete;149// The table contains global aliases of local registers for each machine150// function. The aliases are used to substitute local registers during151// code emission.152RegisterAliasMapTy RegisterAliasTable;153// The counter holds the maximum ID we have in the module.154unsigned MaxID;155// The array contains lists of MIs for each module section.156InstrList MS[NUM_MODULE_SECTIONS];157// The table maps MBB number to SPIR-V unique ID register.158DenseMap<int, Register> BBNumToRegMap;159160Register getFuncReg(const Function *F) {161assert(F && "Function is null");162auto FuncPtrRegPair = FuncMap.find(F);163return FuncPtrRegPair == FuncMap.end() ? Register(0)164: FuncPtrRegPair->second;165}166Register getExtInstSetReg(unsigned SetNum) { return ExtInstSetMap[SetNum]; }167InstrList &getMSInstrs(unsigned MSType) { return MS[MSType]; }168void setSkipEmission(MachineInstr *MI) { InstrsToDelete.insert(MI); }169bool getSkipEmission(const MachineInstr *MI) {170return InstrsToDelete.contains(MI);171}172void setRegisterAlias(const MachineFunction *MF, Register Reg,173Register AliasReg) {174RegisterAliasTable[MF][Reg] = AliasReg;175}176Register getRegisterAlias(const MachineFunction *MF, Register Reg) {177auto RI = RegisterAliasTable[MF].find(Reg);178if (RI == RegisterAliasTable[MF].end()) {179return Register(0);180}181return RegisterAliasTable[MF][Reg];182}183bool hasRegisterAlias(const MachineFunction *MF, Register Reg) {184return RegisterAliasTable.find(MF) != RegisterAliasTable.end() &&185RegisterAliasTable[MF].find(Reg) != RegisterAliasTable[MF].end();186}187unsigned getNextID() { return MaxID++; }188bool hasMBBRegister(const MachineBasicBlock &MBB) {189return BBNumToRegMap.contains(MBB.getNumber());190}191// Convert MBB's number to corresponding ID register.192Register getOrCreateMBBRegister(const MachineBasicBlock &MBB) {193auto f = BBNumToRegMap.find(MBB.getNumber());194if (f != BBNumToRegMap.end())195return f->second;196Register NewReg = Register::index2VirtReg(getNextID());197BBNumToRegMap[MBB.getNumber()] = NewReg;198return NewReg;199}200};201} // namespace SPIRV202203struct SPIRVModuleAnalysis : public ModulePass {204static char ID;205206public:207SPIRVModuleAnalysis() : ModulePass(ID) {}208209bool runOnModule(Module &M) override;210void getAnalysisUsage(AnalysisUsage &AU) const override;211static struct SPIRV::ModuleAnalysisInfo MAI;212213private:214void setBaseInfo(const Module &M);215void collectGlobalEntities(216const std::vector<SPIRV::DTSortableEntry *> &DepsGraph,217SPIRV::ModuleSectionType MSType,218std::function<bool(const SPIRV::DTSortableEntry *)> Pred,219bool UsePreOrder);220void processDefInstrs(const Module &M);221void collectFuncNames(MachineInstr &MI, const Function *F);222void processOtherInstrs(const Module &M);223void numberRegistersGlobally(const Module &M);224void collectFuncPtrs();225void collectFuncPtrs(MachineInstr *MI);226227const SPIRVSubtarget *ST;228SPIRVGlobalRegistry *GR;229const SPIRVInstrInfo *TII;230MachineModuleInfo *MMI;231};232} // namespace llvm233#endif // LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H234235236