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