[PSI] Add the isCold query support with a given percentile value.

Summary: This follows up D67377 that added the isHot side.

Reviewers: davidxl

Subscribers: eraman, hiraditya, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D75283
This commit is contained in:
Hiroshi Yamauchi 2020-02-27 10:49:04 -08:00
parent 7e77cf473a
commit 4d6f3ee2ba
3 changed files with 213 additions and 13 deletions

View File

@ -120,6 +120,11 @@ public:
bool isFunctionHotInCallGraphNthPercentile(int PercentileCutoff,
const Function *F,
BlockFrequencyInfo &BFI);
/// Returns true if \p F contains cold code with regard to a given cold
/// percentile cutoff value.
bool isFunctionColdInCallGraphNthPercentile(int PercentileCutoff,
const Function *F,
BlockFrequencyInfo &BFI);
/// Returns true if count \p C is considered hot.
bool isHotCount(uint64_t C);
/// Returns true if count \p C is considered cold.
@ -127,6 +132,9 @@ public:
/// Returns true if count \p C is considered hot with regard to a given
/// hot percentile cutoff value.
bool isHotCountNthPercentile(int PercentileCutoff, uint64_t C);
/// Returns true if count \p C is considered cold with regard to a given
/// cold percentile cutoff value.
bool isColdCountNthPercentile(int PercentileCutoff, uint64_t C);
/// Returns true if BasicBlock \p BB is considered hot.
bool isHotBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI);
/// Returns true if BasicBlock \p BB is considered cold.
@ -135,6 +143,10 @@ public:
/// hot percentile cutoff value.
bool isHotBlockNthPercentile(int PercentileCutoff,
const BasicBlock *BB, BlockFrequencyInfo *BFI);
/// Returns true if BasicBlock \p BB is considered cold with regard to a given
/// cold percentile cutoff value.
bool isColdBlockNthPercentile(int PercentileCutoff,
const BasicBlock *BB, BlockFrequencyInfo *BFI);
/// Returns true if CallSite \p CS is considered hot.
bool isHotCallSite(const CallSite &CS, BlockFrequencyInfo *BFI);
/// Returns true if Callsite \p CS is considered cold.
@ -153,6 +165,17 @@ public:
uint64_t getColdCountThreshold() {
return ColdCountThreshold ? ColdCountThreshold.getValue() : 0;
}
private:
template<bool isHot>
bool isFunctionHotOrColdInCallGraphNthPercentile(int PercentileCutoff,
const Function *F,
BlockFrequencyInfo &BFI);
template<bool isHot>
bool isHotOrColdCountNthPercentile(int PercentileCutoff, uint64_t C);
template<bool isHot>
bool isHotOrColdBlockNthPercentile(int PercentileCutoff, const BasicBlock *BB,
BlockFrequencyInfo *BFI);
};
/// An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.

View File

@ -195,15 +195,19 @@ bool ProfileSummaryInfo::isFunctionColdInCallGraph(const Function *F,
return true;
}
// Like isFunctionHotInCallGraph but for a given cutoff.
bool ProfileSummaryInfo::isFunctionHotInCallGraphNthPercentile(
template<bool isHot>
bool ProfileSummaryInfo::isFunctionHotOrColdInCallGraphNthPercentile(
int PercentileCutoff, const Function *F, BlockFrequencyInfo &BFI) {
if (!F || !computeSummary())
return false;
if (auto FunctionCount = F->getEntryCount())
if (isHotCountNthPercentile(PercentileCutoff, FunctionCount.getCount()))
if (auto FunctionCount = F->getEntryCount()) {
if (isHot &&
isHotCountNthPercentile(PercentileCutoff, FunctionCount.getCount()))
return true;
if (!isHot &&
!isColdCountNthPercentile(PercentileCutoff, FunctionCount.getCount()))
return false;
}
if (hasSampleProfile()) {
uint64_t TotalCallCount = 0;
for (const auto &BB : *F)
@ -211,13 +215,31 @@ bool ProfileSummaryInfo::isFunctionHotInCallGraphNthPercentile(
if (isa<CallInst>(I) || isa<InvokeInst>(I))
if (auto CallCount = getProfileCount(&I, nullptr))
TotalCallCount += CallCount.getValue();
if (isHotCountNthPercentile(PercentileCutoff, TotalCallCount))
if (isHot && isHotCountNthPercentile(PercentileCutoff, TotalCallCount))
return true;
if (!isHot && !isColdCountNthPercentile(PercentileCutoff, TotalCallCount))
return false;
}
for (const auto &BB : *F)
if (isHotBlockNthPercentile(PercentileCutoff, &BB, &BFI))
for (const auto &BB : *F) {
if (isHot && isHotBlockNthPercentile(PercentileCutoff, &BB, &BFI))
return true;
return false;
if (!isHot && !isColdBlockNthPercentile(PercentileCutoff, &BB, &BFI))
return false;
}
return !isHot;
}
// Like isFunctionHotInCallGraph but for a given cutoff.
bool ProfileSummaryInfo::isFunctionHotInCallGraphNthPercentile(
int PercentileCutoff, const Function *F, BlockFrequencyInfo &BFI) {
return isFunctionHotOrColdInCallGraphNthPercentile<true>(
PercentileCutoff, F, BFI);
}
bool ProfileSummaryInfo::isFunctionColdInCallGraphNthPercentile(
int PercentileCutoff, const Function *F, BlockFrequencyInfo &BFI) {
return isFunctionHotOrColdInCallGraphNthPercentile<false>(
PercentileCutoff, F, BFI);
}
/// Returns true if the function's entry is a cold. If it returns false, it
@ -299,9 +321,22 @@ bool ProfileSummaryInfo::isColdCount(uint64_t C) {
return ColdCountThreshold && C <= ColdCountThreshold.getValue();
}
bool ProfileSummaryInfo::isHotCountNthPercentile(int PercentileCutoff, uint64_t C) {
template<bool isHot>
bool ProfileSummaryInfo::isHotOrColdCountNthPercentile(int PercentileCutoff,
uint64_t C) {
auto CountThreshold = computeThreshold(PercentileCutoff);
return CountThreshold && C >= CountThreshold.getValue();
if (isHot)
return CountThreshold && C >= CountThreshold.getValue();
else
return CountThreshold && C <= CountThreshold.getValue();
}
bool ProfileSummaryInfo::isHotCountNthPercentile(int PercentileCutoff, uint64_t C) {
return isHotOrColdCountNthPercentile<true>(PercentileCutoff, C);
}
bool ProfileSummaryInfo::isColdCountNthPercentile(int PercentileCutoff, uint64_t C) {
return isHotOrColdCountNthPercentile<false>(PercentileCutoff, C);
}
uint64_t ProfileSummaryInfo::getOrCompHotCountThreshold() {
@ -327,11 +362,27 @@ bool ProfileSummaryInfo::isColdBlock(const BasicBlock *BB,
return Count && isColdCount(*Count);
}
template<bool isHot>
bool ProfileSummaryInfo::isHotOrColdBlockNthPercentile(int PercentileCutoff,
const BasicBlock *BB,
BlockFrequencyInfo *BFI) {
auto Count = BFI->getBlockProfileCount(BB);
if (isHot)
return Count && isHotCountNthPercentile(PercentileCutoff, *Count);
else
return Count && isColdCountNthPercentile(PercentileCutoff, *Count);
}
bool ProfileSummaryInfo::isHotBlockNthPercentile(int PercentileCutoff,
const BasicBlock *BB,
BlockFrequencyInfo *BFI) {
auto Count = BFI->getBlockProfileCount(BB);
return Count && isHotCountNthPercentile(PercentileCutoff, *Count);
return isHotOrColdBlockNthPercentile<true>(PercentileCutoff, BB, BFI);
}
bool ProfileSummaryInfo::isColdBlockNthPercentile(int PercentileCutoff,
const BasicBlock *BB,
BlockFrequencyInfo *BFI) {
return isHotOrColdBlockNthPercentile<false>(PercentileCutoff, BB, BFI);
}
bool ProfileSummaryInfo::isHotCallSite(const CallSite &CS,

View File

@ -65,6 +65,20 @@ protected:
" %y2 = phi i32 [0, %bb1], [1, %bb2] \n"
" ret i32 %y2\n"
"}\n"
"define i32 @l(i32 %x) {{\n"
"bb0:\n"
" %y1 = icmp eq i32 %x, 0 \n"
" br i1 %y1, label %bb1, label %bb2, !prof !23 \n"
"bb1:\n"
" %z1 = call i32 @g(i32 %x)\n"
" br label %bb3\n"
"bb2:\n"
" %z2 = call i32 @h(i32 %x)\n"
" br label %bb3\n"
"bb3:\n"
" %y2 = phi i32 [0, %bb1], [1, %bb2] \n"
" ret i32 %y2\n"
"}\n"
"!20 = !{{!\"function_entry_count\", i64 400}\n"
"!21 = !{{!\"function_entry_count\", i64 1}\n"
"!22 = !{{!\"function_entry_count\", i64 100}\n"
@ -141,14 +155,26 @@ TEST_F(ProfileSummaryInfoTest, TestCommon) {
EXPECT_FALSE(PSI.isHotCountNthPercentile(990000, 100));
EXPECT_FALSE(PSI.isHotCountNthPercentile(990000, 2));
EXPECT_FALSE(PSI.isColdCountNthPercentile(990000, 400));
EXPECT_TRUE(PSI.isColdCountNthPercentile(990000, 100));
EXPECT_TRUE(PSI.isColdCountNthPercentile(990000, 2));
EXPECT_TRUE(PSI.isHotCountNthPercentile(999999, 400));
EXPECT_TRUE(PSI.isHotCountNthPercentile(999999, 100));
EXPECT_FALSE(PSI.isHotCountNthPercentile(999999, 2));
EXPECT_FALSE(PSI.isColdCountNthPercentile(999999, 400));
EXPECT_FALSE(PSI.isColdCountNthPercentile(999999, 100));
EXPECT_TRUE(PSI.isColdCountNthPercentile(999999, 2));
EXPECT_FALSE(PSI.isHotCountNthPercentile(10000, 400));
EXPECT_FALSE(PSI.isHotCountNthPercentile(10000, 100));
EXPECT_FALSE(PSI.isHotCountNthPercentile(10000, 2));
EXPECT_TRUE(PSI.isColdCountNthPercentile(10000, 400));
EXPECT_TRUE(PSI.isColdCountNthPercentile(10000, 100));
EXPECT_TRUE(PSI.isColdCountNthPercentile(10000, 2));
EXPECT_TRUE(PSI.isFunctionEntryHot(F));
EXPECT_FALSE(PSI.isFunctionEntryHot(G));
EXPECT_FALSE(PSI.isFunctionEntryHot(H));
@ -177,16 +203,31 @@ TEST_F(ProfileSummaryInfoTest, InstrProf) {
EXPECT_FALSE(PSI.isHotBlockNthPercentile(990000, BB2, &BFI));
EXPECT_TRUE(PSI.isHotBlockNthPercentile(990000, BB3, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(990000, &BB0, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(990000, BB1, &BFI));
EXPECT_TRUE(PSI.isColdBlockNthPercentile(990000, BB2, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(990000, BB3, &BFI));
EXPECT_TRUE(PSI.isHotBlockNthPercentile(999900, &BB0, &BFI));
EXPECT_TRUE(PSI.isHotBlockNthPercentile(999900, BB1, &BFI));
EXPECT_TRUE(PSI.isHotBlockNthPercentile(999900, BB2, &BFI));
EXPECT_TRUE(PSI.isHotBlockNthPercentile(999900, BB3, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(999900, &BB0, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(999900, BB1, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(999900, BB2, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(999900, BB3, &BFI));
EXPECT_FALSE(PSI.isHotBlockNthPercentile(10000, &BB0, &BFI));
EXPECT_FALSE(PSI.isHotBlockNthPercentile(10000, BB1, &BFI));
EXPECT_FALSE(PSI.isHotBlockNthPercentile(10000, BB2, &BFI));
EXPECT_FALSE(PSI.isHotBlockNthPercentile(10000, BB3, &BFI));
EXPECT_TRUE(PSI.isColdBlockNthPercentile(10000, &BB0, &BFI));
EXPECT_TRUE(PSI.isColdBlockNthPercentile(10000, BB1, &BFI));
EXPECT_TRUE(PSI.isColdBlockNthPercentile(10000, BB2, &BFI));
EXPECT_TRUE(PSI.isColdBlockNthPercentile(10000, BB3, &BFI));
CallSite CS1(BB1->getFirstNonPHI());
auto *CI2 = BB2->getFirstNonPHI();
CallSite CS2(CI2);
@ -201,6 +242,31 @@ TEST_F(ProfileSummaryInfoTest, InstrProf) {
EXPECT_FALSE(PSI.isHotCallSite(CS2, &BFI));
}
TEST_F(ProfileSummaryInfoTest, InstrProfNoFuncEntryCount) {
auto M = makeLLVMModule("InstrProf");
Function *F = M->getFunction("l");
ProfileSummaryInfo PSI = buildPSI(M.get());
EXPECT_TRUE(PSI.hasProfileSummary());
EXPECT_TRUE(PSI.hasInstrumentationProfile());
BasicBlock &BB0 = F->getEntryBlock();
BasicBlock *BB1 = BB0.getTerminator()->getSuccessor(0);
BasicBlock *BB2 = BB0.getTerminator()->getSuccessor(1);
BasicBlock *BB3 = BB1->getSingleSuccessor();
BlockFrequencyInfo BFI = buildBFI(*F);
// Without the entry count, all should return false.
EXPECT_FALSE(PSI.isHotBlockNthPercentile(990000, &BB0, &BFI));
EXPECT_FALSE(PSI.isHotBlockNthPercentile(990000, BB1, &BFI));
EXPECT_FALSE(PSI.isHotBlockNthPercentile(990000, BB2, &BFI));
EXPECT_FALSE(PSI.isHotBlockNthPercentile(990000, BB3, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(990000, &BB0, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(990000, BB1, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(990000, BB2, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(990000, BB3, &BFI));
}
TEST_F(ProfileSummaryInfoTest, SampleProf) {
auto M = makeLLVMModule("SampleProfile");
Function *F = M->getFunction("f");
@ -224,16 +290,31 @@ TEST_F(ProfileSummaryInfoTest, SampleProf) {
EXPECT_FALSE(PSI.isHotBlockNthPercentile(990000, BB2, &BFI));
EXPECT_TRUE(PSI.isHotBlockNthPercentile(990000, BB3, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(990000, &BB0, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(990000, BB1, &BFI));
EXPECT_TRUE(PSI.isColdBlockNthPercentile(990000, BB2, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(990000, BB3, &BFI));
EXPECT_TRUE(PSI.isHotBlockNthPercentile(999900, &BB0, &BFI));
EXPECT_TRUE(PSI.isHotBlockNthPercentile(999900, BB1, &BFI));
EXPECT_TRUE(PSI.isHotBlockNthPercentile(999900, BB2, &BFI));
EXPECT_TRUE(PSI.isHotBlockNthPercentile(999900, BB3, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(999900, &BB0, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(999900, BB1, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(999900, BB2, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(999900, BB3, &BFI));
EXPECT_FALSE(PSI.isHotBlockNthPercentile(10000, &BB0, &BFI));
EXPECT_FALSE(PSI.isHotBlockNthPercentile(10000, BB1, &BFI));
EXPECT_FALSE(PSI.isHotBlockNthPercentile(10000, BB2, &BFI));
EXPECT_FALSE(PSI.isHotBlockNthPercentile(10000, BB3, &BFI));
EXPECT_TRUE(PSI.isColdBlockNthPercentile(10000, &BB0, &BFI));
EXPECT_TRUE(PSI.isColdBlockNthPercentile(10000, BB1, &BFI));
EXPECT_TRUE(PSI.isColdBlockNthPercentile(10000, BB2, &BFI));
EXPECT_TRUE(PSI.isColdBlockNthPercentile(10000, BB3, &BFI));
CallSite CS1(BB1->getFirstNonPHI());
auto *CI2 = BB2->getFirstNonPHI();
// Manually attach branch weights metadata to the call instruction.
@ -250,6 +331,51 @@ TEST_F(ProfileSummaryInfoTest, SampleProf) {
// weights that exceed the hot count threshold.
CI2->setMetadata(llvm::LLVMContext::MD_prof, MDB.createBranchWeights({400}));
EXPECT_TRUE(PSI.isHotCallSite(CS2, &BFI));
{
Function *F = M->getFunction("l");
BlockFrequencyInfo BFI = buildBFI(*F);
BasicBlock &BB0 = F->getEntryBlock();
BasicBlock *BB1 = BB0.getTerminator()->getSuccessor(0);
BasicBlock *BB2 = BB0.getTerminator()->getSuccessor(1);
BasicBlock *BB3 = BB1->getSingleSuccessor();
// Without the entry count, all should return false.
EXPECT_FALSE(PSI.isHotBlockNthPercentile(990000, &BB0, &BFI));
EXPECT_FALSE(PSI.isHotBlockNthPercentile(990000, BB1, &BFI));
EXPECT_FALSE(PSI.isHotBlockNthPercentile(990000, BB2, &BFI));
EXPECT_FALSE(PSI.isHotBlockNthPercentile(990000, BB3, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(990000, &BB0, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(990000, BB1, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(990000, BB2, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(990000, BB3, &BFI));
}
}
TEST_F(ProfileSummaryInfoTest, SampleProfNoFuncEntryCount) {
auto M = makeLLVMModule("SampleProfile");
Function *F = M->getFunction("l");
ProfileSummaryInfo PSI = buildPSI(M.get());
EXPECT_TRUE(PSI.hasProfileSummary());
EXPECT_TRUE(PSI.hasSampleProfile());
BasicBlock &BB0 = F->getEntryBlock();
BasicBlock *BB1 = BB0.getTerminator()->getSuccessor(0);
BasicBlock *BB2 = BB0.getTerminator()->getSuccessor(1);
BasicBlock *BB3 = BB1->getSingleSuccessor();
BlockFrequencyInfo BFI = buildBFI(*F);
// Without the entry count, all should return false.
EXPECT_FALSE(PSI.isHotBlockNthPercentile(990000, &BB0, &BFI));
EXPECT_FALSE(PSI.isHotBlockNthPercentile(990000, BB1, &BFI));
EXPECT_FALSE(PSI.isHotBlockNthPercentile(990000, BB2, &BFI));
EXPECT_FALSE(PSI.isHotBlockNthPercentile(990000, BB3, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(990000, &BB0, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(990000, BB1, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(990000, BB2, &BFI));
EXPECT_FALSE(PSI.isColdBlockNthPercentile(990000, BB3, &BFI));
}
} // end anonymous namespace