1 //===-- CGProfile.cpp -----------------------------------------------------===//
2 //
3 //                      The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/ADT/MapVector.h"
11 #include "llvm/Analysis/BlockFrequencyInfo.h"
12 #include "llvm/Analysis/BranchProbabilityInfo.h"
13 #include "llvm/IR/Constants.h"
14 #include "llvm/IR/Instructions.h"
15 #include "llvm/IR/MDBuilder.h"
16 #include "llvm/IR/PassManager.h"
17 #include "llvm/Transforms/Instrumentation.h"
18 
19 #include <array>
20 
21 using namespace llvm;
22 
23 class CGProfilePass : public ModulePass {
24 public:
25   static char ID;
26 
27   CGProfilePass() : ModulePass(ID) {
28     initializeCGProfilePassPass(*PassRegistry::getPassRegistry());
29   }
30 
31   StringRef getPassName() const override { return "CGProfilePass"; }
32 
33 private:
34   bool runOnModule(Module &M) override;
35   bool addModuleFlags(
36       Module &M,
37       MapVector<std::pair<Function *, Function *>, uint64_t> &Counts) const;
38 
39   void getAnalysisUsage(AnalysisUsage &AU) const override {
40     AU.addRequired<BlockFrequencyInfoWrapperPass>();
41     AU.addRequired<BranchProbabilityInfoWrapperPass>();
42   }
43 };
44 
45 bool CGProfilePass::runOnModule(Module &M) {
46   if (skipModule(M))
47     return false;
48 
49   MapVector<std::pair<Function *, Function *>, uint64_t> Counts;
50 
51   for (auto &F : M) {
52     if (F.isDeclaration())
53       continue;
54     getAnalysis<BranchProbabilityInfoWrapperPass>(F).getBPI();
55     auto &BFI = getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI();
56     for (const auto &BB : F) {
57       Optional<uint64_t> BBCount = BFI.getBlockProfileCount(&BB);
58       if (!BBCount)
59         continue;
60       for (const auto &I : BB) {
61         auto *CI = dyn_cast<CallInst>(&I);
62         if (!CI)
63           continue;
64         Function *CalledF = CI->getCalledFunction();
65         if (!CalledF || CalledF->isIntrinsic())
66           continue;
67 
68         uint64_t &Count = Counts[std::make_pair(&F, CalledF)];
69         Count = SaturatingAdd(Count, *BBCount);
70       }
71     }
72   }
73 
74   return addModuleFlags(M, Counts);
75 }
76 
77 bool CGProfilePass::addModuleFlags(
78     Module &M,
79     MapVector<std::pair<Function *, Function *>, uint64_t> &Counts) const {
80   if (Counts.empty())
81     return false;
82 
83   LLVMContext &Context = M.getContext();
84   MDBuilder MDB(Context);
85   std::vector<Metadata *> Nodes;
86 
87   for (auto E : Counts) {
88     SmallVector<Metadata *, 3> Vals;
89     Vals.push_back(ValueAsMetadata::get(E.first.first));
90     Vals.push_back(ValueAsMetadata::get(E.first.second));
91     Vals.push_back(MDB.createConstant(
92         ConstantInt::get(Type::getInt64Ty(Context), E.second)));
93     Nodes.push_back(MDNode::get(Context, Vals));
94   }
95 
96   M.addModuleFlag(Module::Append, "CG Profile", MDNode::get(Context, Nodes));
97   return true;
98 }
99 
100 char CGProfilePass::ID = 0;
101 INITIALIZE_PASS_BEGIN(CGProfilePass, "cg-profile",
102                       "Generate profile information from the call graph.",
103                       false, false)
104 INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
105 INITIALIZE_PASS_DEPENDENCY(BranchProbabilityInfoWrapperPass)
106 INITIALIZE_PASS_END(CGProfilePass, "cg-profile",
107                     "Generate profile information from the call graph.", false,
108                     false)
109 
110 ModulePass *llvm::createCGProfilePass() { return new CGProfilePass(); }
111