xref: /src/contrib/llvm-project/llvm/lib/CodeGen/MIRSampleProfile.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1c0981da4SDimitry Andric //===-------- MIRSampleProfile.cpp: MIRSampleFDO (For FSAFDO) -------------===//
2c0981da4SDimitry Andric //
3c0981da4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4c0981da4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5c0981da4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c0981da4SDimitry Andric //
7c0981da4SDimitry Andric //===----------------------------------------------------------------------===//
8c0981da4SDimitry Andric //
9c0981da4SDimitry Andric // This file provides the implementation of the MIRSampleProfile loader, mainly
10c0981da4SDimitry Andric // for flow sensitive SampleFDO.
11c0981da4SDimitry Andric //
12c0981da4SDimitry Andric //===----------------------------------------------------------------------===//
13c0981da4SDimitry Andric 
14c0981da4SDimitry Andric #include "llvm/CodeGen/MIRSampleProfile.h"
15c0981da4SDimitry Andric #include "llvm/ADT/DenseMap.h"
16c0981da4SDimitry Andric #include "llvm/ADT/DenseSet.h"
17c0981da4SDimitry Andric #include "llvm/Analysis/BlockFrequencyInfoImpl.h"
18145449b1SDimitry Andric #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
19145449b1SDimitry Andric #include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
20145449b1SDimitry Andric #include "llvm/CodeGen/MachineDominators.h"
217fa27ce4SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
22145449b1SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h"
23145449b1SDimitry Andric #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
24145449b1SDimitry Andric #include "llvm/CodeGen/MachinePostDominators.h"
25145449b1SDimitry Andric #include "llvm/CodeGen/Passes.h"
26c0981da4SDimitry Andric #include "llvm/IR/Function.h"
277fa27ce4SDimitry Andric #include "llvm/IR/PseudoProbe.h"
28145449b1SDimitry Andric #include "llvm/InitializePasses.h"
29c0981da4SDimitry Andric #include "llvm/Support/CommandLine.h"
30c0981da4SDimitry Andric #include "llvm/Support/Debug.h"
317fa27ce4SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
32c0981da4SDimitry Andric #include "llvm/Support/raw_ostream.h"
33c0981da4SDimitry Andric #include "llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h"
34c0981da4SDimitry Andric #include "llvm/Transforms/Utils/SampleProfileLoaderBaseUtil.h"
357fa27ce4SDimitry Andric #include <optional>
36c0981da4SDimitry Andric 
37c0981da4SDimitry Andric using namespace llvm;
38c0981da4SDimitry Andric using namespace sampleprof;
39c0981da4SDimitry Andric using namespace llvm::sampleprofutil;
40c0981da4SDimitry Andric using ProfileCount = Function::ProfileCount;
41c0981da4SDimitry Andric 
42c0981da4SDimitry Andric #define DEBUG_TYPE "fs-profile-loader"
43c0981da4SDimitry Andric 
44c0981da4SDimitry Andric static cl::opt<bool> ShowFSBranchProb(
45c0981da4SDimitry Andric     "show-fs-branchprob", cl::Hidden, cl::init(false),
46c0981da4SDimitry Andric     cl::desc("Print setting flow sensitive branch probabilities"));
47c0981da4SDimitry Andric static cl::opt<unsigned> FSProfileDebugProbDiffThreshold(
48c0981da4SDimitry Andric     "fs-profile-debug-prob-diff-threshold", cl::init(10),
49c0981da4SDimitry Andric     cl::desc("Only show debug message if the branch probility is greater than "
50c0981da4SDimitry Andric              "this value (in percentage)."));
51c0981da4SDimitry Andric 
52c0981da4SDimitry Andric static cl::opt<unsigned> FSProfileDebugBWThreshold(
53c0981da4SDimitry Andric     "fs-profile-debug-bw-threshold", cl::init(10000),
54c0981da4SDimitry Andric     cl::desc("Only show debug message if the source branch weight is greater "
55c0981da4SDimitry Andric              " than this value."));
56c0981da4SDimitry Andric 
57c0981da4SDimitry Andric static cl::opt<bool> ViewBFIBefore("fs-viewbfi-before", cl::Hidden,
58c0981da4SDimitry Andric                                    cl::init(false),
59c0981da4SDimitry Andric                                    cl::desc("View BFI before MIR loader"));
60c0981da4SDimitry Andric static cl::opt<bool> ViewBFIAfter("fs-viewbfi-after", cl::Hidden,
61c0981da4SDimitry Andric                                   cl::init(false),
62c0981da4SDimitry Andric                                   cl::desc("View BFI after MIR loader"));
63c0981da4SDimitry Andric 
64b1c73532SDimitry Andric namespace llvm {
657fa27ce4SDimitry Andric extern cl::opt<bool> ImprovedFSDiscriminator;
66b1c73532SDimitry Andric }
67c0981da4SDimitry Andric char MIRProfileLoaderPass::ID = 0;
68c0981da4SDimitry Andric 
69c0981da4SDimitry Andric INITIALIZE_PASS_BEGIN(MIRProfileLoaderPass, DEBUG_TYPE,
70c0981da4SDimitry Andric                       "Load MIR Sample Profile",
71c0981da4SDimitry Andric                       /* cfg = */ false, /* is_analysis = */ false)
72ac9a064cSDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineBlockFrequencyInfoWrapperPass)
73ac9a064cSDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
74ac9a064cSDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTreeWrapperPass)
75ac9a064cSDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass)
76c0981da4SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineOptimizationRemarkEmitterPass)
77c0981da4SDimitry Andric INITIALIZE_PASS_END(MIRProfileLoaderPass, DEBUG_TYPE, "Load MIR Sample Profile",
78c0981da4SDimitry Andric                     /* cfg = */ false, /* is_analysis = */ false)
79c0981da4SDimitry Andric 
80c0981da4SDimitry Andric char &llvm::MIRProfileLoaderPassID = MIRProfileLoaderPass::ID;
81c0981da4SDimitry Andric 
827fa27ce4SDimitry Andric FunctionPass *
createMIRProfileLoaderPass(std::string File,std::string RemappingFile,FSDiscriminatorPass P,IntrusiveRefCntPtr<vfs::FileSystem> FS)837fa27ce4SDimitry Andric llvm::createMIRProfileLoaderPass(std::string File, std::string RemappingFile,
847fa27ce4SDimitry Andric                                  FSDiscriminatorPass P,
857fa27ce4SDimitry Andric                                  IntrusiveRefCntPtr<vfs::FileSystem> FS) {
867fa27ce4SDimitry Andric   return new MIRProfileLoaderPass(File, RemappingFile, P, std::move(FS));
87c0981da4SDimitry Andric }
88c0981da4SDimitry Andric 
89c0981da4SDimitry Andric namespace llvm {
90c0981da4SDimitry Andric 
91c0981da4SDimitry Andric // Internal option used to control BFI display only after MBP pass.
92c0981da4SDimitry Andric // Defined in CodeGen/MachineBlockFrequencyInfo.cpp:
93c0981da4SDimitry Andric // -view-block-layout-with-bfi={none | fraction | integer | count}
94c0981da4SDimitry Andric extern cl::opt<GVDAGType> ViewBlockLayoutWithBFI;
95c0981da4SDimitry Andric 
96c0981da4SDimitry Andric // Command line option to specify the name of the function for CFG dump
97c0981da4SDimitry Andric // Defined in Analysis/BlockFrequencyInfo.cpp:  -view-bfi-func-name=
98c0981da4SDimitry Andric extern cl::opt<std::string> ViewBlockFreqFuncName;
99c0981da4SDimitry Andric 
extractProbe(const MachineInstr & MI)1007fa27ce4SDimitry Andric std::optional<PseudoProbe> extractProbe(const MachineInstr &MI) {
1017fa27ce4SDimitry Andric   if (MI.isPseudoProbe()) {
1027fa27ce4SDimitry Andric     PseudoProbe Probe;
1037fa27ce4SDimitry Andric     Probe.Id = MI.getOperand(1).getImm();
1047fa27ce4SDimitry Andric     Probe.Type = MI.getOperand(2).getImm();
1057fa27ce4SDimitry Andric     Probe.Attr = MI.getOperand(3).getImm();
1067fa27ce4SDimitry Andric     Probe.Factor = 1;
1077fa27ce4SDimitry Andric     DILocation *DebugLoc = MI.getDebugLoc();
1087fa27ce4SDimitry Andric     Probe.Discriminator = DebugLoc ? DebugLoc->getDiscriminator() : 0;
1097fa27ce4SDimitry Andric     return Probe;
1107fa27ce4SDimitry Andric   }
1117fa27ce4SDimitry Andric 
1127fa27ce4SDimitry Andric   // Ignore callsite probes since they do not have FS discriminators.
1137fa27ce4SDimitry Andric   return std::nullopt;
1147fa27ce4SDimitry Andric }
1157fa27ce4SDimitry Andric 
116c0981da4SDimitry Andric namespace afdo_detail {
117c0981da4SDimitry Andric template <> struct IRTraits<MachineBasicBlock> {
118c0981da4SDimitry Andric   using InstructionT = MachineInstr;
119c0981da4SDimitry Andric   using BasicBlockT = MachineBasicBlock;
120c0981da4SDimitry Andric   using FunctionT = MachineFunction;
121c0981da4SDimitry Andric   using BlockFrequencyInfoT = MachineBlockFrequencyInfo;
122c0981da4SDimitry Andric   using LoopT = MachineLoop;
123c0981da4SDimitry Andric   using LoopInfoPtrT = MachineLoopInfo *;
124c0981da4SDimitry Andric   using DominatorTreePtrT = MachineDominatorTree *;
125c0981da4SDimitry Andric   using PostDominatorTreePtrT = MachinePostDominatorTree *;
126c0981da4SDimitry Andric   using PostDominatorTreeT = MachinePostDominatorTree;
127c0981da4SDimitry Andric   using OptRemarkEmitterT = MachineOptimizationRemarkEmitter;
128c0981da4SDimitry Andric   using OptRemarkAnalysisT = MachineOptimizationRemarkAnalysis;
129c0981da4SDimitry Andric   using PredRangeT = iterator_range<std::vector<MachineBasicBlock *>::iterator>;
130c0981da4SDimitry Andric   using SuccRangeT = iterator_range<std::vector<MachineBasicBlock *>::iterator>;
getFunctionllvm::afdo_detail::IRTraits131c0981da4SDimitry Andric   static Function &getFunction(MachineFunction &F) { return F.getFunction(); }
getEntryBBllvm::afdo_detail::IRTraits132c0981da4SDimitry Andric   static const MachineBasicBlock *getEntryBB(const MachineFunction *F) {
133c0981da4SDimitry Andric     return GraphTraits<const MachineFunction *>::getEntryNode(F);
134c0981da4SDimitry Andric   }
getPredecessorsllvm::afdo_detail::IRTraits135c0981da4SDimitry Andric   static PredRangeT getPredecessors(MachineBasicBlock *BB) {
136c0981da4SDimitry Andric     return BB->predecessors();
137c0981da4SDimitry Andric   }
getSuccessorsllvm::afdo_detail::IRTraits138c0981da4SDimitry Andric   static SuccRangeT getSuccessors(MachineBasicBlock *BB) {
139c0981da4SDimitry Andric     return BB->successors();
140c0981da4SDimitry Andric   }
141c0981da4SDimitry Andric };
142c0981da4SDimitry Andric } // namespace afdo_detail
143c0981da4SDimitry Andric 
144c0981da4SDimitry Andric class MIRProfileLoader final
1457fa27ce4SDimitry Andric     : public SampleProfileLoaderBaseImpl<MachineFunction> {
146c0981da4SDimitry Andric public:
setInitVals(MachineDominatorTree * MDT,MachinePostDominatorTree * MPDT,MachineLoopInfo * MLI,MachineBlockFrequencyInfo * MBFI,MachineOptimizationRemarkEmitter * MORE)147c0981da4SDimitry Andric   void setInitVals(MachineDominatorTree *MDT, MachinePostDominatorTree *MPDT,
148c0981da4SDimitry Andric                    MachineLoopInfo *MLI, MachineBlockFrequencyInfo *MBFI,
149c0981da4SDimitry Andric                    MachineOptimizationRemarkEmitter *MORE) {
150c0981da4SDimitry Andric     DT = MDT;
151c0981da4SDimitry Andric     PDT = MPDT;
152c0981da4SDimitry Andric     LI = MLI;
153c0981da4SDimitry Andric     BFI = MBFI;
154c0981da4SDimitry Andric     ORE = MORE;
155c0981da4SDimitry Andric   }
setFSPass(FSDiscriminatorPass Pass)156c0981da4SDimitry Andric   void setFSPass(FSDiscriminatorPass Pass) {
157c0981da4SDimitry Andric     P = Pass;
158c0981da4SDimitry Andric     LowBit = getFSPassBitBegin(P);
159c0981da4SDimitry Andric     HighBit = getFSPassBitEnd(P);
160c0981da4SDimitry Andric     assert(LowBit < HighBit && "HighBit needs to be greater than Lowbit");
161c0981da4SDimitry Andric   }
162c0981da4SDimitry Andric 
MIRProfileLoader(StringRef Name,StringRef RemapName,IntrusiveRefCntPtr<vfs::FileSystem> FS)1637fa27ce4SDimitry Andric   MIRProfileLoader(StringRef Name, StringRef RemapName,
1647fa27ce4SDimitry Andric                    IntrusiveRefCntPtr<vfs::FileSystem> FS)
1657fa27ce4SDimitry Andric       : SampleProfileLoaderBaseImpl(std::string(Name), std::string(RemapName),
1667fa27ce4SDimitry Andric                                     std::move(FS)) {}
167c0981da4SDimitry Andric 
168c0981da4SDimitry Andric   void setBranchProbs(MachineFunction &F);
169c0981da4SDimitry Andric   bool runOnFunction(MachineFunction &F);
170c0981da4SDimitry Andric   bool doInitialization(Module &M);
isValid() const171c0981da4SDimitry Andric   bool isValid() const { return ProfileIsValid; }
172c0981da4SDimitry Andric 
173c0981da4SDimitry Andric protected:
174c0981da4SDimitry Andric   friend class SampleCoverageTracker;
175c0981da4SDimitry Andric 
176c0981da4SDimitry Andric   /// Hold the information of the basic block frequency.
177c0981da4SDimitry Andric   MachineBlockFrequencyInfo *BFI;
178c0981da4SDimitry Andric 
179c0981da4SDimitry Andric   /// PassNum is the sequence number this pass is called, start from 1.
180c0981da4SDimitry Andric   FSDiscriminatorPass P;
181c0981da4SDimitry Andric 
182c0981da4SDimitry Andric   // LowBit in the FS discriminator used by this instance. Note the number is
183c0981da4SDimitry Andric   // 0-based. Base discrimnator use bit 0 to bit 11.
184c0981da4SDimitry Andric   unsigned LowBit;
185c0981da4SDimitry Andric   // HighwBit in the FS discriminator used by this instance. Note the number
186c0981da4SDimitry Andric   // is 0-based.
187c0981da4SDimitry Andric   unsigned HighBit;
188c0981da4SDimitry Andric 
189c0981da4SDimitry Andric   bool ProfileIsValid = true;
getInstWeight(const MachineInstr & MI)1907fa27ce4SDimitry Andric   ErrorOr<uint64_t> getInstWeight(const MachineInstr &MI) override {
1917fa27ce4SDimitry Andric     if (FunctionSamples::ProfileIsProbeBased)
1927fa27ce4SDimitry Andric       return getProbeWeight(MI);
1937fa27ce4SDimitry Andric     if (ImprovedFSDiscriminator && MI.isMetaInstruction())
1947fa27ce4SDimitry Andric       return std::error_code();
1957fa27ce4SDimitry Andric     return getInstWeightImpl(MI);
1967fa27ce4SDimitry Andric   }
197c0981da4SDimitry Andric };
198c0981da4SDimitry Andric 
199c0981da4SDimitry Andric template <>
computeDominanceAndLoopInfo(MachineFunction & F)2007fa27ce4SDimitry Andric void SampleProfileLoaderBaseImpl<MachineFunction>::computeDominanceAndLoopInfo(
2017fa27ce4SDimitry Andric     MachineFunction &F) {}
202c0981da4SDimitry Andric 
setBranchProbs(MachineFunction & F)203c0981da4SDimitry Andric void MIRProfileLoader::setBranchProbs(MachineFunction &F) {
204c0981da4SDimitry Andric   LLVM_DEBUG(dbgs() << "\nPropagation complete. Setting branch probs\n");
205c0981da4SDimitry Andric   for (auto &BI : F) {
206c0981da4SDimitry Andric     MachineBasicBlock *BB = &BI;
207c0981da4SDimitry Andric     if (BB->succ_size() < 2)
208c0981da4SDimitry Andric       continue;
209c0981da4SDimitry Andric     const MachineBasicBlock *EC = EquivalenceClass[BB];
210c0981da4SDimitry Andric     uint64_t BBWeight = BlockWeights[EC];
211c0981da4SDimitry Andric     uint64_t SumEdgeWeight = 0;
212c0981da4SDimitry Andric     for (MachineBasicBlock *Succ : BB->successors()) {
213c0981da4SDimitry Andric       Edge E = std::make_pair(BB, Succ);
214c0981da4SDimitry Andric       SumEdgeWeight += EdgeWeights[E];
215c0981da4SDimitry Andric     }
216c0981da4SDimitry Andric 
217c0981da4SDimitry Andric     if (BBWeight != SumEdgeWeight) {
218c0981da4SDimitry Andric       LLVM_DEBUG(dbgs() << "BBweight is not equal to SumEdgeWeight: BBWWeight="
219c0981da4SDimitry Andric                         << BBWeight << " SumEdgeWeight= " << SumEdgeWeight
220c0981da4SDimitry Andric                         << "\n");
221c0981da4SDimitry Andric       BBWeight = SumEdgeWeight;
222c0981da4SDimitry Andric     }
223c0981da4SDimitry Andric     if (BBWeight == 0) {
224c0981da4SDimitry Andric       LLVM_DEBUG(dbgs() << "SKIPPED. All branch weights are zero.\n");
225c0981da4SDimitry Andric       continue;
226c0981da4SDimitry Andric     }
227c0981da4SDimitry Andric 
228c0981da4SDimitry Andric #ifndef NDEBUG
229c0981da4SDimitry Andric     uint64_t BBWeightOrig = BBWeight;
230c0981da4SDimitry Andric #endif
231c0981da4SDimitry Andric     uint32_t MaxWeight = std::numeric_limits<uint32_t>::max();
232c0981da4SDimitry Andric     uint32_t Factor = 1;
233c0981da4SDimitry Andric     if (BBWeight > MaxWeight) {
234c0981da4SDimitry Andric       Factor = BBWeight / MaxWeight + 1;
235c0981da4SDimitry Andric       BBWeight /= Factor;
236c0981da4SDimitry Andric       LLVM_DEBUG(dbgs() << "Scaling weights by " << Factor << "\n");
237c0981da4SDimitry Andric     }
238c0981da4SDimitry Andric 
239c0981da4SDimitry Andric     for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(),
240c0981da4SDimitry Andric                                           SE = BB->succ_end();
241c0981da4SDimitry Andric          SI != SE; ++SI) {
242c0981da4SDimitry Andric       MachineBasicBlock *Succ = *SI;
243c0981da4SDimitry Andric       Edge E = std::make_pair(BB, Succ);
244c0981da4SDimitry Andric       uint64_t EdgeWeight = EdgeWeights[E];
245c0981da4SDimitry Andric       EdgeWeight /= Factor;
246c0981da4SDimitry Andric 
247c0981da4SDimitry Andric       assert(BBWeight >= EdgeWeight &&
248c0981da4SDimitry Andric              "BBweight is larger than EdgeWeight -- should not happen.\n");
249c0981da4SDimitry Andric 
250c0981da4SDimitry Andric       BranchProbability OldProb = BFI->getMBPI()->getEdgeProbability(BB, SI);
251c0981da4SDimitry Andric       BranchProbability NewProb(EdgeWeight, BBWeight);
252c0981da4SDimitry Andric       if (OldProb == NewProb)
253c0981da4SDimitry Andric         continue;
254c0981da4SDimitry Andric       BB->setSuccProbability(SI, NewProb);
255c0981da4SDimitry Andric #ifndef NDEBUG
256c0981da4SDimitry Andric       if (!ShowFSBranchProb)
257c0981da4SDimitry Andric         continue;
258c0981da4SDimitry Andric       bool Show = false;
259c0981da4SDimitry Andric       BranchProbability Diff;
260c0981da4SDimitry Andric       if (OldProb > NewProb)
261c0981da4SDimitry Andric         Diff = OldProb - NewProb;
262c0981da4SDimitry Andric       else
263c0981da4SDimitry Andric         Diff = NewProb - OldProb;
264c0981da4SDimitry Andric       Show = (Diff >= BranchProbability(FSProfileDebugProbDiffThreshold, 100));
265c0981da4SDimitry Andric       Show &= (BBWeightOrig >= FSProfileDebugBWThreshold);
266c0981da4SDimitry Andric 
267c0981da4SDimitry Andric       auto DIL = BB->findBranchDebugLoc();
268c0981da4SDimitry Andric       auto SuccDIL = Succ->findBranchDebugLoc();
269c0981da4SDimitry Andric       if (Show) {
270c0981da4SDimitry Andric         dbgs() << "Set branch fs prob: MBB (" << BB->getNumber() << " -> "
271c0981da4SDimitry Andric                << Succ->getNumber() << "): ";
272c0981da4SDimitry Andric         if (DIL)
273c0981da4SDimitry Andric           dbgs() << DIL->getFilename() << ":" << DIL->getLine() << ":"
274c0981da4SDimitry Andric                  << DIL->getColumn();
275c0981da4SDimitry Andric         if (SuccDIL)
276c0981da4SDimitry Andric           dbgs() << "-->" << SuccDIL->getFilename() << ":" << SuccDIL->getLine()
277c0981da4SDimitry Andric                  << ":" << SuccDIL->getColumn();
278c0981da4SDimitry Andric         dbgs() << " W=" << BBWeightOrig << "  " << OldProb << " --> " << NewProb
279c0981da4SDimitry Andric                << "\n";
280c0981da4SDimitry Andric       }
281c0981da4SDimitry Andric #endif
282c0981da4SDimitry Andric     }
283c0981da4SDimitry Andric   }
284c0981da4SDimitry Andric }
285c0981da4SDimitry Andric 
doInitialization(Module & M)286c0981da4SDimitry Andric bool MIRProfileLoader::doInitialization(Module &M) {
287c0981da4SDimitry Andric   auto &Ctx = M.getContext();
288c0981da4SDimitry Andric 
2897fa27ce4SDimitry Andric   auto ReaderOrErr = sampleprof::SampleProfileReader::create(
2907fa27ce4SDimitry Andric       Filename, Ctx, *FS, P, RemappingFilename);
291c0981da4SDimitry Andric   if (std::error_code EC = ReaderOrErr.getError()) {
292c0981da4SDimitry Andric     std::string Msg = "Could not open profile: " + EC.message();
293c0981da4SDimitry Andric     Ctx.diagnose(DiagnosticInfoSampleProfile(Filename, Msg));
294c0981da4SDimitry Andric     return false;
295c0981da4SDimitry Andric   }
296c0981da4SDimitry Andric 
297c0981da4SDimitry Andric   Reader = std::move(ReaderOrErr.get());
298c0981da4SDimitry Andric   Reader->setModule(&M);
299c0981da4SDimitry Andric   ProfileIsValid = (Reader->read() == sampleprof_error::success);
3007fa27ce4SDimitry Andric 
3017fa27ce4SDimitry Andric   // Load pseudo probe descriptors for probe-based function samples.
3027fa27ce4SDimitry Andric   if (Reader->profileIsProbeBased()) {
3037fa27ce4SDimitry Andric     ProbeManager = std::make_unique<PseudoProbeManager>(M);
3047fa27ce4SDimitry Andric     if (!ProbeManager->moduleIsProbed(M)) {
3057fa27ce4SDimitry Andric       return false;
3067fa27ce4SDimitry Andric     }
3077fa27ce4SDimitry Andric   }
308c0981da4SDimitry Andric 
309c0981da4SDimitry Andric   return true;
310c0981da4SDimitry Andric }
311c0981da4SDimitry Andric 
runOnFunction(MachineFunction & MF)312c0981da4SDimitry Andric bool MIRProfileLoader::runOnFunction(MachineFunction &MF) {
3137fa27ce4SDimitry Andric   // Do not load non-FS profiles. A line or probe can get a zero-valued
3147fa27ce4SDimitry Andric   // discriminator at certain pass which could result in accidentally loading
3157fa27ce4SDimitry Andric   // the corresponding base counter in the non-FS profile, while a non-zero
3167fa27ce4SDimitry Andric   // discriminator would end up getting zero samples. This could in turn undo
3177fa27ce4SDimitry Andric   // the sample distribution effort done by previous BFI maintenance and the
3187fa27ce4SDimitry Andric   // probe distribution factor work for pseudo probes.
3197fa27ce4SDimitry Andric   if (!Reader->profileIsFS())
3207fa27ce4SDimitry Andric     return false;
3217fa27ce4SDimitry Andric 
322c0981da4SDimitry Andric   Function &Func = MF.getFunction();
323c0981da4SDimitry Andric   clearFunctionData(false);
324c0981da4SDimitry Andric   Samples = Reader->getSamplesFor(Func);
325c0981da4SDimitry Andric   if (!Samples || Samples->empty())
326c0981da4SDimitry Andric     return false;
327c0981da4SDimitry Andric 
3287fa27ce4SDimitry Andric   if (FunctionSamples::ProfileIsProbeBased) {
3297fa27ce4SDimitry Andric     if (!ProbeManager->profileIsValid(MF.getFunction(), *Samples))
3307fa27ce4SDimitry Andric       return false;
3317fa27ce4SDimitry Andric   } else {
332c0981da4SDimitry Andric     if (getFunctionLoc(MF) == 0)
333c0981da4SDimitry Andric       return false;
3347fa27ce4SDimitry Andric   }
335c0981da4SDimitry Andric 
336c0981da4SDimitry Andric   DenseSet<GlobalValue::GUID> InlinedGUIDs;
337c0981da4SDimitry Andric   bool Changed = computeAndPropagateWeights(MF, InlinedGUIDs);
338c0981da4SDimitry Andric 
339c0981da4SDimitry Andric   // Set the new BPI, BFI.
340c0981da4SDimitry Andric   setBranchProbs(MF);
341c0981da4SDimitry Andric 
342c0981da4SDimitry Andric   return Changed;
343c0981da4SDimitry Andric }
344c0981da4SDimitry Andric 
345c0981da4SDimitry Andric } // namespace llvm
346c0981da4SDimitry Andric 
MIRProfileLoaderPass(std::string FileName,std::string RemappingFileName,FSDiscriminatorPass P,IntrusiveRefCntPtr<vfs::FileSystem> FS)3477fa27ce4SDimitry Andric MIRProfileLoaderPass::MIRProfileLoaderPass(
3487fa27ce4SDimitry Andric     std::string FileName, std::string RemappingFileName, FSDiscriminatorPass P,
3497fa27ce4SDimitry Andric     IntrusiveRefCntPtr<vfs::FileSystem> FS)
3507fa27ce4SDimitry Andric     : MachineFunctionPass(ID), ProfileFileName(FileName), P(P) {
351c0981da4SDimitry Andric   LowBit = getFSPassBitBegin(P);
352c0981da4SDimitry Andric   HighBit = getFSPassBitEnd(P);
3537fa27ce4SDimitry Andric 
3547fa27ce4SDimitry Andric   auto VFS = FS ? std::move(FS) : vfs::getRealFileSystem();
3557fa27ce4SDimitry Andric   MIRSampleLoader = std::make_unique<MIRProfileLoader>(
3567fa27ce4SDimitry Andric       FileName, RemappingFileName, std::move(VFS));
357c0981da4SDimitry Andric   assert(LowBit < HighBit && "HighBit needs to be greater than Lowbit");
358c0981da4SDimitry Andric }
359c0981da4SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)360c0981da4SDimitry Andric bool MIRProfileLoaderPass::runOnMachineFunction(MachineFunction &MF) {
361c0981da4SDimitry Andric   if (!MIRSampleLoader->isValid())
362c0981da4SDimitry Andric     return false;
363c0981da4SDimitry Andric 
364c0981da4SDimitry Andric   LLVM_DEBUG(dbgs() << "MIRProfileLoader pass working on Func: "
365c0981da4SDimitry Andric                     << MF.getFunction().getName() << "\n");
366ac9a064cSDimitry Andric   MBFI = &getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI();
367c0981da4SDimitry Andric   MIRSampleLoader->setInitVals(
368ac9a064cSDimitry Andric       &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree(),
369ac9a064cSDimitry Andric       &getAnalysis<MachinePostDominatorTreeWrapperPass>().getPostDomTree(),
370ac9a064cSDimitry Andric       &getAnalysis<MachineLoopInfoWrapperPass>().getLI(), MBFI,
371ac9a064cSDimitry Andric       &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE());
372c0981da4SDimitry Andric 
373c0981da4SDimitry Andric   MF.RenumberBlocks();
374c0981da4SDimitry Andric   if (ViewBFIBefore && ViewBlockLayoutWithBFI != GVDT_None &&
375c0981da4SDimitry Andric       (ViewBlockFreqFuncName.empty() ||
376ac9a064cSDimitry Andric        MF.getFunction().getName() == ViewBlockFreqFuncName)) {
377c0981da4SDimitry Andric     MBFI->view("MIR_Prof_loader_b." + MF.getName(), false);
378c0981da4SDimitry Andric   }
379c0981da4SDimitry Andric 
380c0981da4SDimitry Andric   bool Changed = MIRSampleLoader->runOnFunction(MF);
381f65dcba8SDimitry Andric   if (Changed)
382ac9a064cSDimitry Andric     MBFI->calculate(MF, *MBFI->getMBPI(),
383ac9a064cSDimitry Andric                     *&getAnalysis<MachineLoopInfoWrapperPass>().getLI());
384c0981da4SDimitry Andric 
385c0981da4SDimitry Andric   if (ViewBFIAfter && ViewBlockLayoutWithBFI != GVDT_None &&
386c0981da4SDimitry Andric       (ViewBlockFreqFuncName.empty() ||
387ac9a064cSDimitry Andric        MF.getFunction().getName() == ViewBlockFreqFuncName)) {
388c0981da4SDimitry Andric     MBFI->view("MIR_prof_loader_a." + MF.getName(), false);
389c0981da4SDimitry Andric   }
390c0981da4SDimitry Andric 
391c0981da4SDimitry Andric   return Changed;
392c0981da4SDimitry Andric }
393c0981da4SDimitry Andric 
doInitialization(Module & M)394c0981da4SDimitry Andric bool MIRProfileLoaderPass::doInitialization(Module &M) {
395c0981da4SDimitry Andric   LLVM_DEBUG(dbgs() << "MIRProfileLoader pass working on Module " << M.getName()
396c0981da4SDimitry Andric                     << "\n");
397c0981da4SDimitry Andric 
398c0981da4SDimitry Andric   MIRSampleLoader->setFSPass(P);
399c0981da4SDimitry Andric   return MIRSampleLoader->doInitialization(M);
400c0981da4SDimitry Andric }
401c0981da4SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const402c0981da4SDimitry Andric void MIRProfileLoaderPass::getAnalysisUsage(AnalysisUsage &AU) const {
403c0981da4SDimitry Andric   AU.setPreservesAll();
404ac9a064cSDimitry Andric   AU.addRequired<MachineBlockFrequencyInfoWrapperPass>();
405ac9a064cSDimitry Andric   AU.addRequired<MachineDominatorTreeWrapperPass>();
406ac9a064cSDimitry Andric   AU.addRequired<MachinePostDominatorTreeWrapperPass>();
407ac9a064cSDimitry Andric   AU.addRequiredTransitive<MachineLoopInfoWrapperPass>();
408c0981da4SDimitry Andric   AU.addRequired<MachineOptimizationRemarkEmitterPass>();
409c0981da4SDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
410c0981da4SDimitry Andric }
411