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
addModuleFlags(Module & M,MapVector<std::pair<Function *,Function * >,uint64_t> & Counts)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
runCGProfilePass(Module & M,FunctionAnalysisManager & FAM,bool InLTO)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
run(Module & M,ModuleAnalysisManager & MAM)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