123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- //===-------- MIRSampleProfile.cpp: MIRSampleFDO (For FSAFDO) -------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file provides the implementation of the MIRSampleProfile loader, mainly
- // for flow sensitive SampleFDO.
- //
- //===----------------------------------------------------------------------===//
- #include "llvm/CodeGen/MIRSampleProfile.h"
- #include "llvm/ADT/DenseMap.h"
- #include "llvm/ADT/DenseSet.h"
- #include "llvm/Analysis/BlockFrequencyInfoImpl.h"
- #include "llvm/IR/Function.h"
- #include "llvm/Support/CommandLine.h"
- #include "llvm/Support/Debug.h"
- #include "llvm/Support/raw_ostream.h"
- #include "llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h"
- #include "llvm/Transforms/Utils/SampleProfileLoaderBaseUtil.h"
- using namespace llvm;
- using namespace sampleprof;
- using namespace llvm::sampleprofutil;
- using ProfileCount = Function::ProfileCount;
- #define DEBUG_TYPE "fs-profile-loader"
- static cl::opt<bool> ShowFSBranchProb(
- "show-fs-branchprob", cl::Hidden, cl::init(false),
- cl::desc("Print setting flow sensitive branch probabilities"));
- static cl::opt<unsigned> FSProfileDebugProbDiffThreshold(
- "fs-profile-debug-prob-diff-threshold", cl::init(10),
- cl::desc("Only show debug message if the branch probility is greater than "
- "this value (in percentage)."));
- static cl::opt<unsigned> FSProfileDebugBWThreshold(
- "fs-profile-debug-bw-threshold", cl::init(10000),
- cl::desc("Only show debug message if the source branch weight is greater "
- " than this value."));
- static cl::opt<bool> ViewBFIBefore("fs-viewbfi-before", cl::Hidden,
- cl::init(false),
- cl::desc("View BFI before MIR loader"));
- static cl::opt<bool> ViewBFIAfter("fs-viewbfi-after", cl::Hidden,
- cl::init(false),
- cl::desc("View BFI after MIR loader"));
- char MIRProfileLoaderPass::ID = 0;
- INITIALIZE_PASS_BEGIN(MIRProfileLoaderPass, DEBUG_TYPE,
- "Load MIR Sample Profile",
- /* cfg = */ false, /* is_analysis = */ false)
- INITIALIZE_PASS_DEPENDENCY(MachineBlockFrequencyInfo)
- INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
- INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTree)
- INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
- INITIALIZE_PASS_DEPENDENCY(MachineOptimizationRemarkEmitterPass)
- INITIALIZE_PASS_END(MIRProfileLoaderPass, DEBUG_TYPE, "Load MIR Sample Profile",
- /* cfg = */ false, /* is_analysis = */ false)
- char &llvm::MIRProfileLoaderPassID = MIRProfileLoaderPass::ID;
- FunctionPass *llvm::createMIRProfileLoaderPass(std::string File,
- std::string RemappingFile,
- FSDiscriminatorPass P) {
- return new MIRProfileLoaderPass(File, RemappingFile, P);
- }
- namespace llvm {
- // Internal option used to control BFI display only after MBP pass.
- // Defined in CodeGen/MachineBlockFrequencyInfo.cpp:
- // -view-block-layout-with-bfi={none | fraction | integer | count}
- extern cl::opt<GVDAGType> ViewBlockLayoutWithBFI;
- // Command line option to specify the name of the function for CFG dump
- // Defined in Analysis/BlockFrequencyInfo.cpp: -view-bfi-func-name=
- extern cl::opt<std::string> ViewBlockFreqFuncName;
- namespace afdo_detail {
- template <> struct IRTraits<MachineBasicBlock> {
- using InstructionT = MachineInstr;
- using BasicBlockT = MachineBasicBlock;
- using FunctionT = MachineFunction;
- using BlockFrequencyInfoT = MachineBlockFrequencyInfo;
- using LoopT = MachineLoop;
- using LoopInfoPtrT = MachineLoopInfo *;
- using DominatorTreePtrT = MachineDominatorTree *;
- using PostDominatorTreePtrT = MachinePostDominatorTree *;
- using PostDominatorTreeT = MachinePostDominatorTree;
- using OptRemarkEmitterT = MachineOptimizationRemarkEmitter;
- using OptRemarkAnalysisT = MachineOptimizationRemarkAnalysis;
- using PredRangeT = iterator_range<std::vector<MachineBasicBlock *>::iterator>;
- using SuccRangeT = iterator_range<std::vector<MachineBasicBlock *>::iterator>;
- static Function &getFunction(MachineFunction &F) { return F.getFunction(); }
- static const MachineBasicBlock *getEntryBB(const MachineFunction *F) {
- return GraphTraits<const MachineFunction *>::getEntryNode(F);
- }
- static PredRangeT getPredecessors(MachineBasicBlock *BB) {
- return BB->predecessors();
- }
- static SuccRangeT getSuccessors(MachineBasicBlock *BB) {
- return BB->successors();
- }
- };
- } // namespace afdo_detail
- class MIRProfileLoader final
- : public SampleProfileLoaderBaseImpl<MachineBasicBlock> {
- public:
- void setInitVals(MachineDominatorTree *MDT, MachinePostDominatorTree *MPDT,
- MachineLoopInfo *MLI, MachineBlockFrequencyInfo *MBFI,
- MachineOptimizationRemarkEmitter *MORE) {
- DT = MDT;
- PDT = MPDT;
- LI = MLI;
- BFI = MBFI;
- ORE = MORE;
- }
- void setFSPass(FSDiscriminatorPass Pass) {
- P = Pass;
- LowBit = getFSPassBitBegin(P);
- HighBit = getFSPassBitEnd(P);
- assert(LowBit < HighBit && "HighBit needs to be greater than Lowbit");
- }
- MIRProfileLoader(StringRef Name, StringRef RemapName)
- : SampleProfileLoaderBaseImpl(std::string(Name), std::string(RemapName)) {
- }
- void setBranchProbs(MachineFunction &F);
- bool runOnFunction(MachineFunction &F);
- bool doInitialization(Module &M);
- bool isValid() const { return ProfileIsValid; }
- protected:
- friend class SampleCoverageTracker;
- /// Hold the information of the basic block frequency.
- MachineBlockFrequencyInfo *BFI;
- /// PassNum is the sequence number this pass is called, start from 1.
- FSDiscriminatorPass P;
- // LowBit in the FS discriminator used by this instance. Note the number is
- // 0-based. Base discrimnator use bit 0 to bit 11.
- unsigned LowBit;
- // HighwBit in the FS discriminator used by this instance. Note the number
- // is 0-based.
- unsigned HighBit;
- bool ProfileIsValid = true;
- };
- template <>
- void SampleProfileLoaderBaseImpl<
- MachineBasicBlock>::computeDominanceAndLoopInfo(MachineFunction &F) {}
- void MIRProfileLoader::setBranchProbs(MachineFunction &F) {
- LLVM_DEBUG(dbgs() << "\nPropagation complete. Setting branch probs\n");
- for (auto &BI : F) {
- MachineBasicBlock *BB = &BI;
- if (BB->succ_size() < 2)
- continue;
- const MachineBasicBlock *EC = EquivalenceClass[BB];
- uint64_t BBWeight = BlockWeights[EC];
- uint64_t SumEdgeWeight = 0;
- for (MachineBasicBlock *Succ : BB->successors()) {
- Edge E = std::make_pair(BB, Succ);
- SumEdgeWeight += EdgeWeights[E];
- }
- if (BBWeight != SumEdgeWeight) {
- LLVM_DEBUG(dbgs() << "BBweight is not equal to SumEdgeWeight: BBWWeight="
- << BBWeight << " SumEdgeWeight= " << SumEdgeWeight
- << "\n");
- BBWeight = SumEdgeWeight;
- }
- if (BBWeight == 0) {
- LLVM_DEBUG(dbgs() << "SKIPPED. All branch weights are zero.\n");
- continue;
- }
- #ifndef NDEBUG
- uint64_t BBWeightOrig = BBWeight;
- #endif
- uint32_t MaxWeight = std::numeric_limits<uint32_t>::max();
- uint32_t Factor = 1;
- if (BBWeight > MaxWeight) {
- Factor = BBWeight / MaxWeight + 1;
- BBWeight /= Factor;
- LLVM_DEBUG(dbgs() << "Scaling weights by " << Factor << "\n");
- }
- for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(),
- SE = BB->succ_end();
- SI != SE; ++SI) {
- MachineBasicBlock *Succ = *SI;
- Edge E = std::make_pair(BB, Succ);
- uint64_t EdgeWeight = EdgeWeights[E];
- EdgeWeight /= Factor;
- assert(BBWeight >= EdgeWeight &&
- "BBweight is larger than EdgeWeight -- should not happen.\n");
- BranchProbability OldProb = BFI->getMBPI()->getEdgeProbability(BB, SI);
- BranchProbability NewProb(EdgeWeight, BBWeight);
- if (OldProb == NewProb)
- continue;
- BB->setSuccProbability(SI, NewProb);
- #ifndef NDEBUG
- if (!ShowFSBranchProb)
- continue;
- bool Show = false;
- BranchProbability Diff;
- if (OldProb > NewProb)
- Diff = OldProb - NewProb;
- else
- Diff = NewProb - OldProb;
- Show = (Diff >= BranchProbability(FSProfileDebugProbDiffThreshold, 100));
- Show &= (BBWeightOrig >= FSProfileDebugBWThreshold);
- auto DIL = BB->findBranchDebugLoc();
- auto SuccDIL = Succ->findBranchDebugLoc();
- if (Show) {
- dbgs() << "Set branch fs prob: MBB (" << BB->getNumber() << " -> "
- << Succ->getNumber() << "): ";
- if (DIL)
- dbgs() << DIL->getFilename() << ":" << DIL->getLine() << ":"
- << DIL->getColumn();
- if (SuccDIL)
- dbgs() << "-->" << SuccDIL->getFilename() << ":" << SuccDIL->getLine()
- << ":" << SuccDIL->getColumn();
- dbgs() << " W=" << BBWeightOrig << " " << OldProb << " --> " << NewProb
- << "\n";
- }
- #endif
- }
- }
- }
- bool MIRProfileLoader::doInitialization(Module &M) {
- auto &Ctx = M.getContext();
- auto ReaderOrErr = sampleprof::SampleProfileReader::create(Filename, Ctx, P,
- RemappingFilename);
- if (std::error_code EC = ReaderOrErr.getError()) {
- std::string Msg = "Could not open profile: " + EC.message();
- Ctx.diagnose(DiagnosticInfoSampleProfile(Filename, Msg));
- return false;
- }
- Reader = std::move(ReaderOrErr.get());
- Reader->setModule(&M);
- ProfileIsValid = (Reader->read() == sampleprof_error::success);
- Reader->getSummary();
- return true;
- }
- bool MIRProfileLoader::runOnFunction(MachineFunction &MF) {
- Function &Func = MF.getFunction();
- clearFunctionData(false);
- Samples = Reader->getSamplesFor(Func);
- if (!Samples || Samples->empty())
- return false;
- if (getFunctionLoc(MF) == 0)
- return false;
- DenseSet<GlobalValue::GUID> InlinedGUIDs;
- bool Changed = computeAndPropagateWeights(MF, InlinedGUIDs);
- // Set the new BPI, BFI.
- setBranchProbs(MF);
- return Changed;
- }
- } // namespace llvm
- MIRProfileLoaderPass::MIRProfileLoaderPass(std::string FileName,
- std::string RemappingFileName,
- FSDiscriminatorPass P)
- : MachineFunctionPass(ID), ProfileFileName(FileName), P(P),
- MIRSampleLoader(
- std::make_unique<MIRProfileLoader>(FileName, RemappingFileName)) {
- LowBit = getFSPassBitBegin(P);
- HighBit = getFSPassBitEnd(P);
- assert(LowBit < HighBit && "HighBit needs to be greater than Lowbit");
- }
- bool MIRProfileLoaderPass::runOnMachineFunction(MachineFunction &MF) {
- if (!MIRSampleLoader->isValid())
- return false;
- LLVM_DEBUG(dbgs() << "MIRProfileLoader pass working on Func: "
- << MF.getFunction().getName() << "\n");
- MBFI = &getAnalysis<MachineBlockFrequencyInfo>();
- MIRSampleLoader->setInitVals(
- &getAnalysis<MachineDominatorTree>(),
- &getAnalysis<MachinePostDominatorTree>(), &getAnalysis<MachineLoopInfo>(),
- MBFI, &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE());
- MF.RenumberBlocks();
- if (ViewBFIBefore && ViewBlockLayoutWithBFI != GVDT_None &&
- (ViewBlockFreqFuncName.empty() ||
- MF.getFunction().getName().equals(ViewBlockFreqFuncName))) {
- MBFI->view("MIR_Prof_loader_b." + MF.getName(), false);
- }
- bool Changed = MIRSampleLoader->runOnFunction(MF);
- if (Changed)
- MBFI->calculate(MF, *MBFI->getMBPI(), *&getAnalysis<MachineLoopInfo>());
- if (ViewBFIAfter && ViewBlockLayoutWithBFI != GVDT_None &&
- (ViewBlockFreqFuncName.empty() ||
- MF.getFunction().getName().equals(ViewBlockFreqFuncName))) {
- MBFI->view("MIR_prof_loader_a." + MF.getName(), false);
- }
- return Changed;
- }
- bool MIRProfileLoaderPass::doInitialization(Module &M) {
- LLVM_DEBUG(dbgs() << "MIRProfileLoader pass working on Module " << M.getName()
- << "\n");
- MIRSampleLoader->setFSPass(P);
- return MIRSampleLoader->doInitialization(M);
- }
- void MIRProfileLoaderPass::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- AU.addRequired<MachineBlockFrequencyInfo>();
- AU.addRequired<MachineDominatorTree>();
- AU.addRequired<MachinePostDominatorTree>();
- AU.addRequiredTransitive<MachineLoopInfo>();
- AU.addRequired<MachineOptimizationRemarkEmitterPass>();
- MachineFunctionPass::getAnalysisUsage(AU);
- }
|