Skip to content

Commit 2567f3d

Browse files
author
Diego Novillo
committed
Add function entry count metadata.
Summary: This adds three Function methods to handle function entry counts: setEntryCount() and getEntryCount(). Entry counts are stored under the MD_prof metadata node with the name "function_entry_count". They are unsigned 64 bit values set by profilers (instrumentation and sample profiler changes coming up). Added documentation for new profile metadata and tests. Reviewers: dexonsmith, bogner Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D9628 llvm-svn: 237260
1 parent bbcf75e commit 2567f3d

File tree

9 files changed

+146
-0
lines changed

9 files changed

+146
-0
lines changed

llvm/docs/BranchWeightMetadata.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,26 @@ CFG Modifications
115115
Branch Weight Metatada is not proof against CFG changes. If terminator operands'
116116
are changed some action should be taken. In other case some misoptimizations may
117117
occur due to incorrent branch prediction information.
118+
119+
Function Entry Counts
120+
=====================
121+
122+
To allow comparing different functions durint inter-procedural analysis and
123+
optimization, ``MD_prof`` nodes can also be assigned to a function definition.
124+
The first operand is a string indicating the name of the associated counter.
125+
126+
Currently, one counter is supported: "function_entry_count". This is a 64-bit
127+
counter that indicates the number of times that this function was invoked (in
128+
the case of instrumentation-based profiles). In the case of sampling-based
129+
profiles, this counter is an approximation of how many times the function was
130+
invoked.
131+
132+
For example, in the code below, the instrumentation for function foo()
133+
indicates that it was called 2,590 times at runtime.
134+
135+
.. code-block:: llvm
136+
137+
define i32 @foo() !prof !1 {
138+
ret i32 0
139+
}
140+
!1 = !{!"function_entry_count", i64 2590}

llvm/include/llvm/IR/Function.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#define LLVM_IR_FUNCTION_H
2020

2121
#include "llvm/ADT/iterator_range.h"
22+
#include "llvm/ADT/Optional.h"
2223
#include "llvm/IR/Argument.h"
2324
#include "llvm/IR/Attributes.h"
2425
#include "llvm/IR/BasicBlock.h"
@@ -194,6 +195,12 @@ class Function : public GlobalObject, public ilist_node<Function> {
194195
AttributeSet::FunctionIndex, Kind, Value));
195196
}
196197

198+
/// Set the entry count for this function.
199+
void setEntryCount(uint64_t Count);
200+
201+
/// Get the entry count for this function.
202+
Optional<uint64_t> getEntryCount() const;
203+
197204
/// @brief Return true if the function has the attribute.
198205
bool hasFnAttribute(Attribute::AttrKind Kind) const {
199206
return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind);

llvm/include/llvm/IR/MDBuilder.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ class MDBuilder {
6060
/// \brief Return metadata containing a number of branch weights.
6161
MDNode *createBranchWeights(ArrayRef<uint32_t> Weights);
6262

63+
/// Return metadata containing the entry count for a function.
64+
MDNode *createFunctionEntryCount(uint64_t Count);
65+
6366
//===------------------------------------------------------------------===//
6467
// Range metadata.
6568
//===------------------------------------------------------------------===//

llvm/lib/IR/Function.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@
1919
#include "llvm/ADT/StringExtras.h"
2020
#include "llvm/CodeGen/ValueTypes.h"
2121
#include "llvm/IR/CallSite.h"
22+
#include "llvm/IR/Constants.h"
2223
#include "llvm/IR/DerivedTypes.h"
2324
#include "llvm/IR/InstIterator.h"
2425
#include "llvm/IR/IntrinsicInst.h"
2526
#include "llvm/IR/LLVMContext.h"
27+
#include "llvm/IR/MDBuilder.h"
28+
#include "llvm/IR/Metadata.h"
2629
#include "llvm/IR/Module.h"
2730
#include "llvm/Support/ManagedStatic.h"
2831
#include "llvm/Support/RWMutex.h"
@@ -986,3 +989,19 @@ void llvm::overrideFunctionAttribute(StringRef Kind, StringRef Value,
986989
Attrs = Attrs.addAttribute(Ctx, AttributeSet::FunctionIndex, Kind, Value);
987990
F.setAttributes(Attrs);
988991
}
992+
993+
void Function::setEntryCount(uint64_t Count) {
994+
MDBuilder MDB(getContext());
995+
setMetadata(LLVMContext::MD_prof, MDB.createFunctionEntryCount(Count));
996+
}
997+
998+
Optional<uint64_t> Function::getEntryCount() const {
999+
MDNode *MD = getMetadata(LLVMContext::MD_prof);
1000+
if (MD && MD->getOperand(0))
1001+
if (MDString *MDS = dyn_cast<MDString>(MD->getOperand(0)))
1002+
if (MDS->getString().equals("function_entry_count")) {
1003+
ConstantInt *CI = mdconst::extract<ConstantInt>(MD->getOperand(1));
1004+
return CI->getValue().getZExtValue();
1005+
}
1006+
return None;
1007+
}

llvm/lib/IR/MDBuilder.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ MDNode *MDBuilder::createBranchWeights(ArrayRef<uint32_t> Weights) {
5353
return MDNode::get(Context, Vals);
5454
}
5555

56+
MDNode *MDBuilder::createFunctionEntryCount(uint64_t Count) {
57+
SmallVector<Metadata *, 2> Vals(2);
58+
Vals[0] = createString("function_entry_count");
59+
60+
Type *Int64Ty = Type::getInt64Ty(Context);
61+
Vals[1] = createConstant(ConstantInt::get(Int64Ty, Count));
62+
63+
return MDNode::get(Context, Vals);
64+
}
65+
5666
MDNode *MDBuilder::createRange(const APInt &Lo, const APInt &Hi) {
5767
assert(Lo.getBitWidth() == Hi.getBitWidth() && "Mismatched bitwidths!");
5868

llvm/lib/IR/Verifier.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,8 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
400400
bool isReturnValue, const Value *V);
401401
void VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs,
402402
const Value *V);
403+
void VerifyFunctionMetadata(
404+
const SmallVector<std::pair<unsigned, MDNode *>, 4> MDs);
403405

404406
void VerifyConstantExprBitcastType(const ConstantExpr *CE);
405407
void VerifyStatepoint(ImmutableCallSite CS);
@@ -1463,6 +1465,36 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs,
14631465
}
14641466
}
14651467

1468+
void Verifier::VerifyFunctionMetadata(
1469+
const SmallVector<std::pair<unsigned, MDNode *>, 4> MDs) {
1470+
if (MDs.empty())
1471+
return;
1472+
1473+
for (unsigned i = 0; i < MDs.size(); i++) {
1474+
if (MDs[i].first == LLVMContext::MD_prof) {
1475+
MDNode *MD = MDs[i].second;
1476+
Assert(MD->getNumOperands() == 2,
1477+
"!prof annotations should have exactly 2 operands", MD);
1478+
1479+
// Check first operand.
1480+
Assert(MD->getOperand(0) != nullptr, "first operand should not be null",
1481+
MD);
1482+
Assert(isa<MDString>(MD->getOperand(0)),
1483+
"expected string with name of the !prof annotation", MD);
1484+
MDString *MDS = cast<MDString>(MD->getOperand(0));
1485+
StringRef ProfName = MDS->getString();
1486+
Assert(ProfName.equals("function_entry_count"),
1487+
"first operand should be 'function_entry_count'", MD);
1488+
1489+
// Check second operand.
1490+
Assert(MD->getOperand(1) != nullptr, "second operand should not be null",
1491+
MD);
1492+
Assert(isa<ConstantAsMetadata>(MD->getOperand(1)),
1493+
"expected integer argument to function_entry_count", MD);
1494+
}
1495+
}
1496+
}
1497+
14661498
void Verifier::VerifyConstantExprBitcastType(const ConstantExpr *CE) {
14671499
if (CE->getOpcode() != Instruction::BitCast)
14681500
return;
@@ -1713,6 +1745,7 @@ void Verifier::visitFunction(const Function &F) {
17131745
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
17141746
F.getAllMetadata(MDs);
17151747
assert(F.hasMetadata() != MDs.empty() && "Bit out-of-sync");
1748+
VerifyFunctionMetadata(MDs);
17161749

17171750
if (F.isMaterializable()) {
17181751
// Function has a body somewhere we can't see.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
2+
3+
define i32 @bad1() !prof !0 {
4+
ret i32 0
5+
}
6+
7+
!0 = !{i32 123, i32 3}
8+
; CHECK: assembly parsed, but does not verify as correct!
9+
; CHECK-NEXT: expected string with name of the !prof annotation
10+
; CHECK-NEXT: !0 = !{i32 123, i32 3}
11+
12+
define i32 @bad2() !prof !1 {
13+
ret i32 0
14+
}
15+
16+
!1 = !{!"function_entry_count"}
17+
; CHECK-NEXT: !prof annotations should have exactly 2 operands
18+
; CHECK-NEXT: !1 = !{!"function_entry_count"}
19+
20+
21+
define i32 @bad3() !prof !2 {
22+
ret i32 0
23+
}
24+
25+
!2 = !{!"some_other_count", i64 200}
26+
; CHECK-NEXT: first operand should be 'function_entry_count'
27+
; CHECK-NEXT: !2 = !{!"some_other_count", i64 200}
28+
29+
define i32 @bad4() !prof !3 {
30+
ret i32 0
31+
}
32+
33+
!3 = !{!"function_entry_count", !"string"}
34+
; CHECK-NEXT: expected integer argument to function_entry_count
35+
; CHECK-NEXT: !3 = !{!"function_entry_count", !"string"}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
; RUN: llvm-as < %s -o /dev/null 2>&1
2+
3+
; Function foo() is called 2,304 times at runtime.
4+
define i32 @foo() !prof !0 {
5+
ret i32 0
6+
}
7+
8+
!0 = !{!"function_entry_count", i32 2304}

llvm/unittests/IR/MetadataTest.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2272,4 +2272,12 @@ TEST_F(FunctionAttachmentTest, Verifier) {
22722272
EXPECT_FALSE(verifyFunction(*F));
22732273
}
22742274

2275+
TEST_F(FunctionAttachmentTest, EntryCount) {
2276+
Function *F = getFunction("foo");
2277+
EXPECT_FALSE(F->getEntryCount().hasValue());
2278+
F->setEntryCount(12304);
2279+
EXPECT_TRUE(F->getEntryCount().hasValue());
2280+
EXPECT_EQ(12304u, *F->getEntryCount());
2281+
}
2282+
22752283
}

0 commit comments

Comments
 (0)