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"
25#include "llvm/CodeGen/Passes.h"
30#include "llvm/Pass.h"
33#include <optional>
34
35using namespace llvm;
36
38 // Register the target.
42
47}
48
49static std::string computeDataLayout(const Triple &TT) {
50 const auto Arch = TT.getArch();
51 // TODO: this probably needs to be revisited:
52 // Logical SPIR-V has no pointer size, so any fixed pointer size would be
53 // wrong. The choice to default to 32 or 64 is just motivated by another
54 // memory model used for graphics: PhysicalStorageBuffer64. But it shouldn't
55 // mean anything.
56 if (Arch == Triple::spirv32)
57 return "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-"
58 "v96:128-v192:256-v256:256-v512:512-v1024:1024-G1";
59 if (TT.getVendor() == Triple::VendorType::AMD &&
60 TT.getOS() == Triple::OSType::AMDHSA)
61 return "e-i64:64-v16:16-v24:32-v32:32-v48:64-"
62 "v96:128-v192:256-v256:256-v512:512-v1024:1024-G1-P4-A0";
63 return "e-i64:64-v16:16-v24:32-v32:32-v48:64-"
64 "v96:128-v192:256-v256:256-v512:512-v1024:1024-G1";
65}
66
67static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {
68 if (!RM)
69 return Reloc::PIC_;
70 return *RM;
71}
72
73// Pin SPIRVTargetObjectFile's vtables to this file.
75
77 StringRef CPU, StringRef FS,
79 std::optional<Reloc::Model> RM,
80 std::optional<CodeModel::Model> CM,
81 CodeGenOptLevel OL, bool JIT)
82 : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
84 getEffectiveCodeModel(CM, CodeModel::Small), OL),
85 TLOF(std::make_unique<SPIRVTargetObjectFile>()),
86 Subtarget(TT, CPU.str(), FS.str(), *this) {
88 setGlobalISel(true);
89 setFastISel(false);
90 setO0WantsFastISel(false);
92}
93
94namespace {
95// SPIR-V Code Generator Pass Configuration Options.
96class SPIRVPassConfig : public TargetPassConfig {
97public:
98 SPIRVPassConfig(SPIRVTargetMachine &TM, PassManagerBase &PM)
99 : TargetPassConfig(TM, PM), TM(TM) {}
100
101 SPIRVTargetMachine &getSPIRVTargetMachine() const {
102 return getTM<SPIRVTargetMachine>();
103 }
104 void addIRPasses() override;
105 void addISelPrepare() override;
106
107 bool addIRTranslator() override;
108 void addPreLegalizeMachineIR() override;
109 bool addLegalizeMachineIR() override;
110 bool addRegBankSelect() override;
111 bool addGlobalInstructionSelect() override;
112
113 FunctionPass *createTargetRegisterAllocator(bool) override;
114 void addFastRegAlloc() override {}
115 void addOptimizedRegAlloc() override {}
116
117 void addPostRegAlloc() override;
118
119private:
120 const SPIRVTargetMachine &TM;
121};
122} // namespace
123
124// We do not use physical registers, and maintain virtual registers throughout
125// the entire pipeline, so return nullptr to disable register allocation.
126FunctionPass *SPIRVPassConfig::createTargetRegisterAllocator(bool) {
127 return nullptr;
128}
129
130// Disable passes that break from assuming no virtual registers exist.
131void SPIRVPassConfig::addPostRegAlloc() {
132 // Do not work with vregs instead of physical regs.
133 disablePass(&MachineCopyPropagationID);
134 disablePass(&PostRAMachineSinkingID);
135 disablePass(&PostRASchedulerID);
136 disablePass(&FuncletLayoutID);
137 disablePass(&StackMapLivenessID);
138 disablePass(&PatchableFunctionID);
139 disablePass(&ShrinkWrapID);
140 disablePass(&LiveDebugValuesID);
141 disablePass(&MachineLateInstrsCleanupID);
142
143 // Do not work with OpPhi.
144 disablePass(&BranchFolderPassID);
145 disablePass(&MachineBlockPlacementID);
146
148}
149
152 return TargetTransformInfo(SPIRVTTIImpl(this, F));
153}
154
156 return new SPIRVPassConfig(*this, PM);
157}
158
159void SPIRVPassConfig::addIRPasses() {
160 if (TM.getSubtargetImpl()->isVulkanEnv()) {
161 // Once legalized, we need to structurize the CFG to follow the spec.
162 // This is done through the following 8 steps.
163 // TODO(#75801): add the remaining steps.
164
165 // 1. Simplify loop for subsequent transformations. After this steps, loops
166 // have the following properties:
167 // - loops have a single entry edge (pre-header to loop header).
168 // - all loop exits are dominated by the loop pre-header.
169 // - loops have a single back-edge.
170 addPass(createLoopSimplifyPass());
171
172 // 2. Merge the convergence region exit nodes into one. After this step,
173 // regions are single-entry, single-exit. This will help determine the
174 // correct merge block.
176 }
177
182}
183
184void SPIRVPassConfig::addISelPrepare() {
185 addPass(createSPIRVEmitIntrinsicsPass(&getTM<SPIRVTargetMachine>()));
187}
188
189bool SPIRVPassConfig::addIRTranslator() {
190 addPass(new IRTranslator(getOptLevel()));
191 return false;
192}
193
194void SPIRVPassConfig::addPreLegalizeMachineIR() {
196}
197
198// Use the default legalizer.
199bool SPIRVPassConfig::addLegalizeMachineIR() {
200 addPass(new Legalizer());
202 return false;
203}
204
205// Do not add the RegBankSelect pass, as we only ever need virtual registers.
206bool SPIRVPassConfig::addRegBankSelect() {
207 disablePass(&RegBankSelect::ID);
208 return false;
209}
210
211namespace {
212// A custom subclass of InstructionSelect, which is mostly the same except from
213// not requiring RegBankSelect to occur previously.
214class SPIRVInstructionSelect : public InstructionSelect {
215 // We don't use register banks, so unset the requirement for them
216 MachineFunctionProperties getRequiredProperties() const override {
218 MachineFunctionProperties::Property::RegBankSelected);
219 }
220};
221} // namespace
222
223// Add the custom SPIRVInstructionSelect from above.
224bool SPIRVPassConfig::addGlobalInstructionSelect() {
225 addPass(new SPIRVInstructionSelect());
226 return false;
227}
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:131
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")
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()
Target-Independent Code Generator Pass Configuration Options pass.
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
This class describes a target machine that is implemented with the LLVM target-independent code gener...
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & reset(Property P)
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...
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:50
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 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 ...
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Target & getTheSPIRV32Target()
ModulePass * createSPIRVEmitIntrinsicsPass(SPIRVTargetMachine *TM)
FunctionPass * createSPIRVPreLegalizerPass()
char & PatchableFunctionID
This pass implements the "patchable-function" attribute.
char & PostRASchedulerID
PostRAScheduler - This pass performs post register allocation scheduling.
FunctionPass * createSPIRVStripConvergenceIntrinsicsPass()
char & LiveDebugValuesID
LiveDebugValues pass.
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:288
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()
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,...