10b57cec5SDimitry Andric //===- MachineBlockFrequencyInfo.h - MBB Frequency Analysis -----*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Loops should be simplified before this analysis.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_CODEGEN_MACHINEBLOCKFREQUENCYINFO_H
140b57cec5SDimitry Andric #define LLVM_CODEGEN_MACHINEBLOCKFREQUENCYINFO_H
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
170b57cec5SDimitry Andric #include "llvm/Support/BlockFrequency.h"
180b57cec5SDimitry Andric #include <cstdint>
190b57cec5SDimitry Andric #include <memory>
20bdd1243dSDimitry Andric #include <optional>
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric namespace llvm {
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric template <class BlockT> class BlockFrequencyInfoImpl;
250b57cec5SDimitry Andric class MachineBasicBlock;
260b57cec5SDimitry Andric class MachineBranchProbabilityInfo;
270b57cec5SDimitry Andric class MachineFunction;
280b57cec5SDimitry Andric class MachineLoopInfo;
290b57cec5SDimitry Andric class raw_ostream;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric /// MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation
320b57cec5SDimitry Andric /// to estimate machine basic block frequencies.
330b57cec5SDimitry Andric class MachineBlockFrequencyInfo : public MachineFunctionPass {
340b57cec5SDimitry Andric   using ImplType = BlockFrequencyInfoImpl<MachineBasicBlock>;
350b57cec5SDimitry Andric   std::unique_ptr<ImplType> MBFI;
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric public:
380b57cec5SDimitry Andric   static char ID;
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric   MachineBlockFrequencyInfo();
41480093f4SDimitry Andric   explicit MachineBlockFrequencyInfo(MachineFunction &F,
42480093f4SDimitry Andric                                      MachineBranchProbabilityInfo &MBPI,
43480093f4SDimitry Andric                                      MachineLoopInfo &MLI);
440b57cec5SDimitry Andric   ~MachineBlockFrequencyInfo() override;
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override;
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &F) override;
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric   /// calculate - compute block frequency info for the given function.
510b57cec5SDimitry Andric   void calculate(const MachineFunction &F,
520b57cec5SDimitry Andric                  const MachineBranchProbabilityInfo &MBPI,
530b57cec5SDimitry Andric                  const MachineLoopInfo &MLI);
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   void releaseMemory() override;
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   /// getblockFreq - Return block frequency. Return 0 if we don't have the
580b57cec5SDimitry Andric   /// information. Please note that initial frequency is equal to 1024. It means
590b57cec5SDimitry Andric   /// that we should not rely on the value itself, but only on the comparison to
600b57cec5SDimitry Andric   /// the other block frequencies. We do this to avoid using of floating points.
61e8d8bef9SDimitry Andric   /// For example, to get the frequency of a block relative to the entry block,
62e8d8bef9SDimitry Andric   /// divide the integral value returned by this function (the
63e8d8bef9SDimitry Andric   /// BlockFrequency::getFrequency() value) by getEntryFreq().
640b57cec5SDimitry Andric   BlockFrequency getBlockFreq(const MachineBasicBlock *MBB) const;
650b57cec5SDimitry Andric 
66e8d8bef9SDimitry Andric   /// Compute the frequency of the block, relative to the entry block.
67e8d8bef9SDimitry Andric   /// This API assumes getEntryFreq() is non-zero.
getBlockFreqRelativeToEntryBlock(const MachineBasicBlock * MBB)68*c9157d92SDimitry Andric   double getBlockFreqRelativeToEntryBlock(const MachineBasicBlock *MBB) const {
69*c9157d92SDimitry Andric     assert(getEntryFreq() != BlockFrequency(0) &&
70*c9157d92SDimitry Andric            "getEntryFreq() should not return 0 here!");
71*c9157d92SDimitry Andric     return static_cast<double>(getBlockFreq(MBB).getFrequency()) /
72*c9157d92SDimitry Andric            static_cast<double>(getEntryFreq().getFrequency());
73e8d8bef9SDimitry Andric   }
74e8d8bef9SDimitry Andric 
75bdd1243dSDimitry Andric   std::optional<uint64_t>
76bdd1243dSDimitry Andric   getBlockProfileCount(const MachineBasicBlock *MBB) const;
77*c9157d92SDimitry Andric   std::optional<uint64_t> getProfileCountFromFreq(BlockFrequency Freq) const;
780b57cec5SDimitry Andric 
79e8d8bef9SDimitry Andric   bool isIrrLoopHeader(const MachineBasicBlock *MBB) const;
800b57cec5SDimitry Andric 
81e8d8bef9SDimitry Andric   /// incrementally calculate block frequencies when we split edges, to avoid
82e8d8bef9SDimitry Andric   /// full CFG traversal.
83e8d8bef9SDimitry Andric   void onEdgeSplit(const MachineBasicBlock &NewPredecessor,
84e8d8bef9SDimitry Andric                    const MachineBasicBlock &NewSuccessor,
85e8d8bef9SDimitry Andric                    const MachineBranchProbabilityInfo &MBPI);
865ffd83dbSDimitry Andric 
870b57cec5SDimitry Andric   const MachineFunction *getFunction() const;
880b57cec5SDimitry Andric   const MachineBranchProbabilityInfo *getMBPI() const;
89e8d8bef9SDimitry Andric 
90e8d8bef9SDimitry Andric   /// Pop up a ghostview window with the current block frequency propagation
91e8d8bef9SDimitry Andric   /// rendered using dot.
920b57cec5SDimitry Andric   void view(const Twine &Name, bool isSimple = true) const;
930b57cec5SDimitry Andric 
94e8d8bef9SDimitry Andric   /// Divide a block's BlockFrequency::getFrequency() value by this value to
95e8d8bef9SDimitry Andric   /// obtain the entry block - relative frequency of said block.
96*c9157d92SDimitry Andric   BlockFrequency getEntryFreq() const;
970b57cec5SDimitry Andric };
980b57cec5SDimitry Andric 
99*c9157d92SDimitry Andric /// Print the block frequency @p Freq relative to the current functions entry
100*c9157d92SDimitry Andric /// frequency. Returns a Printable object that can be piped via `<<` to a
101*c9157d92SDimitry Andric /// `raw_ostream`.
102*c9157d92SDimitry Andric Printable printBlockFreq(const MachineBlockFrequencyInfo &MBFI,
103*c9157d92SDimitry Andric                          BlockFrequency Freq);
104*c9157d92SDimitry Andric 
105*c9157d92SDimitry Andric /// Convenience function equivalent to calling
106*c9157d92SDimitry Andric /// `printBlockFreq(MBFI, MBFI.getBlockFreq(&MBB))`.
107*c9157d92SDimitry Andric Printable printBlockFreq(const MachineBlockFrequencyInfo &MBFI,
108*c9157d92SDimitry Andric                          const MachineBasicBlock &MBB);
109*c9157d92SDimitry Andric 
1100b57cec5SDimitry Andric } // end namespace llvm
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric #endif // LLVM_CODEGEN_MACHINEBLOCKFREQUENCYINFO_H
113