LLVM 24.0.0git
SPIRVCodeGenPassBuilder.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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
10#include "SPIRV.h"
11#include "SPIRVAsmPrinter.h"
12#include "SPIRVModuleAnalysis.h"
13#include "SPIRVTargetMachine.h"
39
40using namespace llvm;
41
42namespace {
43
44class SPIRVCodeGenPassBuilder : public CodeGenPassBuilder {
45 using Base = CodeGenPassBuilder;
46
47 SPIRVTargetMachine &getTM() const {
48 return static_cast<SPIRVTargetMachine &>(TM);
49 }
50
51public:
52 explicit SPIRVCodeGenPassBuilder(SPIRVTargetMachine &TM,
53 const CGPassBuilderOption &Opts,
54 PassInstrumentationCallbacks *PIC)
55 : CodeGenPassBuilder(TM, Opts, PIC) {
56 // Disable passes that break from assuming no virtual registers exist.
57 disablePass<MachineCopyPropagationPass, PostRAMachineSinkingPass,
58 PostRASchedulerPass, FuncletLayoutPass, StackMapLivenessPass,
59 PatchableFunctionPass, ShrinkWrapPass, LiveDebugValuesPass,
60 MachineLateInstrsCleanupPass, RemoveLoadsIntoFakeUsesPass,
61 BranchFolderPass, MachineBlockPlacementPass>();
62 }
63
64 void addIRPasses(PassManagerWrapper &PMW) override;
65 void addISelPrepare(PassManagerWrapper &PMW) override;
66 Error addIRTranslator(PassManagerWrapper &PMW) override;
67 void addPreLegalizeMachineIR(PassManagerWrapper &PMW) override;
68 Error addLegalizeMachineIR(PassManagerWrapper &PMW) override;
69 Error addRegBankSelect(PassManagerWrapper &PMW) override;
70 Error addGlobalInstructionSelect(PassManagerWrapper &PMW) override;
71
72 Error addFastRegAlloc(PassManagerWrapper &PMW) override;
73
74 Error addOptimizedRegAlloc(PassManagerWrapper &PMW) override;
75
76 void addPreEmitPass2(PassManagerWrapper &PMW) override;
77
78 void addAsmPrinterBegin(PassManagerWrapper &PMW) override;
79 void addAsmPrinter(PassManagerWrapper &PMW) override;
80 void addAsmPrinterEnd(PassManagerWrapper &PMW) override;
81};
82
83void SPIRVCodeGenPassBuilder::addIRPasses(PassManagerWrapper &PMW) {
84 addFunctionPass(AtomicExpandPass(TM), PMW);
85
86 Base::addIRPasses(PMW);
87
88 flushFPMsToMPM(PMW);
89
90 if (getTM().getSubtargetImpl()->isShader()) {
91 if (getOptLevel() != CodeGenOptLevel::None) {
92 addModulePass(SPIRVFinalizeShaderLinkagePass(getTM()), PMW);
93 }
94 addModulePass(SPIRVRemoveUnusedResourcesPass(), PMW);
95 } else {
96 // Variadic function calls aren't supported in shader code.
97 // This needs to come before SPIRVPrepareFunctions because this
98 // may introduce intrinsic calls.
99 addModulePass(ExpandVariadicsPass(ExpandVariadicsMode::Lowering), PMW);
100 }
101
102 addFunctionPass(SPIRVRegularizerPass(), PMW);
103 flushFPMsToMPM(PMW);
104 addModulePass(SPIRVCtorDtorLoweringPass(), PMW);
105 addModulePass(SPIRVPrepareFunctionsPass(getTM()), PMW);
106 addModulePass(SPIRVPrepareGlobalsPass(), PMW);
107}
108
109void SPIRVCodeGenPassBuilder::addISelPrepare(PassManagerWrapper &PMW) {
110 SPIRVTargetMachine &TM = getTM();
111 if (getTM().getSubtargetImpl()->isShader()) {
112 // Vulkan does not allow address space casts. This pass is run to remove
113 // address space casts that can be removed.
114 // If an address space cast is not removed while targeting Vulkan, lowering
115 // will fail during MIR lowering.
116 addFunctionPass(InferAddressSpacesPass(), PMW);
117
118 // 1. Simplify loop for subsequent transformations. After this steps, loops
119 // have the following properties:
120 // - loops have a single entry edge (pre-header to loop header).
121 // - all loop exits are dominated by the loop pre-header.
122 // - loops have a single back-edge.
123 addFunctionPass(LoopSimplifyPass(), PMW);
124
125 // 2. Removes registers whose lifetime spans across basic blocks. Also
126 // removes phi nodes. This will greatly simplify the next steps.
127 addFunctionPass(RegToMemPass(), PMW);
128
129 // 3. Merge the convergence region exit nodes into one. After this step,
130 // regions are single-entry, single-exit. This will help determine the
131 // correct merge block.
132 addFunctionPass(SPIRVMergeRegionExitTargetsPass(), PMW);
133
134 // 4. Structurize.
135 addFunctionPass(SPIRVStructurizerPass(), PMW);
136
137 // 5. Reduce the amount of variables required by pushing some operations
138 // back to virtual registers.
139 addFunctionPass(PromotePass(), PMW);
140 } else {
141 // Canonicalize loops so they have a single latch and preheader.
142 // This enables OpLoopMerge emission for non-shader targets.
143 addFunctionPass(LoopSimplifyPass(), PMW);
144 }
145 addFunctionPass(StripConvergenceIntrinsicsPass(), PMW);
146 flushFPMsToMPM(PMW);
147 addModulePass(SPIRVLegalizeResourceBindingPass(), PMW);
148 addModulePass(SPIRVLegalizeZeroSizeArraysPass(getTM()), PMW);
149 addModulePass(SPIRVCBufferAccessPass(), PMW);
150 addModulePass(SPIRVPushConstantAccessPass(getTM()), PMW);
151 addModulePass(SPIRVEmitIntrinsicsPass(getTM()), PMW);
153 addFunctionPass(SPIRVLegalizePointerCastPass(getTM()), PMW);
154 Base::addISelPrepare(PMW);
155}
156
157Error SPIRVCodeGenPassBuilder::addIRTranslator(PassManagerWrapper &PMW) {
158 addMachineFunctionPass(IRTranslatorPass(getOptLevel()), PMW);
159 return Error::success();
160}
161
162void SPIRVCodeGenPassBuilder::addPreLegalizeMachineIR(PassManagerWrapper &PMW) {
163 addMachineFunctionPass(SPIRVPreLegalizerCombinerPass(), PMW);
164 addMachineFunctionPass(SPIRVPreLegalizerPass(), PMW);
165}
166
167Error SPIRVCodeGenPassBuilder::addLegalizeMachineIR(PassManagerWrapper &PMW) {
168 addMachineFunctionPass(LegalizerPass(), PMW);
169 addMachineFunctionPass(SPIRVPostLegalizerPass(), PMW);
170 return Error::success();
171}
172
173Error SPIRVCodeGenPassBuilder::addRegBankSelect(PassManagerWrapper &PMW) {
174 // We do not add RegBankSelectPass as we only ever need virtual registers.
175 return Error::success();
176}
177
178Error SPIRVCodeGenPassBuilder::addGlobalInstructionSelect(
179 PassManagerWrapper &PMW) {
180 addMachineFunctionPass(
181 InstructionSelectPass(getOptLevel(), /*RequireRegBankSelection=*/false),
182 PMW);
183 return Error::success();
184}
185
186// We do nothing in register allocation as we keep virtual registers.
187Error SPIRVCodeGenPassBuilder::addFastRegAlloc(PassManagerWrapper &PMW) {
188 return Error::success();
189}
190
191Error SPIRVCodeGenPassBuilder::addOptimizedRegAlloc(PassManagerWrapper &PMW) {
192 return Error::success();
193}
194
195void SPIRVCodeGenPassBuilder::addPreEmitPass2(PassManagerWrapper &PMW) {
196 addMachineFunctionPass(SPIRVPrepareModuleAnalysisPass(), PMW);
197}
198
199void SPIRVCodeGenPassBuilder::addAsmPrinterBegin(PassManagerWrapper &PMW) {
200 addModulePass(SPIRVAsmPrinterBeginPass(), PMW, /*Force=*/true);
201}
202
203void SPIRVCodeGenPassBuilder::addAsmPrinter(PassManagerWrapper &PMW) {
204 // SPIRVModuleAnalysis needs every MachineFunction before printing starts.
205 if (CompletesPipeline) {
206 flushFPMsToMPM(PMW);
207 addModulePass(RequireAnalysisPass<SPIRVModuleAnalysis, Module>(), PMW,
208 /*Force=*/true);
209 }
210 addMachineFunctionPass(SPIRVAsmPrinterPass(), PMW);
211}
212
213void SPIRVCodeGenPassBuilder::addAsmPrinterEnd(PassManagerWrapper &PMW) {
214 addModulePass(SPIRVAsmPrinterEndPass(), PMW, /*Force=*/true);
215}
216
217} // namespace
218
220#define GET_PASS_REGISTRY "SPIRVPassRegistry.def"
222}
223
226 raw_pwrite_stream *DwoOut, CodeGenFileType FileType,
227 const CGPassBuilderOption &Opt, MCContext &Ctx,
229 auto CGPB = SPIRVCodeGenPassBuilder(*this, Opt, PIC);
230 return CGPB.buildPipeline(MPM, MAM, Out, DwoOut, FileType, Ctx);
231}
Interfaces for producing common pass manager configurations.
This file declares the IRTranslator pass.
ModuleAnalysisManager MAM
PassBuilder PB(Mod->getContext(), Machine, PassOpts->PTO, std::nullopt, &PIC)
PassInstrumentationCallbacks PIC
This file defines the Pass Instrumentation classes that provide instrumentation points into the pass ...
const GCNTargetMachine & getTM(const GCNSubtarget *STI)
This pass strips convergence intrinsics and operand bundles as those are only useful when modifying t...
This class provides access to building LLVM's passes.
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Context object for machine code objects.
Definition MCContext.h:83
This class provides access to building LLVM's passes.
This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...
bool isLogicalSPIRV() const
void registerPassBuilderCallbacks(PassBuilder &PB) override
Allow the target to modify the pass pipeline.
const SPIRVSubtarget * getSubtargetImpl() const
Error buildCodeGenPipeline(ModulePassManager &MPM, ModuleAnalysisManager &MAM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, CodeGenFileType FileType, const CGPassBuilderOption &Opt, MCContext &Ctx, PassInstrumentationCallbacks *PIC) override
An abstract base class for streams implementations that also support a pwrite operation.
Interfaces for registering analysis passes, producing common pass manager configurations,...
LLVM_READNONE constexpr bool isShader(CallingConv::ID CC)
This is an optimization pass for GlobalISel generic memory operations.
CodeGenFileType
These enums are meant to be passed into addPassesToEmitFile to indicate what type of file to emit,...
Definition CodeGen.h:309
PassManager< Module > ModulePassManager
Convenience typedef for a pass manager over modules.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39