Skip to content

Commit a6b2de6

Browse files
committed
[ctx_prof] Add analysis utility to fetch ID of a callsite
1 parent e306db0 commit a6b2de6

File tree

4 files changed

+157
-0
lines changed

4 files changed

+157
-0
lines changed

llvm/include/llvm/Analysis/CtxProfAnalysis.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#ifndef LLVM_ANALYSIS_CTXPROFANALYSIS_H
1010
#define LLVM_ANALYSIS_CTXPROFANALYSIS_H
1111

12+
#include "llvm/IR/InstrTypes.h"
13+
#include "llvm/IR/IntrinsicInst.h"
1214
#include "llvm/IR/PassManager.h"
1315
#include "llvm/ProfileData/PGOCtxProfReader.h"
1416

@@ -82,6 +84,8 @@ class CtxProfAnalysis : public AnalysisInfoMixin<CtxProfAnalysis> {
8284
using Result = PGOContextualProfile;
8385

8486
PGOContextualProfile run(Module &M, ModuleAnalysisManager &MAM);
87+
88+
static InstrProfCallsite *getCallsiteInstrumentation(CallBase &CB);
8589
};
8690

8791
class CtxProfAnalysisPrinterPass

llvm/lib/Analysis/CtxProfAnalysis.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,10 @@ PreservedAnalyses CtxProfAnalysisPrinterPass::run(Module &M,
186186
OS << "\n";
187187
return PreservedAnalyses::all();
188188
}
189+
190+
InstrProfCallsite *CtxProfAnalysis::getCallsiteInstrumentation(CallBase &CB) {
191+
while (auto *Prev = CB.getPrevNode())
192+
if (auto *IPC = dyn_cast<InstrProfCallsite>(Prev))
193+
return IPC;
194+
return nullptr;
195+
}

llvm/unittests/Analysis/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ set(ANALYSIS_TEST_SOURCES
2222
CFGTest.cpp
2323
CGSCCPassManagerTest.cpp
2424
ConstraintSystemTest.cpp
25+
CtxProfAnalysisTest.cpp
2526
DDGTest.cpp
2627
DomTreeUpdaterTest.cpp
2728
DXILResourceTest.cpp
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
//===--- CtxProfAnalysisTest.cpp ------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/Analysis/CtxProfAnalysis.h"
10+
#include "llvm/Analysis/BlockFrequencyInfo.h"
11+
#include "llvm/Analysis/BranchProbabilityInfo.h"
12+
#include "llvm/Analysis/CGSCCPassManager.h"
13+
#include "llvm/Analysis/LoopAnalysisManager.h"
14+
#include "llvm/Analysis/TargetLibraryInfo.h"
15+
#include "llvm/AsmParser/Parser.h"
16+
#include "llvm/IR/Analysis.h"
17+
#include "llvm/IR/Module.h"
18+
#include "llvm/IR/PassInstrumentation.h"
19+
#include "llvm/IR/PassManager.h"
20+
#include "llvm/Passes/PassBuilder.h"
21+
#include "llvm/Support/SourceMgr.h"
22+
#include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
23+
#include "gtest/gtest.h"
24+
25+
using namespace llvm;
26+
27+
namespace {
28+
29+
class CtxProfAnalysisTest : public testing::Test {
30+
static constexpr auto *IR = R"IR(
31+
declare void @bar()
32+
33+
define private void @foo(i32 %a, ptr %fct) #0 !guid !0 {
34+
%t = icmp eq i32 %a, 0
35+
br i1 %t, label %yes, label %no
36+
yes:
37+
call void %fct(i32 %a)
38+
br label %exit
39+
no:
40+
call void @bar()
41+
br label %exit
42+
exit:
43+
ret void
44+
}
45+
46+
define void @an_entrypoint(i32 %a) {
47+
%t = icmp eq i32 %a, 0
48+
br i1 %t, label %yes, label %no
49+
50+
yes:
51+
call void @foo(i32 1, ptr null)
52+
ret void
53+
no:
54+
ret void
55+
}
56+
57+
define void @another_entrypoint_no_callees(i32 %a) {
58+
%t = icmp eq i32 %a, 0
59+
br i1 %t, label %yes, label %no
60+
61+
yes:
62+
ret void
63+
no:
64+
ret void
65+
}
66+
67+
attributes #0 = { noinline }
68+
!0 = !{ i64 11872291593386833696 }
69+
)IR";
70+
71+
protected:
72+
LLVMContext C;
73+
PassBuilder PB;
74+
ModuleAnalysisManager MAM;
75+
FunctionAnalysisManager FAM;
76+
CGSCCAnalysisManager CGAM;
77+
LoopAnalysisManager LAM;
78+
std::unique_ptr<Module> M;
79+
80+
void SetUp() override {
81+
SMDiagnostic Err;
82+
M = parseAssemblyString(IR, Err, C);
83+
if (!M)
84+
Err.print("CtxProfAnalysisTest", errs());
85+
}
86+
87+
public:
88+
CtxProfAnalysisTest() {
89+
PB.registerModuleAnalyses(MAM);
90+
PB.registerCGSCCAnalyses(CGAM);
91+
PB.registerFunctionAnalyses(FAM);
92+
PB.registerLoopAnalyses(LAM);
93+
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
94+
}
95+
};
96+
97+
TEST_F(CtxProfAnalysisTest, GetCallsiteIDTest) {
98+
ASSERT_TRUE(!!M);
99+
ModulePassManager MPM;
100+
MPM.addPass(PGOInstrumentationGen(PGOInstrumentationType::CTXPROF));
101+
EXPECT_FALSE(MPM.run(*M, MAM).areAllPreserved());
102+
auto *F = M->getFunction("foo");
103+
ASSERT_NE(F, nullptr);
104+
CallBase *IndCall = nullptr;
105+
CallBase *DirCall = nullptr;
106+
for (auto &BB : *F)
107+
for (auto &I : BB)
108+
if (auto *CB = dyn_cast<CallBase>(&I)) {
109+
if (CB->isIndirectCall()) {
110+
EXPECT_EQ(IndCall, nullptr);
111+
IndCall = CB;
112+
} else if (!CB->getCalledFunction()->isIntrinsic()) {
113+
EXPECT_EQ(DirCall, nullptr);
114+
DirCall = CB;
115+
}
116+
}
117+
EXPECT_NE(IndCall, nullptr);
118+
EXPECT_NE(DirCall, nullptr);
119+
auto *IndIns = CtxProfAnalysis::getCallsiteInstrumentation(*IndCall);
120+
ASSERT_NE(IndIns, nullptr);
121+
EXPECT_EQ(IndIns->getIndex()->getZExtValue(), 0U);
122+
auto *DirIns = CtxProfAnalysis::getCallsiteInstrumentation(*DirCall);
123+
ASSERT_NE(DirIns, nullptr);
124+
EXPECT_EQ(DirIns->getIndex()->getZExtValue(), 1U);
125+
}
126+
127+
TEST_F(CtxProfAnalysisTest, GetCallsiteIDNegativeTest) {
128+
ASSERT_TRUE(!!M);
129+
auto *F = M->getFunction("foo");
130+
ASSERT_NE(F, nullptr);
131+
CallBase *FirstCall = nullptr;
132+
for (auto &BB : *F)
133+
for (auto &I : BB)
134+
if (auto *CB = dyn_cast<CallBase>(&I)) {
135+
if (CB->isIndirectCall() || !CB->getCalledFunction()->isIntrinsic()) {
136+
FirstCall = CB;
137+
break;
138+
}
139+
}
140+
EXPECT_NE(FirstCall, nullptr);
141+
auto *IndIns = CtxProfAnalysis::getCallsiteInstrumentation(*FirstCall);
142+
ASSERT_EQ(IndIns, nullptr);
143+
}
144+
145+
} // namespace

0 commit comments

Comments
 (0)