LLVM 22.0.0git
SPIRVTargetMachine.cpp
Go to the documentation of this file.
1//===- SPIRVTargetMachine.cpp - Define TargetMachine for SPIR-V -*- 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// Implements the info about SPIR-V target spec.
10//
11//===----------------------------------------------------------------------===//
12
13#include "SPIRVTargetMachine.h"
14#include "SPIRV.h"
15#include "SPIRVGlobalRegistry.h"
16#include "SPIRVLegalizerInfo.h"
25#include "llvm/CodeGen/Passes.h"
29#include "llvm/Pass.h"
35#include <optional>
36
37using namespace llvm;
38
40 // Register the target.
44
61}
62
63static std::string computeDataLayout(const Triple &TT) {
64 const auto Arch = TT.getArch();
65 // TODO: this probably needs to be revisited:
66 // Logical SPIR-V has no pointer size, so any fixed pointer size would be
67 // wrong. The choice to default to 32 or 64 is just motivated by another
68 // memory model used for graphics: PhysicalStorageBuffer64. But it shouldn't
69 // mean anything.
70 if (Arch == Triple::spirv32)
71 return "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-"
72 "v256:256-v512:512-v1024:1024-n8:16:32:64-G1";
73 if (Arch == Triple::spirv)
74 return "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-"
75 "v512:512-v1024:1024-n8:16:32:64-G10";
76 if (TT.getVendor() == Triple::VendorType::AMD &&
77 TT.getOS() == Triple::OSType::AMDHSA)
78 return "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-"
79 "v512:512-v1024:1024-n32:64-S32-G1-P4-A0";
80 return "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-"
81 "v512:512-v1024:1024-n8:16:32:64-G1";
82}
83
84static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {
85 if (!RM)
86 return Reloc::PIC_;
87 return *RM;
88}
89
90// Pin SPIRVTargetObjectFile's vtables to this file.
92
94 StringRef CPU, StringRef FS,
96 std::optional<Reloc::Model> RM,
97 std::optional<CodeModel::Model> CM,
98 CodeGenOptLevel OL, bool JIT)
101 getEffectiveCodeModel(CM, CodeModel::Small), OL),
102 TLOF(std::make_unique<SPIRVTargetObjectFile>()),
103 Subtarget(TT, CPU.str(), FS.str(), *this) {
104 initAsmInfo();
105 setGlobalISel(true);
106 setFastISel(false);
107 setO0WantsFastISel(false);
109}
110
112#define GET_PASS_REGISTRY "SPIRVPassRegistry.def"
114}
115
116namespace {
117// SPIR-V Code Generator Pass Configuration Options.
118class SPIRVPassConfig : public TargetPassConfig {
119public:
120 SPIRVPassConfig(SPIRVTargetMachine &TM, PassManagerBase &PM)
121 : TargetPassConfig(TM, PM), TM(TM) {}
122
123 SPIRVTargetMachine &getSPIRVTargetMachine() const {
124 return getTM<SPIRVTargetMachine>();
125 }
126 void addMachineSSAOptimization() override;
127 void addIRPasses() override;
128 void addISelPrepare() override;
129
130 bool addIRTranslator() override;
131 void addPreLegalizeMachineIR() override;
132 bool addLegalizeMachineIR() override;
133 bool addRegBankSelect() override;
134 bool addGlobalInstructionSelect() override;
135
136 FunctionPass *createTargetRegisterAllocator(bool) override;
137 void addFastRegAlloc() override {}
138 void addOptimizedRegAlloc() override {}
139
140 void addPostRegAlloc() override;
141 void addPreEmitPass() override;
142
143private:
144 const SPIRVTargetMachine &TM;
145};
146} // namespace
147
148// We do not use physical registers, and maintain virtual registers throughout
149// the entire pipeline, so return nullptr to disable register allocation.
150FunctionPass *SPIRVPassConfig::createTargetRegisterAllocator(bool) {
151 return nullptr;
152}
153
154// A place to disable passes that may break CFG.
155void SPIRVPassConfig::addMachineSSAOptimization() {
157}
158
159// Disable passes that break from assuming no virtual registers exist.
160void SPIRVPassConfig::addPostRegAlloc() {
161 // Do not work with vregs instead of physical regs.
162 disablePass(&MachineCopyPropagationID);
163 disablePass(&PostRAMachineSinkingID);
164 disablePass(&PostRASchedulerID);
165 disablePass(&FuncletLayoutID);
166 disablePass(&StackMapLivenessID);
167 disablePass(&PatchableFunctionID);
168 disablePass(&ShrinkWrapID);
169 disablePass(&LiveDebugValuesID);
170 disablePass(&MachineLateInstrsCleanupID);
171 disablePass(&RemoveLoadsIntoFakeUsesID);
172
173 // Do not work with OpPhi.
174 disablePass(&BranchFolderPassID);
175 disablePass(&MachineBlockPlacementID);
176
178}
179
182 return TargetTransformInfo(std::make_unique<SPIRVTTIImpl>(this, F));
183}
184
186 return new SPIRVPassConfig(*this, PM);
187}
188
189void SPIRVPassConfig::addIRPasses() {
191
192 if (TM.getSubtargetImpl()->isShader()) {
193 // Vulkan does not allow address space casts. This pass is run to remove
194 // address space casts that can be removed.
195 // If an address space cast is not removed while targeting Vulkan, lowering
196 // will fail during MIR lowering.
198
199 // 1. Simplify loop for subsequent transformations. After this steps, loops
200 // have the following properties:
201 // - loops have a single entry edge (pre-header to loop header).
202 // - all loop exits are dominated by the loop pre-header.
203 // - loops have a single back-edge.
204 addPass(createLoopSimplifyPass());
205
206 // 2. Removes registers whose lifetime spans across basic blocks. Also
207 // removes phi nodes. This will greatly simplify the next steps.
208 addPass(createRegToMemWrapperPass());
209
210 // 3. Merge the convergence region exit nodes into one. After this step,
211 // regions are single-entry, single-exit. This will help determine the
212 // correct merge block.
214
215 // 4. Structurize.
217
218 // 5. Reduce the amount of variables required by pushing some operations
219 // back to virtual registers.
221 }
222
226}
227
228void SPIRVPassConfig::addISelPrepare() {
230 addPass(createSPIRVEmitIntrinsicsPass(&getTM<SPIRVTargetMachine>()));
231 if (TM.getSubtargetImpl()->isLogicalSPIRV())
232 addPass(createSPIRVLegalizePointerCastPass(&getTM<SPIRVTargetMachine>()));
234}
235
236bool SPIRVPassConfig::addIRTranslator() {
237 addPass(new IRTranslator(getOptLevel()));
238 return false;
239}
240
241void SPIRVPassConfig::addPreLegalizeMachineIR() {
244}
245
246// Use the default legalizer.
247bool SPIRVPassConfig::addLegalizeMachineIR() {
248 addPass(new Legalizer());
250 return false;
251}
252
253// Do not add the RegBankSelect pass, as we only ever need virtual registers.
254bool SPIRVPassConfig::addRegBankSelect() {
255 disablePass(&RegBankSelect::ID);
256 return false;
257}
258
260 "spv-emit-nonsemantic-debug-info",
261 cl::desc("Emit SPIR-V NonSemantic.Shader.DebugInfo.100 instructions"),
262 cl::Optional, cl::init(false));
263
264void SPIRVPassConfig::addPreEmitPass() {
266 addPass(createSPIRVEmitNonSemanticDIPass(&getTM<SPIRVTargetMachine>()));
267 }
268}
269
270namespace {
271// A custom subclass of InstructionSelect, which is mostly the same except from
272// not requiring RegBankSelect to occur previously.
273class SPIRVInstructionSelect : public InstructionSelect {
274 // We don't use register banks, so unset the requirement for them
275 MachineFunctionProperties getRequiredProperties() const override {
276 return InstructionSelect::getRequiredProperties().resetRegBankSelected();
277 }
278};
279} // namespace
280
281// Add the custom SPIRVInstructionSelect from above.
282bool SPIRVPassConfig::addGlobalInstructionSelect() {
283 addPass(new SPIRVInstructionSelect());
284 return false;
285}
#define LLVM_ABI
Definition: Compiler.h:213
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:132
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
This file declares the IRTranslator pass.
static LVOptions Options
Definition: LVOptions.cpp:25
static std::string computeDataLayout()
#define F(x, y, z)
Definition: MD5.cpp:55
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
This file describes the interface of the MachineFunctionPass responsible for assigning the generic vi...
LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVTarget()
static Reloc::Model getEffectiveRelocModel(std::optional< Reloc::Model > RM)
static cl::opt< bool > SPVEnableNonSemanticDI("spv-emit-nonsemantic-debug-info", cl::desc("Emit SPIR-V NonSemantic.Shader.DebugInfo.100 instructions"), cl::Optional, cl::init(false))
Target-Independent Code Generator Pass Configuration Options pass.
implements a set of functionality in the TargetMachine class for targets that make use of the indepen...
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:314
This pass is responsible for selecting generic machine instructions to target-specific instructions.
MachineFunctionProperties getRequiredProperties() const override
Properties which a MachineFunction may have at a given point in time.
This class provides access to building LLVM's passes.
Definition: PassBuilder.h:110
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:38
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
void registerPassBuilderCallbacks(PassBuilder &PB) override
Allow the target to modify the pass pipeline.
SPIRVTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, std::optional< Reloc::Model > RM, std::optional< CodeModel::Model > CM, CodeGenOptLevel OL, bool JIT)
TargetTransformInfo getTargetTransformInfo(const Function &F) const override
Get a TargetTransformInfo implementation for the target.
TargetPassConfig * createPassConfig(PassManagerBase &PM) override
Create a pass configuration object to be used by addPassToEmitX methods for generating a pipeline of ...
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
void setFastISel(bool Enable)
void setRequiresStructuredCFG(bool Value)
void setGlobalISel(bool Enable)
void setO0WantsFastISel(bool Enable)
Target-Independent Code Generator Pass Configuration Options.
virtual void addPostRegAlloc()
This method may be implemented by targets that want to run passes after register allocation pass pipe...
virtual void addIRPasses()
Add common target configurable passes that perform LLVM IR to IR transforms following machine indepen...
virtual void addMachineSSAOptimization()
addMachineSSAOptimization - Add standard passes that optimize machine instructions in SSA form.
virtual void addISelPrepare()
Add common passes that perform LLVM IR to IR transforms in preparation for instruction selection.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:47
PassManagerBase - An abstract interface to allow code to add passes to a pass manager without having ...
Interfaces for registering analysis passes, producing common pass manager configurations,...
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:444
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void initializeSPIRVEmitIntrinsicsPass(PassRegistry &)
FunctionPass * createSPIRVStructurizerPass()
LLVM_ABI FunctionPass * createPromoteMemoryToRegisterPass()
Definition: Mem2Reg.cpp:114
MachineFunctionPass * createSPIRVEmitNonSemanticDIPass(SPIRVTargetMachine *TM)
Target & getTheSPIRV32Target()
ModulePass * createSPIRVEmitIntrinsicsPass(SPIRVTargetMachine *TM)
void initializeSPIRVPrepareFunctionsPass(PassRegistry &)
LLVM_ABI FunctionPass * createRegToMemWrapperPass()
Definition: Reg2Mem.cpp:148
FunctionPass * createSPIRVPreLegalizerPass()
LLVM_ABI char & PatchableFunctionID
This pass implements the "patchable-function" attribute.
LLVM_ABI char & PostRASchedulerID
PostRAScheduler - This pass performs post register allocation scheduling.
LLVM_ABI char & RemoveLoadsIntoFakeUsesID
RemoveLoadsIntoFakeUses pass.
void initializeSPIRVMergeRegionExitTargetsPass(PassRegistry &)
FunctionPass * createSPIRVStripConvergenceIntrinsicsPass()
void initializeSPIRVPreLegalizerCombinerPass(PassRegistry &)
LLVM_ABI char & LiveDebugValuesID
LiveDebugValues pass.
void initializeSPIRVLegalizePointerCastPass(PassRegistry &)
FunctionPass * createSPIRVPreLegalizerCombiner()
void initializeSPIRVModuleAnalysisPass(PassRegistry &)
static Reloc::Model getEffectiveRelocModel(std::optional< Reloc::Model > RM)
FunctionPass * createSPIRVPostLegalizerPass()
CodeModel::Model getEffectiveCodeModel(std::optional< CodeModel::Model > CM, CodeModel::Model Default)
Helper method for getting the code model, returning Default if CM does not have a value.
LLVM_ABI char & ShrinkWrapID
ShrinkWrap pass. Look for the best place to insert save and restore.
Definition: ShrinkWrap.cpp:292
LLVM_ABI char & MachineLateInstrsCleanupID
MachineLateInstrsCleanup - This pass removes redundant identical instructions after register allocati...
void initializeSPIRVRegularizerPass(PassRegistry &)
LLVM_ABI char & StackMapLivenessID
StackMapLiveness - This pass analyses the register live-out set of stackmap/patchpoint intrinsics and...
LLVM_ABI char & FuncletLayoutID
This pass lays out funclets contiguously.
LLVM_ABI char & PostRAMachineSinkingID
This pass perform post-ra machine sink for COPY instructions.
CodeGenOptLevel
Code generation optimization level.
Definition: CodeGen.h:82
Target & getTheSPIRV64Target()
void initializeSPIRVPostLegalizerPass(PassRegistry &)
LLVM_ABI void initializeGlobalISel(PassRegistry &)
Initialize all passes linked into the GlobalISel library.
Definition: GlobalISel.cpp:17
Target & getTheSPIRVLogicalTarget()
void initializeSPIRVAsmPrinterPass(PassRegistry &)
FunctionPass * createSPIRVRegularizerPass()
void initializeSPIRVStructurizerPass(PassRegistry &)
void initializeSPIRVEmitNonSemanticDIPass(PassRegistry &)
FunctionPass * createSPIRVMergeRegionExitTargetsPass()
LLVM_ABI FunctionPass * createInferAddressSpacesPass(unsigned AddressSpace=~0u)
void initializeSPIRVPreLegalizerPass(PassRegistry &)
void initializeSPIRVConvergenceRegionAnalysisWrapperPassPass(PassRegistry &)
LLVM_ABI char & MachineBlockPlacementID
MachineBlockPlacement - This pass places basic blocks based on branch probabilities.
LLVM_ABI char & BranchFolderPassID
BranchFolding - This pass performs machine code CFG based optimizations to delete branches to branche...
ModulePass * createSPIRVPrepareFunctionsPass(const SPIRVTargetMachine &TM)
FunctionPass * createSPIRVLegalizePointerCastPass(SPIRVTargetMachine *TM)
LLVM_ABI Pass * createLoopSimplifyPass()
LLVM_ABI char & MachineCopyPropagationID
MachineCopyPropagation - This pass performs copy propagation on machine instructions.
void initializeSPIRVStripConvergentIntrinsicsPass(PassRegistry &)
ModulePass * createSPIRVLegalizeImplicitBindingPass()
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:856
RegisterTargetMachine - Helper template for registering a target machine implementation,...