Files
clang-p2996/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h
Ilia Diachkov b8e1544b9d [SPIRV] add SPIRVPrepareFunctions pass and update other passes
The patch adds SPIRVPrepareFunctions pass, which modifies function
signatures containing aggregate arguments and/or return values before
IR translation. Information about the original signatures is stored in
metadata. It is used during call lowering to restore correct SPIR-V types
of function arguments and return values. This pass also substitutes some
llvm intrinsic calls to function calls, generating the necessary functions
in the module, as the SPIRV translator does.

The patch also includes changes in other modules, fixing errors and
enabling many SPIR-V features that were omitted earlier. And 15 LIT tests
are also added to demonstrate the new functionality.

Differential Revision: https://reviews.llvm.org/D129730

Co-authored-by: Aleksandr Bezzubikov <zuban32s@gmail.com>
Co-authored-by: Michal Paszkowski <michal.paszkowski@outlook.com>
Co-authored-by: Andrey Tretyakov <andrey1.tretyakov@intel.com>
Co-authored-by: Konrad Trifunovic <konrad.trifunovic@intel.com>
2022-07-22 04:00:48 +03:00

150 lines
5.8 KiB
C++

//===- SPIRVModuleAnalysis.h - analysis of global instrs & regs -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// The analysis collects instructions that should be output at the module level
// and performs the global register numbering.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H
#define LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H
#include "MCTargetDesc/SPIRVBaseInfo.h"
#include "SPIRVDuplicatesTracker.h"
#include "SPIRVSubtarget.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
namespace llvm {
class MachineFunction;
class MachineModuleInfo;
namespace SPIRV {
// The enum contains logical module sections for the instruction collection.
enum ModuleSectionType {
// MB_Capabilities, MB_Extensions, MB_ExtInstImports, MB_MemoryModel,
MB_EntryPoints, // All OpEntryPoint instructions (if any).
// MB_ExecutionModes, MB_DebugSourceAndStrings,
MB_DebugNames, // All OpName and OpMemberName intrs.
MB_DebugModuleProcessed, // All OpModuleProcessed instructions.
MB_Annotations, // OpDecorate, OpMemberDecorate etc.
MB_TypeConstVars, // OpTypeXXX, OpConstantXXX, and global OpVariables.
MB_ExtFuncDecls, // OpFunction etc. to declare for external funcs.
NUM_MODULE_SECTIONS // Total number of sections requiring basic blocks.
};
using InstrList = SmallVector<MachineInstr *>;
// Maps a local register to the corresponding global alias.
using LocalToGlobalRegTable = std::map<Register, Register>;
using RegisterAliasMapTy =
std::map<const MachineFunction *, LocalToGlobalRegTable>;
// The struct contains results of the module analysis and methods
// to access them.
struct ModuleAnalysisInfo {
SPIRV::MemoryModel Mem;
SPIRV::AddressingModel Addr;
SPIRV::SourceLanguage SrcLang;
unsigned SrcLangVersion;
StringSet<> SrcExt;
// Maps ExtInstSet to corresponding ID register.
DenseMap<unsigned, Register> ExtInstSetMap;
// Contains the list of all global OpVariables in the module.
SmallVector<MachineInstr *, 4> GlobalVarList;
// Maps function names to coresponding function ID registers.
StringMap<Register> FuncNameMap;
// The set contains machine instructions which are necessary
// for correct MIR but will not be emitted in function bodies.
DenseSet<MachineInstr *> InstrsToDelete;
// The set contains machine basic blocks which are necessary
// for correct MIR but will not be emitted.
DenseSet<MachineBasicBlock *> MBBsToSkip;
// The table contains global aliases of local registers for each machine
// function. The aliases are used to substitute local registers during
// code emission.
RegisterAliasMapTy RegisterAliasTable;
// The counter holds the maximum ID we have in the module.
unsigned MaxID;
// The array contains lists of MIs for each module section.
InstrList MS[NUM_MODULE_SECTIONS];
// The table maps MBB number to SPIR-V unique ID register.
DenseMap<int, Register> BBNumToRegMap;
Register getFuncReg(std::string FuncName) {
auto FuncReg = FuncNameMap.find(FuncName);
assert(FuncReg != FuncNameMap.end() && "Cannot find function Id");
return FuncReg->second;
}
Register getExtInstSetReg(unsigned SetNum) { return ExtInstSetMap[SetNum]; }
InstrList &getMSInstrs(unsigned MSType) { return MS[MSType]; }
void setSkipEmission(MachineInstr *MI) { InstrsToDelete.insert(MI); }
bool getSkipEmission(const MachineInstr *MI) {
return InstrsToDelete.contains(MI);
}
void setRegisterAlias(const MachineFunction *MF, Register Reg,
Register AliasReg) {
RegisterAliasTable[MF][Reg] = AliasReg;
}
Register getRegisterAlias(const MachineFunction *MF, Register Reg) {
auto RI = RegisterAliasTable[MF].find(Reg);
if (RI == RegisterAliasTable[MF].end()) {
return Register(0);
}
return RegisterAliasTable[MF][Reg];
}
bool hasRegisterAlias(const MachineFunction *MF, Register Reg) {
return RegisterAliasTable.find(MF) != RegisterAliasTable.end() &&
RegisterAliasTable[MF].find(Reg) != RegisterAliasTable[MF].end();
}
unsigned getNextID() { return MaxID++; }
bool hasMBBRegister(const MachineBasicBlock &MBB) {
return BBNumToRegMap.find(MBB.getNumber()) != BBNumToRegMap.end();
}
// Convert MBB's number to corresponding ID register.
Register getOrCreateMBBRegister(const MachineBasicBlock &MBB) {
auto f = BBNumToRegMap.find(MBB.getNumber());
if (f != BBNumToRegMap.end())
return f->second;
Register NewReg = Register::index2VirtReg(getNextID());
BBNumToRegMap[MBB.getNumber()] = NewReg;
return NewReg;
}
};
} // namespace SPIRV
struct SPIRVModuleAnalysis : public ModulePass {
static char ID;
public:
SPIRVModuleAnalysis() : ModulePass(ID) {}
bool runOnModule(Module &M) override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
static struct SPIRV::ModuleAnalysisInfo MAI;
private:
void setBaseInfo(const Module &M);
void collectGlobalEntities(
const std::vector<SPIRV::DTSortableEntry *> &DepsGraph,
SPIRV::ModuleSectionType MSType,
std::function<bool(const SPIRV::DTSortableEntry *)> Pred,
bool UsePreOrder);
void processDefInstrs(const Module &M);
void collectFuncNames(MachineInstr &MI, const Function &F);
void processOtherInstrs(const Module &M);
void numberRegistersGlobally(const Module &M);
const SPIRVSubtarget *ST;
SPIRVGlobalRegistry *GR;
const SPIRVInstrInfo *TII;
MachineModuleInfo *MMI;
};
} // namespace llvm
#endif // LLVM_LIB_TARGET_SPIRV_SPIRVMODULEANALYSIS_H