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