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