// The profile summary metadata may be attached either by the frontend or by
// 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
-// available in the module and parses it to get the Summary object.
-void ProfileSummaryInfo::computeSummary() {
+// available in the module and parses it to get the Summary object. Returns true
+// if a valid Summary is available.
+bool ProfileSummaryInfo::computeSummary() {
if (Summary)
- return;
+ return true;
auto *SummaryMD = M.getProfileSummary();
if (!SummaryMD)
- return;
+ return false;
Summary.reset(ProfileSummary::getFromMD(SummaryMD));
+ return true;
}
/// 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
/// example, no profile data is available).
bool ProfileSummaryInfo::isFunctionEntryHot(const Function *F) {
- computeSummary();
- if (!F || !Summary)
+ if (!F || !computeSummary())
return false;
auto FunctionCount = F->getEntryCount();
// FIXME: The heuristic used below for determining hotness is based on
/// either means it is not cold or it is unknown whether it is cold or not (for
/// example, no profile data is available).
bool ProfileSummaryInfo::isFunctionEntryCold(const Function *F) {
- computeSummary();
if (!F)
return false;
if (F->hasFnAttribute(Attribute::Cold)) {
return true;
}
- if (!Summary)
+ if (!computeSummary())
return false;
auto FunctionCount = F->getEntryCount();
// FIXME: The heuristic used below for determining coldness is based on
/// Compute the hot and cold thresholds.
void ProfileSummaryInfo::computeThresholds() {
- if (!Summary)
- computeSummary();
- if (!Summary)
+ if (!computeSummary())
return;
auto &DetailedSummary = Summary->getDetailedSummary();
HotCountThreshold =
bool ProfileSummaryInfo::extractProfTotalWeight(const Instruction *I,
uint64_t &TotalCount) {
+ if (!computeSummary())
+ return false;
// Use profile weight on metadata only for sample profiling where block counts
// could differ from the count of an instruction within the block.
if (Summary.get()->getKind() != ProfileSummary::PSK_Sample)
BPI.reset(new BranchProbabilityInfo(F, *LI));
return BlockFrequencyInfo(F, *BPI, *LI);
}
- std::unique_ptr<Module> makeLLVMModule(StringRef ProfKind) {
- const char *ModuleStrig =
+ std::unique_ptr<Module> makeLLVMModule(const char *ProfKind = nullptr) {
+ const char *ModuleString =
"define i32 @g(i32 %x) !prof !21 {{\n"
" ret i32 0\n"
"}\n"
" %y2 = phi i32 [0, %bb1], [1, %bb2] \n"
" ret i32 %y2\n"
"}\n"
- "!llvm.module.flags = !{{!1}"
- "!20 = !{{!\"function_entry_count\", i64 400}"
- "!21 = !{{!\"function_entry_count\", i64 1}"
- "!22 = !{{!\"function_entry_count\", i64 100}"
- "!23 = !{{!\"branch_weights\", i32 64, i32 4}"
- "!1 = !{{i32 1, !\"ProfileSummary\", !2}"
- "!2 = !{{!3, !4, !5, !6, !7, !8, !9, !10}"
- "!3 = !{{!\"ProfileFormat\", !\"{0}\"}"
- "!4 = !{{!\"TotalCount\", i64 10000}"
- "!5 = !{{!\"MaxCount\", i64 10}"
- "!6 = !{{!\"MaxInternalCount\", i64 1}"
- "!7 = !{{!\"MaxFunctionCount\", i64 1000}"
- "!8 = !{{!\"NumCounts\", i64 3}"
- "!9 = !{{!\"NumFunctions\", i64 3}"
- "!10 = !{{!\"DetailedSummary\", !11}"
- "!11 = !{{!12, !13, !14}"
- "!12 = !{{i32 10000, i64 1000, i32 1}"
- "!13 = !{{i32 999000, i64 300, i32 3}"
- "!14 = !{{i32 999999, i64 5, i32 10}";
+ "!20 = !{{!\"function_entry_count\", i64 400}\n"
+ "!21 = !{{!\"function_entry_count\", i64 1}\n"
+ "!22 = !{{!\"function_entry_count\", i64 100}\n"
+ "!23 = !{{!\"branch_weights\", i32 64, i32 4}\n"
+ "{0}";
+ const char *SummaryString = "!llvm.module.flags = !{{!1}"
+ "!1 = !{{i32 1, !\"ProfileSummary\", !2}"
+ "!2 = !{{!3, !4, !5, !6, !7, !8, !9, !10}"
+ "!3 = !{{!\"ProfileFormat\", !\"{0}\"}"
+ "!4 = !{{!\"TotalCount\", i64 10000}"
+ "!5 = !{{!\"MaxCount\", i64 10}"
+ "!6 = !{{!\"MaxInternalCount\", i64 1}"
+ "!7 = !{{!\"MaxFunctionCount\", i64 1000}"
+ "!8 = !{{!\"NumCounts\", i64 3}"
+ "!9 = !{{!\"NumFunctions\", i64 3}"
+ "!10 = !{{!\"DetailedSummary\", !11}"
+ "!11 = !{{!12, !13, !14}"
+ "!12 = !{{i32 10000, i64 1000, i32 1}"
+ "!13 = !{{i32 999000, i64 300, i32 3}"
+ "!14 = !{{i32 999999, i64 5, i32 10}";
SMDiagnostic Err;
- return parseAssemblyString(StringRef(formatv(ModuleStrig, ProfKind)), Err,
- C);
+ if (ProfKind)
+ 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) {
auto M = makeLLVMModule("InstrProf");
Function *F = M->getFunction("f");