[llvm] 9a4decc - [WebAssembly] Introduce CodeGenPassBuilder
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 15 06:50:26 PDT 2026
Author: Aiden Grossman
Date: 2026-07-15T06:50:22-07:00
New Revision: 9a4deccf90ae914aa6d99acfff44b24bc5dfcb5c
URL: https://github.com/llvm/llvm-project/commit/9a4deccf90ae914aa6d99acfff44b24bc5dfcb5c
DIFF: https://github.com/llvm/llvm-project/commit/9a4deccf90ae914aa6d99acfff44b24bc5dfcb5c.diff
LOG: [WebAssembly] Introduce CodeGenPassBuilder
This is the equivalent of TargetPassConfig for the NewPM. This currently
mirrors the existing TargetPassConfig as close as possible, but with
TODOs for passes that have not been ported to the NewPM.
Reviewers: aheejin, sbc100, dschuff
Pull Request: https://github.com/llvm/llvm-project/pull/208983
Added:
llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp
llvm/lib/Target/WebAssembly/WebAssemblyPassRegistry.def
Modified:
llvm/lib/Target/WebAssembly/CMakeLists.txt
llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h
Removed:
################################################################################
diff --git a/llvm/lib/Target/WebAssembly/CMakeLists.txt b/llvm/lib/Target/WebAssembly/CMakeLists.txt
index a024a354890d2..980250198ff24 100644
--- a/llvm/lib/Target/WebAssembly/CMakeLists.txt
+++ b/llvm/lib/Target/WebAssembly/CMakeLists.txt
@@ -36,6 +36,7 @@ add_llvm_target(WebAssemblyCodeGen
WebAssemblyCFGStackify.cpp
WebAssemblyCleanCodeAfterTrap.cpp
WebAssemblyCFGSort.cpp
+ WebAssemblyCodeGenPassBuilder.cpp
WebAssemblyDebugFixup.cpp
WebAssemblyDebugValueManager.cpp
WebAssemblyLateEHPrepare.cpp
@@ -86,8 +87,10 @@ add_llvm_target(WebAssemblyCodeGen
CodeGen
CodeGenTypes
Core
+ IRPrinter
GlobalISel
MC
+ ObjCARC
Scalar
SelectionDAG
Support
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp
new file mode 100644
index 0000000000000..d82130da3bcf5
--- /dev/null
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp
@@ -0,0 +1,263 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "WebAssembly.h"
+#include "WebAssemblyTargetMachine.h"
+#include "llvm/CodeGen/AtomicExpand.h"
+#include "llvm/CodeGen/IndirectBrExpand.h"
+#include "llvm/CodeGen/MachineBlockPlacement.h"
+#include "llvm/CodeGen/MachineCopyPropagation.h"
+#include "llvm/CodeGen/MachineLateInstrsCleanup.h"
+#include "llvm/CodeGen/PatchableFunction.h"
+#include "llvm/CodeGen/PostRAMachineSink.h"
+#include "llvm/CodeGen/PostRASchedulerList.h"
+#include "llvm/CodeGen/RegisterCoalescerPass.h"
+#include "llvm/CodeGen/RemoveLoadsIntoFakeUses.h"
+#include "llvm/CodeGen/ShrinkWrap.h"
+#include "llvm/CodeGen/UnreachableBlockElim.h"
+#include "llvm/IR/PassInstrumentation.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Passes/CodeGenPassBuilder.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Support/CodeGen.h"
+#include "llvm/Target/CGPassBuilderOption.h"
+#include "llvm/Transforms/Utils/LowerGlobalDtors.h"
+#include "llvm/Transforms/Utils/LowerInvoke.h"
+
+using namespace llvm;
+
+namespace WebAssembly {
+extern cl::opt<bool> WasmDisableExplicitLocals;
+extern cl::opt<bool> WasmEnableEH;
+extern cl::opt<bool> WasmEnableEmEH;
+extern cl::opt<bool> WasmEnableEmSjLj;
+extern cl::opt<bool> WasmEnableSjLj;
+} // namespace WebAssembly
+
+using llvm::WebAssembly::WasmDisableExplicitLocals;
+using llvm::WebAssembly::WasmEnableEH;
+using llvm::WebAssembly::WasmEnableEmEH;
+using llvm::WebAssembly::WasmEnableEmSjLj;
+using llvm::WebAssembly::WasmEnableSjLj;
+
+namespace {
+
+class WebAssemblyCodeGenPassBuilder
+ : public CodeGenPassBuilder<WebAssemblyCodeGenPassBuilder,
+ WebAssemblyTargetMachine> {
+ using Base = CodeGenPassBuilder<WebAssemblyCodeGenPassBuilder,
+ WebAssemblyTargetMachine>;
+
+public:
+ explicit WebAssemblyCodeGenPassBuilder(WebAssemblyTargetMachine &TM,
+ const CGPassBuilderOption &Opts,
+ PassInstrumentationCallbacks *PIC)
+ : CodeGenPassBuilder(TM, Opts, PIC) {
+ disablePass<MachineLateInstrsCleanupPass, MachineCopyPropagationPass,
+ PostRAMachineSinkingPass, PostRASchedulerPass,
+ FuncletLayoutPass, StackMapLivenessPass, PatchableFunctionPass,
+ ShrinkWrapPass, RemoveLoadsIntoFakeUsesPass,
+ MachineBlockPlacementPass>();
+
+ // Currently RegisterCoalesce degrades wasm debug info quality by a
+ // significant margin. As a quick fix, disable this for -O1, which is often
+ // used for debugging large applications. Disabling this increases code size
+ // of Emscripten core benchmarks by ~5%, which is acceptable for -O1, which
+ // is usually not used for production builds.
+ // TODO Investigate why RegisterCoalesce degrades debug info quality and fix
+ // it properly
+ if (getOptLevel() == CodeGenOptLevel::Less)
+ disablePass<RegisterCoalescerPass>();
+ }
+
+ void addIRPasses(PassManagerWrapper &PMW) const;
+ void addISelPrepare(PassManagerWrapper &PMW) const;
+ Error addInstSelector(PassManagerWrapper &PMW) const;
+ void addPreEmitPass(PassManagerWrapper &PMW) const;
+};
+
+void WebAssemblyCodeGenPassBuilder::addIRPasses(PassManagerWrapper &PMW) const {
+ // Add signatures to prototype-less function declarations
+ // TODO(boomanaiden154): WebAssemblyAddMissingPrototypes
+
+ // Lower .llvm.global_dtors into .llvm.global_ctors with __cxa_atexit calls.
+ flushFPMsToMPM(PMW);
+ addModulePass(LowerGlobalDtorsPass(), PMW);
+
+ // Fix function bitcasts, as WebAssembly requires caller and callee signatures
+ // to match.
+ // TODO(boomanaiden154): WebAssemblyFixFunctionBitcasts
+
+ // Optimize "returned" function attributes.
+ if (getOptLevel() != CodeGenOptLevel::None) {
+ // TODO(boomanaiden154): WebAssemblyOptimizeReturned
+ }
+
+ // If exception handling is not enabled and setjmp/longjmp handling is
+ // enabled, we lower invokes into calls and delete unreachable landingpad
+ // blocks. Lowering invokes when there is no EH support is done in
+ // TargetPassConfig::addPassesToHandleExceptions, but that runs after these IR
+ // passes and Emscripten SjLj handling expects all invokes to be lowered
+ // before.
+ if (!WasmEnableEmEH && !WasmEnableEH) {
+ addFunctionPass(LowerInvokePass(), PMW);
+ // The lower invoke pass may create unreachable code. Remove it in order not
+ // to process dead blocks in setjmp/longjmp handling.
+ addFunctionPass(UnreachableBlockElimPass(), PMW);
+ }
+
+ // Handle exceptions and setjmp/longjmp if enabled. Unlike Wasm EH preparation
+ // done in WasmEHPrepare pass, Wasm SjLj preparation shares libraries and
+ // transformation algorithms with Emscripten SjLj, so we run
+ // LowerEmscriptenEHSjLj pass also when Wasm SjLj is enabled.
+ if (WasmEnableEmEH || WasmEnableEmSjLj || WasmEnableSjLj) {
+ // TODO(boomanaiden154): WebAssemblyLowerEmscriptenEHSjLj
+ }
+
+ // Expand indirectbr instructions to switches.
+ addFunctionPass(IndirectBrExpandPass(TM), PMW);
+
+ // Try to expand `vecreduce_{and, or}` into `{any, all}_true`.
+ // TODO(boomanaiden154): WebAssemblyReduceToAnyAllTrue
+
+ Base::addIRPasses(PMW);
+}
+
+void WebAssemblyCodeGenPassBuilder::addISelPrepare(
+ PassManagerWrapper &PMW) const {
+ // We need to move reference type allocas to WASM_ADDRESS_SPACE_VAR so that
+ // loads and stores are promoted to local.gets/local.sets.
+ // TODO(boomanaiden154): WebAssemblyRefTypeMem2Local
+ // Lower atomics and TLS if necessary
+ // TODO(boomanaiden154): CoalesceFeaturesAndStripAtomics
+
+ // This is a no-op if atomics are not used in the module
+ addFunctionPass(AtomicExpandPass(TM), PMW);
+
+ Base::addISelPrepare(PMW);
+}
+
+Error WebAssemblyCodeGenPassBuilder::addInstSelector(
+ PassManagerWrapper &PMW) const {
+ addMachineFunctionPass(WebAssemblyISelDAGToDAGPass(TM, getOptLevel()), PMW);
+
+ // Run the argument-move pass immediately after the ScheduleDAG scheduler
+ // so that we can fix up the ARGUMENT instructions before anything else
+ // sees them in the wrong place.
+ // TODO(boomanaiden154): WebAssemblyArgumentMove
+
+ // Set the p2align operands. This information is present during ISel, however
+ // it's inconvenient to collect. Collect it now, and update the immediate
+ // operands.
+ // TODO(boomanaiden154): WebAssemblySetP2AlignOperands
+
+ // Eliminate range checks and add default targets to br_table instructions.
+ // TODO(boomanaiden154): WebAssemblyFixBrTableDefaults
+
+ // unreachable is terminator, non-terminator instruction after it is not
+ // allowed.
+ // TODO(boomanaiden154): WebAssemblyCleanCodeAfterTrap
+
+ return Error::success();
+}
+
+void WebAssemblyCodeGenPassBuilder::addPreEmitPass(
+ PassManagerWrapper &PMW) const {
+ Base::addPreEmitPass(PMW);
+
+ // Nullify DBG_VALUE_LISTs that we cannot handle.
+ // TODO(boomanaiden154): WebAssemblyNullifyDebugValueLists
+
+ // Remove any unreachable blocks that may be left floating around.
+ // Rare, but possible. Needed for WebAssemblyFixIrreducibleControlFlow.
+ addMachineFunctionPass(UnreachableMachineBlockElimPass(), PMW);
+
+ // Eliminate multiple-entry loops.
+ // TODO(boomanaiden154): WebAssemblyFixIrreducibleControlFlow
+
+ // Do various transformations for exception handling.
+ // Every CFG-changing optimizations should come before this.
+ if (TM.Options.ExceptionModel == ExceptionHandling::Wasm) {
+ // TODO(boomanaiden154): WebAssemblyLateEHPrepare
+ }
+
+ // Now that we have a prologue and epilogue and all frame indices are
+ // rewritten, eliminate SP and FP. This allows them to be stackified,
+ // colored, and numbered with the rest of the registers.
+ // TODO(boomanaiden154): WebAssemblyReplacePhysRegs
+
+ // Preparations and optimizations related to register stackification.
+ if (getOptLevel() != CodeGenOptLevel::None) {
+ // Depend on LiveIntervals and perform some optimizations on it.
+ // TODO(boomanaiden154): WebAssemblyOptimizeLiveIntervals
+
+ // Prepare memory intrinsic calls for register stackifying.
+ // TODO(boomanaiden154): WebAssemblyMemIntrinsicResults
+ }
+
+ // Mark registers as representing wasm's value stack. This is a key
+ // code-compression technique in WebAssembly. We run this pass (and
+ // MemIntrinsicResults above) very late, so that it sees as much code as
+ // possible, including code emitted by PEI and expanded by late tail
+ // duplication.
+ // TODO(boomanaiden154): WebAssemblyRegStackify
+
+ if (getOptLevel() != CodeGenOptLevel::None) {
+ // Run the register coloring pass to reduce the total number of registers.
+ // This runs after stackification so that it doesn't consider registers
+ // that become stackified.
+ // TODO(boomanaiden154): WebAssemblyRegColoring
+ }
+
+ // Sort the blocks of the CFG into topological order, a prerequisite for
+ // BLOCK and LOOP markers.
+ // TODO(boomanaiden154): WebAssemblyCFGSort
+
+ // Insert BLOCK and LOOP markers.
+ // TODO(boomanaiden154): WebAssemblyCFGStackify
+
+ // Insert explicit local.get and local.set operators.
+ if (!WasmDisableExplicitLocals) {
+ // TODO(boomanaiden154): WebAssemblyExplicitLocals
+ }
+
+ // Lower br_unless into br_if.
+ // TODO(boomanaiden154): WebAssemblyLowerBrUnless
+
+ // Perform the very last peephole optimizations on the code.
+ if (getOptLevel() != CodeGenOptLevel::None) {
+ // TODO(boomanaiden154): WebAssemblyPeephole
+ }
+
+ // Create a mapping from LLVM CodeGen virtual registers to wasm registers.
+ // TODO(boomanaiden154): WebAssemblyRegNumbering
+
+ // Fix debug_values whose defs have been stackified.
+ if (!WasmDisableExplicitLocals) {
+ // TODO(boomanaiden154): WebAssemblyDebugFixup
+ }
+
+ // Collect information to prepare for MC lowering / asm printing.
+ // TODO(boomanaiden154): WebAssemblyMCLowerPrePass
+}
+
+} // namespace
+
+void WebAssemblyTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB){
+#define GET_PASS_REGISTRY "WebAssemblyPassRegistry.def"
+#include "llvm/Passes/TargetPassRegistry.inc"
+}
+
+Error WebAssemblyTargetMachine::buildCodeGenPipeline(
+ ModulePassManager &MPM, ModuleAnalysisManager &MAM, raw_pwrite_stream &Out,
+ raw_pwrite_stream *DwoOut, CodeGenFileType FileType,
+ const CGPassBuilderOption &Opt, MCContext &Ctx,
+ PassInstrumentationCallbacks *PIC) {
+ auto CGPB = WebAssemblyCodeGenPassBuilder(*this, Opt, PIC);
+ return CGPB.buildPipeline(MPM, MAM, Out, DwoOut, FileType, Ctx);
+}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyPassRegistry.def b/llvm/lib/Target/WebAssembly/WebAssemblyPassRegistry.def
new file mode 100644
index 0000000000000..b4a5760148c04
--- /dev/null
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyPassRegistry.def
@@ -0,0 +1,18 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is used as the registry of passes that are part of the WebAssembly
+// backend.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MACHINE_FUNCTION_PASS
+#define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS)
+#endif
+MACHINE_FUNCTION_PASS("wasm-isel", WebAssemblyISelDAGToDAGPass(*this, getOptLevel()))
+#undef MACHINE_FUNCTION_PASS
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
index 4ce04458fb1d8..8ac6708b4fdae 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -45,7 +45,7 @@ using namespace llvm;
// for the purpose of testing with lit/llc ONLY.
// This produces output which is not valid WebAssembly, and is not supported
// by assemblers/disassemblers and other MC based tools.
-static cl::opt<bool> WasmDisableExplicitLocals(
+cl::opt<bool> WebAssembly::WasmDisableExplicitLocals(
"wasm-disable-explicit-locals", cl::Hidden,
cl::desc("WebAssembly: output implicit locals in"
" instruction output for test purposes only."),
@@ -134,6 +134,7 @@ static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {
return RM.value_or(Reloc::Static);
}
+using WebAssembly::WasmDisableExplicitLocals;
using WebAssembly::WasmEnableEH;
using WebAssembly::WasmEnableEmEH;
using WebAssembly::WasmEnableEmSjLj;
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h
index 6f97f1302189a..55f8898e387da 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h
@@ -23,6 +23,7 @@ namespace llvm {
namespace WebAssembly {
// Exception handling / setjmp-longjmp handling command-line options
+extern cl::opt<bool> WasmDisableExplicitLocals;
extern cl::opt<bool> WasmEnableEmEH; // asm.js-style EH
extern cl::opt<bool> WasmEnableEmSjLj; // asm.js-style SjLJ
extern cl::opt<bool> WasmEnableEH; // EH using Wasm EH instructions
@@ -74,6 +75,14 @@ class WebAssemblyTargetMachine final : public CodeGenTargetMachineImpl {
SMRange &SourceRange) const override;
bool usesMultivalueABI() const { return UsesMultivalueABI; }
+
+ void registerPassBuilderCallbacks(PassBuilder &PbB) override;
+
+ Error buildCodeGenPipeline(ModulePassManager &MPM, ModuleAnalysisManager &MAM,
+ raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
+ CodeGenFileType FileType,
+ const CGPassBuilderOption &Opt, MCContext &Ctx,
+ PassInstrumentationCallbacks *PIC) override;
};
} // end namespace llvm
More information about the llvm-commits
mailing list