[llvm] [NewPM] Port EHContGuardTargets to the new pass manager (PR #217843)

via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 21 01:23:17 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-x86

Author: Bill Wendling (isanbard)

<details>
<summary>Changes</summary>

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

---
Full diff: https://github.com/llvm/llvm-project/pull/217843.diff


13 Files Affected:

- (added) llvm/include/llvm/CodeGen/EHContGuardTargets.h (+25) 
- (modified) llvm/include/llvm/CodeGen/Passes.h (+1-1) 
- (modified) llvm/include/llvm/InitializePasses.h (+1-1) 
- (modified) llvm/include/llvm/Passes/MachinePassRegistry.def (+1-1) 
- (modified) llvm/lib/CodeGen/CodeGen.cpp (+1-1) 
- (modified) llvm/lib/CodeGen/EHContGuardTargets.cpp (+38-27) 
- (modified) llvm/lib/Passes/PassBuilder.cpp (+1) 
- (modified) llvm/lib/Target/AArch64/AArch64TargetMachine.cpp (+1-1) 
- (modified) llvm/lib/Target/ARM/ARMTargetMachine.cpp (+1-1) 
- (modified) llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp (+2-2) 
- (modified) llvm/lib/Target/X86/X86TargetMachine.cpp (+1-1) 
- (modified) llvm/test/CodeGen/X86/ehcontguard.ll (+1) 
- (modified) llvm/test/CodeGen/X86/llc-pipeline-npm.ll (+2) 


``````````diff
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

``````````

</details>


https://github.com/llvm/llvm-project/pull/217843


More information about the llvm-commits mailing list