10b57cec5SDimitry Andric //===-- CGProfile.cpp -----------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation/CGProfile.h" 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include "llvm/ADT/MapVector.h" 120b57cec5SDimitry Andric #include "llvm/Analysis/BlockFrequencyInfo.h" 135ffd83dbSDimitry Andric #include "llvm/Analysis/LazyBlockFrequencyInfo.h" 140b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 150b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 160b57cec5SDimitry Andric #include "llvm/IR/MDBuilder.h" 17*0fca6ea1SDimitry Andric #include "llvm/IR/Module.h" 180b57cec5SDimitry Andric #include "llvm/IR/PassManager.h" 190b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProf.h" 200b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation.h" 21bdd1243dSDimitry Andric #include <optional> 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric using namespace llvm; 240b57cec5SDimitry Andric 255ffd83dbSDimitry Andric static bool 265ffd83dbSDimitry Andric addModuleFlags(Module &M, 275ffd83dbSDimitry Andric MapVector<std::pair<Function *, Function *>, uint64_t> &Counts) { 280b57cec5SDimitry Andric if (Counts.empty()) 295ffd83dbSDimitry Andric return false; 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric LLVMContext &Context = M.getContext(); 320b57cec5SDimitry Andric MDBuilder MDB(Context); 330b57cec5SDimitry Andric std::vector<Metadata *> Nodes; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric for (auto E : Counts) { 360b57cec5SDimitry Andric Metadata *Vals[] = {ValueAsMetadata::get(E.first.first), 370b57cec5SDimitry Andric ValueAsMetadata::get(E.first.second), 380b57cec5SDimitry Andric MDB.createConstant(ConstantInt::get( 390b57cec5SDimitry Andric Type::getInt64Ty(Context), E.second))}; 400b57cec5SDimitry Andric Nodes.push_back(MDNode::get(Context, Vals)); 410b57cec5SDimitry Andric } 420b57cec5SDimitry Andric 43753f127fSDimitry Andric M.addModuleFlag(Module::Append, "CG Profile", 44753f127fSDimitry Andric MDTuple::getDistinct(Context, Nodes)); 455ffd83dbSDimitry Andric return true; 465ffd83dbSDimitry Andric } 475ffd83dbSDimitry Andric 487a6dacacSDimitry Andric static bool runCGProfilePass(Module &M, FunctionAnalysisManager &FAM, 497a6dacacSDimitry Andric bool InLTO) { 505ffd83dbSDimitry Andric MapVector<std::pair<Function *, Function *>, uint64_t> Counts; 515ffd83dbSDimitry Andric InstrProfSymtab Symtab; 525ffd83dbSDimitry Andric auto UpdateCounts = [&](TargetTransformInfo &TTI, Function *F, 535ffd83dbSDimitry Andric Function *CalledF, uint64_t NewCount) { 54349cc55cSDimitry Andric if (NewCount == 0) 55349cc55cSDimitry Andric return; 56e8d8bef9SDimitry Andric if (!CalledF || !TTI.isLoweredToCall(CalledF) || 57e8d8bef9SDimitry Andric CalledF->hasDLLImportStorageClass()) 585ffd83dbSDimitry Andric return; 595ffd83dbSDimitry Andric uint64_t &Count = Counts[std::make_pair(F, CalledF)]; 605ffd83dbSDimitry Andric Count = SaturatingAdd(Count, NewCount); 615ffd83dbSDimitry Andric }; 625ffd83dbSDimitry Andric // Ignore error here. Indirect calls are ignored if this fails. 637a6dacacSDimitry Andric (void)(bool)Symtab.create(M, InLTO); 645ffd83dbSDimitry Andric for (auto &F : M) { 655ffd83dbSDimitry Andric // Avoid extra cost of running passes for BFI when the function doesn't have 6606c3fb27SDimitry Andric // entry count. 6706c3fb27SDimitry Andric if (F.isDeclaration() || !F.getEntryCount()) 685ffd83dbSDimitry Andric continue; 6906c3fb27SDimitry Andric auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F); 705f757f3fSDimitry Andric if (BFI.getEntryFreq() == BlockFrequency(0)) 715ffd83dbSDimitry Andric continue; 7206c3fb27SDimitry Andric TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F); 735ffd83dbSDimitry Andric for (auto &BB : F) { 74bdd1243dSDimitry Andric std::optional<uint64_t> BBCount = BFI.getBlockProfileCount(&BB); 755ffd83dbSDimitry Andric if (!BBCount) 765ffd83dbSDimitry Andric continue; 775ffd83dbSDimitry Andric for (auto &I : BB) { 785ffd83dbSDimitry Andric CallBase *CB = dyn_cast<CallBase>(&I); 795ffd83dbSDimitry Andric if (!CB) 805ffd83dbSDimitry Andric continue; 815ffd83dbSDimitry Andric if (CB->isIndirectCall()) { 825ffd83dbSDimitry Andric uint64_t TotalC; 83*0fca6ea1SDimitry Andric auto ValueData = 84*0fca6ea1SDimitry Andric getValueProfDataFromInst(*CB, IPVK_IndirectCallTarget, 8, TotalC); 85*0fca6ea1SDimitry Andric for (const auto &VD : ValueData) 865ffd83dbSDimitry Andric UpdateCounts(TTI, &F, Symtab.getFunction(VD.Value), VD.Count); 875ffd83dbSDimitry Andric continue; 885ffd83dbSDimitry Andric } 895ffd83dbSDimitry Andric UpdateCounts(TTI, &F, CB->getCalledFunction(), *BBCount); 905ffd83dbSDimitry Andric } 915ffd83dbSDimitry Andric } 925ffd83dbSDimitry Andric } 935ffd83dbSDimitry Andric 945ffd83dbSDimitry Andric return addModuleFlags(M, Counts); 955ffd83dbSDimitry Andric } 965ffd83dbSDimitry Andric 975ffd83dbSDimitry Andric PreservedAnalyses CGProfilePass::run(Module &M, ModuleAnalysisManager &MAM) { 985ffd83dbSDimitry Andric FunctionAnalysisManager &FAM = 995ffd83dbSDimitry Andric MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 1007a6dacacSDimitry Andric runCGProfilePass(M, FAM, InLTO); 1015ffd83dbSDimitry Andric 1025ffd83dbSDimitry Andric return PreservedAnalyses::all(); 1030b57cec5SDimitry Andric } 104