Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/Instrumentation/CGProfile.cpp
35266 views
//===-- CGProfile.cpp -----------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/Transforms/Instrumentation/CGProfile.h"910#include "llvm/ADT/MapVector.h"11#include "llvm/Analysis/BlockFrequencyInfo.h"12#include "llvm/Analysis/LazyBlockFrequencyInfo.h"13#include "llvm/Analysis/TargetTransformInfo.h"14#include "llvm/IR/Constants.h"15#include "llvm/IR/MDBuilder.h"16#include "llvm/IR/Module.h"17#include "llvm/IR/PassManager.h"18#include "llvm/ProfileData/InstrProf.h"19#include "llvm/Transforms/Instrumentation.h"20#include <optional>2122using namespace llvm;2324static bool25addModuleFlags(Module &M,26MapVector<std::pair<Function *, Function *>, uint64_t> &Counts) {27if (Counts.empty())28return false;2930LLVMContext &Context = M.getContext();31MDBuilder MDB(Context);32std::vector<Metadata *> Nodes;3334for (auto E : Counts) {35Metadata *Vals[] = {ValueAsMetadata::get(E.first.first),36ValueAsMetadata::get(E.first.second),37MDB.createConstant(ConstantInt::get(38Type::getInt64Ty(Context), E.second))};39Nodes.push_back(MDNode::get(Context, Vals));40}4142M.addModuleFlag(Module::Append, "CG Profile",43MDTuple::getDistinct(Context, Nodes));44return true;45}4647static bool runCGProfilePass(Module &M, FunctionAnalysisManager &FAM,48bool InLTO) {49MapVector<std::pair<Function *, Function *>, uint64_t> Counts;50InstrProfSymtab Symtab;51auto UpdateCounts = [&](TargetTransformInfo &TTI, Function *F,52Function *CalledF, uint64_t NewCount) {53if (NewCount == 0)54return;55if (!CalledF || !TTI.isLoweredToCall(CalledF) ||56CalledF->hasDLLImportStorageClass())57return;58uint64_t &Count = Counts[std::make_pair(F, CalledF)];59Count = SaturatingAdd(Count, NewCount);60};61// Ignore error here. Indirect calls are ignored if this fails.62(void)(bool)Symtab.create(M, InLTO);63for (auto &F : M) {64// Avoid extra cost of running passes for BFI when the function doesn't have65// entry count.66if (F.isDeclaration() || !F.getEntryCount())67continue;68auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);69if (BFI.getEntryFreq() == BlockFrequency(0))70continue;71TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F);72for (auto &BB : F) {73std::optional<uint64_t> BBCount = BFI.getBlockProfileCount(&BB);74if (!BBCount)75continue;76for (auto &I : BB) {77CallBase *CB = dyn_cast<CallBase>(&I);78if (!CB)79continue;80if (CB->isIndirectCall()) {81uint64_t TotalC;82auto ValueData =83getValueProfDataFromInst(*CB, IPVK_IndirectCallTarget, 8, TotalC);84for (const auto &VD : ValueData)85UpdateCounts(TTI, &F, Symtab.getFunction(VD.Value), VD.Count);86continue;87}88UpdateCounts(TTI, &F, CB->getCalledFunction(), *BBCount);89}90}91}9293return addModuleFlags(M, Counts);94}9596PreservedAnalyses CGProfilePass::run(Module &M, ModuleAnalysisManager &MAM) {97FunctionAnalysisManager &FAM =98MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();99runCGProfilePass(M, FAM, InLTO);100101return PreservedAnalyses::all();102}103104105