brintos

brintos / llvm-project-archived public Read only

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