Compute summary before calling extractProfTotalWeight
extractProfTotalWeight checks if the profile type is sample profile, but before that we have to ensure that summary is available. Also expanded the unittest to test the case where there is no summar Differential Revision: https://reviews.llvm.org/D28708 llvm-svn: 291982
This commit is contained in:
parent
b66164ca34
commit
a7bdb8a513
|
@ -45,7 +45,7 @@ class ProfileSummaryInfo {
|
||||||
private:
|
private:
|
||||||
Module &M;
|
Module &M;
|
||||||
std::unique_ptr<ProfileSummary> Summary;
|
std::unique_ptr<ProfileSummary> Summary;
|
||||||
void computeSummary();
|
bool computeSummary();
|
||||||
void computeThresholds();
|
void computeThresholds();
|
||||||
// Count thresholds to answer isHotCount and isColdCount queries.
|
// Count thresholds to answer isHotCount and isColdCount queries.
|
||||||
Optional<uint64_t> HotCountThreshold, ColdCountThreshold;
|
Optional<uint64_t> HotCountThreshold, ColdCountThreshold;
|
||||||
|
|
|
@ -56,22 +56,23 @@ static uint64_t getMinCountForPercentile(SummaryEntryVector &DS,
|
||||||
// The profile summary metadata may be attached either by the frontend or by
|
// The profile summary metadata may be attached either by the frontend or by
|
||||||
// any backend passes (IR level instrumentation, for example). This method
|
// any backend passes (IR level instrumentation, for example). This method
|
||||||
// checks if the Summary is null and if so checks if the summary metadata is now
|
// checks if the Summary is null and if so checks if the summary metadata is now
|
||||||
// available in the module and parses it to get the Summary object.
|
// available in the module and parses it to get the Summary object. Returns true
|
||||||
void ProfileSummaryInfo::computeSummary() {
|
// if a valid Summary is available.
|
||||||
|
bool ProfileSummaryInfo::computeSummary() {
|
||||||
if (Summary)
|
if (Summary)
|
||||||
return;
|
return true;
|
||||||
auto *SummaryMD = M.getProfileSummary();
|
auto *SummaryMD = M.getProfileSummary();
|
||||||
if (!SummaryMD)
|
if (!SummaryMD)
|
||||||
return;
|
return false;
|
||||||
Summary.reset(ProfileSummary::getFromMD(SummaryMD));
|
Summary.reset(ProfileSummary::getFromMD(SummaryMD));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the function's entry is hot. If it returns false, it
|
/// Returns true if the function's entry is hot. If it returns false, it
|
||||||
/// either means it is not hot or it is unknown whether it is hot or not (for
|
/// either means it is not hot or it is unknown whether it is hot or not (for
|
||||||
/// example, no profile data is available).
|
/// example, no profile data is available).
|
||||||
bool ProfileSummaryInfo::isFunctionEntryHot(const Function *F) {
|
bool ProfileSummaryInfo::isFunctionEntryHot(const Function *F) {
|
||||||
computeSummary();
|
if (!F || !computeSummary())
|
||||||
if (!F || !Summary)
|
|
||||||
return false;
|
return false;
|
||||||
auto FunctionCount = F->getEntryCount();
|
auto FunctionCount = F->getEntryCount();
|
||||||
// FIXME: The heuristic used below for determining hotness is based on
|
// FIXME: The heuristic used below for determining hotness is based on
|
||||||
|
@ -84,13 +85,12 @@ bool ProfileSummaryInfo::isFunctionEntryHot(const Function *F) {
|
||||||
/// either means it is not cold or it is unknown whether it is cold or not (for
|
/// either means it is not cold or it is unknown whether it is cold or not (for
|
||||||
/// example, no profile data is available).
|
/// example, no profile data is available).
|
||||||
bool ProfileSummaryInfo::isFunctionEntryCold(const Function *F) {
|
bool ProfileSummaryInfo::isFunctionEntryCold(const Function *F) {
|
||||||
computeSummary();
|
|
||||||
if (!F)
|
if (!F)
|
||||||
return false;
|
return false;
|
||||||
if (F->hasFnAttribute(Attribute::Cold)) {
|
if (F->hasFnAttribute(Attribute::Cold)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!Summary)
|
if (!computeSummary())
|
||||||
return false;
|
return false;
|
||||||
auto FunctionCount = F->getEntryCount();
|
auto FunctionCount = F->getEntryCount();
|
||||||
// FIXME: The heuristic used below for determining coldness is based on
|
// FIXME: The heuristic used below for determining coldness is based on
|
||||||
|
@ -101,9 +101,7 @@ bool ProfileSummaryInfo::isFunctionEntryCold(const Function *F) {
|
||||||
|
|
||||||
/// Compute the hot and cold thresholds.
|
/// Compute the hot and cold thresholds.
|
||||||
void ProfileSummaryInfo::computeThresholds() {
|
void ProfileSummaryInfo::computeThresholds() {
|
||||||
if (!Summary)
|
if (!computeSummary())
|
||||||
computeSummary();
|
|
||||||
if (!Summary)
|
|
||||||
return;
|
return;
|
||||||
auto &DetailedSummary = Summary->getDetailedSummary();
|
auto &DetailedSummary = Summary->getDetailedSummary();
|
||||||
HotCountThreshold =
|
HotCountThreshold =
|
||||||
|
@ -148,6 +146,8 @@ bool ProfileSummaryInfo::isColdBB(const BasicBlock *B,
|
||||||
|
|
||||||
bool ProfileSummaryInfo::extractProfTotalWeight(const Instruction *I,
|
bool ProfileSummaryInfo::extractProfTotalWeight(const Instruction *I,
|
||||||
uint64_t &TotalCount) {
|
uint64_t &TotalCount) {
|
||||||
|
if (!computeSummary())
|
||||||
|
return false;
|
||||||
// Use profile weight on metadata only for sample profiling where block counts
|
// Use profile weight on metadata only for sample profiling where block counts
|
||||||
// could differ from the count of an instruction within the block.
|
// could differ from the count of an instruction within the block.
|
||||||
if (Summary.get()->getKind() != ProfileSummary::PSK_Sample)
|
if (Summary.get()->getKind() != ProfileSummary::PSK_Sample)
|
||||||
|
|
|
@ -45,8 +45,8 @@ protected:
|
||||||
BPI.reset(new BranchProbabilityInfo(F, *LI));
|
BPI.reset(new BranchProbabilityInfo(F, *LI));
|
||||||
return BlockFrequencyInfo(F, *BPI, *LI);
|
return BlockFrequencyInfo(F, *BPI, *LI);
|
||||||
}
|
}
|
||||||
std::unique_ptr<Module> makeLLVMModule(StringRef ProfKind) {
|
std::unique_ptr<Module> makeLLVMModule(const char *ProfKind = nullptr) {
|
||||||
const char *ModuleStrig =
|
const char *ModuleString =
|
||||||
"define i32 @g(i32 %x) !prof !21 {{\n"
|
"define i32 @g(i32 %x) !prof !21 {{\n"
|
||||||
" ret i32 0\n"
|
" ret i32 0\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
|
@ -67,31 +67,62 @@ protected:
|
||||||
" %y2 = phi i32 [0, %bb1], [1, %bb2] \n"
|
" %y2 = phi i32 [0, %bb1], [1, %bb2] \n"
|
||||||
" ret i32 %y2\n"
|
" ret i32 %y2\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"!llvm.module.flags = !{{!1}"
|
"!20 = !{{!\"function_entry_count\", i64 400}\n"
|
||||||
"!20 = !{{!\"function_entry_count\", i64 400}"
|
"!21 = !{{!\"function_entry_count\", i64 1}\n"
|
||||||
"!21 = !{{!\"function_entry_count\", i64 1}"
|
"!22 = !{{!\"function_entry_count\", i64 100}\n"
|
||||||
"!22 = !{{!\"function_entry_count\", i64 100}"
|
"!23 = !{{!\"branch_weights\", i32 64, i32 4}\n"
|
||||||
"!23 = !{{!\"branch_weights\", i32 64, i32 4}"
|
"{0}";
|
||||||
"!1 = !{{i32 1, !\"ProfileSummary\", !2}"
|
const char *SummaryString = "!llvm.module.flags = !{{!1}"
|
||||||
"!2 = !{{!3, !4, !5, !6, !7, !8, !9, !10}"
|
"!1 = !{{i32 1, !\"ProfileSummary\", !2}"
|
||||||
"!3 = !{{!\"ProfileFormat\", !\"{0}\"}"
|
"!2 = !{{!3, !4, !5, !6, !7, !8, !9, !10}"
|
||||||
"!4 = !{{!\"TotalCount\", i64 10000}"
|
"!3 = !{{!\"ProfileFormat\", !\"{0}\"}"
|
||||||
"!5 = !{{!\"MaxCount\", i64 10}"
|
"!4 = !{{!\"TotalCount\", i64 10000}"
|
||||||
"!6 = !{{!\"MaxInternalCount\", i64 1}"
|
"!5 = !{{!\"MaxCount\", i64 10}"
|
||||||
"!7 = !{{!\"MaxFunctionCount\", i64 1000}"
|
"!6 = !{{!\"MaxInternalCount\", i64 1}"
|
||||||
"!8 = !{{!\"NumCounts\", i64 3}"
|
"!7 = !{{!\"MaxFunctionCount\", i64 1000}"
|
||||||
"!9 = !{{!\"NumFunctions\", i64 3}"
|
"!8 = !{{!\"NumCounts\", i64 3}"
|
||||||
"!10 = !{{!\"DetailedSummary\", !11}"
|
"!9 = !{{!\"NumFunctions\", i64 3}"
|
||||||
"!11 = !{{!12, !13, !14}"
|
"!10 = !{{!\"DetailedSummary\", !11}"
|
||||||
"!12 = !{{i32 10000, i64 1000, i32 1}"
|
"!11 = !{{!12, !13, !14}"
|
||||||
"!13 = !{{i32 999000, i64 300, i32 3}"
|
"!12 = !{{i32 10000, i64 1000, i32 1}"
|
||||||
"!14 = !{{i32 999999, i64 5, i32 10}";
|
"!13 = !{{i32 999000, i64 300, i32 3}"
|
||||||
|
"!14 = !{{i32 999999, i64 5, i32 10}";
|
||||||
SMDiagnostic Err;
|
SMDiagnostic Err;
|
||||||
return parseAssemblyString(StringRef(formatv(ModuleStrig, ProfKind)), Err,
|
if (ProfKind)
|
||||||
C);
|
return parseAssemblyString(
|
||||||
|
formatv(ModuleString, formatv(SummaryString, ProfKind).str()).str(),
|
||||||
|
Err, C);
|
||||||
|
else
|
||||||
|
return parseAssemblyString(formatv(ModuleString, "").str(), Err, C);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TEST_F(ProfileSummaryInfoTest, TestNoProfile) {
|
||||||
|
auto M = makeLLVMModule(/*ProfKind=*/nullptr);
|
||||||
|
Function *F = M->getFunction("f");
|
||||||
|
|
||||||
|
ProfileSummaryInfo PSI = buildPSI(M.get());
|
||||||
|
// In the absence of profiles, is{Hot|Cold}X methods should always return
|
||||||
|
// false.
|
||||||
|
EXPECT_FALSE(PSI.isHotCount(1000));
|
||||||
|
EXPECT_FALSE(PSI.isHotCount(0));
|
||||||
|
EXPECT_FALSE(PSI.isColdCount(1000));
|
||||||
|
EXPECT_FALSE(PSI.isColdCount(0));
|
||||||
|
|
||||||
|
EXPECT_FALSE(PSI.isFunctionEntryHot(F));
|
||||||
|
EXPECT_FALSE(PSI.isFunctionEntryCold(F));
|
||||||
|
|
||||||
|
BasicBlock &BB0 = F->getEntryBlock();
|
||||||
|
BasicBlock *BB1 = BB0.getTerminator()->getSuccessor(0);
|
||||||
|
|
||||||
|
BlockFrequencyInfo BFI = buildBFI(*F);
|
||||||
|
EXPECT_FALSE(PSI.isHotBB(&BB0, &BFI));
|
||||||
|
EXPECT_FALSE(PSI.isColdBB(&BB0, &BFI));
|
||||||
|
|
||||||
|
CallSite CS1(BB1->getFirstNonPHI());
|
||||||
|
EXPECT_FALSE(PSI.isHotCallSite(CS1, &BFI));
|
||||||
|
EXPECT_FALSE(PSI.isColdCallSite(CS1, &BFI));
|
||||||
|
}
|
||||||
TEST_F(ProfileSummaryInfoTest, TestCommon) {
|
TEST_F(ProfileSummaryInfoTest, TestCommon) {
|
||||||
auto M = makeLLVMModule("InstrProf");
|
auto M = makeLLVMModule("InstrProf");
|
||||||
Function *F = M->getFunction("f");
|
Function *F = M->getFunction("f");
|
||||||
|
|
Loading…
Reference in New Issue