llvm.org GIT mirror llvm / 283d978
Add a pass to generate synthetic function entry counts. Summary: This pass synthesizes function entry counts by traversing the callgraph and using the relative block frequencies of the callsites. The intended use of these counts is in inlining to determine hot/cold callsites in the absence of profile information. The pass is split into two files with the code that propagates the counts in a callgraph in a Utils file. I plan to add support for propagation in the thinlto link phase and the propagation code will be shared and hence this split. I did not add support to the old PM since hot callsite determination in inlining is not possible in old PM (although we could use hot callee heuristic with synthetic counts in the old PM it is not worth the effort tuning it) Reviewers: davidxl, silvas Subscribers: mgorny, mehdi_amini, llvm-commits Differential Revision: https://reviews.llvm.org/D41604 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@322110 91177308-0d34-0410-b5e6-96231b3b80d8 Easwaran Raman 1 year, 8 months ago
17 changed file(s) with 485 addition(s) and 13 deletion(s). Raw diff Collapse all Expand all
0 //===- SyntheticCountsUtils.h - utilities for count propagation--*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines utilities for synthetic counts propagation.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_ANALYSIS_SYNTHETIC_COUNTS_UTILS_H
14 #define LLVM_ANALYSIS_SYNTHETIC_COUNTS_UTILS_H
15
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/IR/CallSite.h"
18 #include "llvm/Support/ScaledNumber.h"
19
20 namespace llvm {
21
22 class CallGraph;
23 class Function;
24
25 using Scaled64 = ScaledNumber;
26 void propagateSyntheticCounts(
27 const CallGraph &CG, function_ref GetCallSiteRelFreq,
28 function_ref GetCount,
29 function_ref AddToCount);
30 } // namespace llvm
31
32 #endif
236236 /// \brief Set the entry count for this function.
237237 ///
238238 /// Entry count is the number of times this function was executed based on
239 /// pgo data. \p Imports points to a set of GUIDs that needs to be imported
240 /// by the function for sample PGO, to enable the same inlines as the
241 /// profiled optimized binary.
242 void setEntryCount(uint64_t Count,
239 /// pgo data. \p Synthetic indicates the count is synthesized by analysis and
240 /// not from a profile run. \p Imports points to a set of GUIDs that needs to
241 /// be imported by the function for sample PGO, to enable the same inlines as
242 /// the profiled optimized binary.
243 void setEntryCount(uint64_t Count, bool Synthetic = false,
243244 const DenseSet *Imports = nullptr);
244245
245246 /// \brief Get the entry count for this function.
6565 /// Return metadata specifying that a branch or switch is unpredictable.
6666 MDNode *createUnpredictable();
6767
68 /// Return metadata containing the entry \p Count for a function, and the
68 /// Return metadata containing the entry \p Count for a function, a boolean
69 /// \Synthetic indicating whether the counts were synthetized, and the
6970 /// GUIDs stored in \p Imports that need to be imported for sample PGO, to
7071 /// enable the same inlines as the profiled optimized binary
71 MDNode *createFunctionEntryCount(uint64_t Count,
72 MDNode *createFunctionEntryCount(uint64_t Count, bool Synthetic,
7273 const DenseSet *Imports);
7374
7475 /// Return metadata containing the section prefix for a function.
0 #ifndef LLVM_TRANSFORMS_IPO_SYNTHETIC_COUNTS_PROPAGATION_H
1 #define LLVM_TRANSFORMS_IPO_SYNTHETIC_COUNTS_PROPAGATION_H
2
3 #include "llvm/ADT/STLExtras.h"
4 #include "llvm/IR/CallSite.h"
5 #include "llvm/IR/PassManager.h"
6 #include "llvm/Support/ScaledNumber.h"
7
8 namespace llvm {
9 class Function;
10 class Module;
11
12 class SyntheticCountsPropagation
13 : public PassInfoMixin {
14 public:
15 PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
16 };
17 } // namespace llvm
18 #endif
7373 ScalarEvolutionAliasAnalysis.cpp
7474 ScalarEvolutionExpander.cpp
7575 ScalarEvolutionNormalization.cpp
76 SyntheticCountsUtils.cpp
7677 TargetLibraryInfo.cpp
7778 TargetTransformInfo.cpp
7879 Trace.cpp
0 //===--- SyntheticCountsUtils.cpp - synthetic counts propagation utils ---===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines utilities for propagating synthetic counts.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/Analysis/SyntheticCountsUtils.h"
14 #include "llvm/ADT/DenseSet.h"
15 #include "llvm/ADT/SCCIterator.h"
16 #include "llvm/ADT/SmallPtrSet.h"
17 #include "llvm/Analysis/CallGraph.h"
18 #include "llvm/IR/CallSite.h"
19 #include "llvm/IR/Function.h"
20 #include "llvm/IR/InstIterator.h"
21 #include "llvm/IR/Instructions.h"
22
23 using namespace llvm;
24
25 // Given a set of functions in an SCC, propagate entry counts to functions
26 // called by the SCC.
27 static void
28 propagateFromSCC(const SmallPtrSetImpl &SCCFunctions,
29 function_ref GetCallSiteRelFreq,
30 function_ref GetCount,
31 function_ref AddToCount) {
32
33 SmallVector CallSites;
34
35 // Gather all callsites in the SCC.
36 auto GatherCallSites = [&]() {
37 for (auto *F : SCCFunctions) {
38 assert(F && !F->isDeclaration());
39 for (auto &I : instructions(F)) {
40 if (auto CS = CallSite(&I)) {
41 CallSites.push_back(CS);
42 }
43 }
44 }
45 };
46
47 GatherCallSites();
48
49 // Partition callsites so that the callsites that call functions in the same
50 // SCC come first.
51 auto Mid = partition(CallSites, [&](CallSite &CS) {
52 auto *Callee = CS.getCalledFunction();
53 if (Callee)
54 return SCCFunctions.count(Callee);
55 // FIXME: Use the !callees metadata to propagate counts through indirect
56 // calls.
57 return 0U;
58 });
59
60 // For functions in the same SCC, update the counts in two steps:
61 // 1. Compute the additional count for each function by propagating the counts
62 // along all incoming edges to the function that originate from the same SCC
63 // and summing them up.
64 // 2. Add the additional counts to the functions in the SCC.
65 // This ensures that the order of
66 // traversal of functions within the SCC doesn't change the final result.
67
68 DenseMap AdditionalCounts;
69 for (auto It = CallSites.begin(); It != Mid; It++) {
70 auto &CS = *It;
71 auto RelFreq = GetCallSiteRelFreq(CS);
72 Function *Callee = CS.getCalledFunction();
73 Function *Caller = CS.getCaller();
74 RelFreq *= Scaled64(GetCount(Caller), 0);
75 uint64_t AdditionalCount = RelFreq.toInt();
76 AdditionalCounts[Callee] += AdditionalCount;
77 }
78
79 // Update the counts for the functions in the SCC.
80 for (auto &Entry : AdditionalCounts)
81 AddToCount(Entry.first, Entry.second);
82
83 // Now update the counts for functions not in SCC.
84 for (auto It = Mid; It != CallSites.end(); It++) {
85 auto &CS = *It;
86 auto Weight = GetCallSiteRelFreq(CS);
87 Function *Callee = CS.getCalledFunction();
88 Function *Caller = CS.getCaller();
89 Weight *= Scaled64(GetCount(Caller), 0);
90 AddToCount(Callee, Weight.toInt());
91 }
92 }
93
94 /// Propgate synthetic entry counts on a callgraph.
95 ///
96 /// This performs a reverse post-order traversal of the callgraph SCC. For each
97 /// SCC, it first propagates the entry counts to the functions within the SCC
98 /// through call edges and updates them in one shot. Then the entry counts are
99 /// propagated to functions outside the SCC.
100 void llvm::propagateSyntheticCounts(
101 const CallGraph &CG, function_ref GetCallSiteRelFreq,
102 function_ref GetCount,
103 function_ref AddToCount) {
104
105 SmallVector, 16> SCCs;
106 for (auto I = scc_begin(&CG); !I.isAtEnd(); ++I) {
107 auto SCC = *I;
108
109 SmallPtrSet SCCFunctions;
110 for (auto *Node : SCC) {
111 Function *F = Node->getFunction();
112 if (F && !F->isDeclaration()) {
113 SCCFunctions.insert(F);
114 }
115 }
116 SCCs.push_back(SCCFunctions);
117 }
118
119 for (auto &SCCFunctions : reverse(SCCs))
120 propagateFromSCC(SCCFunctions, GetCallSiteRelFreq, GetCount, AddToCount);
121 }
13191319 setValueSubclassData(getSubclassDataFromValue() & ~(1 << Bit));
13201320 }
13211321
1322 void Function::setEntryCount(uint64_t Count,
1322 void Function::setEntryCount(uint64_t Count, bool Synthetic,
13231323 const DenseSet *S) {
13241324 MDBuilder MDB(getContext());
1325 setMetadata(LLVMContext::MD_prof, MDB.createFunctionEntryCount(Count, S));
1325 setMetadata(LLVMContext::MD_prof,
1326 MDB.createFunctionEntryCount(Count, Synthetic, S));
13261327 }
13271328
13281329 Optional Function::getEntryCount() const {
5757 }
5858
5959 MDNode *MDBuilder::createFunctionEntryCount(
60 uint64_t Count, const DenseSet *Imports) {
60 uint64_t Count, bool Synthetic,
61 const DenseSet *Imports) {
6162 Type *Int64Ty = Type::getInt64Ty(Context);
6263 SmallVector Ops;
63 Ops.push_back(createString("function_entry_count"));
64 if (Synthetic)
65 Ops.push_back(createString("synthetic_function_entry_count"));
66 else
67 Ops.push_back(createString("function_entry_count"));
6468 Ops.push_back(createConstant(ConstantInt::get(Int64Ty, Count)));
6569 if (Imports) {
6670 SmallVector OrderID(Imports->begin(), Imports->end());
16941694 "expected string with name of the !prof annotation", MD);
16951695 MDString *MDS = cast(MD->getOperand(0));
16961696 StringRef ProfName = MDS->getString();
1697 Assert(ProfName.equals("function_entry_count"),
1698 "first operand should be 'function_entry_count'", MD);
1697 Assert(ProfName.equals("function_entry_count") ||
1698 ProfName.equals("synthetic_function_entry_count"),
1699 "first operand should be 'function_entry_count'"
1700 " or 'synthetic_function_entry_count'",
1701 MD);
16991702
17001703 // Check second operand.
17011704 Assert(MD->getOperand(1) != nullptr, "second operand should not be null",
7979 #include "llvm/Transforms/IPO/PartialInlining.h"
8080 #include "llvm/Transforms/IPO/SCCP.h"
8181 #include "llvm/Transforms/IPO/StripDeadPrototypes.h"
82 #include "llvm/Transforms/IPO/SyntheticCountsPropagation.h"
8283 #include "llvm/Transforms/IPO/WholeProgramDevirt.h"
8384 #include "llvm/Transforms/InstCombine/InstCombine.h"
8485 #include "llvm/Transforms/InstrProfiling.h"
175176 "enable-npm-gvn-sink", cl::init(false), cl::Hidden,
176177 cl::desc("Enable the GVN hoisting pass for the new PM (default = off)"));
177178
179 static cl::opt EnableSyntheticCounts(
180 "enable-npm-synthetic-counts", cl::init(false), cl::Hidden, cl::ZeroOrMore,
181 cl::desc("Run synthetic function entry count generation "
182 "pass"));
183
178184 static Regex DefaultAliasRegex(
179185 "^(default|thinlto-pre-link|thinlto|lto-pre-link|lto)<(O[0123sz])>$");
180186
620626 PGOOpt->ProfileGenFile, PGOOpt->ProfileUseFile);
621627 MPM.addPass(PGOIndirectCallPromotion(false, false));
622628 }
629
630 // Synthesize function entry counts for non-PGO compilation.
631 if (EnableSyntheticCounts && !PGOOpt)
632 MPM.addPass(SyntheticCountsPropagation());
623633
624634 // Require the GlobalsAA analysis for the module so we can query it within
625635 // the CGSCC pipeline.
7272 MODULE_PASS("rpo-functionattrs", ReversePostOrderFunctionAttrsPass())
7373 MODULE_PASS("sample-profile", SampleProfileLoaderPass())
7474 MODULE_PASS("strip-dead-prototypes", StripDeadPrototypesPass())
75 MODULE_PASS("synthetic-counts-propagation", SyntheticCountsPropagation())
7576 MODULE_PASS("wholeprogramdevirt", WholeProgramDevirtPass())
7677 MODULE_PASS("verify", VerifierPass())
7778 #undef MODULE_PASS
2828 SampleProfile.cpp
2929 StripDeadPrototypes.cpp
3030 StripSymbols.cpp
31 SyntheticCountsPropagation.cpp
3132 ThinLTOBitcodeWriter.cpp
3233 WholeProgramDevirt.cpp
3334
14661466 // Sets the GUIDs that are inlined in the profiled binary. This is used
14671467 // for ThinLink to make correct liveness analysis, and also make the IR
14681468 // match the profiled binary before annotation.
1469 F.setEntryCount(Samples->getHeadSamples() + 1, &InlinedGUIDs);
1469 F.setEntryCount(Samples->getHeadSamples() + 1, false, &InlinedGUIDs);
14701470
14711471 // Compute dominance and loop info needed for propagation.
14721472 computeDominanceAndLoopInfo(F);
0 //=- SyntheticCountsPropagation.cpp - Propagate function counts --*- C++ -*-=//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements a transformation that synthesizes entry counts for
10 // functions and attaches !prof metadata to functions with the synthesized
11 // counts. The presence of !prof metadata with counter name set to
12 // 'synthesized_function_entry_count' indicate that the value of the counter is
13 // an estimation of the likely execution count of the function. This transform
14 // is applied only in non PGO mode as functions get 'real' profile-based
15 // function entry counts in the PGO mode.
16 //
17 // The transformation works by first assigning some initial values to the entry
18 // counts of all functions and then doing a top-down traversal of the
19 // callgraph-scc to propagate the counts. For each function the set of callsites
20 // and their relative block frequency is gathered. The relative block frequency
21 // multiplied by the entry count of the caller and added to the callee's entry
22 // count. For non-trivial SCCs, the new counts are computed from the previous
23 // counts and updated in one shot.
24 //
25 //===----------------------------------------------------------------------===//
26
27 #include "llvm/Transforms/IPO/SyntheticCountsPropagation.h"
28 #include "llvm/ADT/DenseSet.h"
29 #include "llvm/ADT/STLExtras.h"
30 #include "llvm/Analysis/BlockFrequencyInfo.h"
31 #include "llvm/Analysis/CallGraph.h"
32 #include "llvm/Analysis/SyntheticCountsUtils.h"
33 #include "llvm/IR/CallSite.h"
34 #include "llvm/IR/Function.h"
35 #include "llvm/IR/Instructions.h"
36 #include "llvm/IR/Module.h"
37 #include "llvm/Support/CommandLine.h"
38 #include "llvm/Support/Debug.h"
39 #include "llvm/Support/raw_ostream.h"
40
41 using namespace llvm;
42 using Scaled64 = ScaledNumber;
43
44 #define DEBUG_TYPE "synthetic-counts-propagation"
45
46 /// Initial synthetic count assigned to functions.
47 static cl::opt
48 InitialSyntheticCount("initial-synthetic-count", cl::Hidden, cl::init(10),
49 cl::ZeroOrMore,
50 cl::desc("Initial value of synthetic entry count."));
51
52 /// Initial synthetic count assigned to inline functions.
53 static cl::opt InlineSyntheticCount(
54 "inline-synthetic-count", cl::Hidden, cl::init(15), cl::ZeroOrMore,
55 cl::desc("Initial synthetic entry count for inline functions."));
56
57 /// Initial synthetic count assigned to cold functions.
58 static cl::opt ColdSyntheticCount(
59 "cold-synthetic-count", cl::Hidden, cl::init(5), cl::ZeroOrMore,
60 cl::desc("Initial synthetic entry count for cold functions."));
61
62 // Assign initial synthetic entry counts to functions.
63 static void
64 initializeCounts(Module &M, function_ref SetCount) {
65 auto MayHaveIndirectCalls = [](Function &F) {
66 for (auto *U : F.users()) {
67 if (!isa(U) && !isa(U))
68 return true;
69 }
70 return false;
71 };
72
73 for (Function &F : M) {
74 uint64_t InitialCount = InitialSyntheticCount;
75 if (F.isDeclaration())
76 continue;
77 if (F.hasFnAttribute(Attribute::AlwaysInline) ||
78 F.hasFnAttribute(Attribute::InlineHint)) {
79 // Use a higher value for inline functions to account for the fact that
80 // these are usually beneficial to inline.
81 InitialCount = InlineSyntheticCount;
82 } else if (F.hasLocalLinkage() && !MayHaveIndirectCalls(F)) {
83 // Local functions without inline hints get counts only through
84 // propagation.
85 InitialCount = 0;
86 } else if (F.hasFnAttribute(Attribute::Cold) ||
87 F.hasFnAttribute(Attribute::NoInline)) {
88 // Use a lower value for noinline and cold functions.
89 InitialCount = ColdSyntheticCount;
90 }
91 SetCount(&F, InitialCount);
92 }
93 }
94
95 PreservedAnalyses SyntheticCountsPropagation::run(Module &M,
96 ModuleAnalysisManager &MAM) {
97 FunctionAnalysisManager &FAM =
98 MAM.getResult(M).getManager();
99 DenseMap Counts;
100 // Set initial entry counts.
101 initializeCounts(M, [&](Function *F, uint64_t Count) { Counts[F] = Count; });
102
103 // Compute the relative block frequency for a callsite. Use scaled numbers
104 // and not integers since the relative block frequency could be less than 1.
105 auto GetCallSiteRelFreq = [&](CallSite CS) {
106 Function *Caller = CS.getCaller();
107 auto &BFI = FAM.getResult(*Caller);
108 BasicBlock *CSBB = CS.getInstruction()->getParent();
109 Scaled64 EntryFreq(BFI.getEntryFreq(), 0);
110 Scaled64 BBFreq(BFI.getBlockFreq(CSBB).getFrequency(), 0);
111 BBFreq /= EntryFreq;
112 return BBFreq;
113 };
114
115 CallGraph CG(M);
116 // Propgate the entry counts on the callgraph.
117 propagateSyntheticCounts(
118 CG, GetCallSiteRelFreq, [&](Function *F) { return Counts[F]; },
119 [&](Function *F, uint64_t New) { Counts[F] += New; });
120
121 // Set the counts as metadata.
122 for (auto Entry : Counts)
123 Entry.first->setEntryCount(Entry.second, true);
124
125 return PreservedAnalyses::all();
126 }
0 ; RUN: opt -passes=synthetic-counts-propagation -S < %s | FileCheck %s
1
2 ; CHECK-LABEL: define void @foo()
3 ; CHECK: !prof ![[COUNT1:[0-9]+]]
4 define void @foo() {
5 ret void
6 }
7
8 ; CHECK-LABEL: define void @foo_inline() #0
9 ; CHECK: !prof ![[COUNT2:[0-9]+]]
10 define void @foo_inline() #0 {
11 ret void
12 }
13
14 ; CHECK-LABEL: define void @foo_always_inline() #1
15 ; CHECK: !prof ![[COUNT2]]
16 define void @foo_always_inline() #1 {
17 ret void
18 }
19
20 ; CHECK-LABEL: define void @foo_cold() #2
21 ; CHECK: !prof ![[COUNT3:[0-9]+]]
22 define void @foo_cold() #2 {
23 ret void
24 }
25
26 ; CHECK-LABEL: define void @foo_noinline() #3
27 ; CHECK: !prof ![[COUNT3]]
28 define void @foo_noinline() #3 {
29 ret void
30 }
31
32 ; CHECK-LABEL: define internal void @foo_local()
33 ; CHECK: !prof ![[COUNT4:[0-9]+]]
34 define internal void @foo_local() {
35 ret void
36 }
37
38 ; CHECK-LABEL: define internal void @foo_local_escaped()
39 ; CHECK: !prof ![[COUNT1]]
40 define internal void @foo_local_escaped() {
41 ret void
42 }
43
44 declare void @ext(void ()*)
45
46 define void @bar() {
47 call void @ext(void ()* nonnull @foo_local_escaped)
48 ret void
49 }
50
51 ; CHECK-LABEL: define internal void @foo_local_inline() #0
52 ; CHECK: !prof ![[COUNT2]]
53 define internal void @foo_local_inline() #0 {
54 ret void
55 }
56
57 ; CHECK-LABEL: define internal void @foo_local_cold() #2
58 ; CHECK: !prof ![[COUNT4]]
59 define internal void @foo_local_cold() #2 {
60 ret void
61 }
62
63 ; CHECK-LABEL: define linkonce void @foo_linkonce()
64 ; CHECK: !prof ![[COUNT1]]
65 define linkonce void @foo_linkonce() {
66 ret void
67 }
68
69 ; CHECK: ![[COUNT1]] = !{!"synthetic_function_entry_count", i64 10}
70 ; CHECK: ![[COUNT2]] = !{!"synthetic_function_entry_count", i64 15}
71 ; CHECK: ![[COUNT3]] = !{!"synthetic_function_entry_count", i64 5}
72 ; CHECK: ![[COUNT4]] = !{!"synthetic_function_entry_count", i64 0}
73
74 attributes #0 = {inlinehint}
75 attributes #1 = {alwaysinline}
76 attributes #2 = {cold}
77 attributes #3 = {noinline}
78
0 ; RUN: opt -passes=synthetic-counts-propagation -S < %s | FileCheck %s
1
2 ; CHECK-LABEL: define void @level1a(i32 %n)
3 ; CHECK: !prof ![[COUNT1:[0-9]+]]
4 define void @level1a(i32 %n) {
5 entry:
6 %cmp = icmp sgt i32 %n, 10
7 br i1 %cmp, label %exit, label %loop
8 loop:
9 %i = phi i32 [%n, %entry], [%i1, %loop]
10 call void @level2a(i32 %n)
11 %i1 = sub i32 %i, 1
12 %cmp2 = icmp eq i32 %i1, 0
13 br i1 %cmp2, label %exit, label %loop, !prof !1
14 exit:
15 ret void
16 }
17
18 ; CHECK-LABEL: define void @level2a(i32 %n)
19 ; CHECK: !prof ![[COUNT2:[0-9]+]]
20 define void @level2a(i32 %n) {
21 call void @level2b(i32 %n)
22 ret void
23 }
24
25 ; CHECK-LABEL: define void @level2b(i32 %n)
26 ; CHECK: !prof ![[COUNT2]]
27 define void @level2b(i32 %n) {
28 entry:
29 call void @level2a(i32 %n)
30 %cmp = icmp eq i32 %n, 0
31 br i1 %cmp, label %then, label %else, !prof !2
32 then:
33 call void @level3a(i32 %n)
34 br label %else
35 else:
36 ret void
37 }
38
39 ; CHECK-LABEL: define internal void @level3a(i32 %n)
40 ; CHECK: !prof ![[COUNT3:[0-9]+]]
41 define internal void @level3a(i32 %n) {
42 ret void
43 }
44
45 !1 = !{!"branch_weights", i32 1, i32 99}
46 !2 = !{!"branch_weights", i32 1, i32 1}
47 ; CHECK: ![[COUNT1]] = !{!"synthetic_function_entry_count", i64 10}
48 ; CHECK: ![[COUNT2]] = !{!"synthetic_function_entry_count", i64 520}
49 ; CHECK: ![[COUNT3]] = !{!"synthetic_function_entry_count", i64 260}
0 ; RUN: opt -passes=synthetic-counts-propagation -S < %s | FileCheck %s
1
2 ; CHECK-LABEL: define void @foo()
3 ; CHECK: !prof ![[COUNT1:[0-9]+]]
4 define void @foo() {
5 call void @bar()
6 ret void
7 }
8
9 ; CHECK-LABEL: define void @bar() #0
10 ; CHECK: !prof ![[COUNT1]]
11 define void @bar() #0 {
12 call void @foo()
13 ret void
14 }
15
16 attributes #0 = {inlinehint}
17
18 ; CHECK: ![[COUNT1]] = !{!"synthetic_function_entry_count", i64 25}