[llvm] [profcheck][coro] Adding Branch weights PGO in Coroutines Passes (PR #184466)

Jin Huang via llvm-commits llvm-commits at lists.llvm.org
Sun Mar 8 15:29:24 PDT 2026


https://github.com/jinhuang1102 updated https://github.com/llvm/llvm-project/pull/184466

>From f678ca93d06076d10e4fafe8ff48b4bdfa516fee Mon Sep 17 00:00:00 2001
From: Jin Huang <jingold at google.com>
Date: Wed, 4 Mar 2026 00:19:01 +0000
Subject: [PATCH] [profcheck][coro] Adding Branch weights PGO in CoroSplit and
 CoroFrame Passes

---
 .../lib/Transforms/Coroutines/CoroCleanup.cpp |  2 +
 llvm/lib/Transforms/Coroutines/CoroFrame.cpp  | 19 +++++++
 llvm/lib/Transforms/Coroutines/CoroSplit.cpp  | 51 ++++++++++++++++++-
 .../coro-await-suspend-lower-invoke.ll        | 30 ++++++++---
 .../Transforms/Coroutines/coro-byval-param.ll | 29 +++++++++--
 .../Coroutines/coro-catchswitch-cleanuppad.ll |  7 ++-
 .../Transforms/Coroutines/coro-noop-pacbti.ll |  6 ++-
 7 files changed, 128 insertions(+), 16 deletions(-)

diff --git a/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp b/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp
index c44eaddd7ee55..d8eedf643df91 100644
--- a/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp
@@ -182,6 +182,8 @@ void Lowerer::lowerCoroNoop(IntrinsicInst *II) {
         M.getDataLayout().getProgramAddressSpace(), "__NoopCoro_ResumeDestroy",
         &M);
     NoopFn->setCallingConv(CallingConv::Fast);
+    // Because this function is a noop, we can set its entry count to 0.
+    NoopFn->setEntryCount(0);
     buildDebugInfoForNoopResumeDestroyFunc(NoopFn);
     auto *Entry = BasicBlock::Create(C, "entry", NoopFn);
     ReturnInst::Create(C, Entry);
diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
index 83b40ee927b51..09921a96f5f20 100644
--- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
@@ -25,8 +25,10 @@
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/InstIterator.h"
 #include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/MDBuilder.h"
 #include "llvm/IR/Module.h"
+#include "llvm/IR/ProfDataUtils.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/OptimizedStructLayout.h"
@@ -43,6 +45,10 @@
 
 using namespace llvm;
 
+namespace llvm {
+extern cl::opt<bool> ProfcheckDisableMetadataFixes;
+}
+
 #define DEBUG_TYPE "coro-frame"
 
 namespace {
@@ -1368,6 +1374,19 @@ static void rewritePHIsForCleanupPad(BasicBlock *CleanupPadBB,
     SwitchOnDispatch->addCase(SwitchConstant, CaseBB);
     SwitchIndex++;
   }
+
+  if (!ProfcheckDisableMetadataFixes) {
+    // Add branch weights to SwitchOnDispatch, where branches are unreachable by
+    // default. We mark two branches as having equal weights because they are
+    // mutually exclusive.
+    if (SwitchIndex == 2) {
+      MDBuilder MDB(SwitchOnDispatch->getContext());
+      SwitchOnDispatch->setMetadata(
+          LLVMContext::MD_prof,
+          MDB.createBranchWeights({0, llvm::MDBuilder::kUnlikelyBranchWeight,
+                                   llvm::MDBuilder::kUnlikelyBranchWeight}));
+    }
+  }
 }
 
 static void cleanupSinglePredPHIs(Function &F) {
diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
index 587f581ded8d5..e085342a24e66 100644
--- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
@@ -55,7 +55,9 @@
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/MDBuilder.h"
 #include "llvm/IR/Module.h"
+#include "llvm/IR/ProfDataUtils.h"
 #include "llvm/IR/Type.h"
 #include "llvm/IR/Value.h"
 #include "llvm/IR/Verifier.h"
@@ -77,6 +79,10 @@
 
 using namespace llvm;
 
+namespace llvm {
+extern cl::opt<bool> ProfcheckDisableMetadataFixes;
+}
+
 #define DEBUG_TYPE "coro-split"
 
 // FIXME:
@@ -412,6 +418,21 @@ void coro::BaseCloner::handleFinalSuspend() {
   auto *Switch = cast<SwitchInst>(VMap[Shape.SwitchLowering.ResumeSwitch]);
   auto FinalCaseIt = std::prev(Switch->case_end());
   BasicBlock *ResumeBB = FinalCaseIt->getCaseSuccessor();
+
+  // If there is branch weight metadata, and we are about to remove the last
+  // case, update the metadata by removing the last weight.
+  if (MDNode *ProfMD = Switch->getMetadata(LLVMContext::MD_prof)) {
+    SmallVector<uint32_t> Weights;
+    if (extractBranchWeights(ProfMD, Weights)) {
+      assert(Weights.size() == Switch->getNumCases() + 1 &&
+             "MD_prof weights mismatch");
+      Weights.pop_back();
+      MDBuilder MDB(Switch->getContext());
+      Switch->setMetadata(LLVMContext::MD_prof,
+                          MDB.createBranchWeights(Weights));
+    }
+  }
+
   Switch->removeCase(FinalCaseIt);
   if (isSwitchDestroyFunction()) {
     BasicBlock *OldSwitchBB = Switch->getParent();
@@ -427,7 +448,11 @@ void coro::BaseCloner::handleFinalSuspend() {
       auto *Load =
           Builder.CreateLoad(Shape.getSwitchResumePointerType(), NewFramePtr);
       auto *Cond = Builder.CreateIsNull(Load);
-      Builder.CreateCondBr(Cond, ResumeBB, NewSwitchBB);
+      auto *Br = Builder.CreateCondBr(Cond, ResumeBB, NewSwitchBB);
+      applyProfMetadataIfEnabled(Br, [&](Instruction *Inst) {
+        setExplicitlyUnknownBranchWeightsIfProfiled(*Inst, DEBUG_TYPE,
+                                                    Inst->getFunction());
+      });
     }
     OldSwitchBB->getTerminator()->eraseFromParent();
   }
@@ -1594,6 +1619,26 @@ struct SwitchCoroutineSplitter {
       ++SuspendIndex;
     }
 
+    // Add the branch weights to the switch instruction.
+    if (!ProfcheckDisableMetadataFixes) {
+      if (Switch->getNumCases() > 0) {
+        SmallVector<uint32_t> Weights;
+        // Add the Unlikly weight for the default case.
+        Weights.push_back(llvm::MDBuilder::kUnlikelyBranchWeight);
+        // The first case (IndexVal == 0) represents the coroutine
+        // initialization, which is expected to be the most common case, so we
+        // give it the highest weight.
+        Weights.push_back(llvm::MDBuilder::kLikelyBranchWeight);
+        // Remaning cases are unlikely to be hit, so we give them the unlikely
+        // weight.
+        for (size_t i = 1, e = Switch->getNumCases(); i < e; ++i)
+          Weights.push_back(llvm::MDBuilder::kUnlikelyBranchWeight);
+        MDBuilder MDB(C);
+        Switch->setMetadata(LLVMContext::MD_prof,
+                            MDB.createBranchWeights(Weights));
+      }
+    }
+
     Builder.SetInsertPoint(UnreachBB);
     Builder.CreateUnreachable();
     DBuilder.finalize();
@@ -1618,6 +1663,10 @@ struct SwitchCoroutineSplitter {
       // If there is a CoroAlloc and it returns false (meaning we elide the
       // allocation, use CleanupFn instead of DestroyFn).
       DestroyOrCleanupFn = Builder.CreateSelect(CA, DestroyFn, CleanupFn);
+      applyProfMetadataIfEnabled(DestroyOrCleanupFn, [&](Instruction *Inst) {
+        setExplicitlyUnknownBranchWeightsIfProfiled(*Inst, DEBUG_TYPE,
+                                                    CoroId->getFunction());
+      });
     }
 
     // Destroy function pointer
diff --git a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll
index 72bb8fcf5b610..b57d6ecdd8148 100644
--- a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll
+++ b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll
@@ -1,10 +1,10 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --include-generated-funcs --version 6
 ; Tests that invoke <type> @llvm.coro.await.suspend lowers to invoke @helper
 ; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split),simplifycfg' -S | FileCheck %s
 
 %Awaiter = type {}
 
-define void @f() presplitcoroutine personality i32 0 {
+define void @f() presplitcoroutine personality i32 0  !prof !0 {
 entry:
   %awaiter = alloca %Awaiter
   %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
@@ -103,7 +103,13 @@ declare void @__cxa_end_catch()
 
 declare noalias ptr @malloc(i32)
 declare void @free(ptr)
-; CHECK-LABEL: define void @f() personality i32 0 {
+
+!0 = !{!"function_entry_count", i64 1000}
+;.
+; CHECK: @f.resumers = private constant [3 x ptr] [ptr @f.resume, ptr @f.destroy, ptr @f.cleanup]
+;.
+; CHECK-LABEL: define void @f(
+; CHECK-SAME: ) personality i32 0 !prof [[PROF0:![0-9]+]] {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
 ; CHECK-NEXT:    [[AWAITER:%.*]] = alloca [[AWAITER:%.*]], align 8
 ; CHECK-NEXT:    [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr @f, ptr @f.resumers)
@@ -119,7 +125,7 @@ declare void @free(ptr)
 ;
 ;
 ; CHECK-LABEL: define internal fastcc void @f.resume(
-; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) personality i32 0 {
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) personality i32 0 !prof [[PROF0]] {
 ; CHECK-NEXT:  [[ENTRY_RESUME:.*]]:
 ; CHECK-NEXT:    [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 0
 ; CHECK-NEXT:    [[INDEX_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
@@ -129,7 +135,7 @@ declare void @free(ptr)
 ; CHECK-NEXT:      i2 1, label %[[AFTERCOROSUSPEND3:.*]]
 ; CHECK-NEXT:      i2 -2, label %[[AFTERCOROSUSPEND7:.*]]
 ; CHECK-NEXT:      i2 -1, label %[[CLEANUP:.*]]
-; CHECK-NEXT:    ]
+; CHECK-NEXT:    ], !prof [[PROF1:![0-9]+]]
 ; CHECK:       [[COROSAVE1]]:
 ; CHECK-NEXT:    [[INDEX_ADDR13:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
 ; CHECK-NEXT:    store i2 1, ptr [[INDEX_ADDR13]], align 1
@@ -176,7 +182,7 @@ declare void @free(ptr)
 ;
 ;
 ; CHECK-LABEL: define internal fastcc void @f.destroy(
-; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) personality i32 0 {
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) personality i32 0 !prof [[PROF0]] {
 ; CHECK-NEXT:  [[ENTRY_DESTROY:.*:]]
 ; CHECK-NEXT:    [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 0
 ; CHECK-NEXT:    call void @free(ptr [[HDL]])
@@ -184,9 +190,19 @@ declare void @free(ptr)
 ;
 ;
 ; CHECK-LABEL: define internal fastcc void @f.cleanup(
-; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) personality i32 0 {
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) personality i32 0 !prof [[PROF0]] {
 ; CHECK-NEXT:  [[ENTRY_CLEANUP:.*:]]
 ; CHECK-NEXT:    [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 0
 ; CHECK-NEXT:    call void @free(ptr null)
 ; CHECK-NEXT:    ret void
 ;
+;.
+; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind memory(argmem: read) }
+; CHECK: attributes #[[ATTR1:[0-9]+]] = { nounwind memory(none) }
+; CHECK: attributes #[[ATTR2:[0-9]+]] = { nounwind }
+; CHECK: attributes #[[ATTR3:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: read) }
+; CHECK: attributes #[[ATTR4:[0-9]+]] = { nomerge nounwind }
+;.
+; CHECK: [[PROF0]] = !{!"function_entry_count", i64 1000}
+; CHECK: [[PROF1]] = !{!"branch_weights", i32 1, i32 1048575, i32 1, i32 1, i32 1}
+;.
diff --git a/llvm/test/Transforms/Coroutines/coro-byval-param.ll b/llvm/test/Transforms/Coroutines/coro-byval-param.ll
index db1f151b59bc5..949f8d29c9820 100644
--- a/llvm/test/Transforms/Coroutines/coro-byval-param.ll
+++ b/llvm/test/Transforms/Coroutines/coro-byval-param.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 6
 ; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
 
 target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
@@ -10,9 +10,12 @@ target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
 ; struct pointer, and that the alignment is taken into account.
 
 ; Function Attrs: noinline ssp uwtable mustprogress
-define ptr @foo(ptr nocapture readonly byval(%struct.A) align 8 %a1) #0 {
+;.
+; CHECK: @foo.resumers = private constant [3 x ptr] [ptr @foo.resume, ptr @foo.destroy, ptr @foo.cleanup]
+;.
+define ptr @foo(ptr nocapture readonly byval(%struct.A) align 8 %a1) #0 !prof !0 {
 ; CHECK-LABEL: define ptr @foo(
-; CHECK-SAME: ptr readonly byval([[STRUCT_A:%.*]]) align 8 [[A1:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-SAME: ptr readonly byval([[STRUCT_A:%.*]]) align 8 [[A1:%.*]]) #[[ATTR0:[0-9]+]] !prof [[PROF0:![0-9]+]] {
 ; CHECK-NEXT:  [[ENTRY:.*]]:
 ; CHECK-NEXT:    [[TMP0:%.*]] = call token @llvm.coro.id(i32 16, ptr nonnull null, ptr @foo, ptr @foo.resumers)
 ; CHECK-NEXT:    [[TMP1:%.*]] = call i1 @llvm.coro.alloc(token [[TMP0]])
@@ -24,7 +27,7 @@ define ptr @foo(ptr nocapture readonly byval(%struct.A) align 8 %a1) #0 {
 ; CHECK-NEXT:    [[TMP2:%.*]] = phi ptr [ [[CALL]], %[[CORO_ALLOC]] ], [ null, %[[ENTRY]] ]
 ; CHECK-NEXT:    [[TMP3:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[TMP0]], ptr [[TMP2]])
 ; CHECK-NEXT:    store ptr @foo.resume, ptr [[TMP3]], align 8
-; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP1]], ptr @foo.destroy, ptr @foo.cleanup
+; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP1]], ptr @foo.destroy, ptr @foo.cleanup, !prof [[PROF1:![0-9]+]]
 ; CHECK-NEXT:    [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i64 8
 ; CHECK-NEXT:    store ptr [[TMP4]], ptr [[DESTROY_ADDR]], align 8
 ; CHECK-NEXT:    [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i64 16
@@ -152,3 +155,21 @@ attributes #8 = { nobuiltin nounwind "frame-pointer"="all" "no-trapping-math"="t
 attributes #9 = { allocsize(0) }
 attributes #10 = { noduplicate }
 
+!0 = !{!"function_entry_count", i64 1000}
+;.
+; CHECK: attributes #[[ATTR0]] = { mustprogress noinline ssp uwtable "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }
+; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: read) }
+; CHECK: attributes #[[ATTR2]] = { nounwind }
+; CHECK: attributes #[[ATTR3:[0-9]+]] = { nobuiltin nofree allocsize(0) "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }
+; CHECK: attributes #[[ATTR4:[0-9]+]] = { nounwind memory(none) }
+; CHECK: attributes #[[ATTR5:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
+; CHECK: attributes #[[ATTR6:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
+; CHECK: attributes #[[ATTR7:[0-9]+]] = { mustprogress noinline nounwind ssp willreturn uwtable "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }
+; CHECK: attributes #[[ATTR8:[0-9]+]] = { nomerge nounwind }
+; CHECK: attributes #[[ATTR9:[0-9]+]] = { nobuiltin nounwind "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }
+; CHECK: attributes #[[ATTR10:[0-9]+]] = { nounwind memory(argmem: read) }
+; CHECK: attributes #[[ATTR11]] = { allocsize(0) }
+;.
+; CHECK: [[PROF0]] = !{!"function_entry_count", i64 1000}
+; CHECK: [[PROF1]] = !{!"unknown", !"coro-split"}
+;.
diff --git a/llvm/test/Transforms/Coroutines/coro-catchswitch-cleanuppad.ll b/llvm/test/Transforms/Coroutines/coro-catchswitch-cleanuppad.ll
index e1e1611ee3362..516da5e4527ab 100644
--- a/llvm/test/Transforms/Coroutines/coro-catchswitch-cleanuppad.ll
+++ b/llvm/test/Transforms/Coroutines/coro-catchswitch-cleanuppad.ll
@@ -3,7 +3,7 @@
 ; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg<switch-range-to-icmp>,early-cse' -S | FileCheck %s
 
 declare i32 @__CxxFrameHandler3(...)
-define ptr @f2(i1 %val) presplitcoroutine personality ptr @__CxxFrameHandler3 {
+define ptr @f2(i1 %val) presplitcoroutine personality ptr @__CxxFrameHandler3 !prof !0 {
 entry:
   %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
   %valueA = call i32 @f();
@@ -81,7 +81,7 @@ cleanup2:
 ; CHECK:   %1 = phi i8 [ 0, %handler2 ], [ 1, %catch.dispatch.2 ]
 ; CHECK:   %2 = cleanuppad within %h1 []
 ; CHECK:   %3 = icmp eq i8 %1, 0
-; CHECK:   br i1 %3, label %cleanup2.from.handler2, label %cleanup2.from.catch.dispatch.2
+; CHECK:   br i1 %3, label %cleanup2.from.handler2, label %cleanup2.from.catch.dispatch.2, !prof [[PROF1:![0-9]+]]
 
 ; CHECK: cleanup2.from.handler2:
 ; CHECK:   %valueB.reload = load i32, ptr %valueB.spill.addr, align 4
@@ -113,3 +113,6 @@ declare void @print(i32)
 declare void @free(ptr)
 
 declare i32 @f()
+
+!0 = !{!"function_entry_count", i64 1000}
+; CHECK: [[PROF1]] = !{!"branch_weights", i32 1, i32 1}
diff --git a/llvm/test/Transforms/Coroutines/coro-noop-pacbti.ll b/llvm/test/Transforms/Coroutines/coro-noop-pacbti.ll
index 910b6b07e1628..15e95ae434f13 100644
--- a/llvm/test/Transforms/Coroutines/coro-noop-pacbti.ll
+++ b/llvm/test/Transforms/Coroutines/coro-noop-pacbti.ll
@@ -1,14 +1,14 @@
 
 ; RUN: opt < %s -S -passes=coro-cleanup | FileCheck %s
 
-; CHECK:      define internal fastcc void @__NoopCoro_ResumeDestroy(ptr %0) #1 {
+; CHECK:      define internal fastcc void @__NoopCoro_ResumeDestroy(ptr %0) #1 !prof [[PROF4:![0-9]+]] {
 ; CHECK-NEXT: entry:
 ; CHECK-NEXT:   ret void
 ; CHECK-NEXT: }
 
 ; CHECK:      attributes #1 = { "branch-target-enforcement" "sign-return-address"="all" "sign-return-address-key"="a_key" }
 
-define ptr @noop() {
+define ptr @noop() !prof !3 {
 entry:
   %n = call ptr @llvm.coro.noop()
   ret ptr %n
@@ -21,3 +21,5 @@ declare ptr @llvm.coro.noop()
 !0 = !{i32 8, !"branch-target-enforcement", i32 1}
 !1 = !{i32 8, !"sign-return-address", i32 1}
 !2 = !{i32 8, !"sign-return-address-all", i32 1}
+!3 = !{!"function_entry_count", i64 1000}
+; CHECK: [[PROF4]] = !{!"function_entry_count", i64 0}



More information about the llvm-commits mailing list