Skip to content

Commit 64f4ceb

Browse files
[Inline][PGO] After inline, update InvokeInst profile counts in caller and cloned callee (#83809)
A related change is https://reviews.llvm.org/D133121, which correctly preserves both branch weights and value profiles for invoke instruction. * If the branch weight of the `invokeinst` specifies taken / not-taken branches, there is no scale.
1 parent 1610eaa commit 64f4ceb

File tree

5 files changed

+72
-12
lines changed

5 files changed

+72
-12
lines changed

llvm/include/llvm/IR/Instructions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4370,6 +4370,9 @@ class InvokeInst : public CallBase {
43704370

43714371
unsigned getNumSuccessors() const { return 2; }
43724372

4373+
/// Updates profile metadata by scaling it by \p S / \p T.
4374+
void updateProfWeight(uint64_t S, uint64_t T);
4375+
43734376
// Methods for support type inquiry through isa, cast, and dyn_cast:
43744377
static bool classof(const Instruction *I) {
43754378
return (I->getOpcode() == Instruction::Invoke);

llvm/lib/IR/Instructions.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -927,6 +927,18 @@ LandingPadInst *InvokeInst::getLandingPadInst() const {
927927
return cast<LandingPadInst>(getUnwindDest()->getFirstNonPHI());
928928
}
929929

930+
void InvokeInst::updateProfWeight(uint64_t S, uint64_t T) {
931+
if (T == 0) {
932+
LLVM_DEBUG(dbgs() << "Attempting to update profile weights will result in "
933+
"div by 0. Ignoring. Likely the function "
934+
<< getParent()->getParent()->getName()
935+
<< " has 0 entry count, and contains call instructions "
936+
"with non-zero prof info.");
937+
return;
938+
}
939+
scaleProfData(*this, S, T);
940+
}
941+
930942
//===----------------------------------------------------------------------===//
931943
// CallBrInst Implementation
932944
//===----------------------------------------------------------------------===//

llvm/lib/IR/ProfDataUtils.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ constexpr unsigned WeightsIdx = 1;
4646
// the minimum number of operands for MD_prof nodes with branch weights
4747
constexpr unsigned MinBWOps = 3;
4848

49+
// the minimum number of operands for MD_prof nodes with value profiles
50+
constexpr unsigned MinVPOps = 5;
51+
4952
// We may want to add support for other MD_prof types, so provide an abstraction
5053
// for checking the metadata type.
5154
bool isTargetMD(const MDNode *ProfData, const char *Name, unsigned MinOps) {
@@ -97,11 +100,25 @@ bool isBranchWeightMD(const MDNode *ProfileData) {
97100
return isTargetMD(ProfileData, "branch_weights", MinBWOps);
98101
}
99102

103+
bool isValueProfileMD(const MDNode *ProfileData) {
104+
return isTargetMD(ProfileData, "VP", MinVPOps);
105+
}
106+
100107
bool hasBranchWeightMD(const Instruction &I) {
101108
auto *ProfileData = I.getMetadata(LLVMContext::MD_prof);
102109
return isBranchWeightMD(ProfileData);
103110
}
104111

112+
bool hasCountTypeMD(const Instruction &I) {
113+
auto *ProfileData = I.getMetadata(LLVMContext::MD_prof);
114+
// Value profiles record count-type information.
115+
if (isValueProfileMD(ProfileData))
116+
return true;
117+
// Conservatively assume non CallBase instruction only get taken/not-taken
118+
// branch probability, so not interpret them as count.
119+
return isa<CallBase>(I) && !isBranchWeightMD(ProfileData);
120+
}
121+
105122
bool hasValidBranchWeightMD(const Instruction &I) {
106123
return getValidBranchWeightMDNode(I);
107124
}
@@ -212,6 +229,9 @@ void scaleProfData(Instruction &I, uint64_t S, uint64_t T) {
212229
ProfDataName->getString() != "VP"))
213230
return;
214231

232+
if (!hasCountTypeMD(I))
233+
return;
234+
215235
LLVMContext &C = I.getContext();
216236

217237
MDBuilder MDB(C);

llvm/lib/Transforms/Utils/InlineFunction.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1982,10 +1982,14 @@ void llvm::updateProfileCallee(
19821982
// During inlining ?
19831983
if (VMap) {
19841984
uint64_t CloneEntryCount = PriorEntryCount - NewEntryCount;
1985-
for (auto Entry : *VMap)
1985+
for (auto Entry : *VMap) {
19861986
if (isa<CallInst>(Entry.first))
19871987
if (auto *CI = dyn_cast_or_null<CallInst>(Entry.second))
19881988
CI->updateProfWeight(CloneEntryCount, PriorEntryCount);
1989+
if (isa<InvokeInst>(Entry.first))
1990+
if (auto *II = dyn_cast_or_null<InvokeInst>(Entry.second))
1991+
II->updateProfWeight(CloneEntryCount, PriorEntryCount);
1992+
}
19891993
}
19901994

19911995
if (EntryDelta) {
@@ -1994,9 +1998,12 @@ void llvm::updateProfileCallee(
19941998
for (BasicBlock &BB : *Callee)
19951999
// No need to update the callsite if it is pruned during inlining.
19962000
if (!VMap || VMap->count(&BB))
1997-
for (Instruction &I : BB)
2001+
for (Instruction &I : BB) {
19982002
if (CallInst *CI = dyn_cast<CallInst>(&I))
19992003
CI->updateProfWeight(NewEntryCount, PriorEntryCount);
2004+
if (InvokeInst *II = dyn_cast<InvokeInst>(&I))
2005+
II->updateProfWeight(NewEntryCount, PriorEntryCount);
2006+
}
20002007
}
20012008
}
20022009

llvm/test/Transforms/Inline/update_invoke_prof.ll

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,31 @@
1-
; A pre-commit test to show that branch weights and value profiles associated with invoke are not updated.
1+
; Test that branch weights and value profiles associated with invoke are updated
2+
; in both caller and callee after inline, but invoke instructions with taken or
3+
; not taken branch probabilities are not updated.
24
; RUN: opt < %s -passes='require<profile-summary>,cgscc(inline)' -S | FileCheck %s
35

46
declare i32 @__gxx_personality_v0(...)
57

68
define void @caller(ptr %func) personality ptr @__gxx_personality_v0 !prof !15 {
79
call void @callee(ptr %func), !prof !16
10+
811
ret void
912
}
1013

11-
declare void @inner_callee(ptr %func)
14+
declare void @callee1(ptr %func)
15+
16+
declare void @callee2(ptr %func)
1217

1318
define void @callee(ptr %func) personality ptr @__gxx_personality_v0 !prof !17 {
1419
invoke void %func()
1520
to label %next unwind label %lpad, !prof !18
1621

1722
next:
18-
invoke void @inner_callee(ptr %func)
19-
to label %ret unwind label %lpad, !prof !19
23+
invoke void @callee1(ptr %func)
24+
to label %cont unwind label %lpad, !prof !19
25+
26+
cont:
27+
invoke void @callee2(ptr %func)
28+
to label %ret unwind label %lpad, !prof !20
2029

2130
lpad:
2231
%exn = landingpad {ptr, i32}
@@ -47,18 +56,27 @@ ret:
4756
!17 = !{!"function_entry_count", i32 1500}
4857
!18 = !{!"VP", i32 0, i64 1500, i64 123, i64 900, i64 456, i64 600}
4958
!19 = !{!"branch_weights", i32 1500}
59+
!20 = !{!"branch_weights", i32 1234, i32 5678}
5060

5161
; CHECK-LABEL: @caller(
5262
; CHECK: invoke void %func(
5363
; CHECK-NEXT: {{.*}} !prof ![[PROF1:[0-9]+]]
54-
; CHECK: invoke void @inner_callee(
64+
; CHECK: invoke void @callee1(
5565
; CHECK-NEXT: {{.*}} !prof ![[PROF2:[0-9]+]]
66+
; CHECK: invoke void @callee2(
67+
; CHECK-NEXT: {{.*}} !prof ![[PROF3:[0-9]+]]
5668

5769
; CHECK-LABL: @callee(
5870
; CHECK: invoke void %func(
59-
; CHECK-NEXT: {{.*}} !prof ![[PROF1]]
60-
; CHECK: invoke void @inner_callee(
61-
; CHECK-NEXT: {{.*}} !prof ![[PROF2]]
71+
; CHECK-NEXT: {{.*}} !prof ![[PROF4:[0-9]+]]
72+
; CHECK: invoke void @callee1(
73+
; CHECK-NEXT: {{.*}} !prof ![[PROF5:[0-9]+]]
74+
; CHECK: invoke void @callee2(
75+
; CHECK-NEXT: {{.*}} !prof ![[PROF3]]
76+
6277

63-
; CHECK: ![[PROF1]] = !{!"VP", i32 0, i64 1500, i64 123, i64 900, i64 456, i64 600}
64-
; CHECK: ![[PROF2]] = !{!"branch_weights", i32 1500}
78+
; CHECK: ![[PROF1]] = !{!"VP", i32 0, i64 1000, i64 123, i64 600, i64 456, i64 400}
79+
; CHECK: ![[PROF2]] = !{!"branch_weights", i32 1000}
80+
; CHECK: ![[PROF3]] = !{!"branch_weights", i32 1234, i32 5678}
81+
; CHECK: ![[PROF4]] = !{!"VP", i32 0, i64 500, i64 123, i64 300, i64 456, i64 200}
82+
; CHECK: ![[PROF5]] = !{!"branch_weights", i32 500}

0 commit comments

Comments
 (0)