1 //===-- CGProfile.cpp -----------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Transforms/Instrumentation/CGProfile.h"
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/Instructions.h"
17 #include "llvm/IR/MDBuilder.h"
18 #include "llvm/IR/PassManager.h"
19 #include "llvm/InitializePasses.h"
20 #include "llvm/ProfileData/InstrProf.h"
21 #include "llvm/Transforms/Instrumentation.h"
28 addModuleFlags(Module
&M
,
29 MapVector
<std::pair
<Function
*, Function
*>, uint64_t> &Counts
) {
33 LLVMContext
&Context
= M
.getContext();
34 MDBuilder
MDB(Context
);
35 std::vector
<Metadata
*> Nodes
;
37 for (auto E
: Counts
) {
38 Metadata
*Vals
[] = {ValueAsMetadata::get(E
.first
.first
),
39 ValueAsMetadata::get(E
.first
.second
),
40 MDB
.createConstant(ConstantInt::get(
41 Type::getInt64Ty(Context
), E
.second
))};
42 Nodes
.push_back(MDNode::get(Context
, Vals
));
45 M
.addModuleFlag(Module::Append
, "CG Profile", MDNode::get(Context
, Nodes
));
49 static bool runCGProfilePass(
50 Module
&M
, function_ref
<BlockFrequencyInfo
&(Function
&)> GetBFI
,
51 function_ref
<TargetTransformInfo
&(Function
&)> GetTTI
, bool LazyBFI
) {
52 MapVector
<std::pair
<Function
*, Function
*>, uint64_t> Counts
;
53 InstrProfSymtab Symtab
;
54 auto UpdateCounts
= [&](TargetTransformInfo
&TTI
, Function
*F
,
55 Function
*CalledF
, uint64_t NewCount
) {
56 if (!CalledF
|| !TTI
.isLoweredToCall(CalledF
) ||
57 CalledF
->hasDLLImportStorageClass())
59 uint64_t &Count
= Counts
[std::make_pair(F
, CalledF
)];
60 Count
= SaturatingAdd(Count
, NewCount
);
62 // Ignore error here. Indirect calls are ignored if this fails.
63 (void)(bool) Symtab
.create(M
);
65 // Avoid extra cost of running passes for BFI when the function doesn't have
66 // entry count. Since LazyBlockFrequencyInfoPass only exists in LPM, check
67 // if using LazyBlockFrequencyInfoPass.
68 // TODO: Remove LazyBFI when LazyBlockFrequencyInfoPass is available in NPM.
69 if (F
.isDeclaration() || (LazyBFI
&& !F
.getEntryCount()))
71 auto &BFI
= GetBFI(F
);
72 if (BFI
.getEntryFreq() == 0)
74 TargetTransformInfo
&TTI
= GetTTI(F
);
76 Optional
<uint64_t> BBCount
= BFI
.getBlockProfileCount(&BB
);
80 CallBase
*CB
= dyn_cast
<CallBase
>(&I
);
83 if (CB
->isIndirectCall()) {
84 InstrProfValueData ValueData
[8];
85 uint32_t ActualNumValueData
;
87 if (!getValueProfDataFromInst(*CB
, IPVK_IndirectCallTarget
, 8,
88 ValueData
, ActualNumValueData
, TotalC
))
91 ArrayRef
<InstrProfValueData
>(ValueData
, ActualNumValueData
)) {
92 UpdateCounts(TTI
, &F
, Symtab
.getFunction(VD
.Value
), VD
.Count
);
96 UpdateCounts(TTI
, &F
, CB
->getCalledFunction(), *BBCount
);
101 return addModuleFlags(M
, Counts
);
105 struct CGProfileLegacyPass final
: public ModulePass
{
107 CGProfileLegacyPass() : ModulePass(ID
) {
108 initializeCGProfileLegacyPassPass(*PassRegistry::getPassRegistry());
111 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
112 AU
.setPreservesCFG();
113 AU
.addRequired
<LazyBlockFrequencyInfoPass
>();
114 AU
.addRequired
<TargetTransformInfoWrapperPass
>();
117 bool runOnModule(Module
&M
) override
{
118 auto GetBFI
= [this](Function
&F
) -> BlockFrequencyInfo
& {
119 return this->getAnalysis
<LazyBlockFrequencyInfoPass
>(F
).getBFI();
121 auto GetTTI
= [this](Function
&F
) -> TargetTransformInfo
& {
122 return this->getAnalysis
<TargetTransformInfoWrapperPass
>().getTTI(F
);
125 return runCGProfilePass(M
, GetBFI
, GetTTI
, true);
131 char CGProfileLegacyPass::ID
= 0;
133 INITIALIZE_PASS(CGProfileLegacyPass
, "cg-profile", "Call Graph Profile", false,
136 ModulePass
*llvm::createCGProfileLegacyPass() {
137 return new CGProfileLegacyPass();
140 PreservedAnalyses
CGProfilePass::run(Module
&M
, ModuleAnalysisManager
&MAM
) {
141 FunctionAnalysisManager
&FAM
=
142 MAM
.getResult
<FunctionAnalysisManagerModuleProxy
>(M
).getManager();
143 auto GetBFI
= [&FAM
](Function
&F
) -> BlockFrequencyInfo
& {
144 return FAM
.getResult
<BlockFrequencyAnalysis
>(F
);
146 auto GetTTI
= [&FAM
](Function
&F
) -> TargetTransformInfo
& {
147 return FAM
.getResult
<TargetIRAnalysis
>(F
);
150 runCGProfilePass(M
, GetBFI
, GetTTI
, false);
152 return PreservedAnalyses::all();