xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/MIRSampleProfile.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1349cc55cSDimitry Andric //===-------- MIRSampleProfile.cpp: MIRSampleFDO (For FSAFDO) -------------===//
2349cc55cSDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6349cc55cSDimitry Andric //
7349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8349cc55cSDimitry Andric //
9349cc55cSDimitry Andric // This file provides the implementation of the MIRSampleProfile loader, mainly
10349cc55cSDimitry Andric // for flow sensitive SampleFDO.
11349cc55cSDimitry Andric //
12349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
13349cc55cSDimitry Andric 
14349cc55cSDimitry Andric #include "llvm/CodeGen/MIRSampleProfile.h"
15349cc55cSDimitry Andric #include "llvm/ADT/DenseMap.h"
16349cc55cSDimitry Andric #include "llvm/ADT/DenseSet.h"
17349cc55cSDimitry Andric #include "llvm/Analysis/BlockFrequencyInfoImpl.h"
1881ad6265SDimitry Andric #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
1981ad6265SDimitry Andric #include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
2081ad6265SDimitry Andric #include "llvm/CodeGen/MachineDominators.h"
2106c3fb27SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
2281ad6265SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h"
2381ad6265SDimitry Andric #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
2481ad6265SDimitry Andric #include "llvm/CodeGen/MachinePostDominators.h"
2581ad6265SDimitry Andric #include "llvm/CodeGen/Passes.h"
26349cc55cSDimitry Andric #include "llvm/IR/Function.h"
2706c3fb27SDimitry Andric #include "llvm/IR/PseudoProbe.h"
2881ad6265SDimitry Andric #include "llvm/InitializePasses.h"
29349cc55cSDimitry Andric #include "llvm/Support/CommandLine.h"
30349cc55cSDimitry Andric #include "llvm/Support/Debug.h"
3106c3fb27SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
32349cc55cSDimitry Andric #include "llvm/Support/raw_ostream.h"
33349cc55cSDimitry Andric #include "llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h"
34349cc55cSDimitry Andric #include "llvm/Transforms/Utils/SampleProfileLoaderBaseUtil.h"
3506c3fb27SDimitry Andric #include <optional>
36349cc55cSDimitry Andric 
37349cc55cSDimitry Andric using namespace llvm;
38349cc55cSDimitry Andric using namespace sampleprof;
39349cc55cSDimitry Andric using namespace llvm::sampleprofutil;
40349cc55cSDimitry Andric using ProfileCount = Function::ProfileCount;
41349cc55cSDimitry Andric 
42349cc55cSDimitry Andric #define DEBUG_TYPE "fs-profile-loader"
43349cc55cSDimitry Andric 
44349cc55cSDimitry Andric static cl::opt<bool> ShowFSBranchProb(
45349cc55cSDimitry Andric     "show-fs-branchprob", cl::Hidden, cl::init(false),
46349cc55cSDimitry Andric     cl::desc("Print setting flow sensitive branch probabilities"));
47349cc55cSDimitry Andric static cl::opt<unsigned> FSProfileDebugProbDiffThreshold(
48349cc55cSDimitry Andric     "fs-profile-debug-prob-diff-threshold", cl::init(10),
49349cc55cSDimitry Andric     cl::desc("Only show debug message if the branch probility is greater than "
50349cc55cSDimitry Andric              "this value (in percentage)."));
51349cc55cSDimitry Andric 
52349cc55cSDimitry Andric static cl::opt<unsigned> FSProfileDebugBWThreshold(
53349cc55cSDimitry Andric     "fs-profile-debug-bw-threshold", cl::init(10000),
54349cc55cSDimitry Andric     cl::desc("Only show debug message if the source branch weight is greater "
55349cc55cSDimitry Andric              " than this value."));
56349cc55cSDimitry Andric 
57349cc55cSDimitry Andric static cl::opt<bool> ViewBFIBefore("fs-viewbfi-before", cl::Hidden,
58349cc55cSDimitry Andric                                    cl::init(false),
59349cc55cSDimitry Andric                                    cl::desc("View BFI before MIR loader"));
60349cc55cSDimitry Andric static cl::opt<bool> ViewBFIAfter("fs-viewbfi-after", cl::Hidden,
61349cc55cSDimitry Andric                                   cl::init(false),
62349cc55cSDimitry Andric                                   cl::desc("View BFI after MIR loader"));
63349cc55cSDimitry Andric 
645f757f3fSDimitry Andric namespace llvm {
6506c3fb27SDimitry Andric extern cl::opt<bool> ImprovedFSDiscriminator;
665f757f3fSDimitry Andric }
67349cc55cSDimitry Andric char MIRProfileLoaderPass::ID = 0;
68349cc55cSDimitry Andric 
69349cc55cSDimitry Andric INITIALIZE_PASS_BEGIN(MIRProfileLoaderPass, DEBUG_TYPE,
70349cc55cSDimitry Andric                       "Load MIR Sample Profile",
71349cc55cSDimitry Andric                       /* cfg = */ false, /* is_analysis = */ false)
72*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineBlockFrequencyInfoWrapperPass)
73*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
74*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTreeWrapperPass)
75*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass)
76349cc55cSDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineOptimizationRemarkEmitterPass)
77349cc55cSDimitry Andric INITIALIZE_PASS_END(MIRProfileLoaderPass, DEBUG_TYPE, "Load MIR Sample Profile",
78349cc55cSDimitry Andric                     /* cfg = */ false, /* is_analysis = */ false)
79349cc55cSDimitry Andric 
80349cc55cSDimitry Andric char &llvm::MIRProfileLoaderPassID = MIRProfileLoaderPass::ID;
81349cc55cSDimitry Andric 
8206c3fb27SDimitry Andric FunctionPass *
8306c3fb27SDimitry Andric llvm::createMIRProfileLoaderPass(std::string File, std::string RemappingFile,
8406c3fb27SDimitry Andric                                  FSDiscriminatorPass P,
8506c3fb27SDimitry Andric                                  IntrusiveRefCntPtr<vfs::FileSystem> FS) {
8606c3fb27SDimitry Andric   return new MIRProfileLoaderPass(File, RemappingFile, P, std::move(FS));
87349cc55cSDimitry Andric }
88349cc55cSDimitry Andric 
89349cc55cSDimitry Andric namespace llvm {
90349cc55cSDimitry Andric 
91349cc55cSDimitry Andric // Internal option used to control BFI display only after MBP pass.
92349cc55cSDimitry Andric // Defined in CodeGen/MachineBlockFrequencyInfo.cpp:
93349cc55cSDimitry Andric // -view-block-layout-with-bfi={none | fraction | integer | count}
94349cc55cSDimitry Andric extern cl::opt<GVDAGType> ViewBlockLayoutWithBFI;
95349cc55cSDimitry Andric 
96349cc55cSDimitry Andric // Command line option to specify the name of the function for CFG dump
97349cc55cSDimitry Andric // Defined in Analysis/BlockFrequencyInfo.cpp:  -view-bfi-func-name=
98349cc55cSDimitry Andric extern cl::opt<std::string> ViewBlockFreqFuncName;
99349cc55cSDimitry Andric 
10006c3fb27SDimitry Andric std::optional<PseudoProbe> extractProbe(const MachineInstr &MI) {
10106c3fb27SDimitry Andric   if (MI.isPseudoProbe()) {
10206c3fb27SDimitry Andric     PseudoProbe Probe;
10306c3fb27SDimitry Andric     Probe.Id = MI.getOperand(1).getImm();
10406c3fb27SDimitry Andric     Probe.Type = MI.getOperand(2).getImm();
10506c3fb27SDimitry Andric     Probe.Attr = MI.getOperand(3).getImm();
10606c3fb27SDimitry Andric     Probe.Factor = 1;
10706c3fb27SDimitry Andric     DILocation *DebugLoc = MI.getDebugLoc();
10806c3fb27SDimitry Andric     Probe.Discriminator = DebugLoc ? DebugLoc->getDiscriminator() : 0;
10906c3fb27SDimitry Andric     return Probe;
11006c3fb27SDimitry Andric   }
11106c3fb27SDimitry Andric 
11206c3fb27SDimitry Andric   // Ignore callsite probes since they do not have FS discriminators.
11306c3fb27SDimitry Andric   return std::nullopt;
11406c3fb27SDimitry Andric }
11506c3fb27SDimitry Andric 
116349cc55cSDimitry Andric namespace afdo_detail {
117349cc55cSDimitry Andric template <> struct IRTraits<MachineBasicBlock> {
118349cc55cSDimitry Andric   using InstructionT = MachineInstr;
119349cc55cSDimitry Andric   using BasicBlockT = MachineBasicBlock;
120349cc55cSDimitry Andric   using FunctionT = MachineFunction;
121349cc55cSDimitry Andric   using BlockFrequencyInfoT = MachineBlockFrequencyInfo;
122349cc55cSDimitry Andric   using LoopT = MachineLoop;
123349cc55cSDimitry Andric   using LoopInfoPtrT = MachineLoopInfo *;
124349cc55cSDimitry Andric   using DominatorTreePtrT = MachineDominatorTree *;
125349cc55cSDimitry Andric   using PostDominatorTreePtrT = MachinePostDominatorTree *;
126349cc55cSDimitry Andric   using PostDominatorTreeT = MachinePostDominatorTree;
127349cc55cSDimitry Andric   using OptRemarkEmitterT = MachineOptimizationRemarkEmitter;
128349cc55cSDimitry Andric   using OptRemarkAnalysisT = MachineOptimizationRemarkAnalysis;
129349cc55cSDimitry Andric   using PredRangeT = iterator_range<std::vector<MachineBasicBlock *>::iterator>;
130349cc55cSDimitry Andric   using SuccRangeT = iterator_range<std::vector<MachineBasicBlock *>::iterator>;
131349cc55cSDimitry Andric   static Function &getFunction(MachineFunction &F) { return F.getFunction(); }
132349cc55cSDimitry Andric   static const MachineBasicBlock *getEntryBB(const MachineFunction *F) {
133349cc55cSDimitry Andric     return GraphTraits<const MachineFunction *>::getEntryNode(F);
134349cc55cSDimitry Andric   }
135349cc55cSDimitry Andric   static PredRangeT getPredecessors(MachineBasicBlock *BB) {
136349cc55cSDimitry Andric     return BB->predecessors();
137349cc55cSDimitry Andric   }
138349cc55cSDimitry Andric   static SuccRangeT getSuccessors(MachineBasicBlock *BB) {
139349cc55cSDimitry Andric     return BB->successors();
140349cc55cSDimitry Andric   }
141349cc55cSDimitry Andric };
142349cc55cSDimitry Andric } // namespace afdo_detail
143349cc55cSDimitry Andric 
144349cc55cSDimitry Andric class MIRProfileLoader final
14506c3fb27SDimitry Andric     : public SampleProfileLoaderBaseImpl<MachineFunction> {
146349cc55cSDimitry Andric public:
147349cc55cSDimitry Andric   void setInitVals(MachineDominatorTree *MDT, MachinePostDominatorTree *MPDT,
148349cc55cSDimitry Andric                    MachineLoopInfo *MLI, MachineBlockFrequencyInfo *MBFI,
149349cc55cSDimitry Andric                    MachineOptimizationRemarkEmitter *MORE) {
150349cc55cSDimitry Andric     DT = MDT;
151349cc55cSDimitry Andric     PDT = MPDT;
152349cc55cSDimitry Andric     LI = MLI;
153349cc55cSDimitry Andric     BFI = MBFI;
154349cc55cSDimitry Andric     ORE = MORE;
155349cc55cSDimitry Andric   }
156349cc55cSDimitry Andric   void setFSPass(FSDiscriminatorPass Pass) {
157349cc55cSDimitry Andric     P = Pass;
158349cc55cSDimitry Andric     LowBit = getFSPassBitBegin(P);
159349cc55cSDimitry Andric     HighBit = getFSPassBitEnd(P);
160349cc55cSDimitry Andric     assert(LowBit < HighBit && "HighBit needs to be greater than Lowbit");
161349cc55cSDimitry Andric   }
162349cc55cSDimitry Andric 
16306c3fb27SDimitry Andric   MIRProfileLoader(StringRef Name, StringRef RemapName,
16406c3fb27SDimitry Andric                    IntrusiveRefCntPtr<vfs::FileSystem> FS)
16506c3fb27SDimitry Andric       : SampleProfileLoaderBaseImpl(std::string(Name), std::string(RemapName),
16606c3fb27SDimitry Andric                                     std::move(FS)) {}
167349cc55cSDimitry Andric 
168349cc55cSDimitry Andric   void setBranchProbs(MachineFunction &F);
169349cc55cSDimitry Andric   bool runOnFunction(MachineFunction &F);
170349cc55cSDimitry Andric   bool doInitialization(Module &M);
171349cc55cSDimitry Andric   bool isValid() const { return ProfileIsValid; }
172349cc55cSDimitry Andric 
173349cc55cSDimitry Andric protected:
174349cc55cSDimitry Andric   friend class SampleCoverageTracker;
175349cc55cSDimitry Andric 
176349cc55cSDimitry Andric   /// Hold the information of the basic block frequency.
177349cc55cSDimitry Andric   MachineBlockFrequencyInfo *BFI;
178349cc55cSDimitry Andric 
179349cc55cSDimitry Andric   /// PassNum is the sequence number this pass is called, start from 1.
180349cc55cSDimitry Andric   FSDiscriminatorPass P;
181349cc55cSDimitry Andric 
182349cc55cSDimitry Andric   // LowBit in the FS discriminator used by this instance. Note the number is
183349cc55cSDimitry Andric   // 0-based. Base discrimnator use bit 0 to bit 11.
184349cc55cSDimitry Andric   unsigned LowBit;
185349cc55cSDimitry Andric   // HighwBit in the FS discriminator used by this instance. Note the number
186349cc55cSDimitry Andric   // is 0-based.
187349cc55cSDimitry Andric   unsigned HighBit;
188349cc55cSDimitry Andric 
189349cc55cSDimitry Andric   bool ProfileIsValid = true;
19006c3fb27SDimitry Andric   ErrorOr<uint64_t> getInstWeight(const MachineInstr &MI) override {
19106c3fb27SDimitry Andric     if (FunctionSamples::ProfileIsProbeBased)
19206c3fb27SDimitry Andric       return getProbeWeight(MI);
19306c3fb27SDimitry Andric     if (ImprovedFSDiscriminator && MI.isMetaInstruction())
19406c3fb27SDimitry Andric       return std::error_code();
19506c3fb27SDimitry Andric     return getInstWeightImpl(MI);
19606c3fb27SDimitry Andric   }
197349cc55cSDimitry Andric };
198349cc55cSDimitry Andric 
199349cc55cSDimitry Andric template <>
20006c3fb27SDimitry Andric void SampleProfileLoaderBaseImpl<MachineFunction>::computeDominanceAndLoopInfo(
20106c3fb27SDimitry Andric     MachineFunction &F) {}
202349cc55cSDimitry Andric 
203349cc55cSDimitry Andric void MIRProfileLoader::setBranchProbs(MachineFunction &F) {
204349cc55cSDimitry Andric   LLVM_DEBUG(dbgs() << "\nPropagation complete. Setting branch probs\n");
205349cc55cSDimitry Andric   for (auto &BI : F) {
206349cc55cSDimitry Andric     MachineBasicBlock *BB = &BI;
207349cc55cSDimitry Andric     if (BB->succ_size() < 2)
208349cc55cSDimitry Andric       continue;
209349cc55cSDimitry Andric     const MachineBasicBlock *EC = EquivalenceClass[BB];
210349cc55cSDimitry Andric     uint64_t BBWeight = BlockWeights[EC];
211349cc55cSDimitry Andric     uint64_t SumEdgeWeight = 0;
212349cc55cSDimitry Andric     for (MachineBasicBlock *Succ : BB->successors()) {
213349cc55cSDimitry Andric       Edge E = std::make_pair(BB, Succ);
214349cc55cSDimitry Andric       SumEdgeWeight += EdgeWeights[E];
215349cc55cSDimitry Andric     }
216349cc55cSDimitry Andric 
217349cc55cSDimitry Andric     if (BBWeight != SumEdgeWeight) {
218349cc55cSDimitry Andric       LLVM_DEBUG(dbgs() << "BBweight is not equal to SumEdgeWeight: BBWWeight="
219349cc55cSDimitry Andric                         << BBWeight << " SumEdgeWeight= " << SumEdgeWeight
220349cc55cSDimitry Andric                         << "\n");
221349cc55cSDimitry Andric       BBWeight = SumEdgeWeight;
222349cc55cSDimitry Andric     }
223349cc55cSDimitry Andric     if (BBWeight == 0) {
224349cc55cSDimitry Andric       LLVM_DEBUG(dbgs() << "SKIPPED. All branch weights are zero.\n");
225349cc55cSDimitry Andric       continue;
226349cc55cSDimitry Andric     }
227349cc55cSDimitry Andric 
228349cc55cSDimitry Andric #ifndef NDEBUG
229349cc55cSDimitry Andric     uint64_t BBWeightOrig = BBWeight;
230349cc55cSDimitry Andric #endif
231349cc55cSDimitry Andric     uint32_t MaxWeight = std::numeric_limits<uint32_t>::max();
232349cc55cSDimitry Andric     uint32_t Factor = 1;
233349cc55cSDimitry Andric     if (BBWeight > MaxWeight) {
234349cc55cSDimitry Andric       Factor = BBWeight / MaxWeight + 1;
235349cc55cSDimitry Andric       BBWeight /= Factor;
236349cc55cSDimitry Andric       LLVM_DEBUG(dbgs() << "Scaling weights by " << Factor << "\n");
237349cc55cSDimitry Andric     }
238349cc55cSDimitry Andric 
239349cc55cSDimitry Andric     for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(),
240349cc55cSDimitry Andric                                           SE = BB->succ_end();
241349cc55cSDimitry Andric          SI != SE; ++SI) {
242349cc55cSDimitry Andric       MachineBasicBlock *Succ = *SI;
243349cc55cSDimitry Andric       Edge E = std::make_pair(BB, Succ);
244349cc55cSDimitry Andric       uint64_t EdgeWeight = EdgeWeights[E];
245349cc55cSDimitry Andric       EdgeWeight /= Factor;
246349cc55cSDimitry Andric 
247349cc55cSDimitry Andric       assert(BBWeight >= EdgeWeight &&
248349cc55cSDimitry Andric              "BBweight is larger than EdgeWeight -- should not happen.\n");
249349cc55cSDimitry Andric 
250349cc55cSDimitry Andric       BranchProbability OldProb = BFI->getMBPI()->getEdgeProbability(BB, SI);
251349cc55cSDimitry Andric       BranchProbability NewProb(EdgeWeight, BBWeight);
252349cc55cSDimitry Andric       if (OldProb == NewProb)
253349cc55cSDimitry Andric         continue;
254349cc55cSDimitry Andric       BB->setSuccProbability(SI, NewProb);
255349cc55cSDimitry Andric #ifndef NDEBUG
256349cc55cSDimitry Andric       if (!ShowFSBranchProb)
257349cc55cSDimitry Andric         continue;
258349cc55cSDimitry Andric       bool Show = false;
259349cc55cSDimitry Andric       BranchProbability Diff;
260349cc55cSDimitry Andric       if (OldProb > NewProb)
261349cc55cSDimitry Andric         Diff = OldProb - NewProb;
262349cc55cSDimitry Andric       else
263349cc55cSDimitry Andric         Diff = NewProb - OldProb;
264349cc55cSDimitry Andric       Show = (Diff >= BranchProbability(FSProfileDebugProbDiffThreshold, 100));
265349cc55cSDimitry Andric       Show &= (BBWeightOrig >= FSProfileDebugBWThreshold);
266349cc55cSDimitry Andric 
267349cc55cSDimitry Andric       auto DIL = BB->findBranchDebugLoc();
268349cc55cSDimitry Andric       auto SuccDIL = Succ->findBranchDebugLoc();
269349cc55cSDimitry Andric       if (Show) {
270349cc55cSDimitry Andric         dbgs() << "Set branch fs prob: MBB (" << BB->getNumber() << " -> "
271349cc55cSDimitry Andric                << Succ->getNumber() << "): ";
272349cc55cSDimitry Andric         if (DIL)
273349cc55cSDimitry Andric           dbgs() << DIL->getFilename() << ":" << DIL->getLine() << ":"
274349cc55cSDimitry Andric                  << DIL->getColumn();
275349cc55cSDimitry Andric         if (SuccDIL)
276349cc55cSDimitry Andric           dbgs() << "-->" << SuccDIL->getFilename() << ":" << SuccDIL->getLine()
277349cc55cSDimitry Andric                  << ":" << SuccDIL->getColumn();
278349cc55cSDimitry Andric         dbgs() << " W=" << BBWeightOrig << "  " << OldProb << " --> " << NewProb
279349cc55cSDimitry Andric                << "\n";
280349cc55cSDimitry Andric       }
281349cc55cSDimitry Andric #endif
282349cc55cSDimitry Andric     }
283349cc55cSDimitry Andric   }
284349cc55cSDimitry Andric }
285349cc55cSDimitry Andric 
286349cc55cSDimitry Andric bool MIRProfileLoader::doInitialization(Module &M) {
287349cc55cSDimitry Andric   auto &Ctx = M.getContext();
288349cc55cSDimitry Andric 
28906c3fb27SDimitry Andric   auto ReaderOrErr = sampleprof::SampleProfileReader::create(
29006c3fb27SDimitry Andric       Filename, Ctx, *FS, P, RemappingFilename);
291349cc55cSDimitry Andric   if (std::error_code EC = ReaderOrErr.getError()) {
292349cc55cSDimitry Andric     std::string Msg = "Could not open profile: " + EC.message();
293349cc55cSDimitry Andric     Ctx.diagnose(DiagnosticInfoSampleProfile(Filename, Msg));
294349cc55cSDimitry Andric     return false;
295349cc55cSDimitry Andric   }
296349cc55cSDimitry Andric 
297349cc55cSDimitry Andric   Reader = std::move(ReaderOrErr.get());
298349cc55cSDimitry Andric   Reader->setModule(&M);
299349cc55cSDimitry Andric   ProfileIsValid = (Reader->read() == sampleprof_error::success);
30006c3fb27SDimitry Andric 
30106c3fb27SDimitry Andric   // Load pseudo probe descriptors for probe-based function samples.
30206c3fb27SDimitry Andric   if (Reader->profileIsProbeBased()) {
30306c3fb27SDimitry Andric     ProbeManager = std::make_unique<PseudoProbeManager>(M);
30406c3fb27SDimitry Andric     if (!ProbeManager->moduleIsProbed(M)) {
30506c3fb27SDimitry Andric       return false;
30606c3fb27SDimitry Andric     }
30706c3fb27SDimitry Andric   }
308349cc55cSDimitry Andric 
309349cc55cSDimitry Andric   return true;
310349cc55cSDimitry Andric }
311349cc55cSDimitry Andric 
312349cc55cSDimitry Andric bool MIRProfileLoader::runOnFunction(MachineFunction &MF) {
31306c3fb27SDimitry Andric   // Do not load non-FS profiles. A line or probe can get a zero-valued
31406c3fb27SDimitry Andric   // discriminator at certain pass which could result in accidentally loading
31506c3fb27SDimitry Andric   // the corresponding base counter in the non-FS profile, while a non-zero
31606c3fb27SDimitry Andric   // discriminator would end up getting zero samples. This could in turn undo
31706c3fb27SDimitry Andric   // the sample distribution effort done by previous BFI maintenance and the
31806c3fb27SDimitry Andric   // probe distribution factor work for pseudo probes.
31906c3fb27SDimitry Andric   if (!Reader->profileIsFS())
32006c3fb27SDimitry Andric     return false;
32106c3fb27SDimitry Andric 
322349cc55cSDimitry Andric   Function &Func = MF.getFunction();
323349cc55cSDimitry Andric   clearFunctionData(false);
324349cc55cSDimitry Andric   Samples = Reader->getSamplesFor(Func);
325349cc55cSDimitry Andric   if (!Samples || Samples->empty())
326349cc55cSDimitry Andric     return false;
327349cc55cSDimitry Andric 
32806c3fb27SDimitry Andric   if (FunctionSamples::ProfileIsProbeBased) {
32906c3fb27SDimitry Andric     if (!ProbeManager->profileIsValid(MF.getFunction(), *Samples))
33006c3fb27SDimitry Andric       return false;
33106c3fb27SDimitry Andric   } else {
332349cc55cSDimitry Andric     if (getFunctionLoc(MF) == 0)
333349cc55cSDimitry Andric       return false;
33406c3fb27SDimitry Andric   }
335349cc55cSDimitry Andric 
336349cc55cSDimitry Andric   DenseSet<GlobalValue::GUID> InlinedGUIDs;
337349cc55cSDimitry Andric   bool Changed = computeAndPropagateWeights(MF, InlinedGUIDs);
338349cc55cSDimitry Andric 
339349cc55cSDimitry Andric   // Set the new BPI, BFI.
340349cc55cSDimitry Andric   setBranchProbs(MF);
341349cc55cSDimitry Andric 
342349cc55cSDimitry Andric   return Changed;
343349cc55cSDimitry Andric }
344349cc55cSDimitry Andric 
345349cc55cSDimitry Andric } // namespace llvm
346349cc55cSDimitry Andric 
34706c3fb27SDimitry Andric MIRProfileLoaderPass::MIRProfileLoaderPass(
34806c3fb27SDimitry Andric     std::string FileName, std::string RemappingFileName, FSDiscriminatorPass P,
34906c3fb27SDimitry Andric     IntrusiveRefCntPtr<vfs::FileSystem> FS)
35006c3fb27SDimitry Andric     : MachineFunctionPass(ID), ProfileFileName(FileName), P(P) {
351349cc55cSDimitry Andric   LowBit = getFSPassBitBegin(P);
352349cc55cSDimitry Andric   HighBit = getFSPassBitEnd(P);
35306c3fb27SDimitry Andric 
35406c3fb27SDimitry Andric   auto VFS = FS ? std::move(FS) : vfs::getRealFileSystem();
35506c3fb27SDimitry Andric   MIRSampleLoader = std::make_unique<MIRProfileLoader>(
35606c3fb27SDimitry Andric       FileName, RemappingFileName, std::move(VFS));
357349cc55cSDimitry Andric   assert(LowBit < HighBit && "HighBit needs to be greater than Lowbit");
358349cc55cSDimitry Andric }
359349cc55cSDimitry Andric 
360349cc55cSDimitry Andric bool MIRProfileLoaderPass::runOnMachineFunction(MachineFunction &MF) {
361349cc55cSDimitry Andric   if (!MIRSampleLoader->isValid())
362349cc55cSDimitry Andric     return false;
363349cc55cSDimitry Andric 
364349cc55cSDimitry Andric   LLVM_DEBUG(dbgs() << "MIRProfileLoader pass working on Func: "
365349cc55cSDimitry Andric                     << MF.getFunction().getName() << "\n");
366*0fca6ea1SDimitry Andric   MBFI = &getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI();
367349cc55cSDimitry Andric   MIRSampleLoader->setInitVals(
368*0fca6ea1SDimitry Andric       &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree(),
369*0fca6ea1SDimitry Andric       &getAnalysis<MachinePostDominatorTreeWrapperPass>().getPostDomTree(),
370*0fca6ea1SDimitry Andric       &getAnalysis<MachineLoopInfoWrapperPass>().getLI(), MBFI,
371*0fca6ea1SDimitry Andric       &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE());
372349cc55cSDimitry Andric 
373349cc55cSDimitry Andric   MF.RenumberBlocks();
374349cc55cSDimitry Andric   if (ViewBFIBefore && ViewBlockLayoutWithBFI != GVDT_None &&
375349cc55cSDimitry Andric       (ViewBlockFreqFuncName.empty() ||
376*0fca6ea1SDimitry Andric        MF.getFunction().getName() == ViewBlockFreqFuncName)) {
377349cc55cSDimitry Andric     MBFI->view("MIR_Prof_loader_b." + MF.getName(), false);
378349cc55cSDimitry Andric   }
379349cc55cSDimitry Andric 
380349cc55cSDimitry Andric   bool Changed = MIRSampleLoader->runOnFunction(MF);
3814824e7fdSDimitry Andric   if (Changed)
382*0fca6ea1SDimitry Andric     MBFI->calculate(MF, *MBFI->getMBPI(),
383*0fca6ea1SDimitry Andric                     *&getAnalysis<MachineLoopInfoWrapperPass>().getLI());
384349cc55cSDimitry Andric 
385349cc55cSDimitry Andric   if (ViewBFIAfter && ViewBlockLayoutWithBFI != GVDT_None &&
386349cc55cSDimitry Andric       (ViewBlockFreqFuncName.empty() ||
387*0fca6ea1SDimitry Andric        MF.getFunction().getName() == ViewBlockFreqFuncName)) {
388349cc55cSDimitry Andric     MBFI->view("MIR_prof_loader_a." + MF.getName(), false);
389349cc55cSDimitry Andric   }
390349cc55cSDimitry Andric 
391349cc55cSDimitry Andric   return Changed;
392349cc55cSDimitry Andric }
393349cc55cSDimitry Andric 
394349cc55cSDimitry Andric bool MIRProfileLoaderPass::doInitialization(Module &M) {
395349cc55cSDimitry Andric   LLVM_DEBUG(dbgs() << "MIRProfileLoader pass working on Module " << M.getName()
396349cc55cSDimitry Andric                     << "\n");
397349cc55cSDimitry Andric 
398349cc55cSDimitry Andric   MIRSampleLoader->setFSPass(P);
399349cc55cSDimitry Andric   return MIRSampleLoader->doInitialization(M);
400349cc55cSDimitry Andric }
401349cc55cSDimitry Andric 
402349cc55cSDimitry Andric void MIRProfileLoaderPass::getAnalysisUsage(AnalysisUsage &AU) const {
403349cc55cSDimitry Andric   AU.setPreservesAll();
404*0fca6ea1SDimitry Andric   AU.addRequired<MachineBlockFrequencyInfoWrapperPass>();
405*0fca6ea1SDimitry Andric   AU.addRequired<MachineDominatorTreeWrapperPass>();
406*0fca6ea1SDimitry Andric   AU.addRequired<MachinePostDominatorTreeWrapperPass>();
407*0fca6ea1SDimitry Andric   AU.addRequiredTransitive<MachineLoopInfoWrapperPass>();
408349cc55cSDimitry Andric   AU.addRequired<MachineOptimizationRemarkEmitterPass>();
409349cc55cSDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
410349cc55cSDimitry Andric }
411