LLVM 24.0.0git
WebAssemblyCodeGenPassBuilder.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
9#include "WebAssembly.h"
31#include "llvm/MC/MCStreamer.h"
35#include "llvm/Support/Error.h"
39
40using namespace llvm;
41
42namespace WebAssembly {
46} // namespace WebAssembly
47
51
52namespace {
53
54class WebAssemblyCodeGenPassBuilder : public CodeGenPassBuilder {
56
58 return static_cast<WebAssemblyTargetMachine &>(TM);
59 }
60
61public:
62 explicit WebAssemblyCodeGenPassBuilder(WebAssemblyTargetMachine &TM,
63 const CGPassBuilderOption &Opts,
64 PassInstrumentationCallbacks *PIC)
65 : CodeGenPassBuilder(TM, Opts, PIC) {
66 disablePass<MachineLateInstrsCleanupPass, MachineCopyPropagationPass,
67 PostRAMachineSinkingPass, PostRASchedulerPass,
68 FuncletLayoutPass, StackMapLivenessPass, PatchableFunctionPass,
69 ShrinkWrapPass, RemoveLoadsIntoFakeUsesPass,
70 MachineBlockPlacementPass>();
71
72 // Currently RegisterCoalesce degrades wasm debug info quality by a
73 // significant margin. As a quick fix, disable this for -O1, which is often
74 // used for debugging large applications. Disabling this increases code size
75 // of Emscripten core benchmarks by ~5%, which is acceptable for -O1, which
76 // is usually not used for production builds.
77 // TODO Investigate why RegisterCoalesce degrades debug info quality and fix
78 // it properly
79 if (getOptLevel() == CodeGenOptLevel::Less)
80 disablePass<RegisterCoalescerPass>();
81 }
82
83 void addIRPasses(PassManagerWrapper &PMW) override;
84 void addISelPrepare(PassManagerWrapper &PMW) override;
85
86 Error addInstSelector(PassManagerWrapper &PMW) override;
87
88 Error addIRTranslator(PassManagerWrapper &PMW) override;
89 void addPreLegalizeMachineIR(PassManagerWrapper &PMW) override;
90 Error addLegalizeMachineIR(PassManagerWrapper &PMW) override;
91 void addPreRegBankSelect(PassManagerWrapper &PMW) override;
92 Error addRegBankSelect(PassManagerWrapper &PMW) override;
93 Error addGlobalInstructionSelect(PassManagerWrapper &PMW) override;
94
95 Error addRegAssignAndRewriteFast(PassManagerWrapper &PMW) override;
96 Expected<bool>
97 addRegAssignAndRewriteOptimized(PassManagerWrapper &PMW) override;
98 void addPreEmitPass(PassManagerWrapper &PMW) override;
99 void addAsmPrinterBegin(PassManagerWrapper &PMW) override;
100 void addAsmPrinter(PassManagerWrapper &PMW) override;
101 void addAsmPrinterEnd(PassManagerWrapper &PMW) override;
102};
103
104void WebAssemblyCodeGenPassBuilder::addIRPasses(PassManagerWrapper &PMW) {
105 // Add signatures to prototype-less function declarations
106 flushFPMsToMPM(PMW);
107 addModulePass(WebAssemblyAddMissingPrototypesPass(), PMW);
108
109 // Lower .llvm.global_dtors into .llvm.global_ctors with __cxa_atexit calls.
110 addModulePass(LowerGlobalDtorsPass(), PMW);
111
112 // Fix function bitcasts, as WebAssembly requires caller and callee signatures
113 // to match.
114 addModulePass(WebAssemblyFixFunctionBitcastsPass(), PMW);
115
116 // Optimize "returned" function attributes.
117 if (getOptLevel() != CodeGenOptLevel::None)
118 addFunctionPass(WebAssemblyOptimizeReturnedPass(), PMW);
119
120 // If exception handling is not enabled and setjmp/longjmp handling is
121 // enabled, we lower invokes into calls and delete unreachable landingpad
122 // blocks. Lowering invokes when there is no EH support is done in
123 // TargetPassConfig::addPassesToHandleExceptions, but that runs after these IR
124 // passes and Emscripten SjLj handling expects all invokes to be lowered
125 // before.
126 bool EnableEmEH = TM.Options.ExceptionModel == ExceptionHandling::Emscripten;
127 bool EnableWasmEH = TM.Options.ExceptionModel == ExceptionHandling::Wasm;
128 if (!EnableEmEH && !EnableWasmEH) {
129 addFunctionPass(LowerInvokePass(), PMW);
130 // The lower invoke pass may create unreachable code. Remove it in order not
131 // to process dead blocks in setjmp/longjmp handling.
132 addFunctionPass(UnreachableBlockElimPass(), PMW);
133 }
134
135 // Handle exceptions and setjmp/longjmp if enabled. Unlike Wasm EH preparation
136 // done in WasmEHPrepare pass, Wasm SjLj preparation shares libraries and
137 // transformation algorithms with Emscripten SjLj, so we run
138 // LowerEmscriptenEHSjLj pass also when Wasm SjLj is enabled.
139 if (EnableEmEH || WasmEnableEmSjLj || WasmEnableSjLj) {
140 flushFPMsToMPM(PMW);
141 addModulePass(WebAssemblyLowerEmscriptenEHSjLjPass(EnableEmEH), PMW);
142 }
143
144 // Expand indirectbr instructions to switches.
145 addFunctionPass(IndirectBrExpandPass(TM), PMW);
146
147 // Try to expand `vecreduce_{and, or}` into `{any, all}_true`.
148 addFunctionPass(WebAssemblyReduceToAnyAllTruePass(getTM()), PMW);
149
150 Base::addIRPasses(PMW);
151}
152
153void WebAssemblyCodeGenPassBuilder::addISelPrepare(PassManagerWrapper &PMW) {
154 // We need to move reference type allocas to WASM_ADDRESS_SPACE_VAR so that
155 // loads and stores are promoted to local.gets/local.sets.
156 addFunctionPass(WebAssemblyRefTypeMem2LocalPass(), PMW);
157 // Lower atomics and TLS if necessary
158 flushFPMsToMPM(PMW);
159 addModulePass(WebAssemblyCoalesceFeaturesAndStripAtomicsPass(getTM()), PMW);
160
161 // This is a no-op if atomics are not used in the module
162 addFunctionPass(AtomicExpandPass(TM), PMW);
163
164 Base::addISelPrepare(PMW);
165}
166
167Error WebAssemblyCodeGenPassBuilder::addInstSelector(PassManagerWrapper &PMW) {
168 addMachineFunctionPass(WebAssemblyISelDAGToDAGPass(getTM(), getOptLevel()),
169 PMW);
170
171 // Run the argument-move pass immediately after the ScheduleDAG scheduler
172 // so that we can fix up the ARGUMENT instructions before anything else
173 // sees them in the wrong place.
174 addMachineFunctionPass(WebAssemblyArgumentMovePass(), PMW);
175
176 // Set the p2align operands. This information is present during ISel, however
177 // it's inconvenient to collect. Collect it now, and update the immediate
178 // operands.
179 addMachineFunctionPass(WebAssemblySetP2AlignOperandsPass(), PMW);
180
181 // Eliminate range checks and add default targets to br_table instructions.
182 addMachineFunctionPass(WebAssemblyFixBrTableDefaultsPass(), PMW);
183
184 // unreachable is terminator, non-terminator instruction after it is not
185 // allowed.
186 addMachineFunctionPass(WebAssemblyCleanCodeAfterTrapPass(), PMW);
187
188 return Error::success();
189}
190
191Error WebAssemblyCodeGenPassBuilder::addIRTranslator(PassManagerWrapper &PMW) {
192 addMachineFunctionPass(IRTranslatorPass(getOptLevel()), PMW);
193 return Error::success();
194}
195
196void WebAssemblyCodeGenPassBuilder::addPreLegalizeMachineIR(
197 PassManagerWrapper &PMW) {
198 if (getOptLevel() != CodeGenOptLevel::None)
199 addMachineFunctionPass(WebAssemblyPreLegalizerCombinerPass(), PMW);
200}
201
202Error WebAssemblyCodeGenPassBuilder::addLegalizeMachineIR(
203 PassManagerWrapper &PMW) {
204 addMachineFunctionPass(LegalizerPass(), PMW);
205 return Error::success();
206}
207
208void WebAssemblyCodeGenPassBuilder::addPreRegBankSelect(
209 PassManagerWrapper &PMW) {
210 if (getOptLevel() != CodeGenOptLevel::None)
211 addMachineFunctionPass(WebAssemblyPostLegalizerCombinerPass(), PMW);
212}
213
214Error WebAssemblyCodeGenPassBuilder::addRegBankSelect(PassManagerWrapper &PMW) {
215 addMachineFunctionPass(RegBankSelectPass(), PMW);
216 return Error::success();
217}
218
219Error WebAssemblyCodeGenPassBuilder::addGlobalInstructionSelect(
220 PassManagerWrapper &PMW) {
221 addMachineFunctionPass(InstructionSelectPass(getOptLevel()), PMW);
222
223 if (isGlobalISelAbortEnabled()) {
224 addMachineFunctionPass(WebAssemblyArgumentMovePass(), PMW);
225 addMachineFunctionPass(WebAssemblySetP2AlignOperandsPass(), PMW);
226 addMachineFunctionPass(WebAssemblyFixBrTableDefaultsPass(), PMW);
227 addMachineFunctionPass(WebAssemblyCleanCodeAfterTrapPass(), PMW);
228 }
229
230 return Error::success();
231}
232
233Error WebAssemblyCodeGenPassBuilder::addRegAssignAndRewriteFast(
234 PassManagerWrapper &PMW) {
235 return Error::success();
236}
237
238Expected<bool> WebAssemblyCodeGenPassBuilder::addRegAssignAndRewriteOptimized(
239 PassManagerWrapper &PMW) {
240 return false;
241}
242
243void WebAssemblyCodeGenPassBuilder::addPreEmitPass(PassManagerWrapper &PMW) {
244 Base::addPreEmitPass(PMW);
245
246 // Nullify DBG_VALUE_LISTs that we cannot handle.
247 addMachineFunctionPass(WebAssemblyNullifyDebugValueListsPass(), PMW);
248
249 // Remove any unreachable blocks that may be left floating around.
250 // Rare, but possible. Needed for WebAssemblyFixIrreducibleControlFlow.
251 addMachineFunctionPass(UnreachableMachineBlockElimPass(), PMW);
252
253 // Eliminate multiple-entry loops.
254 addMachineFunctionPass(WebAssemblyFixIrreducibleControlFlowPass(), PMW);
255
256 // Do various transformations for exception handling.
257 // Every CFG-changing optimizations should come before this.
258 if (TM.Options.ExceptionModel == ExceptionHandling::Wasm)
259 addMachineFunctionPass(WebAssemblyLateEHPreparePass(), PMW);
260
261 // Now that we have a prologue and epilogue and all frame indices are
262 // rewritten, eliminate SP and FP. This allows them to be stackified,
263 // colored, and numbered with the rest of the registers.
264 addMachineFunctionPass(WebAssemblyReplacePhysRegsPass(), PMW);
265
266 // Preparations and optimizations related to register stackification.
267 if (getOptLevel() != CodeGenOptLevel::None) {
268 // Depend on LiveIntervals and perform some optimizations on it.
269 addMachineFunctionPass(WebAssemblyOptimizeLiveIntervalsPass(), PMW);
270
271 // Prepare memory intrinsic calls for register stackifying.
272 addMachineFunctionPass(WebAssemblyMemIntrinsicResultsPass(), PMW);
273 }
274
275 // Mark registers as representing wasm's value stack. This is a key
276 // code-compression technique in WebAssembly. We run this pass (and
277 // MemIntrinsicResults above) very late, so that it sees as much code as
278 // possible, including code emitted by PEI and expanded by late tail
279 // duplication.
280 addMachineFunctionPass(WebAssemblyRegStackifyPass(getOptLevel()), PMW);
281
282 if (getOptLevel() != CodeGenOptLevel::None) {
283 // Run the register coloring pass to reduce the total number of registers.
284 // This runs after stackification so that it doesn't consider registers
285 // that become stackified.
286 addMachineFunctionPass(WebAssemblyRegColoringPass(), PMW);
287 }
288
289 // Sort the blocks of the CFG into topological order, a prerequisite for
290 // BLOCK and LOOP markers.
291 addMachineFunctionPass(WebAssemblyCFGSortPass(), PMW);
292
293 // Insert BLOCK and LOOP markers.
294 addMachineFunctionPass(WebAssemblyCFGStackifyPass(), PMW);
295
296 // Insert explicit local.get and local.set operators.
298 addMachineFunctionPass(WebAssemblyExplicitLocalsPass(), PMW);
299
300 // Lower br_unless into br_if.
301 addMachineFunctionPass(WebAssemblyLowerBrUnlessPass(), PMW);
302
303 // Perform the very last peephole optimizations on the code.
304 if (getOptLevel() != CodeGenOptLevel::None)
305 addMachineFunctionPass(WebAssemblyPeepholePass(), PMW);
306
307 // Create a mapping from LLVM CodeGen virtual registers to wasm registers.
308 addMachineFunctionPass(WebAssemblyRegNumberingPass(), PMW);
309
310 // Fix debug_values whose defs have been stackified.
312 addMachineFunctionPass(WebAssemblyDebugFixupPass(), PMW);
313
314 // Collect information to prepare for MC lowering / asm printing.
315 flushFPMsToMPM(PMW);
316 addModulePass(WebAssemblyMCLowerPrePass(), PMW);
317}
318
319void WebAssemblyCodeGenPassBuilder::addAsmPrinterBegin(
320 PassManagerWrapper &PMW) {
321 addModulePass(WebAssemblyAsmPrinterBeginPass(), PMW, /*Force=*/true);
322}
323
324void WebAssemblyCodeGenPassBuilder::addAsmPrinter(PassManagerWrapper &PMW) {
325 addMachineFunctionPass(WebAssemblyAsmPrinterPass(), PMW);
326}
327
328void WebAssemblyCodeGenPassBuilder::addAsmPrinterEnd(PassManagerWrapper &PMW) {
329 addModulePass(WebAssemblyAsmPrinterEndPass(), PMW);
330}
331
332} // namespace
333
335#define GET_PASS_REGISTRY "WebAssemblyPassRegistry.def"
337}
338
341 raw_pwrite_stream *DwoOut, CodeGenFileType FileType,
342 const CGPassBuilderOption &Opt, MCContext &Ctx,
344 auto CGPB = WebAssemblyCodeGenPassBuilder(*this, Opt, PIC);
345 return CGPB.buildPipeline(MPM, MAM, Out, DwoOut, FileType, Ctx);
346}
Interfaces for producing common pass manager configurations.
This file declares the IRTranslator pass.
ModuleAnalysisManager MAM
PassInstrumentationCallbacks PIC
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
This file defines the Pass Instrumentation classes that provide instrumentation points into the pass ...
This file describes the interface of the MachineFunctionPass responsible for assigning the generic vi...
const GCNTargetMachine & getTM(const GCNSubtarget *STI)
cl::opt< bool > WasmEnableSjLj
cl::opt< bool > WasmEnableEmSjLj
cl::opt< bool > WasmDisableExplicitLocals
This file implements WebAssemblyException information analysis.
This file declares the WebAssembly-specific subclass of TargetMachine.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.
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 ...
TargetOptions Options
ExceptionHandling ExceptionModel
What exception model to use.
void registerPassBuilderCallbacks(PassBuilder &PbB) override
Allow the target to modify the pass pipeline.
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,...
cl::opt< bool > WasmEnableSjLj
cl::opt< bool > WasmEnableEmSjLj
cl::opt< bool > WasmDisableExplicitLocals
cl::opt< bool > WasmEnableSjLj
cl::opt< bool > WasmEnableEmSjLj
cl::opt< bool > WasmDisableExplicitLocals
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:256
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