Path: blob/main/contrib/llvm-project/llvm/lib/Analysis/BlockFrequencyInfo.cpp
35234 views
//===- BlockFrequencyInfo.cpp - Block Frequency Analysis ------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Loops should be simplified before this analysis.9//10//===----------------------------------------------------------------------===//1112#include "llvm/Analysis/BlockFrequencyInfo.h"13#include "llvm/ADT/APInt.h"14#include "llvm/ADT/iterator.h"15#include "llvm/Analysis/BlockFrequencyInfoImpl.h"16#include "llvm/Analysis/BranchProbabilityInfo.h"17#include "llvm/Analysis/LoopInfo.h"18#include "llvm/IR/CFG.h"19#include "llvm/IR/Function.h"20#include "llvm/IR/PassManager.h"21#include "llvm/InitializePasses.h"22#include "llvm/Pass.h"23#include "llvm/Support/CommandLine.h"24#include "llvm/Support/GraphWriter.h"25#include "llvm/Support/raw_ostream.h"26#include <cassert>27#include <optional>28#include <string>2930using namespace llvm;3132#define DEBUG_TYPE "block-freq"3334static cl::opt<GVDAGType> ViewBlockFreqPropagationDAG(35"view-block-freq-propagation-dags", cl::Hidden,36cl::desc("Pop up a window to show a dag displaying how block "37"frequencies propagation through the CFG."),38cl::values(clEnumValN(GVDT_None, "none", "do not display graphs."),39clEnumValN(GVDT_Fraction, "fraction",40"display a graph using the "41"fractional block frequency representation."),42clEnumValN(GVDT_Integer, "integer",43"display a graph using the raw "44"integer fractional block frequency representation."),45clEnumValN(GVDT_Count, "count", "display a graph using the real "46"profile count if available.")));4748namespace llvm {49cl::opt<std::string>50ViewBlockFreqFuncName("view-bfi-func-name", cl::Hidden,51cl::desc("The option to specify "52"the name of the function "53"whose CFG will be displayed."));5455cl::opt<unsigned>56ViewHotFreqPercent("view-hot-freq-percent", cl::init(10), cl::Hidden,57cl::desc("An integer in percent used to specify "58"the hot blocks/edges to be displayed "59"in red: a block or edge whose frequency "60"is no less than the max frequency of the "61"function multiplied by this percent."));6263// Command line option to turn on CFG dot or text dump after profile annotation.64cl::opt<PGOViewCountsType> PGOViewCounts(65"pgo-view-counts", cl::Hidden,66cl::desc("A boolean option to show CFG dag or text with "67"block profile counts and branch probabilities "68"right after PGO profile annotation step. The "69"profile counts are computed using branch "70"probabilities from the runtime profile data and "71"block frequency propagation algorithm. To view "72"the raw counts from the profile, use option "73"-pgo-view-raw-counts instead. To limit graph "74"display to only one function, use filtering option "75"-view-bfi-func-name."),76cl::values(clEnumValN(PGOVCT_None, "none", "do not show."),77clEnumValN(PGOVCT_Graph, "graph", "show a graph."),78clEnumValN(PGOVCT_Text, "text", "show in text.")));7980static cl::opt<bool> PrintBFI("print-bfi", cl::init(false), cl::Hidden,81cl::desc("Print the block frequency info."));8283cl::opt<std::string>84PrintBFIFuncName("print-bfi-func-name", cl::Hidden,85cl::desc("The option to specify the name of the function "86"whose block frequency info is printed."));87} // namespace llvm8889namespace llvm {9091static GVDAGType getGVDT() {92if (PGOViewCounts == PGOVCT_Graph)93return GVDT_Count;94return ViewBlockFreqPropagationDAG;95}9697template <>98struct GraphTraits<BlockFrequencyInfo *> {99using NodeRef = const BasicBlock *;100using ChildIteratorType = const_succ_iterator;101using nodes_iterator = pointer_iterator<Function::const_iterator>;102103static NodeRef getEntryNode(const BlockFrequencyInfo *G) {104return &G->getFunction()->front();105}106107static ChildIteratorType child_begin(const NodeRef N) {108return succ_begin(N);109}110111static ChildIteratorType child_end(const NodeRef N) { return succ_end(N); }112113static nodes_iterator nodes_begin(const BlockFrequencyInfo *G) {114return nodes_iterator(G->getFunction()->begin());115}116117static nodes_iterator nodes_end(const BlockFrequencyInfo *G) {118return nodes_iterator(G->getFunction()->end());119}120};121122using BFIDOTGTraitsBase =123BFIDOTGraphTraitsBase<BlockFrequencyInfo, BranchProbabilityInfo>;124125template <>126struct DOTGraphTraits<BlockFrequencyInfo *> : public BFIDOTGTraitsBase {127explicit DOTGraphTraits(bool isSimple = false)128: BFIDOTGTraitsBase(isSimple) {}129130std::string getNodeLabel(const BasicBlock *Node,131const BlockFrequencyInfo *Graph) {132133return BFIDOTGTraitsBase::getNodeLabel(Node, Graph, getGVDT());134}135136std::string getNodeAttributes(const BasicBlock *Node,137const BlockFrequencyInfo *Graph) {138return BFIDOTGTraitsBase::getNodeAttributes(Node, Graph,139ViewHotFreqPercent);140}141142std::string getEdgeAttributes(const BasicBlock *Node, EdgeIter EI,143const BlockFrequencyInfo *BFI) {144return BFIDOTGTraitsBase::getEdgeAttributes(Node, EI, BFI, BFI->getBPI(),145ViewHotFreqPercent);146}147};148149} // end namespace llvm150151BlockFrequencyInfo::BlockFrequencyInfo() = default;152153BlockFrequencyInfo::BlockFrequencyInfo(const Function &F,154const BranchProbabilityInfo &BPI,155const LoopInfo &LI) {156calculate(F, BPI, LI);157}158159BlockFrequencyInfo::BlockFrequencyInfo(BlockFrequencyInfo &&Arg)160: BFI(std::move(Arg.BFI)) {}161162BlockFrequencyInfo &BlockFrequencyInfo::operator=(BlockFrequencyInfo &&RHS) {163releaseMemory();164BFI = std::move(RHS.BFI);165return *this;166}167168// Explicitly define the default constructor otherwise it would be implicitly169// defined at the first ODR-use which is the BFI member in the170// LazyBlockFrequencyInfo header. The dtor needs the BlockFrequencyInfoImpl171// template instantiated which is not available in the header.172BlockFrequencyInfo::~BlockFrequencyInfo() = default;173174bool BlockFrequencyInfo::invalidate(Function &F, const PreservedAnalyses &PA,175FunctionAnalysisManager::Invalidator &) {176// Check whether the analysis, all analyses on functions, or the function's177// CFG have been preserved.178auto PAC = PA.getChecker<BlockFrequencyAnalysis>();179return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>() ||180PAC.preservedSet<CFGAnalyses>());181}182183void BlockFrequencyInfo::calculate(const Function &F,184const BranchProbabilityInfo &BPI,185const LoopInfo &LI) {186if (!BFI)187BFI.reset(new ImplType);188BFI->calculate(F, BPI, LI);189if (ViewBlockFreqPropagationDAG != GVDT_None &&190(ViewBlockFreqFuncName.empty() || F.getName() == ViewBlockFreqFuncName)) {191view();192}193if (PrintBFI &&194(PrintBFIFuncName.empty() || F.getName() == PrintBFIFuncName)) {195print(dbgs());196}197}198199BlockFrequency BlockFrequencyInfo::getBlockFreq(const BasicBlock *BB) const {200return BFI ? BFI->getBlockFreq(BB) : BlockFrequency(0);201}202203std::optional<uint64_t>204BlockFrequencyInfo::getBlockProfileCount(const BasicBlock *BB,205bool AllowSynthetic) const {206if (!BFI)207return std::nullopt;208209return BFI->getBlockProfileCount(*getFunction(), BB, AllowSynthetic);210}211212std::optional<uint64_t>213BlockFrequencyInfo::getProfileCountFromFreq(BlockFrequency Freq) const {214if (!BFI)215return std::nullopt;216return BFI->getProfileCountFromFreq(*getFunction(), Freq);217}218219bool BlockFrequencyInfo::isIrrLoopHeader(const BasicBlock *BB) {220assert(BFI && "Expected analysis to be available");221return BFI->isIrrLoopHeader(BB);222}223224void BlockFrequencyInfo::setBlockFreq(const BasicBlock *BB,225BlockFrequency Freq) {226assert(BFI && "Expected analysis to be available");227BFI->setBlockFreq(BB, Freq);228}229230void BlockFrequencyInfo::setBlockFreqAndScale(231const BasicBlock *ReferenceBB, BlockFrequency Freq,232SmallPtrSetImpl<BasicBlock *> &BlocksToScale) {233assert(BFI && "Expected analysis to be available");234// Use 128 bits APInt to avoid overflow.235APInt NewFreq(128, Freq.getFrequency());236APInt OldFreq(128, BFI->getBlockFreq(ReferenceBB).getFrequency());237APInt BBFreq(128, 0);238for (auto *BB : BlocksToScale) {239BBFreq = BFI->getBlockFreq(BB).getFrequency();240// Multiply first by NewFreq and then divide by OldFreq241// to minimize loss of precision.242BBFreq *= NewFreq;243// udiv is an expensive operation in the general case. If this ends up being244// a hot spot, one of the options proposed in245// https://reviews.llvm.org/D28535#650071 could be used to avoid this.246BBFreq = BBFreq.udiv(OldFreq);247BFI->setBlockFreq(BB, BlockFrequency(BBFreq.getLimitedValue()));248}249BFI->setBlockFreq(ReferenceBB, Freq);250}251252/// Pop up a ghostview window with the current block frequency propagation253/// rendered using dot.254void BlockFrequencyInfo::view(StringRef title) const {255ViewGraph(const_cast<BlockFrequencyInfo *>(this), title);256}257258const Function *BlockFrequencyInfo::getFunction() const {259return BFI ? BFI->getFunction() : nullptr;260}261262const BranchProbabilityInfo *BlockFrequencyInfo::getBPI() const {263return BFI ? &BFI->getBPI() : nullptr;264}265266BlockFrequency BlockFrequencyInfo::getEntryFreq() const {267return BFI ? BFI->getEntryFreq() : BlockFrequency(0);268}269270void BlockFrequencyInfo::releaseMemory() { BFI.reset(); }271272void BlockFrequencyInfo::print(raw_ostream &OS) const {273if (BFI)274BFI->print(OS);275}276277void BlockFrequencyInfo::verifyMatch(BlockFrequencyInfo &Other) const {278if (BFI)279BFI->verifyMatch(*Other.BFI);280}281282Printable llvm::printBlockFreq(const BlockFrequencyInfo &BFI,283BlockFrequency Freq) {284return Printable([&BFI, Freq](raw_ostream &OS) {285printRelativeBlockFreq(OS, BFI.getEntryFreq(), Freq);286});287}288289Printable llvm::printBlockFreq(const BlockFrequencyInfo &BFI,290const BasicBlock &BB) {291return printBlockFreq(BFI, BFI.getBlockFreq(&BB));292}293294INITIALIZE_PASS_BEGIN(BlockFrequencyInfoWrapperPass, "block-freq",295"Block Frequency Analysis", true, true)296INITIALIZE_PASS_DEPENDENCY(BranchProbabilityInfoWrapperPass)297INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)298INITIALIZE_PASS_END(BlockFrequencyInfoWrapperPass, "block-freq",299"Block Frequency Analysis", true, true)300301char BlockFrequencyInfoWrapperPass::ID = 0;302303BlockFrequencyInfoWrapperPass::BlockFrequencyInfoWrapperPass()304: FunctionPass(ID) {305initializeBlockFrequencyInfoWrapperPassPass(*PassRegistry::getPassRegistry());306}307308BlockFrequencyInfoWrapperPass::~BlockFrequencyInfoWrapperPass() = default;309310void BlockFrequencyInfoWrapperPass::print(raw_ostream &OS,311const Module *) const {312BFI.print(OS);313}314315void BlockFrequencyInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {316AU.addRequired<BranchProbabilityInfoWrapperPass>();317AU.addRequired<LoopInfoWrapperPass>();318AU.setPreservesAll();319}320321void BlockFrequencyInfoWrapperPass::releaseMemory() { BFI.releaseMemory(); }322323bool BlockFrequencyInfoWrapperPass::runOnFunction(Function &F) {324BranchProbabilityInfo &BPI =325getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();326LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();327BFI.calculate(F, BPI, LI);328return false;329}330331AnalysisKey BlockFrequencyAnalysis::Key;332BlockFrequencyInfo BlockFrequencyAnalysis::run(Function &F,333FunctionAnalysisManager &AM) {334auto &BP = AM.getResult<BranchProbabilityAnalysis>(F);335auto &LI = AM.getResult<LoopAnalysis>(F);336BlockFrequencyInfo BFI;337BFI.calculate(F, BP, LI);338return BFI;339}340341PreservedAnalyses342BlockFrequencyPrinterPass::run(Function &F, FunctionAnalysisManager &AM) {343OS << "Printing analysis results of BFI for function "344<< "'" << F.getName() << "':"345<< "\n";346AM.getResult<BlockFrequencyAnalysis>(F).print(OS);347return PreservedAnalyses::all();348}349350351