Skip to content

Commit f5b81aa

Browse files
[InstrProf] Support conditional counter updates (#102542)
This patch adds support for conditional counter updates in single byte counters mode to reduce the write contention by first checking whether the counter is set before overwriting it. --------- Co-authored-by: Juan Manuel Martinez Caamaño <jmartinezcaamao@gmail.com>
1 parent 7ff377b commit f5b81aa

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed

llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ cl::opt<bool> AtomicFirstCounter(
132132
"the entry counter)"),
133133
cl::init(false));
134134

135+
cl::opt<bool> ConditionalCounterUpdate(
136+
"conditional-counter-update",
137+
cl::desc("Do conditional counter updates in single byte counters mode)"),
138+
cl::init(false));
139+
135140
// If the option is not specified, the default behavior about whether
136141
// counter promotion is done depends on how instrumentaiton lowering
137142
// pipeline is setup, i.e., the default value of true of this option
@@ -1213,6 +1218,17 @@ Value *InstrLowerer::getBitmapAddress(InstrProfMCDCTVBitmapUpdate *I) {
12131218
void InstrLowerer::lowerCover(InstrProfCoverInst *CoverInstruction) {
12141219
auto *Addr = getCounterAddress(CoverInstruction);
12151220
IRBuilder<> Builder(CoverInstruction);
1221+
if (ConditionalCounterUpdate) {
1222+
Instruction *SplitBefore = CoverInstruction->getNextNode();
1223+
auto &Ctx = CoverInstruction->getParent()->getContext();
1224+
auto *Int8Ty = llvm::Type::getInt8Ty(Ctx);
1225+
Value *Load = Builder.CreateLoad(Int8Ty, Addr, "pgocount");
1226+
Value *Cmp = Builder.CreateIsNotNull(Load, "pgocount.ifnonzero");
1227+
Instruction *ThenBranch =
1228+
SplitBlockAndInsertIfThen(Cmp, SplitBefore, false);
1229+
Builder.SetInsertPoint(ThenBranch);
1230+
}
1231+
12161232
// We store zero to represent that this block is covered.
12171233
Builder.CreateStore(Builder.getInt8(0), Addr);
12181234
CoverInstruction->eraseFromParent();
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
; RUN: opt < %s -S -passes=instrprof -conditional-counter-update | FileCheck %s
2+
3+
target triple = "x86_64-unknown-linux-gnu"
4+
5+
@__profn_foo = private constant [3 x i8] c"foo"
6+
@__profn_bar = private constant [3 x i8] c"bar"
7+
8+
; CHECK-LABEL: define void @foo
9+
; CHECK-NEXT: %pgocount = load i8, ptr @__profc_foo, align 1
10+
; CHECK-NEXT: %pgocount.ifnonzero = icmp ne i8 %pgocount, 0
11+
; CHECK-NEXT: br i1 %pgocount.ifnonzero, label %1, label %2
12+
13+
; CHECK-LABEL: 1:
14+
; CHECK-NEXT: store i8 0, ptr @__profc_foo, align 1
15+
; CHECK-NEXT: br label %2
16+
17+
; CHECK-LABEL: 2:
18+
; CHECK-NEXT: ret void
19+
define void @foo() {
20+
call void @llvm.instrprof.cover(ptr @__profn_foo, i64 0, i32 1, i32 0)
21+
ret void
22+
}
23+
24+
; CHECK-LABEL: define i32 @bar
25+
; CHECK-LABEL: entry:
26+
; CHECK-NEXT: %retval = alloca i32, align 4
27+
; CHECK-NEXT: %cond.addr = alloca i32, align 4
28+
; CHECK-NEXT: store i32 %cond, ptr %cond.addr, align 4
29+
; CHECK-NEXT: %pgocount = load i8, ptr @__profc_bar, align 1
30+
; CHECK-NEXT: %pgocount.ifnonzero = icmp ne i8 %pgocount, 0
31+
; CHECK-NEXT: br i1 %pgocount.ifnonzero, label %0, label %1
32+
33+
; CHECK-LABEL: 0: ; preds = %entry
34+
; CHECK-NEXT: store i8 0, ptr @__profc_bar, align 1
35+
; CHECK-NEXT: br label %1
36+
37+
; CHECK-LABEL: 1: ; preds = %entry, %0
38+
; CHECK-NEXT: %2 = load i32, ptr %cond.addr, align 4
39+
; CHECK-NEXT: %cmp = icmp slt i32 %2, 0
40+
; CHECK-NEXT: br i1 %cmp, label %if.then, label %if.end
41+
42+
; CHECK-LABEL: if.then: ; preds = %1
43+
; CHECK-NEXT: %pgocount1 = load i8, ptr getelementptr inbounds ([3 x i8], ptr @__profc_bar, i32 0, i32 1), align 1
44+
; CHECK-NEXT: %pgocount.ifnonzero2 = icmp ne i8 %pgocount1, 0
45+
; CHECK-NEXT: br i1 %pgocount.ifnonzero2, label %3, label %4
46+
define i32 @bar(i32 %cond) #0 {
47+
entry:
48+
%retval = alloca i32, align 4
49+
%cond.addr = alloca i32, align 4
50+
store i32 %cond, ptr %cond.addr, align 4
51+
call void @llvm.instrprof.cover(ptr @__profn_bar, i64 0, i32 3, i32 0)
52+
%0 = load i32, ptr %cond.addr, align 4
53+
%cmp = icmp slt i32 %0, 0
54+
br i1 %cmp, label %if.then, label %if.end
55+
56+
if.then: ; preds = %entry
57+
call void @llvm.instrprof.cover(ptr @__profn_bar, i64 0, i32 3, i32 1)
58+
store i32 -1, ptr %retval, align 4
59+
br label %return
60+
61+
if.end: ; preds = %entry
62+
call void @llvm.instrprof.cover(ptr @__profn_bar, i64 0, i32 3, i32 2)
63+
store i32 0, ptr %retval, align 4
64+
br label %return
65+
66+
return: ; preds = %if.end, %if.then
67+
%1 = load i32, ptr %retval, align 4
68+
ret i32 %1
69+
}

0 commit comments

Comments
 (0)