Skip to content

Commit f675483

Browse files
authored
[profcheck] Annotate select instructions (#152171)
For `select`, we don't have the equivalent of the branch probability analysis to offer defaults, so we make up our own and allow their overriding with flags. Issue #147390
1 parent 7268478 commit f675483

File tree

2 files changed

+90
-2
lines changed

2 files changed

+90
-2
lines changed

llvm/lib/Transforms/Utils/ProfileVerify.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ using namespace llvm;
2626
static cl::opt<int64_t>
2727
DefaultFunctionEntryCount("profcheck-default-function-entry-count",
2828
cl::init(1000));
29+
static cl::opt<bool>
30+
AnnotateSelect("profcheck-annotate-select", cl::init(true),
31+
cl::desc("Also inject (if missing) and verify MD_prof for "
32+
"`select` instructions"));
33+
static cl::opt<uint32_t> SelectTrueWeight(
34+
"profcheck-default-select-true-weight", cl::init(2U),
35+
cl::desc("When annotating `select` instructions, this value will be used "
36+
"for the first ('true') case."));
37+
static cl::opt<uint32_t> SelectFalseWeight(
38+
"profcheck-default-select-false-weight", cl::init(3U),
39+
cl::desc("When annotating `select` instructions, this value will be used "
40+
"for the second ('false') case."));
2941
namespace {
3042
class ProfileInjector {
3143
Function &F;
@@ -82,6 +94,13 @@ bool ProfileInjector::inject() {
8294
return false;
8395
bool Changed = false;
8496
for (auto &BB : F) {
97+
if (AnnotateSelect) {
98+
for (auto &I : BB) {
99+
if (isa<SelectInst>(I) && !I.getMetadata(LLVMContext::MD_prof))
100+
setBranchWeights(I, {SelectTrueWeight, SelectFalseWeight},
101+
/*IsExpected=*/false);
102+
}
103+
}
85104
auto *Term = getTerminatorBenefitingFromMDProf(BB);
86105
if (!Term || Term->getMetadata(LLVMContext::MD_prof))
87106
continue;
@@ -144,12 +163,18 @@ PreservedAnalyses ProfileVerifierPass::run(Function &F,
144163
}
145164
if (EntryCount->getCount() == 0)
146165
return PreservedAnalyses::all();
147-
for (const auto &BB : F)
166+
for (const auto &BB : F) {
167+
if (AnnotateSelect) {
168+
for (const auto &I : BB)
169+
if (isa<SelectInst>(I) && !I.getMetadata(LLVMContext::MD_prof))
170+
F.getContext().emitError(
171+
"Profile verification failed: select annotation missing");
172+
}
148173
if (const auto *Term =
149174
ProfileInjector::getTerminatorBenefitingFromMDProf(BB))
150175
if (!Term->getMetadata(LLVMContext::MD_prof))
151176
F.getContext().emitError(
152177
"Profile verification failed: branch annotation missing");
153-
178+
}
154179
return PreservedAnalyses::all();
155180
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
; RUN: split-file %s %t
2+
3+
; RUN: opt -passes=prof-inject %t/inject.ll -S -o - | FileCheck %t/inject.ll
4+
5+
; RUN: opt -passes=prof-inject %t/inject-some.ll \
6+
; RUN: -profcheck-default-select-true-weight=1 -profcheck-default-select-false-weight=6 \
7+
; RUN: -S -o - | FileCheck %t/inject-some.ll
8+
9+
; RUN: opt -passes=prof-verify %t/verify.ll 2>&1 | FileCheck %t/verify.ll
10+
11+
; RUN: not opt -passes=prof-verify %t/verify-missing.ll 2>&1 | FileCheck %t/verify-missing.ll
12+
13+
; verify we can disable it. It's sufficient to see opt not failing.
14+
; RUN: opt -passes=prof-verify -profcheck-annotate-select=0 %t/verify-missing.ll
15+
16+
;--- inject.ll
17+
declare void @foo(i32 %a);
18+
define void @bar(i1 %c) {
19+
%v = select i1 %c, i32 1, i32 2
20+
call void @foo(i32 %v)
21+
ret void
22+
}
23+
; CHECK-LABEL: @bar
24+
; CHECK: %v = select i1 %c, i32 1, i32 2, !prof !1
25+
; CHECK: !0 = !{!"function_entry_count", i64 1000}
26+
; CHECK: !1 = !{!"branch_weights", i32 2, i32 3}
27+
28+
;--- inject-some.ll
29+
declare void @foo(i32 %a);
30+
define void @bar(i1 %c) {
31+
%e = select i1 %c, i32 1, i32 2, !prof !0
32+
%c2 = icmp eq i32 %e, 2
33+
%v = select i1 %c2, i32 5, i32 10
34+
call void @foo(i32 %v)
35+
ret void
36+
}
37+
!0 = !{!"branch_weights", i32 2, i32 3}
38+
; CHECK-LABEL: @bar
39+
; CHECK: %v = select i1 %c2, i32 5, i32 10, !prof !2
40+
; CHECK: !0 = !{!"function_entry_count", i64 1000}
41+
; CHECK: !1 = !{!"branch_weights", i32 2, i32 3}
42+
; CHECK: !2 = !{!"branch_weights", i32 1, i32 6}
43+
44+
;--- verify.ll
45+
declare void @foo(i32 %a);
46+
define void @bar(i1 %c) !prof !0 {
47+
%v = select i1 %c, i32 1, i32 2, !prof !1
48+
call void @foo(i32 %v)
49+
ret void
50+
}
51+
!0 = !{!"function_entry_count", i64 1000}
52+
!1 = !{!"branch_weights", i32 1, i32 7}
53+
; CHECK-NOT: Profile verification failed: select annotation missing
54+
55+
;--- verify-missing.ll
56+
declare void @foo(i32 %a);
57+
define void @bar(i1 %c) !prof !0 {
58+
%v = select i1 %c, i32 1, i32 2
59+
call void @foo(i32 %v)
60+
ret void
61+
}
62+
!0 = !{!"function_entry_count", i64 1000}
63+
; CHECK: Profile verification failed: select annotation missing

0 commit comments

Comments
 (0)