Index: include/llvm/Analysis/ProfileSummaryInfo.h =================================================================== --- include/llvm/Analysis/ProfileSummaryInfo.h +++ include/llvm/Analysis/ProfileSummaryInfo.h @@ -45,7 +45,7 @@ private: Module &M; std::unique_ptr Summary; - void computeSummary(); + bool computeSummary(); void computeThresholds(); // Count thresholds to answer isHotCount and isColdCount queries. Optional HotCountThreshold, ColdCountThreshold; Index: lib/Analysis/ProfileSummaryInfo.cpp =================================================================== --- lib/Analysis/ProfileSummaryInfo.cpp +++ lib/Analysis/ProfileSummaryInfo.cpp @@ -56,22 +56,23 @@ // 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 @@ -84,13 +85,12 @@ /// 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 @@ -101,9 +101,7 @@ /// Compute the hot and cold thresholds. void ProfileSummaryInfo::computeThresholds() { - if (!Summary) - computeSummary(); - if (!Summary) + if (!computeSummary()) return; auto &DetailedSummary = Summary->getDetailedSummary(); HotCountThreshold = @@ -148,6 +146,8 @@ 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) Index: unittests/Analysis/ProfileSummaryInfoTest.cpp =================================================================== --- unittests/Analysis/ProfileSummaryInfoTest.cpp +++ unittests/Analysis/ProfileSummaryInfoTest.cpp @@ -45,8 +45,8 @@ BPI.reset(new BranchProbabilityInfo(F, *LI)); return BlockFrequencyInfo(F, *BPI, *LI); } - std::unique_ptr makeLLVMModule(StringRef ProfKind) { - const char *ModuleStrig = + std::unique_ptr makeLLVMModule(const char *ProfKind = nullptr) { + const char *ModuleString = "define i32 @g(i32 %x) !prof !21 {{\n" " ret i32 0\n" "}\n" @@ -67,31 +67,62 @@ " %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(); + 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"); @@ -135,7 +166,7 @@ // Test that adding an MD_prof metadata with a hot count on CS2 does not // change itas hotness as it has no effect in instrumented profiling. MDBuilder MDB(M->getContext()); - CI2->setMetadata(llvm::LLVMContext::MD_prof, MDB.createBranchWeights({200})); + CI2->setMetadata(llvm::LLVMContext::MD_prof, MDB.createBranchWeights({400})); EXPECT_FALSE(PSI.isHotCallSite(CS2, &BFI)); } @@ -165,7 +196,7 @@ // Test that CS2 is considered hot when it gets an MD_prof metadata with // weights that exceed the hot count threshold. MDBuilder MDB(M->getContext()); - CI2->setMetadata(llvm::LLVMContext::MD_prof, MDB.createBranchWeights({300})); + CI2->setMetadata(llvm::LLVMContext::MD_prof, MDB.createBranchWeights({400})); EXPECT_TRUE(PSI.isHotCallSite(CS2, &BFI)); }