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