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