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