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 addMachineFunctionPass(WebAssemblySetP2AlignOperandsPass(), PMW);
159
160 // Eliminate range checks and add default targets to br_table instructions.
161 addMachineFunctionPass(WebAssemblyFixBrTableDefaultsPass(), PMW);
162
163 // unreachable is terminator, non-terminator instruction after it is not
164 // allowed.
165 addMachineFunctionPass(WebAssemblyCleanCodeAfterTrapPass(), PMW);
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 addMachineFunctionPass(WebAssemblyLateEHPreparePass(), PMW);
188
189 // Now that we have a prologue and epilogue and all frame indices are
190 // rewritten, eliminate SP and FP. This allows them to be stackified,
191 // colored, and numbered with the rest of the registers.
192 addMachineFunctionPass(WebAssemblyReplacePhysRegsPass(), PMW);
193
194 // Preparations and optimizations related to register stackification.
195 if (getOptLevel() != CodeGenOptLevel::None) {
196 // Depend on LiveIntervals and perform some optimizations on it.
197 // TODO(boomanaiden154): WebAssemblyOptimizeLiveIntervals
198
199 // Prepare memory intrinsic calls for register stackifying.
200 // TODO(boomanaiden154): WebAssemblyMemIntrinsicResults
201 }
202
203 // Mark registers as representing wasm's value stack. This is a key
204 // code-compression technique in WebAssembly. We run this pass (and
205 // MemIntrinsicResults above) very late, so that it sees as much code as
206 // possible, including code emitted by PEI and expanded by late tail
207 // duplication.
208 // TODO(boomanaiden154): WebAssemblyRegStackify
209
210 if (getOptLevel() != CodeGenOptLevel::None) {
211 // Run the register coloring pass to reduce the total number of registers.
212 // This runs after stackification so that it doesn't consider registers
213 // that become stackified.
214 // TODO(boomanaiden154): WebAssemblyRegColoring
215 }
216
217 // Sort the blocks of the CFG into topological order, a prerequisite for
218 // BLOCK and LOOP markers.
219 // TODO(boomanaiden154): WebAssemblyCFGSort
220
221 // Insert BLOCK and LOOP markers.
222 // TODO(boomanaiden154): WebAssemblyCFGStackify
223
224 // Insert explicit local.get and local.set operators.
226 // TODO(boomanaiden154): WebAssemblyExplicitLocals
227 }
228
229 // Lower br_unless into br_if.
230 // TODO(boomanaiden154): WebAssemblyLowerBrUnless
231
232 // Perform the very last peephole optimizations on the code.
233 if (getOptLevel() != CodeGenOptLevel::None) {
234 // TODO(boomanaiden154): WebAssemblyPeephole
235 }
236
237 // Create a mapping from LLVM CodeGen virtual registers to wasm registers.
238 // TODO(boomanaiden154): WebAssemblyRegNumbering
239
240 // Fix debug_values whose defs have been stackified.
242 // TODO(boomanaiden154): WebAssemblyDebugFixup
243 }
244
245 // Collect information to prepare for MC lowering / asm printing.
246 // TODO(boomanaiden154): WebAssemblyMCLowerPrePass
247}
248
249} // namespace
250
252#define GET_PASS_REGISTRY "WebAssemblyPassRegistry.def"
254}
255
258 raw_pwrite_stream *DwoOut, CodeGenFileType FileType,
259 const CGPassBuilderOption &Opt, MCContext &Ctx,
261 auto CGPB = WebAssemblyCodeGenPassBuilder(*this, Opt, PIC);
262 return CGPB.buildPipeline(MPM, MAM, Out, DwoOut, FileType, Ctx);
263}
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