blob: 358abab3cceb76fa7f75742e6ecafb07058d1a36 [file] [log] [blame]
Michael J. Spencer7bb27672018-07-16 00:28:24 +00001//===-- CGProfile.cpp -----------------------------------------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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-exception
Michael J. Spencer7bb27672018-07-16 00:28:24 +00006//
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/TargetTransformInfo.h"
14#include "llvm/IR/CallSite.h"
15#include "llvm/IR/Constants.h"
16#include "llvm/IR/Instructions.h"
17#include "llvm/IR/MDBuilder.h"
18#include "llvm/IR/PassManager.h"
19#include "llvm/ProfileData/InstrProf.h"
20#include "llvm/Transforms/Instrumentation.h"
21
22#include <array>
23
24using namespace llvm;
25
26PreservedAnalyses CGProfilePass::run(Module &M, ModuleAnalysisManager &MAM) {
27 MapVector<std::pair<Function *, Function *>, uint64_t> Counts;
28 FunctionAnalysisManager &FAM =
29 MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
30 InstrProfSymtab Symtab;
31 auto UpdateCounts = [&](TargetTransformInfo &TTI, Function *F,
32 Function *CalledF, uint64_t NewCount) {
33 if (!CalledF || !TTI.isLoweredToCall(CalledF))
34 return;
35 uint64_t &Count = Counts[std::make_pair(F, CalledF)];
36 Count = SaturatingAdd(Count, NewCount);
37 };
38 // Ignore error here. Indirect calls are ignored if this fails.
39 (void)(bool)Symtab.create(M);
40 for (auto &F : M) {
41 if (F.isDeclaration())
42 continue;
43 auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);
44 if (BFI.getEntryFreq() == 0)
45 continue;
46 TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F);
47 for (auto &BB : F) {
48 Optional<uint64_t> BBCount = BFI.getBlockProfileCount(&BB);
49 if (!BBCount)
50 continue;
51 for (auto &I : BB) {
52 CallSite CS(&I);
53 if (!CS)
54 continue;
55 if (CS.isIndirectCall()) {
56 InstrProfValueData ValueData[8];
57 uint32_t ActualNumValueData;
58 uint64_t TotalC;
59 if (!getValueProfDataFromInst(*CS.getInstruction(),
60 IPVK_IndirectCallTarget, 8, ValueData,
61 ActualNumValueData, TotalC))
62 continue;
63 for (const auto &VD :
64 ArrayRef<InstrProfValueData>(ValueData, ActualNumValueData)) {
65 UpdateCounts(TTI, &F, Symtab.getFunction(VD.Value), VD.Count);
66 }
67 continue;
68 }
69 UpdateCounts(TTI, &F, CS.getCalledFunction(), *BBCount);
70 }
71 }
72 }
73
74 addModuleFlags(M, Counts);
75
76 return PreservedAnalyses::all();
77}
78
79void CGProfilePass::addModuleFlags(
80 Module &M,
81 MapVector<std::pair<Function *, Function *>, uint64_t> &Counts) const {
82 if (Counts.empty())
83 return;
84
85 LLVMContext &Context = M.getContext();
86 MDBuilder MDB(Context);
87 std::vector<Metadata *> Nodes;
88
89 for (auto E : Counts) {
Benjamin Kramer3e778162018-10-22 10:51:34 +000090 Metadata *Vals[] = {ValueAsMetadata::get(E.first.first),
91 ValueAsMetadata::get(E.first.second),
92 MDB.createConstant(ConstantInt::get(
93 Type::getInt64Ty(Context), E.second))};
Michael J. Spencer7bb27672018-07-16 00:28:24 +000094 Nodes.push_back(MDNode::get(Context, Vals));
95 }
96
97 M.addModuleFlag(Module::Append, "CG Profile", MDNode::get(Context, Nodes));
98}