LLVM  15.0.0git
SPIRVModuleAnalysis.cpp
Go to the documentation of this file.
1 //===- SPIRVModuleAnalysis.cpp - 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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // The analysis collects instructions that should be output at the module level
10 // and performs the global register numbering.
11 //
12 // The results of this analysis are used in AsmPrinter to rename registers
13 // globally and to output required instructions at the module level.
14 //
15 //===----------------------------------------------------------------------===//
16 
17 #include "SPIRVModuleAnalysis.h"
18 #include "SPIRV.h"
19 #include "SPIRVGlobalRegistry.h"
20 #include "SPIRVSubtarget.h"
21 #include "SPIRVTargetMachine.h"
22 #include "SPIRVUtils.h"
26 
27 using namespace llvm;
28 
29 #define DEBUG_TYPE "spirv-module-analysis"
30 
32 
33 namespace llvm {
35 } // namespace llvm
36 
37 INITIALIZE_PASS(SPIRVModuleAnalysis, DEBUG_TYPE, "SPIRV module analysis", true,
38  true)
39 
40 // Retrieve an unsigned from an MDNode with a list of them as operands.
41 static unsigned getMetadataUInt(MDNode *MdNode, unsigned OpIndex,
42  unsigned DefaultVal = 0) {
43  if (MdNode && OpIndex < MdNode->getNumOperands()) {
44  const auto &Op = MdNode->getOperand(OpIndex);
45  return mdconst::extract<ConstantInt>(Op)->getZExtValue();
46  }
47  return DefaultVal;
48 }
49 
50 void SPIRVModuleAnalysis::setBaseInfo(const Module &M) {
51  MAI.MaxID = 0;
52  for (int i = 0; i < SPIRV::NUM_MODULE_SECTIONS; i++)
53  MAI.MS[i].clear();
54  MAI.RegisterAliasTable.clear();
55  MAI.InstrsToDelete.clear();
56  MAI.FuncNameMap.clear();
58 
59  // TODO: determine memory model and source language from the configuratoin.
62  unsigned PtrSize = ST->getPointerSize();
64  : PtrSize == 64 ? SPIRV::AddressingModel::Physical64
66  // Get the OpenCL version number from metadata.
67  // TODO: support other source languages.
68  MAI.SrcLangVersion = 0;
69  if (auto VerNode = M.getNamedMetadata("opencl.ocl.version")) {
70  // Construct version literal according to OpenCL 2.2 environment spec.
71  auto VersionMD = VerNode->getOperand(0);
72  unsigned MajorNum = getMetadataUInt(VersionMD, 0, 2);
73  unsigned MinorNum = getMetadataUInt(VersionMD, 1);
74  unsigned RevNum = getMetadataUInt(VersionMD, 2);
75  MAI.SrcLangVersion = 0 | (MajorNum << 16) | (MinorNum << 8) | RevNum;
76  }
77 }
78 
79 // True if there is an instruction in the MS list with all the same operands as
80 // the given instruction has (after the given starting index).
81 // TODO: maybe it needs to check Opcodes too.
82 static bool findSameInstrInMS(const MachineInstr &A,
85  bool UpdateRegAliases,
86  unsigned StartOpIndex = 0) {
87  for (const auto *B : MAI.MS[MSType]) {
88  const unsigned NumAOps = A.getNumOperands();
89  if (NumAOps == B->getNumOperands() && A.getNumDefs() == B->getNumDefs()) {
90  bool AllOpsMatch = true;
91  for (unsigned i = StartOpIndex; i < NumAOps && AllOpsMatch; ++i) {
92  if (A.getOperand(i).isReg() && B->getOperand(i).isReg()) {
93  Register RegA = A.getOperand(i).getReg();
94  Register RegB = B->getOperand(i).getReg();
95  AllOpsMatch = MAI.getRegisterAlias(A.getMF(), RegA) ==
96  MAI.getRegisterAlias(B->getMF(), RegB);
97  } else {
98  AllOpsMatch = A.getOperand(i).isIdenticalTo(B->getOperand(i));
99  }
100  }
101  if (AllOpsMatch) {
102  if (UpdateRegAliases) {
103  assert(A.getOperand(0).isReg() && B->getOperand(0).isReg());
104  Register LocalReg = A.getOperand(0).getReg();
105  Register GlobalReg =
106  MAI.getRegisterAlias(B->getMF(), B->getOperand(0).getReg());
107  MAI.setRegisterAlias(A.getMF(), LocalReg, GlobalReg);
108  }
109  return true;
110  }
111  }
112  }
113  return false;
114 }
115 
116 // Look for IDs declared with Import linkage, and map the imported name string
117 // to the register defining that variable (which will usually be the result of
118 // an OpFunction). This lets us call externally imported functions using
119 // the correct ID registers.
120 void SPIRVModuleAnalysis::collectFuncNames(MachineInstr &MI,
121  const Function &F) {
122  if (MI.getOpcode() == SPIRV::OpDecorate) {
123  // If it's got Import linkage.
124  auto Dec = MI.getOperand(1).getImm();
125  if (Dec == static_cast<unsigned>(SPIRV::Decoration::LinkageAttributes)) {
126  auto Lnk = MI.getOperand(MI.getNumOperands() - 1).getImm();
127  if (Lnk == static_cast<unsigned>(SPIRV::LinkageType::Import)) {
128  // Map imported function name to function ID register.
129  std::string Name = getStringImm(MI, 2);
130  Register Target = MI.getOperand(0).getReg();
131  // TODO: check defs from different MFs.
133  }
134  }
135  } else if (MI.getOpcode() == SPIRV::OpFunction) {
136  // Record all internal OpFunction declarations.
137  Register Reg = MI.defs().begin()->getReg();
138  Register GlobalReg = MAI.getRegisterAlias(MI.getMF(), Reg);
139  assert(GlobalReg.isValid());
140  // TODO: check that it does not conflict with existing entries.
141  MAI.FuncNameMap[F.getGlobalIdentifier()] = GlobalReg;
142  }
143 }
144 
145 // Collect the given instruction in the specified MS. We assume global register
146 // numbering has already occurred by this point. We can directly compare reg
147 // arguments when detecting duplicates.
148 static void collectOtherInstr(MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI,
150  bool IsConstOrType = false) {
151  MAI.setSkipEmission(&MI);
152  if (findSameInstrInMS(MI, MSType, MAI, IsConstOrType, IsConstOrType ? 1 : 0))
153  return; // Found a duplicate, so don't add it.
154  // No duplicates, so add it.
155  MAI.MS[MSType].push_back(&MI);
156 }
157 
158 // Some global instructions make reference to function-local ID regs, so cannot
159 // be correctly collected until these registers are globally numbered.
160 void SPIRVModuleAnalysis::processOtherInstrs(const Module &M) {
161  for (auto F = M.begin(), E = M.end(); F != E; ++F) {
162  if ((*F).isDeclaration())
163  continue;
164  MachineFunction *MF = MMI->getMachineFunction(*F);
165  assert(MF);
166  unsigned FCounter = 0;
167  for (MachineBasicBlock &MBB : *MF)
168  for (MachineInstr &MI : MBB) {
169  if (MI.getOpcode() == SPIRV::OpFunction)
170  FCounter++;
171  if (MAI.getSkipEmission(&MI))
172  continue;
173  const unsigned OpCode = MI.getOpcode();
174  const bool IsFuncOrParm =
175  OpCode == SPIRV::OpFunction || OpCode == SPIRV::OpFunctionParameter;
176  const bool IsConstOrType =
177  TII->isConstantInstr(MI) || TII->isTypeDeclInstr(MI);
178  if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
179  collectOtherInstr(MI, MAI, SPIRV::MB_DebugNames);
180  } else if (OpCode == SPIRV::OpEntryPoint) {
181  collectOtherInstr(MI, MAI, SPIRV::MB_EntryPoints);
182  } else if (TII->isDecorationInstr(MI)) {
183  collectOtherInstr(MI, MAI, SPIRV::MB_Annotations);
184  collectFuncNames(MI, *F);
185  } else if (IsConstOrType || (FCounter > 1 && IsFuncOrParm)) {
186  // Now OpSpecConstant*s are not in DT,
187  // but they need to be collected anyway.
190  collectOtherInstr(MI, MAI, Type, IsConstOrType);
191  } else if (OpCode == SPIRV::OpFunction) {
192  collectFuncNames(MI, *F);
193  }
194  }
195  }
196 }
197 
198 // Number registers in all functions globally from 0 onwards and store
199 // the result in global register alias table.
200 void SPIRVModuleAnalysis::numberRegistersGlobally(const Module &M) {
201  for (auto F = M.begin(), E = M.end(); F != E; ++F) {
202  if ((*F).isDeclaration())
203  continue;
204  MachineFunction *MF = MMI->getMachineFunction(*F);
205  assert(MF);
206  for (MachineBasicBlock &MBB : *MF) {
207  for (MachineInstr &MI : MBB) {
208  for (MachineOperand &Op : MI.operands()) {
209  if (!Op.isReg())
210  continue;
211  Register Reg = Op.getReg();
212  if (MAI.hasRegisterAlias(MF, Reg))
213  continue;
215  MAI.setRegisterAlias(MF, Reg, NewReg);
216  }
217  }
218  }
219  }
220 }
221 
223 
225  AU.addRequired<TargetPassConfig>();
226  AU.addRequired<MachineModuleInfoWrapperPass>();
227 }
228 
231  getAnalysis<TargetPassConfig>().getTM<SPIRVTargetMachine>();
232  ST = TM.getSubtargetImpl();
233  GR = ST->getSPIRVGlobalRegistry();
234  TII = ST->getInstrInfo();
235 
236  MMI = &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
237 
238  setBaseInfo(M);
239 
240  // TODO: Process type/const/global var/func decl instructions, number their
241  // destination registers from 0 to N, collect Extensions and Capabilities.
242 
243  // Number rest of registers from N+1 onwards.
244  numberRegistersGlobally(M);
245 
246  // Collect OpName, OpEntryPoint, OpDecorate etc, process other instructions.
247  processOtherInstrs(M);
248 
249  return false;
250 }
llvm::SPIRV::ModuleAnalysisInfo::setRegisterAlias
void setRegisterAlias(const MachineFunction *MF, Register Reg, Register AliasReg)
Definition: SPIRVModuleAnalysis.h:82
i
i
Definition: README.txt:29
DefaultVal
unsigned unsigned DefaultVal
Definition: SPIRVModuleAnalysis.cpp:42
llvm::SPIRV::ModuleSectionType
ModuleSectionType
Definition: SPIRVModuleAnalysis.h:29
llvm::SPIRV::SourceLanguage::OpenCL_C
@ OpenCL_C
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:104
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
SPIRVModuleAnalysis.h
DEBUG_TYPE
#define DEBUG_TYPE
Definition: SPIRVModuleAnalysis.cpp:29
llvm::SPIRVInstrInfo::isDecorationInstr
bool isDecorationInstr(const MachineInstr &MI) const
Definition: SPIRVInstrInfo.cpp:59
llvm::SPIRV::MB_TypeConstVars
@ MB_TypeConstVars
Definition: SPIRVModuleAnalysis.h:36
llvm::Function
Definition: Function.h:60
llvm::SPIRV::NUM_MODULE_SECTIONS
@ NUM_MODULE_SECTIONS
Definition: SPIRVModuleAnalysis.h:38
llvm::Target
Target - Wrapper for Target specific information.
Definition: TargetRegistry.h:145
llvm::SPIRV::ModuleAnalysisInfo::Mem
SPIRV::MemoryModel Mem
Definition: SPIRVModuleAnalysis.h:50
llvm::X86Disassembler::Reg
Reg
All possible values of the reg field in the ModR/M byte.
Definition: X86DisassemblerDecoder.h:462
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
llvm::SPIRV::ModuleAnalysisInfo::MaxID
unsigned MaxID
Definition: SPIRVModuleAnalysis.h:66
llvm::Register::index2VirtReg
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
Definition: Register.h:84
llvm::SPIRV::ModuleAnalysisInfo
Definition: SPIRVModuleAnalysis.h:49
SPIRVSubtarget.h
llvm::SPIRVInstrInfo::isConstantInstr
bool isConstantInstr(const MachineInstr &MI) const
Definition: SPIRVInstrInfo.cpp:28
INITIALIZE_PASS
INITIALIZE_PASS(SPIRVModuleAnalysis, DEBUG_TYPE, "SPIRV module analysis", true, true) static unsigned getMetadataUInt(MDNode *MdNode
SPIRVTargetInfo.h
OpIndex
unsigned OpIndex
Definition: SPIRVModuleAnalysis.cpp:41
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::initializeSPIRVModuleAnalysisPass
void initializeSPIRVModuleAnalysisPass(PassRegistry &)
llvm::SPIRV::ModuleAnalysisInfo::setSkipEmission
void setSkipEmission(MachineInstr *MI)
Definition: SPIRVModuleAnalysis.h:78
llvm::SPIRV::MemoryModel::OpenCL
@ OpenCL
llvm::SPIRV::ModuleAnalysisInfo::Addr
SPIRV::AddressingModel Addr
Definition: SPIRVModuleAnalysis.h:51
llvm::SPIRVInstrInfo::isTypeDeclInstr
bool isTypeDeclInstr(const MachineInstr &MI) const
Definition: SPIRVInstrInfo.cpp:49
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::ARM_PROC::A
@ A
Definition: ARMBaseInfo.h:34
llvm::SPIRVModuleAnalysis::MAI
static struct SPIRV::ModuleAnalysisInfo MAI
Definition: SPIRVModuleAnalysis.h:121
llvm::SPIRV::LinkageType::Import
@ Import
llvm::SPIRV::ModuleAnalysisInfo::getNextID
unsigned getNextID()
Definition: SPIRVModuleAnalysis.h:97
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::MachineOperand
MachineOperand class - Representation of each machine instruction operand.
Definition: MachineOperand.h:48
llvm::SPIRV::ModuleAnalysisInfo::SrcLangVersion
unsigned SrcLangVersion
Definition: SPIRVModuleAnalysis.h:53
SPIRVUtils.h
llvm::PassRegistry
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:38
llvm::SPIRV::MB_Annotations
@ MB_Annotations
Definition: SPIRVModuleAnalysis.h:35
llvm::SPIRV::ModuleAnalysisInfo::RegisterAliasTable
RegisterAliasMapTy RegisterAliasTable
Definition: SPIRVModuleAnalysis.h:64
llvm::SPIRV::ModuleAnalysisInfo::getSkipEmission
bool getSkipEmission(const MachineInstr *MI)
Definition: SPIRVModuleAnalysis.h:79
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:94
llvm::SPIRV::Decoration::LinkageAttributes
@ LinkageAttributes
llvm::SPIRV::MB_ExtFuncDecls
@ MB_ExtFuncDecls
Definition: SPIRVModuleAnalysis.h:37
llvm::TargetPassConfig
Target-Independent Code Generator Pass Configuration Options.
Definition: TargetPassConfig.h:84
SPIRVTargetMachine.h
llvm::SPIRV::ModuleAnalysisInfo::hasRegisterAlias
bool hasRegisterAlias(const MachineFunction *MF, Register Reg)
Definition: SPIRVModuleAnalysis.h:93
llvm::SPIRVModuleAnalysis::ID
static char ID
Definition: SPIRVModuleAnalysis.h:114
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:66
SPIRVGlobalRegistry.h
llvm::MachineModuleInfoWrapperPass
Definition: MachineModuleInfo.h:215
const
aarch64 promote const
Definition: AArch64PromoteConstant.cpp:232
llvm::SPIRV::ModuleAnalysisInfo::GlobalVarList
SmallVector< MachineInstr *, 4 > GlobalVarList
Definition: SPIRVModuleAnalysis.h:55
llvm::SPIRVSubtarget::getPointerSize
unsigned getPointerSize() const
Definition: SPIRVSubtarget.h:63
llvm::SPIRV::ModuleAnalysisInfo::FuncNameMap
StringMap< Register > FuncNameMap
Definition: SPIRVModuleAnalysis.h:57
llvm::SPIRV::ModuleAnalysisInfo::MS
InstrList MS[NUM_MODULE_SECTIONS]
Definition: SPIRVModuleAnalysis.h:68
TargetPassConfig.h
SPIRV.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::SPIRV::MB_DebugNames
@ MB_DebugNames
Definition: SPIRVModuleAnalysis.h:33
llvm::SPIRV::AddressingModel::Physical64
@ Physical64
MachineModuleInfo.h
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
llvm::MDNode
Metadata node.
Definition: Metadata.h:944
llvm::MachineFunction
Definition: MachineFunction.h:257
llvm::SPIRV::AddressingModel::Physical32
@ Physical32
llvm::SPIRV::AddressingModel::Logical
@ Logical
llvm::SPIRV::ModuleAnalysisInfo::SrcLang
SPIRV::SourceLanguage SrcLang
Definition: SPIRVModuleAnalysis.h:52
llvm::SPIRVModuleAnalysis
Definition: SPIRVModuleAnalysis.h:113
llvm::SPIRV::ModuleAnalysisInfo::getRegisterAlias
Register getRegisterAlias(const MachineFunction *MF, Register Reg)
Definition: SPIRVModuleAnalysis.h:86
llvm::SPIRVTargetMachine
Definition: SPIRVTargetMachine.h:20
llvm::Register
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
llvm::MachineModuleInfo::getMachineFunction
MachineFunction * getMachineFunction(const Function &F) const
Returns the MachineFunction associated to IR function F if there is one, otherwise nullptr.
Definition: MachineModuleInfo.cpp:103
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:348
llvm::SmallVectorImpl::clear
void clear()
Definition: SmallVector.h:591
getStringImm
std::string getStringImm(const MachineInstr &MI, unsigned StartIndex)
Definition: SPIRVUtils.cpp:65
llvm::SPIRV::MB_EntryPoints
@ MB_EntryPoints
Definition: SPIRVModuleAnalysis.h:31
llvm::Register::isValid
bool isValid() const
Definition: Register.h:126
llvm::SPIRVModuleAnalysis::runOnModule
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
Definition: SPIRVModuleAnalysis.cpp:229
TM
const char LLVMTargetMachineRef TM
Definition: PassBuilderBindings.cpp:47
llvm::SPIRV::ModuleAnalysisInfo::InstrsToDelete
DenseSet< MachineInstr * > InstrsToDelete
Definition: SPIRVModuleAnalysis.h:60
llvm::SPIRVModuleAnalysis::getAnalysisUsage
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: SPIRVModuleAnalysis.cpp:224