xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/MachineBlockFrequencyInfo.cpp (revision 66bee50af774673bfaeb4c66a5a82e0ac99e70a4)
1  //===- MachineBlockFrequencyInfo.cpp - MBB Frequency Analysis -------------===//
2  //
3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4  // See https://llvm.org/LICENSE.txt for license information.
5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6  //
7  //===----------------------------------------------------------------------===//
8  //
9  // Loops should be simplified before this analysis.
10  //
11  //===----------------------------------------------------------------------===//
12  
13  #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
14  #include "llvm/ADT/DenseMap.h"
15  #include "llvm/ADT/iterator.h"
16  #include "llvm/Analysis/BlockFrequencyInfoImpl.h"
17  #include "llvm/CodeGen/MachineBasicBlock.h"
18  #include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
19  #include "llvm/CodeGen/MachineFunction.h"
20  #include "llvm/CodeGen/MachineLoopInfo.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 <optional>
26  #include <string>
27  
28  using namespace llvm;
29  
30  #define DEBUG_TYPE "machine-block-freq"
31  
32  namespace llvm {
33  static cl::opt<GVDAGType> ViewMachineBlockFreqPropagationDAG(
34      "view-machine-block-freq-propagation-dags", cl::Hidden,
35      cl::desc("Pop up a window to show a dag displaying how machine block "
36               "frequencies propagate through the CFG."),
37      cl::values(clEnumValN(GVDT_None, "none", "do not display graphs."),
38                 clEnumValN(GVDT_Fraction, "fraction",
39                            "display a graph using the "
40                            "fractional block frequency representation."),
41                 clEnumValN(GVDT_Integer, "integer",
42                            "display a graph using the raw "
43                            "integer fractional block frequency representation."),
44                 clEnumValN(GVDT_Count, "count", "display a graph using the real "
45                                                 "profile count if available.")));
46  
47  // Similar option above, but used to control BFI display only after MBP pass
48  cl::opt<GVDAGType> ViewBlockLayoutWithBFI(
49      "view-block-layout-with-bfi", cl::Hidden,
50      cl::desc(
51          "Pop up a window to show a dag displaying MBP layout and associated "
52          "block frequencies of the CFG."),
53      cl::values(clEnumValN(GVDT_None, "none", "do not display graphs."),
54                 clEnumValN(GVDT_Fraction, "fraction",
55                            "display a graph using the "
56                            "fractional block frequency representation."),
57                 clEnumValN(GVDT_Integer, "integer",
58                            "display a graph using the raw "
59                            "integer fractional block frequency representation."),
60                 clEnumValN(GVDT_Count, "count",
61                            "display a graph using the real "
62                            "profile count if available.")));
63  
64  // Command line option to specify the name of the function for CFG dump
65  // Defined in Analysis/BlockFrequencyInfo.cpp:  -view-bfi-func-name=
66  extern cl::opt<std::string> ViewBlockFreqFuncName;
67  
68  // Command line option to specify hot frequency threshold.
69  // Defined in Analysis/BlockFrequencyInfo.cpp:  -view-hot-freq-perc=
70  extern cl::opt<unsigned> ViewHotFreqPercent;
71  
72  static cl::opt<bool> PrintMachineBlockFreq(
73      "print-machine-bfi", cl::init(false), cl::Hidden,
74      cl::desc("Print the machine block frequency info."));
75  
76  // Command line option to specify the name of the function for block frequency
77  // dump. Defined in Analysis/BlockFrequencyInfo.cpp.
78  extern cl::opt<std::string> PrintBFIFuncName;
79  } // namespace llvm
80  
81  static GVDAGType getGVDT() {
82    if (ViewBlockLayoutWithBFI != GVDT_None)
83      return ViewBlockLayoutWithBFI;
84  
85    return ViewMachineBlockFreqPropagationDAG;
86  }
87  
88  namespace llvm {
89  
90  template <> struct GraphTraits<MachineBlockFrequencyInfo *> {
91    using NodeRef = const MachineBasicBlock *;
92    using ChildIteratorType = MachineBasicBlock::const_succ_iterator;
93    using nodes_iterator = pointer_iterator<MachineFunction::const_iterator>;
94  
95    static NodeRef getEntryNode(const MachineBlockFrequencyInfo *G) {
96      return &G->getFunction()->front();
97    }
98  
99    static ChildIteratorType child_begin(const NodeRef N) {
100      return N->succ_begin();
101    }
102  
103    static ChildIteratorType child_end(const NodeRef N) { return N->succ_end(); }
104  
105    static nodes_iterator nodes_begin(const MachineBlockFrequencyInfo *G) {
106      return nodes_iterator(G->getFunction()->begin());
107    }
108  
109    static nodes_iterator nodes_end(const MachineBlockFrequencyInfo *G) {
110      return nodes_iterator(G->getFunction()->end());
111    }
112  };
113  
114  using MBFIDOTGraphTraitsBase =
115      BFIDOTGraphTraitsBase<MachineBlockFrequencyInfo,
116                            MachineBranchProbabilityInfo>;
117  
118  template <>
119  struct DOTGraphTraits<MachineBlockFrequencyInfo *>
120      : public MBFIDOTGraphTraitsBase {
121    const MachineFunction *CurFunc = nullptr;
122    DenseMap<const MachineBasicBlock *, int> LayoutOrderMap;
123  
124    explicit DOTGraphTraits(bool isSimple = false)
125        : MBFIDOTGraphTraitsBase(isSimple) {}
126  
127    std::string getNodeLabel(const MachineBasicBlock *Node,
128                             const MachineBlockFrequencyInfo *Graph) {
129      int layout_order = -1;
130      // Attach additional ordering information if 'isSimple' is false.
131      if (!isSimple()) {
132        const MachineFunction *F = Node->getParent();
133        if (!CurFunc || F != CurFunc) {
134          if (CurFunc)
135            LayoutOrderMap.clear();
136  
137          CurFunc = F;
138          int O = 0;
139          for (auto MBI = F->begin(); MBI != F->end(); ++MBI, ++O) {
140            LayoutOrderMap[&*MBI] = O;
141          }
142        }
143        layout_order = LayoutOrderMap[Node];
144      }
145      return MBFIDOTGraphTraitsBase::getNodeLabel(Node, Graph, getGVDT(),
146                                                  layout_order);
147    }
148  
149    std::string getNodeAttributes(const MachineBasicBlock *Node,
150                                  const MachineBlockFrequencyInfo *Graph) {
151      return MBFIDOTGraphTraitsBase::getNodeAttributes(Node, Graph,
152                                                       ViewHotFreqPercent);
153    }
154  
155    std::string getEdgeAttributes(const MachineBasicBlock *Node, EdgeIter EI,
156                                  const MachineBlockFrequencyInfo *MBFI) {
157      return MBFIDOTGraphTraitsBase::getEdgeAttributes(
158          Node, EI, MBFI, MBFI->getMBPI(), ViewHotFreqPercent);
159    }
160  };
161  
162  } // end namespace llvm
163  
164  INITIALIZE_PASS_BEGIN(MachineBlockFrequencyInfo, DEBUG_TYPE,
165                        "Machine Block Frequency Analysis", true, true)
166  INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
167  INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
168  INITIALIZE_PASS_END(MachineBlockFrequencyInfo, DEBUG_TYPE,
169                      "Machine Block Frequency Analysis", true, true)
170  
171  char MachineBlockFrequencyInfo::ID = 0;
172  
173  MachineBlockFrequencyInfo::MachineBlockFrequencyInfo()
174      : MachineFunctionPass(ID) {
175    initializeMachineBlockFrequencyInfoPass(*PassRegistry::getPassRegistry());
176  }
177  
178  MachineBlockFrequencyInfo::MachineBlockFrequencyInfo(
179        MachineFunction &F,
180        MachineBranchProbabilityInfo &MBPI,
181        MachineLoopInfo &MLI) : MachineFunctionPass(ID) {
182    calculate(F, MBPI, MLI);
183  }
184  
185  MachineBlockFrequencyInfo::~MachineBlockFrequencyInfo() = default;
186  
187  void MachineBlockFrequencyInfo::getAnalysisUsage(AnalysisUsage &AU) const {
188    AU.addRequired<MachineBranchProbabilityInfo>();
189    AU.addRequired<MachineLoopInfo>();
190    AU.setPreservesAll();
191    MachineFunctionPass::getAnalysisUsage(AU);
192  }
193  
194  void MachineBlockFrequencyInfo::calculate(
195      const MachineFunction &F, const MachineBranchProbabilityInfo &MBPI,
196      const MachineLoopInfo &MLI) {
197    if (!MBFI)
198      MBFI.reset(new ImplType);
199    MBFI->calculate(F, MBPI, MLI);
200    if (ViewMachineBlockFreqPropagationDAG != GVDT_None &&
201        (ViewBlockFreqFuncName.empty() ||
202         F.getName().equals(ViewBlockFreqFuncName))) {
203      view("MachineBlockFrequencyDAGS." + F.getName());
204    }
205    if (PrintMachineBlockFreq &&
206        (PrintBFIFuncName.empty() || F.getName().equals(PrintBFIFuncName))) {
207      MBFI->print(dbgs());
208    }
209  }
210  
211  bool MachineBlockFrequencyInfo::runOnMachineFunction(MachineFunction &F) {
212    MachineBranchProbabilityInfo &MBPI =
213        getAnalysis<MachineBranchProbabilityInfo>();
214    MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>();
215    calculate(F, MBPI, MLI);
216    return false;
217  }
218  
219  void MachineBlockFrequencyInfo::releaseMemory() { MBFI.reset(); }
220  
221  /// Pop up a ghostview window with the current block frequency propagation
222  /// rendered using dot.
223  void MachineBlockFrequencyInfo::view(const Twine &Name, bool isSimple) const {
224    // This code is only for debugging.
225    ViewGraph(const_cast<MachineBlockFrequencyInfo *>(this), Name, isSimple);
226  }
227  
228  BlockFrequency
229  MachineBlockFrequencyInfo::getBlockFreq(const MachineBasicBlock *MBB) const {
230    return MBFI ? MBFI->getBlockFreq(MBB) : BlockFrequency(0);
231  }
232  
233  std::optional<uint64_t> MachineBlockFrequencyInfo::getBlockProfileCount(
234      const MachineBasicBlock *MBB) const {
235    if (!MBFI)
236      return std::nullopt;
237  
238    const Function &F = MBFI->getFunction()->getFunction();
239    return MBFI->getBlockProfileCount(F, MBB);
240  }
241  
242  std::optional<uint64_t>
243  MachineBlockFrequencyInfo::getProfileCountFromFreq(BlockFrequency Freq) const {
244    if (!MBFI)
245      return std::nullopt;
246  
247    const Function &F = MBFI->getFunction()->getFunction();
248    return MBFI->getProfileCountFromFreq(F, Freq);
249  }
250  
251  bool MachineBlockFrequencyInfo::isIrrLoopHeader(
252      const MachineBasicBlock *MBB) const {
253    assert(MBFI && "Expected analysis to be available");
254    return MBFI->isIrrLoopHeader(MBB);
255  }
256  
257  void MachineBlockFrequencyInfo::onEdgeSplit(
258      const MachineBasicBlock &NewPredecessor,
259      const MachineBasicBlock &NewSuccessor,
260      const MachineBranchProbabilityInfo &MBPI) {
261    assert(MBFI && "Expected analysis to be available");
262    auto NewSuccFreq = MBFI->getBlockFreq(&NewPredecessor) *
263                       MBPI.getEdgeProbability(&NewPredecessor, &NewSuccessor);
264  
265    MBFI->setBlockFreq(&NewSuccessor, NewSuccFreq);
266  }
267  
268  const MachineFunction *MachineBlockFrequencyInfo::getFunction() const {
269    return MBFI ? MBFI->getFunction() : nullptr;
270  }
271  
272  const MachineBranchProbabilityInfo *MachineBlockFrequencyInfo::getMBPI() const {
273    return MBFI ? &MBFI->getBPI() : nullptr;
274  }
275  
276  BlockFrequency MachineBlockFrequencyInfo::getEntryFreq() const {
277    return MBFI ? MBFI->getEntryFreq() : BlockFrequency(0);
278  }
279  
280  Printable llvm::printBlockFreq(const MachineBlockFrequencyInfo &MBFI,
281                                 BlockFrequency Freq) {
282    return Printable([&MBFI, Freq](raw_ostream &OS) {
283      printBlockFreqImpl(OS, MBFI.getEntryFreq(), Freq);
284    });
285  }
286  
287  Printable llvm::printBlockFreq(const MachineBlockFrequencyInfo &MBFI,
288                                 const MachineBasicBlock &MBB) {
289    return printBlockFreq(MBFI, MBFI.getBlockFreq(&MBB));
290  }
291