LLVM 20.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 "SPIRVCallLowering.h"
16#include "SPIRVGlobalRegistry.h"
17#include "SPIRVLegalizerInfo.h"
26#include "llvm/CodeGen/Passes.h"
31#include "llvm/Pass.h"
36#include <optional>
37
38using namespace llvm;
39
41 // Register the target.
45
52}
53
54static std::string computeDataLayout(const Triple &TT) {
55 const auto Arch = TT.getArch();
56 // TODO: this probably needs to be revisited:
57 // Logical SPIR-V has no pointer size, so any fixed pointer size would be
58 // wrong. The choice to default to 32 or 64 is just motivated by another
59 // memory model used for graphics: PhysicalStorageBuffer64. But it shouldn't
60 // mean anything.
61 if (Arch == Triple::spirv32)
62 return "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-"
63 "v256:256-v512:512-v1024:1024-n8:16:32:64-G1";
64 if (TT.getVendor() == Triple::VendorType::AMD &&
65 TT.getOS() == Triple::OSType::AMDHSA)
66 return "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-"
67 "v512:512-v1024:1024-n32:64-S32-G1-P4-A0";
68 return "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-"
69 "v512:512-v1024:1024-n8:16:32:64-G1";
70}
71
72static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {
73 if (!RM)
74 return Reloc::PIC_;
75 return *RM;
76}
77
78// Pin SPIRVTargetObjectFile's vtables to this file.
80
82 StringRef CPU, StringRef FS,
84 std::optional<Reloc::Model> RM,
85 std::optional<CodeModel::Model> CM,
86 CodeGenOptLevel OL, bool JIT)
89 getEffectiveCodeModel(CM, CodeModel::Small), OL),
90 TLOF(std::make_unique<SPIRVTargetObjectFile>()),
91 Subtarget(TT, CPU.str(), FS.str(), *this) {
93 setGlobalISel(true);
94 setFastISel(false);
95 setO0WantsFastISel(false);
97}
98
100#define GET_PASS_REGISTRY "SPIRVPassRegistry.def"
102}
103
104namespace {
105// SPIR-V Code Generator Pass Configuration Options.
106class SPIRVPassConfig : public TargetPassConfig {
107public:
108 SPIRVPassConfig(SPIRVTargetMachine &TM, PassManagerBase &PM)
109 : TargetPassConfig(TM, PM), TM(TM) {}
110
111 SPIRVTargetMachine &getSPIRVTargetMachine() const {
112 return getTM<SPIRVTargetMachine>();
113 }
114 void addMachineSSAOptimization() override;
115 void addIRPasses() override;
116 void addISelPrepare() override;
117
118 bool addIRTranslator() override;
119 void addPreLegalizeMachineIR() override;
120 bool addLegalizeMachineIR() override;
121 bool addRegBankSelect() override;
122 bool addGlobalInstructionSelect() override;
123
124 FunctionPass *createTargetRegisterAllocator(bool) override;
125 void addFastRegAlloc() override {}
126 void addOptimizedRegAlloc() override {}
127
128 void addPostRegAlloc() override;
129 void addPreEmitPass() override;
130
131private:
132 const SPIRVTargetMachine &TM;
133};
134} // namespace
135
136// We do not use physical registers, and maintain virtual registers throughout
137// the entire pipeline, so return nullptr to disable register allocation.
138FunctionPass *SPIRVPassConfig::createTargetRegisterAllocator(bool) {
139 return nullptr;
140}
141
142// A place to disable passes that may break CFG.
143void SPIRVPassConfig::addMachineSSAOptimization() {
145}
146
147// Disable passes that break from assuming no virtual registers exist.
148void SPIRVPassConfig::addPostRegAlloc() {
149 // Do not work with vregs instead of physical regs.
150 disablePass(&MachineCopyPropagationID);
151 disablePass(&PostRAMachineSinkingID);
152 disablePass(&PostRASchedulerID);
153 disablePass(&FuncletLayoutID);
154 disablePass(&StackMapLivenessID);
155 disablePass(&PatchableFunctionID);
156 disablePass(&ShrinkWrapID);
157 disablePass(&LiveDebugValuesID);
158 disablePass(&MachineLateInstrsCleanupID);
159 disablePass(&RemoveLoadsIntoFakeUsesID);
160
161 // Do not work with OpPhi.
162 disablePass(&BranchFolderPassID);
163 disablePass(&MachineBlockPlacementID);
164
166}
167
170 return TargetTransformInfo(SPIRVTTIImpl(this, F));
171}
172
174 return new SPIRVPassConfig(*this, PM);
175}
176
177void SPIRVPassConfig::addIRPasses() {
179
180 if (TM.getSubtargetImpl()->isVulkanEnv()) {
181 // 1. Simplify loop for subsequent transformations. After this steps, loops
182 // have the following properties:
183 // - loops have a single entry edge (pre-header to loop header).
184 // - all loop exits are dominated by the loop pre-header.
185 // - loops have a single back-edge.
186 addPass(createLoopSimplifyPass());
187
188 // 2. Removes registers whose lifetime spans across basic blocks. Also
189 // removes phi nodes. This will greatly simplify the next steps.
190 addPass(createRegToMemWrapperPass());
191
192 // 3. Merge the convergence region exit nodes into one. After this step,
193 // regions are single-entry, single-exit. This will help determine the
194 // correct merge block.
196
197 // 4. Structurize.
199
200 // 5. Reduce the amount of variables required by pushing some operations
201 // back to virtual registers.
203 }
204
208}
209
210void SPIRVPassConfig::addISelPrepare() {
211 addPass(createSPIRVEmitIntrinsicsPass(&getTM<SPIRVTargetMachine>()));
213}
214
215bool SPIRVPassConfig::addIRTranslator() {
216 addPass(new IRTranslator(getOptLevel()));
217 return false;
218}
219
220void SPIRVPassConfig::addPreLegalizeMachineIR() {
223}
224
225// Use the default legalizer.
226bool SPIRVPassConfig::addLegalizeMachineIR() {
227 addPass(new Legalizer());
229 return false;
230}
231
232// Do not add the RegBankSelect pass, as we only ever need virtual registers.
233bool SPIRVPassConfig::addRegBankSelect() {
234 disablePass(&RegBankSelect::ID);
235 return false;
236}
237
239 "spv-emit-nonsemantic-debug-info",
240 cl::desc("Emit SPIR-V NonSemantic.Shader.DebugInfo.100 instructions"),
241 cl::Optional, cl::init(false));
242
243void SPIRVPassConfig::addPreEmitPass() {
245 addPass(createSPIRVEmitNonSemanticDIPass(&getTM<SPIRVTargetMachine>()));
246 }
247}
248
249namespace {
250// A custom subclass of InstructionSelect, which is mostly the same except from
251// not requiring RegBankSelect to occur previously.
252class SPIRVInstructionSelect : public InstructionSelect {
253 // We don't use register banks, so unset the requirement for them
254 MachineFunctionProperties getRequiredProperties() const override {
256 MachineFunctionProperties::Property::RegBankSelected);
257 }
258};
259} // namespace
260
261// Add the custom SPIRVInstructionSelect from above.
262bool SPIRVPassConfig::addGlobalInstructionSelect() {
263 addPass(new SPIRVInstructionSelect());
264 return false;
265}
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:128
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...
static Reloc::Model getEffectiveRelocModel(std::optional< Reloc::Model > RM)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVTarget()
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:310
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.
MachineFunctionProperties & reset(Property P)
This class provides access to building LLVM's passes.
Definition: PassBuilder.h:105
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:37
static 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:51
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:44
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:443
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
FunctionPass * createSPIRVStructurizerPass()
FunctionPass * createPromoteMemoryToRegisterPass()
Definition: Mem2Reg.cpp:114
MachineFunctionPass * createSPIRVEmitNonSemanticDIPass(SPIRVTargetMachine *TM)
Target & getTheSPIRV32Target()
ModulePass * createSPIRVEmitIntrinsicsPass(SPIRVTargetMachine *TM)
FunctionPass * createRegToMemWrapperPass()
Definition: Reg2Mem.cpp:148
FunctionPass * createSPIRVPreLegalizerPass()
char & PatchableFunctionID
This pass implements the "patchable-function" attribute.
char & PostRASchedulerID
PostRAScheduler - This pass performs post register allocation scheduling.
char & RemoveLoadsIntoFakeUsesID
RemoveLoadsIntoFakeUses pass.
FunctionPass * createSPIRVStripConvergenceIntrinsicsPass()
void initializeSPIRVPreLegalizerCombinerPass(PassRegistry &)
char & LiveDebugValuesID
LiveDebugValues pass.
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.
char & ShrinkWrapID
ShrinkWrap pass. Look for the best place to insert save and restore.
Definition: ShrinkWrap.cpp:287
char & MachineLateInstrsCleanupID
MachineLateInstrsCleanup - This pass removes redundant identical instructions after register allocati...
char & StackMapLivenessID
StackMapLiveness - This pass analyses the register live-out set of stackmap/patchpoint intrinsics and...
char & FuncletLayoutID
This pass lays out funclets contiguously.
char & PostRAMachineSinkingID
This pass perform post-ra machine sink for COPY instructions.
CodeGenOptLevel
Code generation optimization level.
Definition: CodeGen.h:54
Target & getTheSPIRV64Target()
void initializeGlobalISel(PassRegistry &)
Initialize all passes linked into the GlobalISel library.
Definition: GlobalISel.cpp:17
Target & getTheSPIRVLogicalTarget()
FunctionPass * createSPIRVRegularizerPass()
void initializeSPIRVStructurizerPass(PassRegistry &)
FunctionPass * createSPIRVMergeRegionExitTargetsPass()
void initializeSPIRVConvergenceRegionAnalysisWrapperPassPass(PassRegistry &)
char & MachineBlockPlacementID
MachineBlockPlacement - This pass places basic blocks based on branch probabilities.
char & BranchFolderPassID
BranchFolding - This pass performs machine code CFG based optimizations to delete branches to branche...
ModulePass * createSPIRVPrepareFunctionsPass(const SPIRVTargetMachine &TM)
Pass * createLoopSimplifyPass()
char & MachineCopyPropagationID
MachineCopyPropagation - This pass performs copy propagation on machine instructions.
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
RegisterTargetMachine - Helper template for registering a target machine implementation,...