]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/Transforms/Instrumentation/CGProfile.cpp
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / lib / Transforms / Instrumentation / CGProfile.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-exception
6 //
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
24 using namespace llvm;
25
26 PreservedAnalyses 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
79 void 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) {
90     Metadata *Vals[] = {ValueAsMetadata::get(E.first.first),
91                         ValueAsMetadata::get(E.first.second),
92                         MDB.createConstant(ConstantInt::get(
93                             Type::getInt64Ty(Context), E.second))};
94     Nodes.push_back(MDNode::get(Context, Vals));
95   }
96
97   M.addModuleFlag(Module::Append, "CG Profile", MDNode::get(Context, Nodes));
98 }