[llvm] [NewPM] Port x86-winehstate (PR #180687)

via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 9 22:53:12 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-x86

Author: Anshul Nigham (nigham)

<details>
<summary>Changes</summary>

x86-winehstate has been converted to a module pass for NewPM since it uses data from the Module by overriding `doInitialization` and `doFinalization`.

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


5 Files Affected:

- (modified) llvm/lib/Target/X86/X86.h (+9-2) 
- (modified) llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp (+1-1) 
- (modified) llvm/lib/Target/X86/X86PassRegistry.def (+6-6) 
- (modified) llvm/lib/Target/X86/X86TargetMachine.cpp (+2-2) 
- (modified) llvm/lib/Target/X86/X86WinEHState.cpp (+76-38) 


``````````diff
diff --git a/llvm/lib/Target/X86/X86.h b/llvm/lib/Target/X86/X86.h
index 355f0959b4c7d..324c645dc994c 100644
--- a/llvm/lib/Target/X86/X86.h
+++ b/llvm/lib/Target/X86/X86.h
@@ -16,6 +16,7 @@
 
 #include "llvm/CodeGen/MachineFunctionAnalysisManager.h"
 #include "llvm/IR/Analysis.h"
+#include "llvm/IR/Module.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/PassInfo.h"
 #include "llvm/Support/CodeGen.h"
@@ -227,7 +228,13 @@ FunctionPass *createX86CallFrameOptimizationLegacyPass();
 /// Return an IR pass that inserts EH registration stack objects and explicit
 /// EH state updates. This pass must run after EH preparation, which does
 /// Windows-specific but architecture-neutral preparation.
-FunctionPass *createX86WinEHStatePass();
+class X86WinEHStatePass : public PassInfoMixin<X86WinEHStatePass> {
+public:
+  X86WinEHStatePass() = default;
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
+};
+
+FunctionPass *createX86WinEHStateLegacyPass();
 
 /// Return a Machine IR pass that expands X86-specific pseudo
 /// instructions into a sequence of actual instructions. This pass
@@ -421,7 +428,7 @@ void initializeX86ArgumentStackSlotLegacyPass(PassRegistry &);
 void initializeX86AsmPrinterPass(PassRegistry &);
 void initializeX86FixupInstTuningLegacyPass(PassRegistry &);
 void initializeX86FixupVectorConstantsLegacyPass(PassRegistry &);
-void initializeWinEHStatePassPass(PassRegistry &);
+void initializeWinEHStateLegacyPass(PassRegistry &);
 void initializeX86AvoidSFBLegacyPass(PassRegistry &);
 void initializeX86AvoidTrailingCallLegacyPassPass(PassRegistry &);
 void initializeX86CallFrameOptimizationLegacyPass(PassRegistry &);
diff --git a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
index d7c9932dd3f0d..723be02ed61dc 100644
--- a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
+++ b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
@@ -95,7 +95,7 @@ void X86CodeGenPassBuilder::addPreISel(PassManagerWrapper &PMW) const {
   // Only add this pass for 32-bit x86 Windows.
   const Triple &TT = TM.getTargetTriple();
   if (TT.isOSWindows() && TT.isX86_32()) {
-    // TODO(boomanaiden154): Add X86WinEHStatePass here once it has been ported.
+    addModulePass(X86WinEHStatePass(), PMW);
   }
 }
 
diff --git a/llvm/lib/Target/X86/X86PassRegistry.def b/llvm/lib/Target/X86/X86PassRegistry.def
index 2f9b880249465..bf2b2349d28a6 100644
--- a/llvm/lib/Target/X86/X86PassRegistry.def
+++ b/llvm/lib/Target/X86/X86PassRegistry.def
@@ -12,6 +12,12 @@
 
 // NOTE: NO INCLUDE GUARD DESIRED!
 
+#ifndef MODULE_PASS
+#define MODULE_PASS(NAME, CREATE_PASS)
+#endif
+MODULE_PASS("x86-winehstate", X86WinEHStatePass())
+#undef MODULE_PASS
+
 #ifndef FUNCTION_PASS
 #define FUNCTION_PASS(NAME, CREATE_PASS)
 #endif
@@ -20,12 +26,6 @@ FUNCTION_PASS("x86-lower-amx-type", X86LowerAMXTypePass(this))
 FUNCTION_PASS("x86-partial-reduction", X86PartialReductionPass(this))
 #undef FUNCTION_PASS
 
-#ifndef DUMMY_FUNCTION_PASS
-#define DUMMY_FUNCTION_PASS(NAME, CREATE_PASS)
-#endif
-DUMMY_FUNCTION_PASS("x86-winehstate", WinEHStatePass())
-#undef DUMMY_FUNCTION_PASS
-
 #ifndef MACHINE_FUNCTION_PASS
 #define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS)
 #endif
diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp
index 48fc38a1f11f5..5299352bd2a7e 100644
--- a/llvm/lib/Target/X86/X86TargetMachine.cpp
+++ b/llvm/lib/Target/X86/X86TargetMachine.cpp
@@ -73,7 +73,7 @@ extern "C" LLVM_C_ABI void LLVMInitializeX86Target() {
   initializeX86LowerAMXTypeLegacyPassPass(PR);
   initializeX86PreTileConfigLegacyPass(PR);
   initializeGlobalISel(PR);
-  initializeWinEHStatePassPass(PR);
+  initializeWinEHStateLegacyPass(PR);
   initializeX86FixupBWInstLegacyPass(PR);
   initializeCompressEVEXLegacyPass(PR);
   initializeFixupLEAsLegacyPass(PR);
@@ -514,7 +514,7 @@ bool X86PassConfig::addPreISel() {
   // Only add this pass for 32-bit x86 Windows.
   const Triple &TT = TM->getTargetTriple();
   if (TT.isOSWindows() && TT.isX86_32())
-    addPass(createX86WinEHStatePass());
+    addPass(createX86WinEHStateLegacyPass());
   return true;
 }
 
diff --git a/llvm/lib/Target/X86/X86WinEHState.cpp b/llvm/lib/Target/X86/X86WinEHState.cpp
index b568f1b4086ed..114b347706e24 100644
--- a/llvm/lib/Target/X86/X86WinEHState.cpp
+++ b/llvm/lib/Target/X86/X86WinEHState.cpp
@@ -38,23 +38,18 @@ using namespace llvm;
 namespace {
 const int OverdefinedState = INT_MIN;
 
-class WinEHStatePass : public FunctionPass {
-public:
-  static char ID; // Pass identification, replacement for typeid.
-
-  WinEHStatePass() : FunctionPass(ID) {}
-
-  bool runOnFunction(Function &Fn) override;
+constexpr StringRef X86WinEHStatePassName =
+    "Windows 32-bit x86 EH state insertion";
 
-  bool doInitialization(Module &M) override;
+class WinEHStateFnPassImpl {
+public:
+  WinEHStateFnPassImpl() = default;
 
-  bool doFinalization(Module &M) override;
+  bool init(Module &M);
 
-  void getAnalysisUsage(AnalysisUsage &AU) const override;
+  bool finalize(Module &M);
 
-  StringRef getPassName() const override {
-    return "Windows 32-bit x86 EH state insertion";
-  }
+  bool runOnFunction(Function &F);
 
 private:
   void emitExceptionRegistrationRecord(Function *F);
@@ -115,21 +110,63 @@ class WinEHStatePass : public FunctionPass {
   /// The linked list node subobject inside of RegNode.
   Value *Link = nullptr;
 };
+
+class WinEHStateLegacy : public FunctionPass {
+public:
+  static char ID; // Pass identification, replacement for typeid.
+
+  WinEHStateLegacy() : FunctionPass(ID) {}
+
+  bool runOnFunction(Function &Fn) override { return Impl.runOnFunction(Fn); }
+
+  bool doInitialization(Module &M) override { return Impl.init(M); }
+
+  bool doFinalization(Module &M) override { return Impl.finalize(M); }
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+  StringRef getPassName() const override { return X86WinEHStatePassName; }
+
+private:
+  WinEHStateFnPassImpl Impl;
+};
+
 } // namespace
 
-FunctionPass *llvm::createX86WinEHStatePass() { return new WinEHStatePass(); }
+PreservedAnalyses X86WinEHStatePass::run(Module &M,
+                                         ModuleAnalysisManager &MAM) {
+  WinEHStateFnPassImpl Impl;
+  Impl.init(M);
+
+  bool Changed = false;
+  for (Function &F : M) {
+    bool ModifiedForFn = Impl.runOnFunction(F);
+    Changed = Changed || ModifiedForFn;
+  }
+
+  Impl.finalize(M);
+
+  // This pass should only insert a stack allocation, memory accesses, and
+  // localrecovers.
+  return Changed ? PreservedAnalyses::none().preserveSet<CFGAnalyses>()
+                 : PreservedAnalyses::all();
+}
+
+FunctionPass *llvm::createX86WinEHStateLegacyPass() {
+  return new WinEHStateLegacy();
+}
 
-char WinEHStatePass::ID = 0;
+char WinEHStateLegacy::ID = 0;
 
-INITIALIZE_PASS(WinEHStatePass, "x86-winehstate",
+INITIALIZE_PASS(WinEHStateLegacy, "x86-winehstate",
                 "Insert stores for EH state numbers", false, false)
 
-bool WinEHStatePass::doInitialization(Module &M) {
+bool WinEHStateFnPassImpl::init(Module &M) {
   TheModule = &M;
   return false;
 }
 
-bool WinEHStatePass::doFinalization(Module &M) {
+bool WinEHStateFnPassImpl::finalize(Module &M) {
   assert(TheModule == &M);
   TheModule = nullptr;
   EHLinkRegistrationTy = nullptr;
@@ -142,13 +179,13 @@ bool WinEHStatePass::doFinalization(Module &M) {
   return false;
 }
 
-void WinEHStatePass::getAnalysisUsage(AnalysisUsage &AU) const {
+void WinEHStateLegacy::getAnalysisUsage(AnalysisUsage &AU) const {
   // This pass should only insert a stack allocation, memory accesses, and
   // localrecovers.
   AU.setPreservesCFG();
 }
 
-bool WinEHStatePass::runOnFunction(Function &F) {
+bool WinEHStateFnPassImpl::runOnFunction(Function &F) {
   // Don't insert state stores or exception handler thunks for
   // available_externally functions. The handler needs to reference the LSDA,
   // which will not be emitted in this case.
@@ -213,7 +250,7 @@ bool WinEHStatePass::runOnFunction(Function &F) {
 ///     EHRegistrationNode *Next;
 ///     PEXCEPTION_ROUTINE Handler;
 ///   };
-Type *WinEHStatePass::getEHLinkRegistrationType() {
+Type *WinEHStateFnPassImpl::getEHLinkRegistrationType() {
   if (EHLinkRegistrationTy)
     return EHLinkRegistrationTy;
   LLVMContext &Context = TheModule->getContext();
@@ -231,7 +268,7 @@ Type *WinEHStatePass::getEHLinkRegistrationType() {
 ///     EHRegistrationNode SubRecord;
 ///     int32_t TryLevel;
 ///   };
-Type *WinEHStatePass::getCXXEHRegistrationType() {
+Type *WinEHStateFnPassImpl::getCXXEHRegistrationType() {
   if (CXXEHRegistrationTy)
     return CXXEHRegistrationTy;
   LLVMContext &Context = TheModule->getContext();
@@ -253,7 +290,7 @@ Type *WinEHStatePass::getCXXEHRegistrationType() {
 ///     int32_t EncodedScopeTable;
 ///     int32_t TryLevel;
 ///   };
-Type *WinEHStatePass::getSEHRegistrationType() {
+Type *WinEHStateFnPassImpl::getSEHRegistrationType() {
   if (SEHRegistrationTy)
     return SEHRegistrationTy;
   LLVMContext &Context = TheModule->getContext();
@@ -272,7 +309,7 @@ Type *WinEHStatePass::getSEHRegistrationType() {
 // common subobject of two pointers: the previous registration record (the old
 // fs:00) and the personality function for the current frame. The data before
 // and after that is personality function specific.
-void WinEHStatePass::emitExceptionRegistrationRecord(Function *F) {
+void WinEHStateFnPassImpl::emitExceptionRegistrationRecord(Function *F) {
   assert(Personality == EHPersonality::MSVC_CXX ||
          Personality == EHPersonality::MSVC_X86SEH);
 
@@ -373,7 +410,7 @@ void WinEHStatePass::emitExceptionRegistrationRecord(Function *F) {
   }
 }
 
-Value *WinEHStatePass::emitEHLSDA(IRBuilder<> &Builder, Function *F) {
+Value *WinEHStateFnPassImpl::emitEHLSDA(IRBuilder<> &Builder, Function *F) {
   return Builder.CreateIntrinsic(Intrinsic::x86_seh_lsda, F);
 }
 
@@ -384,7 +421,7 @@ Value *WinEHStatePass::emitEHLSDA(IRBuilder<> &Builder, Function *F) {
 /// We essentially want this code:
 ///   movl $lsda, %eax
 ///   jmpl ___CxxFrameHandler3
-Function *WinEHStatePass::generateLSDAInEAXThunk(Function *ParentFunc) {
+Function *WinEHStateFnPassImpl::generateLSDAInEAXThunk(Function *ParentFunc) {
   LLVMContext &Context = ParentFunc->getContext();
   Type *Int32Ty = Type::getInt32Ty(Context);
   Type *Int8PtrType = PointerType::getUnqual(Context);
@@ -417,8 +454,8 @@ Function *WinEHStatePass::generateLSDAInEAXThunk(Function *ParentFunc) {
   return Trampoline;
 }
 
-void WinEHStatePass::linkExceptionRegistration(IRBuilder<> &Builder,
-                                               Function *Handler) {
+void WinEHStateFnPassImpl::linkExceptionRegistration(IRBuilder<> &Builder,
+                                                     Function *Handler) {
   // Emit the .safeseh directive for this function.
   Handler->addFnAttr("safeseh");
 
@@ -434,7 +471,7 @@ void WinEHStatePass::linkExceptionRegistration(IRBuilder<> &Builder,
   Builder.CreateStore(Link, FSZero);
 }
 
-void WinEHStatePass::unlinkExceptionRegistration(IRBuilder<> &Builder) {
+void WinEHStateFnPassImpl::unlinkExceptionRegistration(IRBuilder<> &Builder) {
   // Clone Link into the current BB for better address mode folding.
   if (auto *GEP = dyn_cast<GetElementPtrInst>(Link)) {
     GEP = cast<GetElementPtrInst>(GEP->clone());
@@ -455,8 +492,8 @@ void WinEHStatePass::unlinkExceptionRegistration(IRBuilder<> &Builder) {
 // The idea behind _setjmp3 is that it takes an optional number of personality
 // specific parameters to indicate how to restore the personality-specific frame
 // state when longjmp is initiated.  Typically, the current TryLevel is saved.
-void WinEHStatePass::rewriteSetJmpCall(IRBuilder<> &Builder, Function &F,
-                                       CallBase &Call, Value *State) {
+void WinEHStateFnPassImpl::rewriteSetJmpCall(IRBuilder<> &Builder, Function &F,
+                                             CallBase &Call, Value *State) {
   // Don't rewrite calls with a weird number of arguments.
   if (Call.arg_size() != 2)
     return;
@@ -504,7 +541,7 @@ void WinEHStatePass::rewriteSetJmpCall(IRBuilder<> &Builder, Function &F,
 }
 
 // Figure out what state we should assign calls in this block.
-int WinEHStatePass::getBaseStateForBB(
+int WinEHStateFnPassImpl::getBaseStateForBB(
     DenseMap<BasicBlock *, ColorVector> &BlockColors, WinEHFuncInfo &FuncInfo,
     BasicBlock *BB) {
   int BaseState = ParentBaseState;
@@ -536,7 +573,7 @@ static bool isSehScopeBegin(const CallBase &Call) {
 }
 
 // Calculate the state a call-site is in.
-int WinEHStatePass::getStateForCall(
+int WinEHStateFnPassImpl::getStateForCall(
     DenseMap<BasicBlock *, ColorVector> &BlockColors, WinEHFuncInfo &FuncInfo,
     CallBase &Call) {
   if (auto *II = dyn_cast<InvokeInst>(&Call)) {
@@ -630,8 +667,8 @@ static int getSuccState(DenseMap<BasicBlock *, int> &InitialStates, Function &F,
   return CommonState;
 }
 
-bool WinEHStatePass::isStateStoreNeeded(EHPersonality Personality,
-                                        CallBase &Call) {
+bool WinEHStateFnPassImpl::isStateStoreNeeded(EHPersonality Personality,
+                                              CallBase &Call) {
   if (isSehScopeBegin(Call) || isSehScopeEnd(Call)) {
     return true;
   }
@@ -644,7 +681,8 @@ bool WinEHStatePass::isStateStoreNeeded(EHPersonality Personality,
   return !Call.doesNotThrow();
 }
 
-void WinEHStatePass::addStateStores(Function &F, WinEHFuncInfo &FuncInfo) {
+void WinEHStateFnPassImpl::addStateStores(Function &F,
+                                          WinEHFuncInfo &FuncInfo) {
   // Mark the registration node. The backend needs to know which alloca it is so
   // that it can recover the original frame pointer.
   IRBuilder<> Builder(RegNode->getNextNode());
@@ -798,14 +836,14 @@ void WinEHStatePass::addStateStores(Function &F, WinEHFuncInfo &FuncInfo) {
   }
 }
 
-void WinEHStatePass::insertStateNumberStore(Instruction *IP, int State) {
+void WinEHStateFnPassImpl::insertStateNumberStore(Instruction *IP, int State) {
   IRBuilder<> Builder(IP);
   Value *StateField =
       Builder.CreateStructGEP(RegNodeTy, RegNode, StateFieldIndex);
   Builder.CreateStore(Builder.getInt32(State), StateField);
 }
 
-void WinEHStatePass::updateEspForInAllocas(Function &F) {
+void WinEHStateFnPassImpl::updateEspForInAllocas(Function &F) {
   for (BasicBlock &BB : F) {
     for (Instruction &I : BB) {
       if (auto *Alloca = dyn_cast<AllocaInst>(&I)) {

``````````

</details>


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


More information about the llvm-commits mailing list