[llvm] [NewPM] Port EHContGuardTargets to the new pass manager (PR #217843)
Bill Wendling via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 21 01:22:42 PDT 2026
https://github.com/isanbard created https://github.com/llvm/llvm-project/pull/217843
Adds a newPM pass for EHContGuardTargets (eh-cont-guard-targets).
- Extracts the pass's logic (which has no per-instance state) into a shared runEHContGuardTargets free function, called by both the legacy pass and the new pass manager pass.
- Renames the old pass with the "Legacy" suffix, and (matching the same convention already applied to CFIInstrInserter) renames createEHContGuardTargetsPass() to createEHContGuardTargetsLegacy() at all three legacy call sites (X86, AArch64, ARM).
- Adds the new pass manager pass EHContGuardTargetsPass, using RequiredPassInfoMixin: the legacy pass's runOnMachineFunction never calls skipFunction, so it always runs unconditionally and should not be skippable in the new PM either.
- Updates MachinePassRegistry.def and PassBuilder.
- Wires the pass into X86's newPM pipeline, replacing an existing TODO inside the already-correct TT.isOSWindows() conditional in X86CodeGenPassBuilder.cpp. AArch64 and ARM have no newPM CodeGenPassBuilder yet (legacy-only), so no wiring was needed there.
- Adds a -enable-new-pm RUN line to ehcontguard.ll (X86 only, the only target with newPM support), since no dedicated unit test existed to extend, and updates llc-pipeline-npm.ll's O0-WINDOWS/O3-WINDOWS pipeline-dump expectations (verified empirically where the pass lands in the dump).
Assisted-by: Claude Sonnet 5
>From f40f3176229795048b46f4949211cc91ee15c6af Mon Sep 17 00:00:00 2001
From: Bill Wendling <isanbard at gmail.com>
Date: Thu, 20 Aug 2026 18:52:12 -0700
Subject: [PATCH] [NewPM] Port EHContGuardTargets to the new pass manager
Adds a newPM pass for EHContGuardTargets (eh-cont-guard-targets).
- Extracts the pass's logic (which has no per-instance state) into a
shared runEHContGuardTargets free function, called by both the
legacy pass and the new pass manager pass.
- Renames the old pass with the "Legacy" suffix, and (matching the
same convention already applied to CFIInstrInserter) renames
createEHContGuardTargetsPass() to createEHContGuardTargetsLegacy()
at all three legacy call sites (X86, AArch64, ARM).
- Adds the new pass manager pass EHContGuardTargetsPass, using
RequiredPassInfoMixin: the legacy pass's runOnMachineFunction never
calls skipFunction, so it always runs unconditionally and should not
be skippable in the new PM either.
- Updates MachinePassRegistry.def and PassBuilder.
- Wires the pass into X86's newPM pipeline, replacing an existing TODO
inside the already-correct TT.isOSWindows() conditional in
X86CodeGenPassBuilder.cpp. AArch64 and ARM have no newPM
CodeGenPassBuilder yet (legacy-only), so no wiring was needed there.
- Adds a -enable-new-pm RUN line to ehcontguard.ll (X86 only, the only
target with newPM support), since no dedicated unit test existed to
extend, and updates llc-pipeline-npm.ll's O0-WINDOWS/O3-WINDOWS
pipeline-dump expectations (verified empirically where the pass
lands in the dump).
Assisted-by: Claude Sonnet 5
---
.../include/llvm/CodeGen/EHContGuardTargets.h | 25 +++++++
llvm/include/llvm/CodeGen/Passes.h | 2 +-
llvm/include/llvm/InitializePasses.h | 2 +-
.../llvm/Passes/MachinePassRegistry.def | 2 +-
llvm/lib/CodeGen/CodeGen.cpp | 2 +-
llvm/lib/CodeGen/EHContGuardTargets.cpp | 65 +++++++++++--------
llvm/lib/Passes/PassBuilder.cpp | 1 +
.../Target/AArch64/AArch64TargetMachine.cpp | 2 +-
llvm/lib/Target/ARM/ARMTargetMachine.cpp | 2 +-
llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp | 4 +-
llvm/lib/Target/X86/X86TargetMachine.cpp | 2 +-
llvm/test/CodeGen/X86/ehcontguard.ll | 1 +
llvm/test/CodeGen/X86/llc-pipeline-npm.ll | 2 +
13 files changed, 76 insertions(+), 36 deletions(-)
create mode 100644 llvm/include/llvm/CodeGen/EHContGuardTargets.h
diff --git a/llvm/include/llvm/CodeGen/EHContGuardTargets.h b/llvm/include/llvm/CodeGen/EHContGuardTargets.h
new file mode 100644
index 0000000000000..052183d39226a
--- /dev/null
+++ b/llvm/include/llvm/CodeGen/EHContGuardTargets.h
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_EHCONTGUARDTARGETS_H
+#define LLVM_CODEGEN_EHCONTGUARDTARGETS_H
+
+#include "llvm/CodeGen/MachinePassManager.h"
+
+namespace llvm {
+
+class EHContGuardTargetsPass
+ : public RequiredPassInfoMixin<EHContGuardTargetsPass> {
+public:
+ LLVM_ABI PreservedAnalyses run(MachineFunction &MF,
+ MachineFunctionAnalysisManager &MFAM);
+};
+
+} // namespace llvm
+
+#endif // LLVM_CODEGEN_EHCONTGUARDTARGETS_H
diff --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h
index 0009373a68c78..8c2b923aeb807 100644
--- a/llvm/include/llvm/CodeGen/Passes.h
+++ b/llvm/include/llvm/CodeGen/Passes.h
@@ -580,7 +580,7 @@ LLVM_ABI FunctionPass *createCFGuardLongjmpPass();
/// Creates Windows EH Continuation Guard target identification pass.
/// \see EHContGuardTargets.cpp
-LLVM_ABI FunctionPass *createEHContGuardTargetsPass();
+LLVM_ABI FunctionPass *createEHContGuardTargetsLegacy();
/// Create Hardware Loop pass. \see HardwareLoops.cpp
LLVM_ABI FunctionPass *createHardwareLoopsLegacyPass();
diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h
index 921f1586049d8..3c05a2bd8472d 100644
--- a/llvm/include/llvm/InitializePasses.h
+++ b/llvm/include/llvm/InitializePasses.h
@@ -111,7 +111,7 @@ LLVM_ABI void initializeEarlyIfPredicatorPass(PassRegistry &);
LLVM_ABI void initializeEarlyMachineLICMPass(PassRegistry &);
LLVM_ABI void initializeEarlyTailDuplicateLegacyPass(PassRegistry &);
LLVM_ABI void initializeEdgeBundlesWrapperLegacyPass(PassRegistry &);
-LLVM_ABI void initializeEHContGuardTargetsPass(PassRegistry &);
+LLVM_ABI void initializeEHContGuardTargetsLegacyPass(PassRegistry &);
LLVM_ABI void initializeExpandIRInstsLegacyPassPass(PassRegistry &);
LLVM_ABI void initializeExpandPostRALegacyPass(PassRegistry &);
LLVM_ABI void initializeExpandReductionsPass(PassRegistry &);
diff --git a/llvm/include/llvm/Passes/MachinePassRegistry.def b/llvm/include/llvm/Passes/MachinePassRegistry.def
index de0ba23ad2818..d82b525b4a3af 100644
--- a/llvm/include/llvm/Passes/MachinePassRegistry.def
+++ b/llvm/include/llvm/Passes/MachinePassRegistry.def
@@ -76,6 +76,7 @@ MACHINE_FUNCTION_PASS("dot-machine-cfg", MachineCFGPrinterPass())
MACHINE_FUNCTION_PASS("early-ifcvt", EarlyIfConverterPass())
MACHINE_FUNCTION_PASS("early-machinelicm", EarlyMachineLICMPass())
MACHINE_FUNCTION_PASS("early-tailduplication", EarlyTailDuplicatePass())
+MACHINE_FUNCTION_PASS("eh-cont-guard-targets", EHContGuardTargetsPass())
MACHINE_FUNCTION_PASS("fentry-insert", FEntryInserterPass())
MACHINE_FUNCTION_PASS("finalize-isel", FinalizeISelPass())
MACHINE_FUNCTION_PASS("finalizebundle-test", FinalizeBundleTestPass())
@@ -245,7 +246,6 @@ DUMMY_MACHINE_MODULE_PASS("pseudo-probe-inserter", PseudoProbeInserterPass)
DUMMY_MACHINE_FUNCTION_PASS("bbsections-prepare", BasicBlockSectionsPass)
DUMMY_MACHINE_FUNCTION_PASS("bbsections-profile-reader", BasicBlockSectionsProfileReaderPass)
DUMMY_MACHINE_FUNCTION_PASS("cfguard-longjmp", CFGuardLongjmpPass)
-DUMMY_MACHINE_FUNCTION_PASS("eh-cont-guard-targets", EHContGuardTargetsPass)
DUMMY_MACHINE_FUNCTION_PASS("fs-profile-loader", MIRProfileLoaderNewPass)
DUMMY_MACHINE_FUNCTION_PASS("instruction-select", InstructionSelectPass)
DUMMY_MACHINE_FUNCTION_PASS("lrshrink", LiveRangeShrinkPass)
diff --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp
index 6be46b0f6cef1..7fb2fca6b6494 100644
--- a/llvm/lib/CodeGen/CodeGen.cpp
+++ b/llvm/lib/CodeGen/CodeGen.cpp
@@ -38,7 +38,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
initializeDetectDeadLanesLegacyPass(Registry);
initializeDummyCGSCCPassPass(Registry);
initializeDwarfEHPrepareLegacyPassPass(Registry);
- initializeEHContGuardTargetsPass(Registry);
+ initializeEHContGuardTargetsLegacyPass(Registry);
initializeEarlyIfConverterLegacyPass(Registry);
initializeEarlyIfPredicatorPass(Registry);
initializeEarlyMachineLICMPass(Registry);
diff --git a/llvm/lib/CodeGen/EHContGuardTargets.cpp b/llvm/lib/CodeGen/EHContGuardTargets.cpp
index 9ad3f671798c9..daf82ef2e26be 100644
--- a/llvm/lib/CodeGen/EHContGuardTargets.cpp
+++ b/llvm/lib/CodeGen/EHContGuardTargets.cpp
@@ -15,6 +15,7 @@
///
//===----------------------------------------------------------------------===//
+#include "llvm/CodeGen/EHContGuardTargets.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
@@ -29,53 +30,63 @@ using namespace llvm;
STATISTIC(EHContGuardTargetsFound, "Number of EHCont Guard targets");
+static bool runEHContGuardTargets(MachineFunction &MF) {
+ // Skip modules for which the ehcontguard flag is not set.
+ if (!MF.getFunction().getParent()->getModuleFlag("ehcontguard"))
+ return false;
+
+ // Skip functions that do not have targets
+ if (!MF.hasEHContTarget())
+ return false;
+
+ bool Result = false;
+
+ for (MachineBasicBlock &MBB : MF) {
+ if (MBB.isEHContTarget()) {
+ MF.addEHContTarget(MBB.getEHContSymbol());
+ EHContGuardTargetsFound++;
+ Result = true;
+ }
+ }
+
+ return Result;
+}
+
namespace {
/// MachineFunction pass to insert a symbol before each valid catchret target
/// and store these in the MachineFunction's CatchRetTargets vector.
-class EHContGuardTargets : public MachineFunctionPass {
+class EHContGuardTargetsLegacy : public MachineFunctionPass {
public:
static char ID;
- EHContGuardTargets() : MachineFunctionPass(ID) {}
+ EHContGuardTargetsLegacy() : MachineFunctionPass(ID) {}
StringRef getPassName() const override {
return "EH Cont Guard catchret targets";
}
- bool runOnMachineFunction(MachineFunction &MF) override;
+ bool runOnMachineFunction(MachineFunction &MF) override {
+ return runEHContGuardTargets(MF);
+ }
};
} // end anonymous namespace
-char EHContGuardTargets::ID = 0;
+char EHContGuardTargetsLegacy::ID = 0;
-INITIALIZE_PASS(EHContGuardTargets, "EHContGuardTargets",
+INITIALIZE_PASS(EHContGuardTargetsLegacy, "EHContGuardTargets",
"Insert symbols at valid targets for /guard:ehcont", false,
false)
-FunctionPass *llvm::createEHContGuardTargetsPass() {
- return new EHContGuardTargets();
+FunctionPass *llvm::createEHContGuardTargetsLegacy() {
+ return new EHContGuardTargetsLegacy();
}
-bool EHContGuardTargets::runOnMachineFunction(MachineFunction &MF) {
-
- // Skip modules for which the ehcontguard flag is not set.
- if (!MF.getFunction().getParent()->getModuleFlag("ehcontguard"))
- return false;
-
- // Skip functions that do not have targets
- if (!MF.hasEHContTarget())
- return false;
-
- bool Result = false;
-
- for (MachineBasicBlock &MBB : MF) {
- if (MBB.isEHContTarget()) {
- MF.addEHContTarget(MBB.getEHContSymbol());
- EHContGuardTargetsFound++;
- Result = true;
- }
- }
+PreservedAnalyses
+EHContGuardTargetsPass::run(MachineFunction &MF,
+ MachineFunctionAnalysisManager &MFAM) {
+ if (!runEHContGuardTargets(MF))
+ return PreservedAnalyses::all();
- return Result;
+ return getMachineFunctionPassPreservedAnalyses();
}
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 64c7c1237456a..27df98c0d892d 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -94,6 +94,7 @@
#include "llvm/CodeGen/DeadMachineInstructionElim.h"
#include "llvm/CodeGen/DetectDeadLanes.h"
#include "llvm/CodeGen/DwarfEHPrepare.h"
+#include "llvm/CodeGen/EHContGuardTargets.h"
#include "llvm/CodeGen/EarlyIfConversion.h"
#include "llvm/CodeGen/EdgeBundles.h"
#include "llvm/CodeGen/ExpandIRInsts.h"
diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
index 2669647a8f56b..beec7897f5962 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
@@ -930,7 +930,7 @@ void AArch64PassConfig::addPreEmitPass() {
// Identify valid longjmp targets for Windows Control Flow Guard.
addPass(createCFGuardLongjmpPass());
// Identify valid eh continuation targets for Windows EHCont Guard.
- addPass(createEHContGuardTargetsPass());
+ addPass(createEHContGuardTargetsLegacy());
}
if (TM->getOptLevel() != CodeGenOptLevel::None && EnableCollectLOH &&
diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
index ea993dd33f550..dd05e38c075ea 100644
--- a/llvm/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
@@ -618,7 +618,7 @@ void ARMPassConfig::addPreEmitPass2() {
// Identify valid longjmp targets for Windows Control Flow Guard.
addPass(createCFGuardLongjmpPass());
// Identify valid eh continuation targets for Windows EHCont Guard.
- addPass(createEHContGuardTargetsPass());
+ addPass(createEHContGuardTargetsLegacy());
}
}
diff --git a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
index ca8a324ae590b..c05bd2ca7f3be 100644
--- a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
+++ b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
@@ -17,6 +17,7 @@
#include "llvm/CodeGen/AtomicExpand.h"
#include "llvm/CodeGen/BreakFalseDeps.h"
#include "llvm/CodeGen/CFIInstrInserter.h"
+#include "llvm/CodeGen/EHContGuardTargets.h"
#include "llvm/CodeGen/EarlyIfConversion.h"
#include "llvm/CodeGen/IndirectBrExpand.h"
#include "llvm/CodeGen/InterleavedAccess.h"
@@ -239,8 +240,7 @@ void X86CodeGenPassBuilder::addPreEmitPass2(PassManagerWrapper &PMW) {
// TODO(boomanaiden154): Add CFGuardLongjmpPass here when it has been
// ported.
// Identify valid eh continuation targets for Windows EHCont Guard.
- // TODO(boomanaiden154): Add EHContGuardTargetsPass when it has been
- // ported.
+ addMachineFunctionPass(EHContGuardTargetsPass(), PMW);
}
addMachineFunctionPass(X86LoadValueInjectionRetHardeningPass(), PMW);
diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp
index c3f6d42c45d8a..a32a30e4bae34 100644
--- a/llvm/lib/Target/X86/X86TargetMachine.cpp
+++ b/llvm/lib/Target/X86/X86TargetMachine.cpp
@@ -609,7 +609,7 @@ void X86PassConfig::addPreEmitPass2() {
// Identify valid longjmp targets for Windows Control Flow Guard.
addPass(createCFGuardLongjmpPass());
// Identify valid eh continuation targets for Windows EHCont Guard.
- addPass(createEHContGuardTargetsPass());
+ addPass(createEHContGuardTargetsLegacy());
}
addPass(createX86LoadValueInjectionRetHardeningLegacyPass());
diff --git a/llvm/test/CodeGen/X86/ehcontguard.ll b/llvm/test/CodeGen/X86/ehcontguard.ll
index e868209babce6..6cd5d2e8935d3 100644
--- a/llvm/test/CodeGen/X86/ehcontguard.ll
+++ b/llvm/test/CodeGen/X86/ehcontguard.ll
@@ -1,4 +1,5 @@
; RUN: llc < %s -mtriple=x86_64-pc-windows-msvc | FileCheck %s
+; RUN: llc -enable-new-pm < %s -mtriple=x86_64-pc-windows-msvc | FileCheck %s
; EHCont Guard is currently only available on Windows
; CHECK: @feat.00 = 16384
diff --git a/llvm/test/CodeGen/X86/llc-pipeline-npm.ll b/llvm/test/CodeGen/X86/llc-pipeline-npm.ll
index d0369d93d1710..52363d9844c00 100644
--- a/llvm/test/CodeGen/X86/llc-pipeline-npm.ll
+++ b/llvm/test/CodeGen/X86/llc-pipeline-npm.ll
@@ -275,6 +275,7 @@
; O0-WINDOWS-NEXT: x86-seses
; O0-WINDOWS-NEXT: x86-return-thunks
; O0-WINDOWS-NEXT: x86-avoid-trailing-call
+; O0-WINDOWS-NEXT: eh-cont-guard-targets
; O0-WINDOWS-NEXT: x86-lvi-ret
; O0-WINDOWS-NEXT: x86-wineh-unwindv2
; O0-WINDOWS-NEXT: verify
@@ -404,6 +405,7 @@
; O3-WINDOWS-NEXT: x86-seses
; O3-WINDOWS-NEXT: x86-return-thunks
; O3-WINDOWS-NEXT: x86-avoid-trailing-call
+; O3-WINDOWS-NEXT: eh-cont-guard-targets
; O3-WINDOWS-NEXT: x86-lvi-ret
; O3-WINDOWS-NEXT: x86-wineh-unwindv2
; O3-WINDOWS-NEXT: verify
More information about the llvm-commits
mailing list