Coverage Report

Created: 2024-01-17 10:31

/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
}