Skip to content

Conversation

@mtrofin
Copy link
Member

@mtrofin mtrofin commented Nov 17, 2025

We can't do anything meaningful to such functions: they aren't optimizable, and even if inlined, they would bring no code open to optimization.

Copy link
Member Author

mtrofin commented Nov 17, 2025

This stack of pull requests is managed by Graphite. Learn more about stacking.

@mtrofin mtrofin force-pushed the users/mtrofin/11-17-_profcheck_exclude_naked_functions_from_profcheck branch from e677112 to 7605200 Compare November 17, 2025 22:05
@mtrofin mtrofin changed the title [profcheck] Exclude naked functions from profcheck [profcheck] Exclude naked, asm-only functions from profcheck Nov 17, 2025
@mtrofin mtrofin marked this pull request as ready for review November 17, 2025 22:06
@llvmbot llvmbot added PGO Profile Guided Optimizations llvm:transforms labels Nov 17, 2025
@llvmbot
Copy link
Member

llvmbot commented Nov 17, 2025

@llvm/pr-subscribers-pgo

@llvm/pr-subscribers-llvm-transforms

Author: Mircea Trofin (mtrofin)

Changes

We can't do anything meaningful to such functions: they aren't optimizable, and even if inlined, they would bring no code open to optimization.


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

2 Files Affected:

  • (modified) llvm/lib/Transforms/Utils/ProfileVerify.cpp (+19)
  • (added) llvm/test/Transforms/PGOProfile/profcheck-exclusions.ll (+10)
diff --git a/llvm/lib/Transforms/Utils/ProfileVerify.cpp b/llvm/lib/Transforms/Utils/ProfileVerify.cpp
index c7cf8256d393c..ca6bd91b1f530 100644
--- a/llvm/lib/Transforms/Utils/ProfileVerify.cpp
+++ b/llvm/lib/Transforms/Utils/ProfileVerify.cpp
@@ -65,11 +65,26 @@ class ProfileInjector {
   ProfileInjector(Function &F, FunctionAnalysisManager &FAM) : F(F), FAM(FAM) {}
   bool inject();
 };
+
+bool isAsmOnly(const Function &F) {
+  if (!F.hasFnAttribute(Attribute::AttrKind::Naked))
+    return false;
+  for (const auto &BB : F)
+    for (const auto &I : drop_end(BB.instructionsWithoutDebug())) {
+      const auto *CB = dyn_cast<CallBase>(&I);
+      if (!CB || !CB->isInlineAsm())
+        return false;
+    }
+  return true;
+}
 } // namespace
 
 // FIXME: currently this injects only for terminators. Select isn't yet
 // supported.
 bool ProfileInjector::inject() {
+  // skip purely asm functions
+  if (isAsmOnly(F))
+    return false;
   // Get whatever branch probability info can be derived from the given IR -
   // whether it has or not metadata. The main intention for this pass is to
   // ensure that other passes don't drop or "forget" to update MD_prof. We do
@@ -176,6 +191,10 @@ PreservedAnalyses ProfileInjectorPass::run(Function &F,
 
 PreservedAnalyses ProfileVerifierPass::run(Function &F,
                                            FunctionAnalysisManager &FAM) {
+  // skip purely asm functions
+  if (isAsmOnly(F))
+    return PreservedAnalyses::all();
+
   const auto EntryCount = F.getEntryCount(/*AllowSynthetic=*/true);
   if (!EntryCount) {
     auto *MD = F.getMetadata(LLVMContext::MD_prof);
diff --git a/llvm/test/Transforms/PGOProfile/profcheck-exclusions.ll b/llvm/test/Transforms/PGOProfile/profcheck-exclusions.ll
new file mode 100644
index 0000000000000..a2420be4fac30
--- /dev/null
+++ b/llvm/test/Transforms/PGOProfile/profcheck-exclusions.ll
@@ -0,0 +1,10 @@
+; RUN: opt -passes=prof-inject %s -S -o - | FileCheck %s
+; RUN: opt -passes=prof-verify %s --disable-output
+
+
+define void @bar(i1 %c) #0 {
+  ret void
+}
+
+attributes #0 = { naked }
+; CHECK-NOT: !prof

@github-actions
Copy link

🐧 Linux x64 Test Results

  • 186262 tests passed
  • 4848 tests skipped

bool isAsmOnly(const Function &F) {
if (!F.hasFnAttribute(Attribute::AttrKind::Naked))
return false;
for (const auto &BB : F)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just check for the attribute, it's invalid to have anything other than asm in a naked function.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought so too initially, but then (1) read https://llvm.org/docs/LangRef.html which just says

This attribute disables prologue / epilogue emission for the function. This can have very system-specific consequences. The arguments of a naked function can not be referenced through IR values.

...which is more permissive; and (2) couldn't find any check in Verifier.cpp that's more than

  if (Attrs.hasFnAttr(Attribute::Naked))
    for (const Argument &Arg : F.args())
      Check(Arg.use_empty(), "cannot use argument of naked function", &Arg);

Maybe there was a subsequent discussion but no doc/verifier update? (Happy to do those separately)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's just saying that some targets might accept more than asm (which I'm not sure is even true). Even if true, that still doesn't necessarily mean that it's valid to inline.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't sound like the extra checks hurt, and they might catch something weird some day.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

llvm:transforms PGO Profile Guided Optimizations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants