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"
26#include "llvm/MC/MCStreamer.h"
33
34using namespace llvm;
35
43
49
50namespace {
51
52class WebAssemblyCodeGenPassBuilder
53 : public CodeGenPassBuilder<WebAssemblyCodeGenPassBuilder,
54 WebAssemblyTargetMachine> {
55 using Base = CodeGenPassBuilder<WebAssemblyCodeGenPassBuilder,
57
58public:
59 explicit WebAssemblyCodeGenPassBuilder(WebAssemblyTargetMachine &TM,
60 const CGPassBuilderOption &Opts,
62 : CodeGenPassBuilder(TM, Opts, PIC) {
65 FuncletLayoutPass, StackMapLivenessPass, PatchableFunctionPass,
68
69 // Currently RegisterCoalesce degrades wasm debug info quality by a
70 // significant margin. As a quick fix, disable this for -O1, which is often
71 // used for debugging large applications. Disabling this increases code size
72 // of Emscripten core benchmarks by ~5%, which is acceptable for -O1, which
73 // is usually not used for production builds.
74 // TODO Investigate why RegisterCoalesce degrades debug info quality and fix
75 // it properly
76 if (getOptLevel() == CodeGenOptLevel::Less)
77 disablePass<RegisterCoalescerPass>();
78 }
79
80 void addIRPasses(PassManagerWrapper &PMW) const;
81 void addISelPrepare(PassManagerWrapper &PMW) const;
82 Error addInstSelector(PassManagerWrapper &PMW) const;
83 void addPreEmitPass(PassManagerWrapper &PMW) const;
84 void addAsmPrinterBegin(PassManagerWrapper &PMW) const;
85 void addAsmPrinter(PassManagerWrapper &PMW) const;
86 void addAsmPrinterEnd(PassManagerWrapper &PMW) const;
87};
88
89void WebAssemblyCodeGenPassBuilder::addIRPasses(PassManagerWrapper &PMW) const {
90 // Add signatures to prototype-less function declarations
91 flushFPMsToMPM(PMW);
92 addModulePass(WebAssemblyAddMissingPrototypesPass(), PMW);
93
94 // Lower .llvm.global_dtors into .llvm.global_ctors with __cxa_atexit calls.
95 addModulePass(LowerGlobalDtorsPass(), PMW);
96
97 // Fix function bitcasts, as WebAssembly requires caller and callee signatures
98 // to match.
99 addModulePass(WebAssemblyFixFunctionBitcastsPass(), PMW);
100
101 // Optimize "returned" function attributes.
102 if (getOptLevel() != CodeGenOptLevel::None)
103 addFunctionPass(WebAssemblyOptimizeReturnedPass(), PMW);
104
105 // If exception handling is not enabled and setjmp/longjmp handling is
106 // enabled, we lower invokes into calls and delete unreachable landingpad
107 // blocks. Lowering invokes when there is no EH support is done in
108 // TargetPassConfig::addPassesToHandleExceptions, but that runs after these IR
109 // passes and Emscripten SjLj handling expects all invokes to be lowered
110 // before.
111 if (!WasmEnableEmEH && !WasmEnableEH) {
112 addFunctionPass(LowerInvokePass(), PMW);
113 // The lower invoke pass may create unreachable code. Remove it in order not
114 // to process dead blocks in setjmp/longjmp handling.
115 addFunctionPass(UnreachableBlockElimPass(), PMW);
116 }
117
118 // Handle exceptions and setjmp/longjmp if enabled. Unlike Wasm EH preparation
119 // done in WasmEHPrepare pass, Wasm SjLj preparation shares libraries and
120 // transformation algorithms with Emscripten SjLj, so we run
121 // LowerEmscriptenEHSjLj pass also when Wasm SjLj is enabled.
123 flushFPMsToMPM(PMW);
124 addModulePass(WebAssemblyLowerEmscriptenEHSjLjPass(), PMW);
125 }
126
127 // Expand indirectbr instructions to switches.
128 addFunctionPass(IndirectBrExpandPass(TM), PMW);
129
130 // Try to expand `vecreduce_{and, or}` into `{any, all}_true`.
131 addFunctionPass(WebAssemblyReduceToAnyAllTruePass(TM), PMW);
132
133 Base::addIRPasses(PMW);
134}
135
136void WebAssemblyCodeGenPassBuilder::addISelPrepare(
137 PassManagerWrapper &PMW) const {
138 // We need to move reference type allocas to WASM_ADDRESS_SPACE_VAR so that
139 // loads and stores are promoted to local.gets/local.sets.
140 addFunctionPass(WebAssemblyRefTypeMem2LocalPass(), PMW);
141 // Lower atomics and TLS if necessary
142 flushFPMsToMPM(PMW);
143 addModulePass(WebAssemblyCoalesceFeaturesAndStripAtomicsPass(TM), PMW);
144
145 // This is a no-op if atomics are not used in the module
146 addFunctionPass(AtomicExpandPass(TM), PMW);
147
148 Base::addISelPrepare(PMW);
149}
150
151Error WebAssemblyCodeGenPassBuilder::addInstSelector(
152 PassManagerWrapper &PMW) const {
153 addMachineFunctionPass(WebAssemblyISelDAGToDAGPass(TM, getOptLevel()), PMW);
154
155 // Run the argument-move pass immediately after the ScheduleDAG scheduler
156 // so that we can fix up the ARGUMENT instructions before anything else
157 // sees them in the wrong place.
158 addMachineFunctionPass(WebAssemblyArgumentMovePass(), PMW);
159
160 // Set the p2align operands. This information is present during ISel, however
161 // it's inconvenient to collect. Collect it now, and update the immediate
162 // operands.
163 addMachineFunctionPass(WebAssemblySetP2AlignOperandsPass(), PMW);
164
165 // Eliminate range checks and add default targets to br_table instructions.
166 addMachineFunctionPass(WebAssemblyFixBrTableDefaultsPass(), PMW);
167
168 // unreachable is terminator, non-terminator instruction after it is not
169 // allowed.
170 addMachineFunctionPass(WebAssemblyCleanCodeAfterTrapPass(), PMW);
171
172 return Error::success();
173}
174
175void WebAssemblyCodeGenPassBuilder::addPreEmitPass(
176 PassManagerWrapper &PMW) const {
177 Base::addPreEmitPass(PMW);
178
179 // Nullify DBG_VALUE_LISTs that we cannot handle.
180 addMachineFunctionPass(WebAssemblyNullifyDebugValueListsPass(), PMW);
181
182 // Remove any unreachable blocks that may be left floating around.
183 // Rare, but possible. Needed for WebAssemblyFixIrreducibleControlFlow.
184 addMachineFunctionPass(UnreachableMachineBlockElimPass(), PMW);
185
186 // Eliminate multiple-entry loops.
187 addMachineFunctionPass(WebAssemblyFixIrreducibleControlFlowPass(), PMW);
188
189 // Do various transformations for exception handling.
190 // Every CFG-changing optimizations should come before this.
191 if (TM.Options.ExceptionModel == ExceptionHandling::Wasm)
192 addMachineFunctionPass(WebAssemblyLateEHPreparePass(), PMW);
193
194 // Now that we have a prologue and epilogue and all frame indices are
195 // rewritten, eliminate SP and FP. This allows them to be stackified,
196 // colored, and numbered with the rest of the registers.
197 addMachineFunctionPass(WebAssemblyReplacePhysRegsPass(), PMW);
198
199 // Preparations and optimizations related to register stackification.
200 if (getOptLevel() != CodeGenOptLevel::None) {
201 // Depend on LiveIntervals and perform some optimizations on it.
202 addMachineFunctionPass(WebAssemblyOptimizeLiveIntervalsPass(), PMW);
203
204 // Prepare memory intrinsic calls for register stackifying.
205 addMachineFunctionPass(WebAssemblyMemIntrinsicResultsPass(), PMW);
206 }
207
208 // Mark registers as representing wasm's value stack. This is a key
209 // code-compression technique in WebAssembly. We run this pass (and
210 // MemIntrinsicResults above) very late, so that it sees as much code as
211 // possible, including code emitted by PEI and expanded by late tail
212 // duplication.
213 addMachineFunctionPass(WebAssemblyRegStackifyPass(getOptLevel()), PMW);
214
215 if (getOptLevel() != CodeGenOptLevel::None) {
216 // Run the register coloring pass to reduce the total number of registers.
217 // This runs after stackification so that it doesn't consider registers
218 // that become stackified.
219 addMachineFunctionPass(WebAssemblyRegColoringPass(), PMW);
220 }
221
222 // Sort the blocks of the CFG into topological order, a prerequisite for
223 // BLOCK and LOOP markers.
224 addMachineFunctionPass(WebAssemblyCFGSortPass(), PMW);
225
226 // Insert BLOCK and LOOP markers.
227 addMachineFunctionPass(WebAssemblyCFGStackifyPass(), PMW);
228
229 // Insert explicit local.get and local.set operators.
231 addMachineFunctionPass(WebAssemblyExplicitLocalsPass(), PMW);
232
233 // Lower br_unless into br_if.
234 addMachineFunctionPass(WebAssemblyLowerBrUnlessPass(), PMW);
235
236 // Perform the very last peephole optimizations on the code.
237 if (getOptLevel() != CodeGenOptLevel::None)
238 addMachineFunctionPass(WebAssemblyPeepholePass(), PMW);
239
240 // Create a mapping from LLVM CodeGen virtual registers to wasm registers.
241 addMachineFunctionPass(WebAssemblyRegNumberingPass(), PMW);
242
243 // Fix debug_values whose defs have been stackified.
245 addMachineFunctionPass(WebAssemblyDebugFixupPass(), PMW);
246
247 // Collect information to prepare for MC lowering / asm printing.
248 flushFPMsToMPM(PMW);
249 addModulePass(WebAssemblyMCLowerPrePass(), PMW);
250}
251
252void WebAssemblyCodeGenPassBuilder::addAsmPrinterBegin(
253 PassManagerWrapper &PMW) const {
254 addModulePass(WebAssemblyAsmPrinterBeginPass(), PMW);
255}
256
257void WebAssemblyCodeGenPassBuilder::addAsmPrinter(
258 PassManagerWrapper &PMW) const {
259 addMachineFunctionPass(WebAssemblyAsmPrinterPass(), PMW);
260}
261
262void WebAssemblyCodeGenPassBuilder::addAsmPrinterEnd(
263 PassManagerWrapper &PMW) const {
264 addModulePass(WebAssemblyAsmPrinterEndPass(), PMW);
265}
266
267} // namespace
268
270#define GET_PASS_REGISTRY "WebAssemblyPassRegistry.def"
272 // TODO(boomanaiden154): Move this into the base CodeGenPassBuilder once all
273 // targets that currently implement it have a ported asm-printer pass.
274 if (PIC) {
275 PIC->addClassToPassName(WebAssemblyAsmPrinterBeginPass::name(),
276 "wasm-asm-printer-begin");
277 PIC->addClassToPassName(WebAssemblyAsmPrinterPass::name(),
278 "wasm-asm-printer");
279 PIC->addClassToPassName(WebAssemblyAsmPrinterEndPass::name(),
280 "wasm-asm-printer-end");
281 }
282}
283
286 raw_pwrite_stream *DwoOut, CodeGenFileType FileType,
287 const CGPassBuilderOption &Opt, MCContext &Ctx,
289 auto CGPB = WebAssemblyCodeGenPassBuilder(*this, Opt, PIC);
290 return CGPB.buildPipeline(MPM, MAM, Out, DwoOut, FileType, Ctx);
291}
Interfaces for producing common pass manager configurations.
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 ...
cl::opt< bool > WasmEnableEH
cl::opt< bool > WasmEnableSjLj
cl::opt< bool > WasmEnableEmEH
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 > WasmEnableEmEH
cl::opt< bool > WasmEnableEH
cl::opt< bool > WasmEnableSjLj
cl::opt< bool > WasmEnableEmSjLj
cl::opt< bool > WasmDisableExplicitLocals
cl::opt< bool > WasmEnableEH
cl::opt< bool > WasmEnableSjLj
cl::opt< bool > WasmEnableEmEH
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:111
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