diff --git a/llvm/include/llvm/Analysis/ProfileSummaryInfo.h b/llvm/include/llvm/Analysis/ProfileSummaryInfo.h --- a/llvm/include/llvm/Analysis/ProfileSummaryInfo.h +++ b/llvm/include/llvm/Analysis/ProfileSummaryInfo.h @@ -15,6 +15,10 @@ #define LLVM_ANALYSIS_PROFILESUMMARYINFO_H #include "llvm/ADT/DenseMap.h" +#include "llvm/Analysis/BlockFrequencyInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/PassManager.h" #include "llvm/IR/ProfileSummary.h" #include "llvm/Pass.h" @@ -23,9 +27,7 @@ namespace llvm { class BasicBlock; -class BlockFrequencyInfo; class CallBase; -class Function; /// Analysis providing profile information. /// @@ -107,28 +109,83 @@ bool hasHugeWorkingSetSize() const; /// Returns true if the working set size of the code is considered large. bool hasLargeWorkingSetSize() const; - /// Returns true if \p F has hot function entry. - bool isFunctionEntryHot(const Function *F) const; + /// Returns true if \p F has hot function entry. 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). + template + bool isFunctionEntryHot(const FunctionType *F) const { + if (!F || !hasProfileSummary()) + return false; + std::optional FunctionCount = getEntryCount(F); + // FIXME: The heuristic used below for determining hotness is based on + // preliminary SPEC tuning for inliner. This will eventually be a + // convenience method that calls isHotCount. + return FunctionCount && isHotCount(FunctionCount->getCount()); + } + /// Returns true if \p F contains hot code. - bool isFunctionHotInCallGraph(const Function *F, - BlockFrequencyInfo &BFI) const; + template + bool isFunctionHotInCallGraph(const FunctionType *F, FreqInfoType &FI) const { + if (!F || !hasProfileSummary()) + return false; + if (auto FunctionCount = getEntryCount(F)) + if (isHotCount(FunctionCount->getCount())) + return true; + + if (auto TotalCallCount = getTotalCallCount(F)) { + if (isHotCount(*TotalCallCount)) + return true; + } + + for (const auto &BB : *F) + if (isHotBlock(&BB, &FI)) + return true; + return false; + } /// Returns true if \p F has cold function entry. bool isFunctionEntryCold(const Function *F) const; /// Returns true if \p F contains only cold code. - bool isFunctionColdInCallGraph(const Function *F, - BlockFrequencyInfo &BFI) const; + template + bool isFunctionColdInCallGraph(const FunctionType *F, + FreqInfoType &FreqInfo) const { + if (!F || !hasProfileSummary()) + return false; + if (auto FunctionCount = getEntryCount(F)) + if (!isColdCount(FunctionCount->getCount())) + return false; + + if (auto TotalCallCount = getTotalCallCount(F)) { + if (!isColdCount(*TotalCallCount)) + return false; + } + + for (const auto &BB : *F) + if (!isColdBlock(&BB, &FreqInfo)) + return false; + return true; + } /// Returns true if the hotness of \p F is unknown. bool isFunctionHotnessUnknown(const Function &F) const; /// Returns true if \p F contains hot code with regard to a given hot /// percentile cutoff value. + template bool isFunctionHotInCallGraphNthPercentile(int PercentileCutoff, - const Function *F, - BlockFrequencyInfo &BFI) const; + const FunctionType *F, + FreqInfoType &FI) const { + return isFunctionHotOrColdInCallGraphNthPercentile( + PercentileCutoff, F, FI); + } /// Returns true if \p F contains cold code with regard to a given cold /// percentile cutoff value. + template bool isFunctionColdInCallGraphNthPercentile(int PercentileCutoff, - const Function *F, - BlockFrequencyInfo &BFI) const; + const FunctionType *F, + FreqInfoType &FI) const { + return isFunctionHotOrColdInCallGraphNthPercentile( + PercentileCutoff, F, FI); + } /// Returns true if count \p C is considered hot. bool isHotCount(uint64_t C) const; /// Returns true if count \p C is considered cold. @@ -143,22 +200,57 @@ /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile. bool isColdCountNthPercentile(int PercentileCutoff, uint64_t C) const; + /// Returns true if BasicBlock \p BB is considered hot. - bool isHotBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI) const; + template + bool isHotBlock(const BBType *BB, FreqInfoType *FI) const { + auto Count = FI->getBlockProfileCount(BB); + return Count && isHotCount(*Count); + } + /// Returns true if BasicBlock \p BB is considered cold. - bool isColdBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI) const; - /// Returns true if BasicBlock \p BB is considered hot with regard to a given - /// hot percentile cutoff value. - /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where - /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile. - bool isHotBlockNthPercentile(int PercentileCutoff, const BasicBlock *BB, - BlockFrequencyInfo *BFI) const; + template + bool isColdBlock(const BBType *BB, FreqInfoType *FI) const { + auto Count = FI->getBlockProfileCount(BB); + return Count && isColdCount(*Count); + } + + template + bool isColdBlock(BlockFrequency BlockFreq, const FreqInfoType *FI) const { + auto Count = FI->getProfileCountFromFreq(BlockFreq.getFrequency()); + return Count && isColdCount(*Count); + } + + template + bool isHotBlockNthPercentile(int PercentileCutoff, const BBType *BB, + FreqInfoType *FI) const { + return isHotOrColdBlockNthPercentile( + PercentileCutoff, BB, FI); + } + + template + bool isHotBlockNthPercentile(int PercentileCutoff, BlockFrequency BlockFreq, + FreqInfoType *FI) const { + return isHotOrColdBlockNthPercentile(PercentileCutoff, + BlockFreq, FI); + } + /// Returns true if BasicBlock \p BB is considered cold with regard to a given /// cold percentile cutoff value. /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile. - bool isColdBlockNthPercentile(int PercentileCutoff, const BasicBlock *BB, - BlockFrequencyInfo *BFI) const; + template + bool isColdBlockNthPercentile(int PercentileCutoff, const BBType *BB, + FreqInfoType *FI) const { + return isHotOrColdBlockNthPercentile( + PercentileCutoff, BB, FI); + } + template + bool isColdBlockNthPercentile(int PercentileCutoff, BlockFrequency BlockFreq, + FreqInfoType *FI) const { + return isHotOrColdBlockNthPercentile(PercentileCutoff, + BlockFreq, FI); + } /// Returns true if the call site \p CB is considered hot. bool isHotCallSite(const CallBase &CB, BlockFrequencyInfo *BFI) const; /// Returns true if call site \p CB is considered cold. @@ -178,16 +270,94 @@ return ColdCountThreshold.value_or(0); } - private: - template - bool isFunctionHotOrColdInCallGraphNthPercentile( - int PercentileCutoff, const Function *F, BlockFrequencyInfo &BFI) const; - template - bool isHotOrColdCountNthPercentile(int PercentileCutoff, uint64_t C) const; - template - bool isHotOrColdBlockNthPercentile(int PercentileCutoff, - const BasicBlock *BB, - BlockFrequencyInfo *BFI) const; +private: + template + std::optional getTotalCallCount(const FunctionType *F) const { + return std::nullopt; + } + + template <> + std::optional getTotalCallCount(const Function *F) const { + if (!hasSampleProfile()) + return std::nullopt; + uint64_t TotalCallCount = 0; + for (const auto &BB : *F) { + for (const auto &I : BB) { + if (isa(I) || isa(I)) { + if (auto CallCount = getProfileCount(cast(I), nullptr)) { + TotalCallCount += *CallCount; + } + } + } + } + return TotalCallCount; + } + + template + bool isFunctionHotOrColdInCallGraphNthPercentile(int PercentileCutoff, + const FunctionType *F, + FreqInfoType &FI) const { + if (!F || !hasProfileSummary()) + return false; + if (auto FunctionCount = getEntryCount(F)) { + if (isHot && + isHotCountNthPercentile(PercentileCutoff, FunctionCount->getCount())) + return true; + if (!isHot && !isColdCountNthPercentile(PercentileCutoff, + FunctionCount->getCount())) + return false; + } + if (auto TotalCallCount = getTotalCallCount(F)) { + if (isHot && isHotCountNthPercentile(PercentileCutoff, *TotalCallCount)) + return true; + if (!isHot && + !isColdCountNthPercentile(PercentileCutoff, *TotalCallCount)) + return false; + } + for (const auto &BB : *F) { + if (isHot && isHotBlockNthPercentile(PercentileCutoff, &BB, &FI)) + return true; + if (!isHot && !isColdBlockNthPercentile(PercentileCutoff, &BB, &FI)) + return false; + } + return !isHot; + } + + template + bool isHotOrColdCountNthPercentile(int PercentileCutoff, uint64_t C) const; + + template + bool isHotOrColdBlockNthPercentile(int PercentileCutoff, const BBType *BB, + FreqInfoType *FI) const { + auto Count = FI->getBlockProfileCount(BB); + if (isHot) + return Count && isHotCountNthPercentile(PercentileCutoff, *Count); + else + return Count && isColdCountNthPercentile(PercentileCutoff, *Count); + } + + template + bool isHotOrColdBlockNthPercentile(int PercentileCutoff, + BlockFrequency BlockFreq, + FreqInfoType *FreqInfo) const { + auto Count = FreqInfo->getProfileCountFromFreq(BlockFreq.getFrequency()); + if (isHot) + return Count && isHotCountNthPercentile(PercentileCutoff, *Count); + else + return Count && isColdCountNthPercentile(PercentileCutoff, *Count); + } + + template + std::optional + getEntryCount(const FunctionType *F) const { + return F->getEntryCount(); + } + + template <> + std::optional + getEntryCount(const MachineFunction *F) const { + return F->getFunction().getEntryCount(); + } }; /// An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo. diff --git a/llvm/lib/Analysis/ProfileSummaryInfo.cpp b/llvm/lib/Analysis/ProfileSummaryInfo.cpp --- a/llvm/lib/Analysis/ProfileSummaryInfo.cpp +++ b/llvm/lib/Analysis/ProfileSummaryInfo.cpp @@ -95,129 +95,11 @@ return std::nullopt; } -/// 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) const { - if (!F || !hasProfileSummary()) - return false; - auto FunctionCount = F->getEntryCount(); - // FIXME: The heuristic used below for determining hotness is based on - // preliminary SPEC tuning for inliner. This will eventually be a - // convenience method that calls isHotCount. - return FunctionCount && isHotCount(FunctionCount->getCount()); -} - -/// Returns true if the function contains hot code. This can include a hot -/// function entry count, hot basic block, or (in the case of Sample PGO) -/// hot total call edge count. -/// If it returns false, it either means it is not hot or it is unknown -/// (for example, no profile data is available). -bool ProfileSummaryInfo::isFunctionHotInCallGraph( - const Function *F, BlockFrequencyInfo &BFI) const { - if (!F || !hasProfileSummary()) - return false; - if (auto FunctionCount = F->getEntryCount()) - if (isHotCount(FunctionCount->getCount())) - return true; - - if (hasSampleProfile()) { - uint64_t TotalCallCount = 0; - for (const auto &BB : *F) - for (const auto &I : BB) - if (isa(I) || isa(I)) - if (auto CallCount = getProfileCount(cast(I), nullptr)) - TotalCallCount += *CallCount; - if (isHotCount(TotalCallCount)) - return true; - } - for (const auto &BB : *F) - if (isHotBlock(&BB, &BFI)) - return true; - return false; -} - -/// Returns true if the function only contains cold code. This means that -/// the function entry and blocks are all cold, and (in the case of Sample PGO) -/// the total call edge count is cold. -/// If it returns false, it either means it is not cold or it is unknown -/// (for example, no profile data is available). -bool ProfileSummaryInfo::isFunctionColdInCallGraph( - const Function *F, BlockFrequencyInfo &BFI) const { - if (!F || !hasProfileSummary()) - return false; - if (auto FunctionCount = F->getEntryCount()) - if (!isColdCount(FunctionCount->getCount())) - return false; - - if (hasSampleProfile()) { - uint64_t TotalCallCount = 0; - for (const auto &BB : *F) - for (const auto &I : BB) - if (isa(I) || isa(I)) - if (auto CallCount = getProfileCount(cast(I), nullptr)) - TotalCallCount += *CallCount; - if (!isColdCount(TotalCallCount)) - return false; - } - for (const auto &BB : *F) - if (!isColdBlock(&BB, &BFI)) - return false; - return true; -} - bool ProfileSummaryInfo::isFunctionHotnessUnknown(const Function &F) const { assert(hasPartialSampleProfile() && "Expect partial sample profile"); return !F.getEntryCount(); } -template -bool ProfileSummaryInfo::isFunctionHotOrColdInCallGraphNthPercentile( - int PercentileCutoff, const Function *F, BlockFrequencyInfo &BFI) const { - if (!F || !hasProfileSummary()) - return false; - 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) - for (const auto &I : BB) - if (isa(I) || isa(I)) - if (auto CallCount = getProfileCount(cast(I), nullptr)) - TotalCallCount += *CallCount; - if (isHot && isHotCountNthPercentile(PercentileCutoff, TotalCallCount)) - return true; - if (!isHot && !isColdCountNthPercentile(PercentileCutoff, TotalCallCount)) - return false; - } - for (const auto &BB : *F) { - if (isHot && isHotBlockNthPercentile(PercentileCutoff, &BB, &BFI)) - return true; - 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) const { - return isFunctionHotOrColdInCallGraphNthPercentile( - PercentileCutoff, F, BFI); -} - -bool ProfileSummaryInfo::isFunctionColdInCallGraphNthPercentile( - int PercentileCutoff, const Function *F, BlockFrequencyInfo &BFI) const { - return isFunctionHotOrColdInCallGraphNthPercentile( - PercentileCutoff, F, BFI); -} - /// Returns true if the function's entry is a cold. If it returns false, it /// either means it is not cold or it is unknown whether it is cold or not (for /// example, no profile data is available). @@ -325,38 +207,6 @@ return ColdCountThreshold.value_or(0); } -bool ProfileSummaryInfo::isHotBlock(const BasicBlock *BB, - BlockFrequencyInfo *BFI) const { - auto Count = BFI->getBlockProfileCount(BB); - return Count && isHotCount(*Count); -} - -bool ProfileSummaryInfo::isColdBlock(const BasicBlock *BB, - BlockFrequencyInfo *BFI) const { - auto Count = BFI->getBlockProfileCount(BB); - return Count && isColdCount(*Count); -} - -template -bool ProfileSummaryInfo::isHotOrColdBlockNthPercentile( - int PercentileCutoff, const BasicBlock *BB, BlockFrequencyInfo *BFI) const { - 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) const { - return isHotOrColdBlockNthPercentile(PercentileCutoff, BB, BFI); -} - -bool ProfileSummaryInfo::isColdBlockNthPercentile( - int PercentileCutoff, const BasicBlock *BB, BlockFrequencyInfo *BFI) const { - return isHotOrColdBlockNthPercentile(PercentileCutoff, BB, BFI); -} - bool ProfileSummaryInfo::isHotCallSite(const CallBase &CB, BlockFrequencyInfo *BFI) const { auto C = getProfileCount(CB, BFI); diff --git a/llvm/lib/CodeGen/MachineSizeOpts.cpp b/llvm/lib/CodeGen/MachineSizeOpts.cpp --- a/llvm/lib/CodeGen/MachineSizeOpts.cpp +++ b/llvm/lib/CodeGen/MachineSizeOpts.cpp @@ -25,157 +25,55 @@ extern cl::opt PgsoCutoffSampleProf; namespace { -namespace machine_size_opts_detail { - -/// Like ProfileSummaryInfo::isColdBlock but for MachineBasicBlock. -bool isColdBlock(const MachineBasicBlock *MBB, - ProfileSummaryInfo *PSI, - const MachineBlockFrequencyInfo *MBFI) { - auto Count = MBFI->getBlockProfileCount(MBB); - return Count && PSI->isColdCount(*Count); -} - -bool isColdBlock(BlockFrequency BlockFreq, - ProfileSummaryInfo *PSI, - const MachineBlockFrequencyInfo *MBFI) { - auto Count = MBFI->getProfileCountFromFreq(BlockFreq.getFrequency()); - return Count && PSI->isColdCount(*Count); -} - -/// Like ProfileSummaryInfo::isHotBlockNthPercentile but for MachineBasicBlock. -static bool isHotBlockNthPercentile(int PercentileCutoff, - const MachineBasicBlock *MBB, - ProfileSummaryInfo *PSI, - const MachineBlockFrequencyInfo *MBFI) { - auto Count = MBFI->getBlockProfileCount(MBB); - return Count && PSI->isHotCountNthPercentile(PercentileCutoff, *Count); -} - -static bool isHotBlockNthPercentile(int PercentileCutoff, - BlockFrequency BlockFreq, - ProfileSummaryInfo *PSI, - const MachineBlockFrequencyInfo *MBFI) { - auto Count = MBFI->getProfileCountFromFreq(BlockFreq.getFrequency()); - return Count && PSI->isHotCountNthPercentile(PercentileCutoff, *Count); -} - -static bool isColdBlockNthPercentile(int PercentileCutoff, - const MachineBasicBlock *MBB, - ProfileSummaryInfo *PSI, - const MachineBlockFrequencyInfo *MBFI) { - auto Count = MBFI->getBlockProfileCount(MBB); - return Count && PSI->isColdCountNthPercentile(PercentileCutoff, *Count); -} - -static bool isColdBlockNthPercentile(int PercentileCutoff, - BlockFrequency BlockFreq, - ProfileSummaryInfo *PSI, - const MachineBlockFrequencyInfo *MBFI) { - auto Count = MBFI->getProfileCountFromFreq(BlockFreq.getFrequency()); - return Count && PSI->isColdCountNthPercentile(PercentileCutoff, *Count); -} - -/// Like ProfileSummaryInfo::isFunctionColdInCallGraph but for -/// MachineFunction. -bool isFunctionColdInCallGraph( - const MachineFunction *MF, - ProfileSummaryInfo *PSI, - const MachineBlockFrequencyInfo &MBFI) { - if (auto FunctionCount = MF->getFunction().getEntryCount()) - if (!PSI->isColdCount(FunctionCount->getCount())) - return false; - for (const auto &MBB : *MF) - if (!isColdBlock(&MBB, PSI, &MBFI)) - return false; - return true; -} - -/// Like ProfileSummaryInfo::isFunctionHotInCallGraphNthPercentile but for -/// MachineFunction. -bool isFunctionHotInCallGraphNthPercentile( - int PercentileCutoff, - const MachineFunction *MF, - ProfileSummaryInfo *PSI, - const MachineBlockFrequencyInfo &MBFI) { - if (auto FunctionCount = MF->getFunction().getEntryCount()) - if (PSI->isHotCountNthPercentile(PercentileCutoff, - FunctionCount->getCount())) - return true; - for (const auto &MBB : *MF) - if (isHotBlockNthPercentile(PercentileCutoff, &MBB, PSI, &MBFI)) - return true; - return false; -} - -bool isFunctionColdInCallGraphNthPercentile( - int PercentileCutoff, const MachineFunction *MF, ProfileSummaryInfo *PSI, - const MachineBlockFrequencyInfo &MBFI) { - if (auto FunctionCount = MF->getFunction().getEntryCount()) - if (!PSI->isColdCountNthPercentile(PercentileCutoff, - FunctionCount->getCount())) - return false; - for (const auto &MBB : *MF) - if (!isColdBlockNthPercentile(PercentileCutoff, &MBB, PSI, &MBFI)) - return false; - return true; -} -} // namespace machine_size_opts_detail - struct MachineBasicBlockBFIAdapter { static bool isFunctionColdInCallGraph(const MachineFunction *MF, ProfileSummaryInfo *PSI, const MachineBlockFrequencyInfo &MBFI) { - return machine_size_opts_detail::isFunctionColdInCallGraph(MF, PSI, MBFI); + return PSI->isFunctionColdInCallGraph(MF, MBFI); } static bool isFunctionHotInCallGraphNthPercentile( int CutOff, const MachineFunction *MF, ProfileSummaryInfo *PSI, const MachineBlockFrequencyInfo &MBFI) { - return machine_size_opts_detail::isFunctionHotInCallGraphNthPercentile( - CutOff, MF, PSI, MBFI); + return PSI->isFunctionHotInCallGraphNthPercentile(CutOff, MF, MBFI); } static bool isFunctionColdInCallGraphNthPercentile( int CutOff, const MachineFunction *MF, ProfileSummaryInfo *PSI, const MachineBlockFrequencyInfo &MBFI) { - return machine_size_opts_detail::isFunctionColdInCallGraphNthPercentile( - CutOff, MF, PSI, MBFI); + return PSI->isFunctionColdInCallGraphNthPercentile(CutOff, MF, MBFI); } static bool isColdBlock(const MachineBasicBlock *MBB, ProfileSummaryInfo *PSI, const MachineBlockFrequencyInfo *MBFI) { - return machine_size_opts_detail::isColdBlock(MBB, PSI, MBFI); + return PSI->isColdBlock(MBB, MBFI); } static bool isColdBlock(BlockFrequency BlockFreq, ProfileSummaryInfo *PSI, const MachineBlockFrequencyInfo *MBFI) { - return machine_size_opts_detail::isColdBlock(BlockFreq, PSI, MBFI); + return PSI->isColdBlock(BlockFreq, MBFI); } static bool isHotBlockNthPercentile(int CutOff, const MachineBasicBlock *MBB, ProfileSummaryInfo *PSI, const MachineBlockFrequencyInfo *MBFI) { - return machine_size_opts_detail::isHotBlockNthPercentile( - CutOff, MBB, PSI, MBFI); + return PSI->isHotBlockNthPercentile(CutOff, MBB, MBFI); } static bool isHotBlockNthPercentile(int CutOff, BlockFrequency BlockFreq, ProfileSummaryInfo *PSI, const MachineBlockFrequencyInfo *MBFI) { - return machine_size_opts_detail::isHotBlockNthPercentile( - CutOff, BlockFreq, PSI, MBFI); + return PSI->isHotBlockNthPercentile(CutOff, BlockFreq, MBFI); } static bool isColdBlockNthPercentile(int CutOff, const MachineBasicBlock *MBB, ProfileSummaryInfo *PSI, const MachineBlockFrequencyInfo *MBFI) { - return machine_size_opts_detail::isColdBlockNthPercentile(CutOff, MBB, PSI, - MBFI); + return PSI->isColdBlockNthPercentile(CutOff, MBB, MBFI); } static bool isColdBlockNthPercentile(int CutOff, BlockFrequency BlockFreq, ProfileSummaryInfo *PSI, const MachineBlockFrequencyInfo *MBFI) { - return machine_size_opts_detail::isColdBlockNthPercentile(CutOff, BlockFreq, - PSI, MBFI); + return PSI->isColdBlockNthPercentile(CutOff, BlockFreq, MBFI); } }; } // end anonymous namespace