brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.0 KiB · 44b6c66 Raw
263 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// The analysis collects instructions that should be output at the module level10// and performs the global register numbering.11//12//===----------------------------------------------------------------------===//13 14#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H15#define LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H16 17#include "MCTargetDesc/SPIRVBaseInfo.h"18#include "SPIRVGlobalRegistry.h"19#include "SPIRVUtils.h"20#include "llvm/ADT/DenseMap.h"21#include "llvm/ADT/SmallSet.h"22#include "llvm/ADT/SmallVector.h"23 24namespace llvm {25class SPIRVSubtarget;26class MachineFunction;27class MachineModuleInfo;28 29namespace SPIRV {30// The enum contains logical module sections for the instruction collection.31enum ModuleSectionType {32  //  MB_Capabilities, MB_Extensions, MB_ExtInstImports, MB_MemoryModel,33  MB_EntryPoints, // All OpEntryPoint instructions (if any).34  //  MB_ExecutionModes, MB_DebugSourceAndStrings,35  MB_DebugNames,           // All OpName and OpMemberName intrs.36  MB_DebugStrings,         // All OpString intrs.37  MB_DebugModuleProcessed, // All OpModuleProcessed instructions.38  MB_AliasingInsts,        // SPV_INTEL_memory_access_aliasing instructions.39  MB_Annotations,          // OpDecorate, OpMemberDecorate etc.40  MB_TypeConstVars,        // OpTypeXXX, OpConstantXXX, and global OpVariables.41  MB_NonSemanticGlobalDI,  // OpExtInst with e.g. DebugSource, DebugTypeBasic.42  MB_ExtFuncDecls,         // OpFunction etc. to declare for external funcs.43  NUM_MODULE_SECTIONS      // Total number of sections requiring basic blocks.44};45 46struct Requirements {47  const bool IsSatisfiable;48  const std::optional<Capability::Capability> Cap;49  const ExtensionList Exts;50  const VersionTuple MinVer; // 0 if no min version is required.51  const VersionTuple MaxVer; // 0 if no max version is required.52 53  Requirements(bool IsSatisfiable = false,54               std::optional<Capability::Capability> Cap = {},55               ExtensionList Exts = {}, VersionTuple MinVer = VersionTuple(),56               VersionTuple MaxVer = VersionTuple())57      : IsSatisfiable(IsSatisfiable), Cap(Cap), Exts(std::move(Exts)),58        MinVer(MinVer), MaxVer(MaxVer) {}59  Requirements(Capability::Capability Cap) : Requirements(true, {Cap}) {}60};61 62struct RequirementHandler {63private:64  CapabilityList MinimalCaps;65 66  // AllCaps and AvailableCaps are related but different. AllCaps is a subset of67  // AvailableCaps. AvailableCaps is the complete set of capabilities that are68  // available to the current target. AllCaps is the set of capabilities that69  // are required by the current module.70  SmallSet<Capability::Capability, 8> AllCaps;71  DenseSet<unsigned> AvailableCaps;72 73  SmallSet<Extension::Extension, 4> AllExtensions;74  VersionTuple MinVersion; // 0 if no min version is defined.75  VersionTuple MaxVersion; // 0 if no max version is defined.76  // Add capabilities to AllCaps, recursing through their implicitly declared77  // capabilities too.78  void recursiveAddCapabilities(const CapabilityList &ToPrune);79 80  void initAvailableCapabilitiesForOpenCL(const SPIRVSubtarget &ST);81  void initAvailableCapabilitiesForVulkan(const SPIRVSubtarget &ST);82 83public:84  RequirementHandler() = default;85  void clear() {86    MinimalCaps.clear();87    AllCaps.clear();88    AvailableCaps.clear();89    AllExtensions.clear();90    MinVersion = VersionTuple();91    MaxVersion = VersionTuple();92  }93  const CapabilityList &getMinimalCapabilities() const { return MinimalCaps; }94  const SmallSet<Extension::Extension, 4> &getExtensions() const {95    return AllExtensions;96  }97  // Add a list of capabilities, ensuring AllCaps captures all the implicitly98  // declared capabilities, and MinimalCaps has the minimal set of required99  // capabilities (so all implicitly declared ones are removed).100  void addCapabilities(const CapabilityList &ToAdd);101  void addCapability(Capability::Capability ToAdd) { addCapabilities({ToAdd}); }102  void addExtensions(const ExtensionList &ToAdd) {103    AllExtensions.insert_range(ToAdd);104  }105  void addExtension(Extension::Extension ToAdd) { AllExtensions.insert(ToAdd); }106  // Add the given requirements to the lists. If constraints conflict, or these107  // requirements cannot be satisfied, then abort the compilation.108  void addRequirements(const Requirements &Req);109  // Get requirement and add it to the list.110  void getAndAddRequirements(SPIRV::OperandCategory::OperandCategory Category,111                             uint32_t i, const SPIRVSubtarget &ST);112  // Check if all the requirements can be satisfied for the given subtarget, and113  // if not abort compilation.114  void checkSatisfiable(const SPIRVSubtarget &ST) const;115  void initAvailableCapabilities(const SPIRVSubtarget &ST);116  // Add the given capabilities to available and all their implicitly defined117  // capabilities too.118  void addAvailableCaps(const CapabilityList &ToAdd);119  bool isCapabilityAvailable(Capability::Capability Cap) const {120    return AvailableCaps.contains(Cap);121  }122 123  // Remove capability ToRemove, but only if IfPresent is present.124  void removeCapabilityIf(const Capability::Capability ToRemove,125                          const Capability::Capability IfPresent);126};127 128using InstrList = SmallVector<const MachineInstr *>;129// Maps a local register to the corresponding global alias.130using LocalToGlobalRegTable = std::map<Register, MCRegister>;131using RegisterAliasMapTy =132    std::map<const MachineFunction *, LocalToGlobalRegTable>;133 134// The struct contains results of the module analysis and methods135// to access them.136struct ModuleAnalysisInfo {137  RequirementHandler Reqs;138  MemoryModel::MemoryModel Mem;139  AddressingModel::AddressingModel Addr;140  SourceLanguage::SourceLanguage SrcLang;141  unsigned SrcLangVersion;142  StringSet<> SrcExt;143  // Maps ExtInstSet to corresponding ID register.144  DenseMap<unsigned, MCRegister> ExtInstSetMap;145  // Contains the list of all global OpVariables in the module.146  SmallVector<const MachineInstr *, 4> GlobalVarList;147  // Maps functions to corresponding function ID registers.148  DenseMap<const Function *, MCRegister> FuncMap;149  // The set contains machine instructions which are necessary150  // for correct MIR but will not be emitted in function bodies.151  DenseSet<const MachineInstr *> InstrsToDelete;152  // The table contains global aliases of local registers for each machine153  // function. The aliases are used to substitute local registers during154  // code emission.155  RegisterAliasMapTy RegisterAliasTable;156  // The counter holds the maximum ID we have in the module.157  unsigned MaxID;158  // The array contains lists of MIs for each module section.159  InstrList MS[NUM_MODULE_SECTIONS];160  // The table maps MBB number to SPIR-V unique ID register.161  DenseMap<std::pair<const MachineFunction *, int>, MCRegister> BBNumToRegMap;162  // The table maps function pointers to their default FP fast math info. It can163  // be assumed that the SmallVector is sorted by the bit width of the type. The164  // first element is the smallest bit width, and the last element is the165  // largest bit width, therefore, we will have {half, float, double} in166  // the order of their bit widths.167  DenseMap<const Function *, SPIRV::FPFastMathDefaultInfoVector>168      FPFastMathDefaultInfoMap;169 170  MCRegister getFuncReg(const Function *F) {171    assert(F && "Function is null");172    return FuncMap.lookup(F);173  }174  MCRegister getExtInstSetReg(unsigned SetNum) { return ExtInstSetMap[SetNum]; }175  InstrList &getMSInstrs(unsigned MSType) { return MS[MSType]; }176  void setSkipEmission(const MachineInstr *MI) { InstrsToDelete.insert(MI); }177  bool getSkipEmission(const MachineInstr *MI) {178    return InstrsToDelete.contains(MI);179  }180  void setRegisterAlias(const MachineFunction *MF, Register Reg,181                        MCRegister AliasReg) {182    RegisterAliasTable[MF][Reg] = AliasReg;183  }184  MCRegister getRegisterAlias(const MachineFunction *MF, Register Reg) {185    auto &RegTable = RegisterAliasTable[MF];186    auto RI = RegTable.find(Reg);187    if (RI == RegTable.end()) {188      return MCRegister();189    }190    return RI->second;191  }192  bool hasRegisterAlias(const MachineFunction *MF, Register Reg) {193    auto RI = RegisterAliasTable.find(MF);194    if (RI == RegisterAliasTable.end())195      return false;196    return RI->second.find(Reg) != RI->second.end();197  }198  unsigned getNextID() { return MaxID++; }199  MCRegister getNextIDRegister() {200    return MCRegister((1U << 31) | getNextID());201  }202  bool hasMBBRegister(const MachineBasicBlock &MBB) {203    auto Key = std::make_pair(MBB.getParent(), MBB.getNumber());204    return BBNumToRegMap.contains(Key);205  }206  // Convert MBB's number to corresponding ID register.207  MCRegister getOrCreateMBBRegister(const MachineBasicBlock &MBB) {208    auto Key = std::make_pair(MBB.getParent(), MBB.getNumber());209    auto [It, Inserted] = BBNumToRegMap.try_emplace(Key);210    if (Inserted)211      It->second = getNextIDRegister();212    return It->second;213  }214};215} // namespace SPIRV216 217using InstrSignature = SmallVector<size_t>;218using InstrTraces = std::set<InstrSignature>;219using InstrGRegsMap = std::map<SmallVector<size_t>, unsigned>;220 221struct SPIRVModuleAnalysis : public ModulePass {222  static char ID;223 224public:225  SPIRVModuleAnalysis()226      : ModulePass(ID), ST(nullptr), GR(nullptr), TII(nullptr), MMI(nullptr) {}227 228  bool runOnModule(Module &M) override;229  void getAnalysisUsage(AnalysisUsage &AU) const override;230  static struct SPIRV::ModuleAnalysisInfo MAI;231 232private:233  void setBaseInfo(const Module &M);234  void collectFuncNames(MachineInstr &MI, const Function *F);235  void processOtherInstrs(const Module &M);236  void numberRegistersGlobally(const Module &M);237 238  // analyze dependencies to collect module scope definitions239  void collectDeclarations(const Module &M);240  void visitDecl(const MachineRegisterInfo &MRI, InstrGRegsMap &SignatureToGReg,241                 std::map<const Value *, unsigned> &GlobalToGReg,242                 const MachineFunction *MF, const MachineInstr &MI);243  MCRegister handleVariable(const MachineFunction *MF, const MachineInstr &MI,244                            std::map<const Value *, unsigned> &GlobalToGReg);245  MCRegister handleTypeDeclOrConstant(const MachineInstr &MI,246                                      InstrGRegsMap &SignatureToGReg);247  MCRegister248  handleFunctionOrParameter(const MachineFunction *MF, const MachineInstr &MI,249                            std::map<const Value *, unsigned> &GlobalToGReg,250                            bool &IsFunDef);251  void visitFunPtrUse(Register OpReg, InstrGRegsMap &SignatureToGReg,252                      std::map<const Value *, unsigned> &GlobalToGReg,253                      const MachineFunction *MF, const MachineInstr &MI);254  bool isDeclSection(const MachineRegisterInfo &MRI, const MachineInstr &MI);255 256  const SPIRVSubtarget *ST;257  SPIRVGlobalRegistry *GR;258  const SPIRVInstrInfo *TII;259  MachineModuleInfo *MMI;260};261} // namespace llvm262#endif // LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H263