[llvm] 4b42944 - [profcheck] Don't verify generated global ctors/dtors (#170597)

via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 4 13:01:51 PST 2025


Author: Mircea Trofin
Date: 2025-12-04T13:01:46-08:00
New Revision: 4b4294473280a8e37d818a9362e33544799cb4e4

URL: https://github.com/llvm/llvm-project/commit/4b4294473280a8e37d818a9362e33544799cb4e4
DIFF: https://github.com/llvm/llvm-project/commit/4b4294473280a8e37d818a9362e33544799cb4e4.diff

LOG: [profcheck] Don't verify generated global ctors/dtors (#170597)

Functions listed in `llvm.global_ctors` or `llvm.global_dtors` aren't too interesting for performance. Passes like LowerTypeTests synthesize some of these, and, while we could add a "0" entry count explicitly, we can also just not bother verifying in the first place.

Added: 
    llvm/test/Transforms/PGOProfile/profcheck-llvm.global_ctors.ll

Modified: 
    llvm/include/llvm/Transforms/Utils/ProfileVerify.h
    llvm/lib/Passes/PassRegistry.def
    llvm/lib/Transforms/Utils/ProfileVerify.cpp
    llvm/test/Transforms/PGOProfile/prof-verify-known-cold.ll
    llvm/test/Transforms/PGOProfile/prof-verify.ll
    llvm/tools/opt/NewPMDriver.cpp
    llvm/utils/profcheck-xfail.txt

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Transforms/Utils/ProfileVerify.h b/llvm/include/llvm/Transforms/Utils/ProfileVerify.h
index 5c9c44c23bc01..bf953b529b80c 100644
--- a/llvm/include/llvm/Transforms/Utils/ProfileVerify.h
+++ b/llvm/include/llvm/Transforms/Utils/ProfileVerify.h
@@ -13,6 +13,7 @@
 #ifndef LLVM_TRANSFORMS_UTILS_PROFILEVERIFY_H
 #define LLVM_TRANSFORMS_UTILS_PROFILEVERIFY_H
 
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/IR/Analysis.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/Support/Compiler.h"
@@ -29,8 +30,15 @@ class ProfileInjectorPass : public PassInfoMixin<ProfileInjectorPass> {
 /// in conjunction with the ProfileInjectorPass. MD_prof "unknown" is considered
 /// valid (i.e. !{!"unknown"})
 class ProfileVerifierPass : public PassInfoMixin<ProfileVerifierPass> {
+  DenseSet<const Function *> IgnoreList;
+  // This pass is mostly a function pass but we want to initialize the
+  // IngoreList once, which is why we present it as a module-level pass. We make
+  // the function-level run private to avoid accidentally hooking up the pass as
+  // a function pass.
+  PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
+
 public:
-  LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
+  LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
 };
 
 } // namespace llvm

diff  --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index e9874ecd553ee..cf998f29ef38c 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -149,6 +149,7 @@ MODULE_PASS("print<ir2vec>", IR2VecPrinterPass(errs()))
 MODULE_PASS("print<ir2vec-vocab>", IR2VecVocabPrinterPass(errs()))
 MODULE_PASS("print<module-debuginfo>", ModuleDebugInfoPrinterPass(errs()))
 MODULE_PASS("print<reg-usage>", PhysicalRegisterUsageInfoPrinterPass(errs()))
+MODULE_PASS("prof-verify", ProfileVerifierPass())
 MODULE_PASS("pseudo-probe", SampleProfileProbePass(TM))
 MODULE_PASS("pseudo-probe-update", PseudoProbeUpdatePass())
 MODULE_PASS("recompute-globalsaa", RecomputeGlobalsAAPass())
@@ -526,7 +527,6 @@ FUNCTION_PASS("print<scev-division>", SCEVDivisionPrinterPass(errs()))
 FUNCTION_PASS("print<stack-safety-local>", StackSafetyPrinterPass(errs()))
 FUNCTION_PASS("print<uniformity>", UniformityInfoPrinterPass(errs()))
 FUNCTION_PASS("prof-inject", ProfileInjectorPass())
-FUNCTION_PASS("prof-verify", ProfileVerifierPass())
 FUNCTION_PASS("reassociate", ReassociatePass())
 FUNCTION_PASS("redundant-dbg-inst-elim", RedundantDbgInstEliminationPass())
 FUNCTION_PASS("replace-with-veclib", ReplaceWithVeclib())

diff  --git a/llvm/lib/Transforms/Utils/ProfileVerify.cpp b/llvm/lib/Transforms/Utils/ProfileVerify.cpp
index ca6bd91b1f530..69e03f01245db 100644
--- a/llvm/lib/Transforms/Utils/ProfileVerify.cpp
+++ b/llvm/lib/Transforms/Utils/ProfileVerify.cpp
@@ -11,13 +11,19 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Analysis/BranchProbabilityInfo.h"
 #include "llvm/IR/Analysis.h"
+#include "llvm/IR/Constants.h"
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/GlobalVariable.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/MDBuilder.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
 #include "llvm/IR/ProfDataUtils.h"
 #include "llvm/Support/BranchProbability.h"
+#include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
 
 using namespace llvm;
@@ -189,11 +195,43 @@ PreservedAnalyses ProfileInjectorPass::run(Function &F,
   return PreservedAnalyses::none();
 }
 
+PreservedAnalyses ProfileVerifierPass::run(Module &M,
+                                           ModuleAnalysisManager &MAM) {
+  auto PopulateIgnoreList = [&](StringRef GVName) {
+    if (const auto *CT = M.getGlobalVariable(GVName))
+      if (const auto *CA =
+              dyn_cast_if_present<ConstantArray>(CT->getInitializer()))
+        for (const auto &Elt : CA->operands())
+          if (const auto *CS = dyn_cast<ConstantStruct>(Elt))
+            if (CS->getNumOperands() >= 2 && CS->getOperand(1))
+              if (const auto *F = dyn_cast<Function>(
+                      CS->getOperand(1)->stripPointerCasts()))
+                IgnoreList.insert(F);
+  };
+  PopulateIgnoreList("llvm.global_ctors");
+  PopulateIgnoreList("llvm.global_dtors");
+
+  // expose the function-level run as public through a wrapper, so we can use
+  // pass manager mechanisms dealing with declarations and with composing the
+  // returned PreservedAnalyses values.
+  struct Wrapper : PassInfoMixin<Wrapper> {
+    ProfileVerifierPass &PVP;
+    PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM) {
+      return PVP.run(F, FAM);
+    }
+    explicit Wrapper(ProfileVerifierPass &PVP) : PVP(PVP) {}
+  };
+
+  return createModuleToFunctionPassAdaptor(Wrapper(*this)).run(M, MAM);
+}
+
 PreservedAnalyses ProfileVerifierPass::run(Function &F,
                                            FunctionAnalysisManager &FAM) {
   // skip purely asm functions
   if (isAsmOnly(F))
     return PreservedAnalyses::all();
+  if (IgnoreList.contains(&F))
+    return PreservedAnalyses::all();
 
   const auto EntryCount = F.getEntryCount(/*AllowSynthetic=*/true);
   if (!EntryCount) {

diff  --git a/llvm/test/Transforms/PGOProfile/prof-verify-known-cold.ll b/llvm/test/Transforms/PGOProfile/prof-verify-known-cold.ll
index 7875300006761..9fa2732fbc6b5 100644
--- a/llvm/test/Transforms/PGOProfile/prof-verify-known-cold.ll
+++ b/llvm/test/Transforms/PGOProfile/prof-verify-known-cold.ll
@@ -1,6 +1,6 @@
 ; Test prof-verify for functions explicitly marked as cold
 
-; RUN: opt -passes=prof-inject,prof-verify %s -o - 2>&1 | FileCheck %s
+; RUN: opt -passes=function(prof-inject),module(prof-verify) %s -o - 2>&1 | FileCheck %s
 
 define void @foo(i32 %i) !prof !0 {
   %c = icmp eq i32 %i, 0

diff  --git a/llvm/test/Transforms/PGOProfile/prof-verify.ll b/llvm/test/Transforms/PGOProfile/prof-verify.ll
index 75d1e6a3db571..90a20b68ab23c 100644
--- a/llvm/test/Transforms/PGOProfile/prof-verify.ll
+++ b/llvm/test/Transforms/PGOProfile/prof-verify.ll
@@ -6,7 +6,7 @@
 
 ; RUN: opt -passes=prof-inject %s -S -o - | FileCheck %s --check-prefix=INJECT
 ; RUN: not opt -passes=prof-verify %s -S -o - 2>&1 | FileCheck %s --check-prefix=VERIFY
-; RUN: opt -passes=prof-inject,prof-verify %s --disable-output
+; RUN: opt -passes=function(prof-inject),module(prof-verify) %s --disable-output
 ; RUN: opt -enable-profcheck %s -S -o - | FileCheck %s --check-prefix=INJECT
 
 define void @foo(i32 %i) !prof !0 {

diff  --git a/llvm/test/Transforms/PGOProfile/profcheck-llvm.global_ctors.ll b/llvm/test/Transforms/PGOProfile/profcheck-llvm.global_ctors.ll
new file mode 100644
index 0000000000000..84c680fc158ac
--- /dev/null
+++ b/llvm/test/Transforms/PGOProfile/profcheck-llvm.global_ctors.ll
@@ -0,0 +1,13 @@
+; RUN: opt -passes=prof-verify %s -o - 2>&1 | FileCheck %s
+ at llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @ctor, ptr null }]
+ at llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @dtor, ptr null }]
+
+define internal void @ctor() {
+  ret void
+}
+
+define internal void @dtor() {
+  ret void
+}
+
+; CHECK-NOT: Profile verification failed: function entry count missing

diff  --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp
index 3209b652b44b4..eaa1d8f958a4d 100644
--- a/llvm/tools/opt/NewPMDriver.cpp
+++ b/llvm/tools/opt/NewPMDriver.cpp
@@ -520,7 +520,7 @@ bool llvm::runPassPipeline(
         false, "", nullptr, DebugifyMode::OriginalDebugInfo,
         &DebugInfoBeforePass, VerifyDIPreserveExport));
   if (EnableProfcheck)
-    MPM.addPass(createModuleToFunctionPassAdaptor(ProfileVerifierPass()));
+    MPM.addPass(ProfileVerifierPass());
 
   // Add any relevant output pass at the end of the pipeline.
   switch (OK) {

diff  --git a/llvm/utils/profcheck-xfail.txt b/llvm/utils/profcheck-xfail.txt
index 980f99687c4cc..3cde50de7d0c1 100644
--- a/llvm/utils/profcheck-xfail.txt
+++ b/llvm/utils/profcheck-xfail.txt
@@ -20,7 +20,6 @@ CodeGen/X86/masked_gather_scatter.ll
 DebugInfo/AArch64/ir-outliner.ll
 DebugInfo/assignment-tracking/X86/hotcoldsplit.ll
 DebugInfo/Generic/block-asan.ll
-DebugInfo/X86/asan_debug_info.ll
 LTO/X86/diagnostic-handler-remarks-with-hotness.ll
 Other/optimization-remarks-auto.ll
 Transforms/AtomicExpand/ARM/atomic-expansion-v7.ll
@@ -475,10 +474,6 @@ Transforms/LowerConstantIntrinsics/objectsize_basic.ll
 Transforms/LowerGlobalDestructors/lower-global-dtors-existing-dos_handle.ll
 Transforms/LowerGlobalDestructors/lower-global-dtors.ll
 Transforms/LowerGlobalDestructors/non-literal-type.ll
-Transforms/LowerIFunc/ifunc-alias.ll
-Transforms/LowerIFunc/ifunc-nonsense-resolvers.ll
-Transforms/LowerIFunc/ifunc-program-addrspace.ll
-Transforms/LowerIFunc/lower-ifunc.ll
 Transforms/LowerMatrixIntrinsics/data-layout-multiply-fused.ll
 Transforms/LowerMatrixIntrinsics/multiply-fused-dominance.ll
 Transforms/LowerMatrixIntrinsics/multiply-fused.ll
@@ -498,9 +493,6 @@ Transforms/LowerSwitch/do-not-handle-impossible-values.ll
 Transforms/LowerSwitch/feature.ll
 Transforms/LowerSwitch/fold-popular-case-to-unreachable-default.ll
 Transforms/LowerSwitch/pr59316.ll
-Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll
-Transforms/LowerTypeTests/function.ll
-Transforms/LowerTypeTests/function-weak.ll
 Transforms/LowerTypeTests/import.ll
 Transforms/LowerTypeTests/simple.ll
 Transforms/MergeFunc/2011-02-08-RemoveEqual.ll


        


More information about the llvm-commits mailing list