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