[llvm] [PassInstrumentation] Make getPassNameForClassName return optional (PR #150029)

Danila Malyutin via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 22 08:36:35 PDT 2025


https://github.com/danilaml updated https://github.com/llvm/llvm-project/pull/150029

>From 3c3ed5a6a9144fbf48519471e2dd7ff0fadf49bf Mon Sep 17 00:00:00 2001
From: Danila Malyutin <dmalyutin at azul.com>
Date: Tue, 22 Jul 2025 17:47:32 +0400
Subject: [PATCH 1/2] [PassInstrumentation] Make getPassNameForClassName return
 optional

Don't modify ClassToPassName map unless ClassName is found.
Instead, return nullopt if there is no matching entry. This will
prevent possible dangling references in ClassToPassName map in case
of ClassName being freed.
See https://github.com/llvm/llvm-project/pull/145059/files#r2219763671 for more context.
---
 llvm/include/llvm/IR/PassInstrumentation.h    |  6 ++++--
 llvm/include/llvm/Passes/CodeGenPassBuilder.h |  3 ++-
 llvm/lib/IR/PassInstrumentation.cpp           |  8 ++++++--
 llvm/lib/LTO/LTOBackend.cpp                   |  2 +-
 llvm/lib/Passes/StandardInstrumentations.cpp  | 17 +++++++++--------
 llvm/tools/llc/NewPMDriver.cpp                |  2 +-
 llvm/tools/opt/NewPMDriver.cpp                |  2 +-
 7 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/llvm/include/llvm/IR/PassInstrumentation.h b/llvm/include/llvm/IR/PassInstrumentation.h
index 031571599f9ad..628103c7fe759 100644
--- a/llvm/include/llvm/IR/PassInstrumentation.h
+++ b/llvm/include/llvm/IR/PassInstrumentation.h
@@ -165,7 +165,8 @@ class PassInstrumentationCallbacks {
   /// Add a class name to pass name mapping for use by pass instrumentation.
   LLVM_ABI void addClassToPassName(StringRef ClassName, StringRef PassName);
   /// Get the pass name for a given pass class name.
-  LLVM_ABI StringRef getPassNameForClassName(StringRef ClassName);
+  LLVM_ABI std::optional<StringRef>
+  getPassNameForClassName(StringRef ClassName);
 
 private:
   friend class PassInstrumentation;
@@ -339,7 +340,8 @@ class PassInstrumentation {
   /// Get the pass name for a given pass class name.
   StringRef getPassNameForClassName(StringRef ClassName) const {
     if (Callbacks)
-      return Callbacks->getPassNameForClassName(ClassName);
+      return Callbacks->getPassNameForClassName(ClassName).value_or(
+          StringRef());
     return {};
   }
 };
diff --git a/llvm/include/llvm/Passes/CodeGenPassBuilder.h b/llvm/include/llvm/Passes/CodeGenPassBuilder.h
index b0360f1903c0e..a392f457c2b3b 100644
--- a/llvm/include/llvm/Passes/CodeGenPassBuilder.h
+++ b/llvm/include/llvm/Passes/CodeGenPassBuilder.h
@@ -681,7 +681,8 @@ void CodeGenPassBuilder<Derived, TargetMachineT>::setStartStopPasses(
       }
 
       auto PassName = PIC->getPassNameForClassName(ClassName);
-      if (Info.StartPass == PassName && ++Count == Info.StartInstanceNum)
+      if (PassName && Info.StartPass == *PassName &&
+          ++Count == Info.StartInstanceNum)
         Started = !Info.StartAfter;
 
       return Started;
diff --git a/llvm/lib/IR/PassInstrumentation.cpp b/llvm/lib/IR/PassInstrumentation.cpp
index 94ad124a6c770..ee0ed8807ed12 100644
--- a/llvm/lib/IR/PassInstrumentation.cpp
+++ b/llvm/lib/IR/PassInstrumentation.cpp
@@ -23,17 +23,21 @@ template struct LLVM_EXPORT_TEMPLATE Any::TypeId<const Loop *>;
 
 void PassInstrumentationCallbacks::addClassToPassName(StringRef ClassName,
                                                       StringRef PassName) {
+  assert(!PassName.empty() && "PassName can't be empty!");
   ClassToPassName.try_emplace(ClassName, PassName.str());
 }
 
-StringRef
+std::optional<StringRef>
 PassInstrumentationCallbacks::getPassNameForClassName(StringRef ClassName) {
   if (!ClassToPassNameCallbacks.empty()) {
     for (auto &Fn : ClassToPassNameCallbacks)
       Fn();
     ClassToPassNameCallbacks.clear();
   }
-  return ClassToPassName[ClassName];
+  auto PassNameIter = ClassToPassName.find(ClassName);
+  if (PassNameIter != ClassToPassName.end())
+    return PassNameIter->second;
+  return std::nullopt;
 }
 
 AnalysisKey PassInstrumentationAnalysis::Key;
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index 5e8cd12fe040b..4d4370394dece 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -346,7 +346,7 @@ static void runNewPMPasses(const Config &Conf, Module &Mod, TargetMachine *TM,
     raw_string_ostream OS(PipelineStr);
     MPM.printPipeline(OS, [&PIC](StringRef ClassName) {
       auto PassName = PIC.getPassNameForClassName(ClassName);
-      return PassName.empty() ? ClassName : PassName;
+      return PassName ? ClassName : *PassName;
     });
     outs() << "pipeline-passes: " << PipelineStr << '\n';
   }
diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp
index f165e85baf611..0155ea44bb8e9 100644
--- a/llvm/lib/Passes/StandardInstrumentations.cpp
+++ b/llvm/lib/Passes/StandardInstrumentations.cpp
@@ -454,12 +454,12 @@ template <typename T>
 void ChangeReporter<T>::registerRequiredCallbacks(
     PassInstrumentationCallbacks &PIC) {
   PIC.registerBeforeNonSkippedPassCallback([&PIC, this](StringRef P, Any IR) {
-    saveIRBeforePass(IR, P, PIC.getPassNameForClassName(P));
+    saveIRBeforePass(IR, P, PIC.getPassNameForClassName(P).value_or(""));
   });
 
   PIC.registerAfterPassCallback(
       [&PIC, this](StringRef P, Any IR, const PreservedAnalyses &) {
-        handleIRAfterPass(IR, P, PIC.getPassNameForClassName(P));
+        handleIRAfterPass(IR, P, PIC.getPassNameForClassName(P).value_or(""));
       });
   PIC.registerAfterPassInvalidatedCallback(
       [this](StringRef P, const PreservedAnalyses &) {
@@ -970,7 +970,7 @@ bool PrintIRInstrumentation::shouldPrintBeforePass(StringRef PassID) {
   if (shouldPrintBeforeAll())
     return true;
 
-  StringRef PassName = PIC->getPassNameForClassName(PassID);
+  StringRef PassName = PIC->getPassNameForClassName(PassID).value_or("");
   return is_contained(printBeforePasses(), PassName);
 }
 
@@ -978,7 +978,7 @@ bool PrintIRInstrumentation::shouldPrintAfterPass(StringRef PassID) {
   if (shouldPrintAfterAll())
     return true;
 
-  StringRef PassName = PIC->getPassNameForClassName(PassID);
+  StringRef PassName = PIC->getPassNameForClassName(PassID).value_or("");
   return is_contained(printAfterPasses(), PassName);
 }
 
@@ -1080,10 +1080,10 @@ void OptPassGateInstrumentation::registerCallbacks(
 
   PIC.registerShouldRunOptionalPassCallback(
       [this, &PIC](StringRef ClassName, Any IR) {
-        StringRef PassName = PIC.getPassNameForClassName(ClassName);
-        if (PassName.empty())
+        auto PassName = PIC.getPassNameForClassName(ClassName);
+        if (!PassName)
           return this->shouldRun(ClassName, IR);
-        return this->shouldRun(PassName, IR);
+        return this->shouldRun(*PassName, IR);
       });
 }
 
@@ -2501,7 +2501,8 @@ void PrintCrashIRInstrumentation::registerCallbacks(
         raw_string_ostream OS(SavedIR);
         OS << formatv("*** Dump of {0}IR Before Last Pass {1}",
                       llvm::forcePrintModuleIR() ? "Module " : "", PassID);
-        if (!isInteresting(IR, PassID, PIC.getPassNameForClassName(PassID))) {
+        if (!isInteresting(IR, PassID,
+                           PIC.getPassNameForClassName(PassID).value_or(""))) {
           OS << " Filtered Out ***\n";
           return;
         }
diff --git a/llvm/tools/llc/NewPMDriver.cpp b/llvm/tools/llc/NewPMDriver.cpp
index fa82689ecf9ae..559aff3533a64 100644
--- a/llvm/tools/llc/NewPMDriver.cpp
+++ b/llvm/tools/llc/NewPMDriver.cpp
@@ -164,7 +164,7 @@ int llvm::compileModuleWithNewPM(
     raw_string_ostream OS(PipelineStr);
     MPM.printPipeline(OS, [&PIC](StringRef ClassName) {
       auto PassName = PIC.getPassNameForClassName(ClassName);
-      return PassName.empty() ? ClassName : PassName;
+      return PassName ? ClassName : *PassName;
     });
     outs() << PipelineStr << '\n';
     return 0;
diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp
index 7d168a6ceb17c..dda7204718252 100644
--- a/llvm/tools/opt/NewPMDriver.cpp
+++ b/llvm/tools/opt/NewPMDriver.cpp
@@ -534,7 +534,7 @@ bool llvm::runPassPipeline(
     raw_string_ostream SOS(Pipeline);
     MPM.printPipeline(SOS, [&PIC](StringRef ClassName) {
       auto PassName = PIC.getPassNameForClassName(ClassName);
-      return PassName.empty() ? ClassName : PassName;
+      return PassName ? ClassName : *PassName;
     });
     outs() << Pipeline;
     outs() << "\n";

>From 16f12ce9f0089ce22651eb4d438defd7144539b5 Mon Sep 17 00:00:00 2001
From: Danila Malyutin <dmalyutin at azul.com>
Date: Tue, 22 Jul 2025 19:32:30 +0400
Subject: [PATCH 2/2] Use empty StringRef instead of nullopt optional

---
 llvm/include/llvm/IR/PassInstrumentation.h    |  8 +++-----
 llvm/include/llvm/Passes/CodeGenPassBuilder.h |  3 +--
 llvm/lib/IR/PassInstrumentation.cpp           |  4 ++--
 llvm/lib/LTO/LTOBackend.cpp                   |  2 +-
 llvm/lib/Passes/StandardInstrumentations.cpp  | 17 ++++++++---------
 llvm/tools/llc/NewPMDriver.cpp                |  2 +-
 llvm/tools/opt/NewPMDriver.cpp                |  2 +-
 7 files changed, 17 insertions(+), 21 deletions(-)

diff --git a/llvm/include/llvm/IR/PassInstrumentation.h b/llvm/include/llvm/IR/PassInstrumentation.h
index 628103c7fe759..33eda5a4222f1 100644
--- a/llvm/include/llvm/IR/PassInstrumentation.h
+++ b/llvm/include/llvm/IR/PassInstrumentation.h
@@ -164,9 +164,8 @@ class PassInstrumentationCallbacks {
 
   /// Add a class name to pass name mapping for use by pass instrumentation.
   LLVM_ABI void addClassToPassName(StringRef ClassName, StringRef PassName);
-  /// Get the pass name for a given pass class name.
-  LLVM_ABI std::optional<StringRef>
-  getPassNameForClassName(StringRef ClassName);
+  /// Get the pass name for a given pass class name. Empty if no match found.
+  LLVM_ABI StringRef getPassNameForClassName(StringRef ClassName);
 
 private:
   friend class PassInstrumentation;
@@ -340,8 +339,7 @@ class PassInstrumentation {
   /// Get the pass name for a given pass class name.
   StringRef getPassNameForClassName(StringRef ClassName) const {
     if (Callbacks)
-      return Callbacks->getPassNameForClassName(ClassName).value_or(
-          StringRef());
+      return Callbacks->getPassNameForClassName(ClassName);
     return {};
   }
 };
diff --git a/llvm/include/llvm/Passes/CodeGenPassBuilder.h b/llvm/include/llvm/Passes/CodeGenPassBuilder.h
index a392f457c2b3b..b0360f1903c0e 100644
--- a/llvm/include/llvm/Passes/CodeGenPassBuilder.h
+++ b/llvm/include/llvm/Passes/CodeGenPassBuilder.h
@@ -681,8 +681,7 @@ void CodeGenPassBuilder<Derived, TargetMachineT>::setStartStopPasses(
       }
 
       auto PassName = PIC->getPassNameForClassName(ClassName);
-      if (PassName && Info.StartPass == *PassName &&
-          ++Count == Info.StartInstanceNum)
+      if (Info.StartPass == PassName && ++Count == Info.StartInstanceNum)
         Started = !Info.StartAfter;
 
       return Started;
diff --git a/llvm/lib/IR/PassInstrumentation.cpp b/llvm/lib/IR/PassInstrumentation.cpp
index ee0ed8807ed12..70bbe8f6234b1 100644
--- a/llvm/lib/IR/PassInstrumentation.cpp
+++ b/llvm/lib/IR/PassInstrumentation.cpp
@@ -27,7 +27,7 @@ void PassInstrumentationCallbacks::addClassToPassName(StringRef ClassName,
   ClassToPassName.try_emplace(ClassName, PassName.str());
 }
 
-std::optional<StringRef>
+StringRef
 PassInstrumentationCallbacks::getPassNameForClassName(StringRef ClassName) {
   if (!ClassToPassNameCallbacks.empty()) {
     for (auto &Fn : ClassToPassNameCallbacks)
@@ -37,7 +37,7 @@ PassInstrumentationCallbacks::getPassNameForClassName(StringRef ClassName) {
   auto PassNameIter = ClassToPassName.find(ClassName);
   if (PassNameIter != ClassToPassName.end())
     return PassNameIter->second;
-  return std::nullopt;
+  return {};
 }
 
 AnalysisKey PassInstrumentationAnalysis::Key;
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index 4d4370394dece..5e8cd12fe040b 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -346,7 +346,7 @@ static void runNewPMPasses(const Config &Conf, Module &Mod, TargetMachine *TM,
     raw_string_ostream OS(PipelineStr);
     MPM.printPipeline(OS, [&PIC](StringRef ClassName) {
       auto PassName = PIC.getPassNameForClassName(ClassName);
-      return PassName ? ClassName : *PassName;
+      return PassName.empty() ? ClassName : PassName;
     });
     outs() << "pipeline-passes: " << PipelineStr << '\n';
   }
diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp
index 0155ea44bb8e9..f165e85baf611 100644
--- a/llvm/lib/Passes/StandardInstrumentations.cpp
+++ b/llvm/lib/Passes/StandardInstrumentations.cpp
@@ -454,12 +454,12 @@ template <typename T>
 void ChangeReporter<T>::registerRequiredCallbacks(
     PassInstrumentationCallbacks &PIC) {
   PIC.registerBeforeNonSkippedPassCallback([&PIC, this](StringRef P, Any IR) {
-    saveIRBeforePass(IR, P, PIC.getPassNameForClassName(P).value_or(""));
+    saveIRBeforePass(IR, P, PIC.getPassNameForClassName(P));
   });
 
   PIC.registerAfterPassCallback(
       [&PIC, this](StringRef P, Any IR, const PreservedAnalyses &) {
-        handleIRAfterPass(IR, P, PIC.getPassNameForClassName(P).value_or(""));
+        handleIRAfterPass(IR, P, PIC.getPassNameForClassName(P));
       });
   PIC.registerAfterPassInvalidatedCallback(
       [this](StringRef P, const PreservedAnalyses &) {
@@ -970,7 +970,7 @@ bool PrintIRInstrumentation::shouldPrintBeforePass(StringRef PassID) {
   if (shouldPrintBeforeAll())
     return true;
 
-  StringRef PassName = PIC->getPassNameForClassName(PassID).value_or("");
+  StringRef PassName = PIC->getPassNameForClassName(PassID);
   return is_contained(printBeforePasses(), PassName);
 }
 
@@ -978,7 +978,7 @@ bool PrintIRInstrumentation::shouldPrintAfterPass(StringRef PassID) {
   if (shouldPrintAfterAll())
     return true;
 
-  StringRef PassName = PIC->getPassNameForClassName(PassID).value_or("");
+  StringRef PassName = PIC->getPassNameForClassName(PassID);
   return is_contained(printAfterPasses(), PassName);
 }
 
@@ -1080,10 +1080,10 @@ void OptPassGateInstrumentation::registerCallbacks(
 
   PIC.registerShouldRunOptionalPassCallback(
       [this, &PIC](StringRef ClassName, Any IR) {
-        auto PassName = PIC.getPassNameForClassName(ClassName);
-        if (!PassName)
+        StringRef PassName = PIC.getPassNameForClassName(ClassName);
+        if (PassName.empty())
           return this->shouldRun(ClassName, IR);
-        return this->shouldRun(*PassName, IR);
+        return this->shouldRun(PassName, IR);
       });
 }
 
@@ -2501,8 +2501,7 @@ void PrintCrashIRInstrumentation::registerCallbacks(
         raw_string_ostream OS(SavedIR);
         OS << formatv("*** Dump of {0}IR Before Last Pass {1}",
                       llvm::forcePrintModuleIR() ? "Module " : "", PassID);
-        if (!isInteresting(IR, PassID,
-                           PIC.getPassNameForClassName(PassID).value_or(""))) {
+        if (!isInteresting(IR, PassID, PIC.getPassNameForClassName(PassID))) {
           OS << " Filtered Out ***\n";
           return;
         }
diff --git a/llvm/tools/llc/NewPMDriver.cpp b/llvm/tools/llc/NewPMDriver.cpp
index 559aff3533a64..fa82689ecf9ae 100644
--- a/llvm/tools/llc/NewPMDriver.cpp
+++ b/llvm/tools/llc/NewPMDriver.cpp
@@ -164,7 +164,7 @@ int llvm::compileModuleWithNewPM(
     raw_string_ostream OS(PipelineStr);
     MPM.printPipeline(OS, [&PIC](StringRef ClassName) {
       auto PassName = PIC.getPassNameForClassName(ClassName);
-      return PassName ? ClassName : *PassName;
+      return PassName.empty() ? ClassName : PassName;
     });
     outs() << PipelineStr << '\n';
     return 0;
diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp
index dda7204718252..7d168a6ceb17c 100644
--- a/llvm/tools/opt/NewPMDriver.cpp
+++ b/llvm/tools/opt/NewPMDriver.cpp
@@ -534,7 +534,7 @@ bool llvm::runPassPipeline(
     raw_string_ostream SOS(Pipeline);
     MPM.printPipeline(SOS, [&PIC](StringRef ClassName) {
       auto PassName = PIC.getPassNameForClassName(ClassName);
-      return PassName ? ClassName : *PassName;
+      return PassName.empty() ? ClassName : PassName;
     });
     outs() << Pipeline;
     outs() << "\n";



More information about the llvm-commits mailing list