17bb2767fSMichael J. Spencer //===-- CGProfile.cpp -----------------------------------------------------===//
27bb2767fSMichael J. Spencer //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67bb2767fSMichael J. Spencer //
77bb2767fSMichael J. Spencer //===----------------------------------------------------------------------===//
87bb2767fSMichael J. Spencer 
97bb2767fSMichael J. Spencer #include "llvm/Transforms/Instrumentation/CGProfile.h"
100128b950SSimon Pilgrim 
117bb2767fSMichael J. Spencer #include "llvm/ADT/MapVector.h"
127bb2767fSMichael J. Spencer #include "llvm/Analysis/BlockFrequencyInfo.h"
131fbb7194SZequan Wu #include "llvm/Analysis/LazyBlockFrequencyInfo.h"
147bb2767fSMichael J. Spencer #include "llvm/Analysis/TargetTransformInfo.h"
157bb2767fSMichael J. Spencer #include "llvm/IR/Constants.h"
167bb2767fSMichael J. Spencer #include "llvm/IR/MDBuilder.h"
177bb2767fSMichael J. Spencer #include "llvm/IR/PassManager.h"
181fbb7194SZequan Wu #include "llvm/InitializePasses.h"
197bb2767fSMichael J. Spencer #include "llvm/ProfileData/InstrProf.h"
207bb2767fSMichael J. Spencer #include "llvm/Transforms/Instrumentation.h"
210128b950SSimon Pilgrim 
227bb2767fSMichael J. Spencer using namespace llvm;
237bb2767fSMichael J. Spencer 
241fbb7194SZequan Wu static bool
addModuleFlags(Module & M,MapVector<std::pair<Function *,Function * >,uint64_t> & Counts)251fbb7194SZequan Wu addModuleFlags(Module &M,
261fbb7194SZequan Wu                MapVector<std::pair<Function *, Function *>, uint64_t> &Counts) {
271fbb7194SZequan Wu   if (Counts.empty())
281fbb7194SZequan Wu     return false;
291fbb7194SZequan Wu 
301fbb7194SZequan Wu   LLVMContext &Context = M.getContext();
311fbb7194SZequan Wu   MDBuilder MDB(Context);
321fbb7194SZequan Wu   std::vector<Metadata *> Nodes;
331fbb7194SZequan Wu 
341fbb7194SZequan Wu   for (auto E : Counts) {
351fbb7194SZequan Wu     Metadata *Vals[] = {ValueAsMetadata::get(E.first.first),
361fbb7194SZequan Wu                         ValueAsMetadata::get(E.first.second),
371fbb7194SZequan Wu                         MDB.createConstant(ConstantInt::get(
381fbb7194SZequan Wu                             Type::getInt64Ty(Context), E.second))};
391fbb7194SZequan Wu     Nodes.push_back(MDNode::get(Context, Vals));
401fbb7194SZequan Wu   }
411fbb7194SZequan Wu 
42*ff87ee4dSWolfgang Pieb   M.addModuleFlag(Module::Append, "CG Profile",
43*ff87ee4dSWolfgang Pieb                   MDTuple::getDistinct(Context, Nodes));
441fbb7194SZequan Wu   return true;
451fbb7194SZequan Wu }
461fbb7194SZequan Wu 
runCGProfilePass(Module & M,function_ref<BlockFrequencyInfo & (Function &)> GetBFI,function_ref<TargetTransformInfo & (Function &)> GetTTI,bool LazyBFI)471fbb7194SZequan Wu static bool runCGProfilePass(
481fbb7194SZequan Wu     Module &M, function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
491fbb7194SZequan Wu     function_ref<TargetTransformInfo &(Function &)> GetTTI, bool LazyBFI) {
507bb2767fSMichael J. Spencer   MapVector<std::pair<Function *, Function *>, uint64_t> Counts;
517bb2767fSMichael J. Spencer   InstrProfSymtab Symtab;
527bb2767fSMichael J. Spencer   auto UpdateCounts = [&](TargetTransformInfo &TTI, Function *F,
537bb2767fSMichael J. Spencer                           Function *CalledF, uint64_t NewCount) {
54793b481fSLeonard Grey     if (NewCount == 0)
55793b481fSLeonard Grey       return;
56f5435399SZequan Wu     if (!CalledF || !TTI.isLoweredToCall(CalledF) ||
57f5435399SZequan Wu         CalledF->hasDLLImportStorageClass())
587bb2767fSMichael J. Spencer       return;
597bb2767fSMichael J. Spencer     uint64_t &Count = Counts[std::make_pair(F, CalledF)];
607bb2767fSMichael J. Spencer     Count = SaturatingAdd(Count, NewCount);
617bb2767fSMichael J. Spencer   };
627bb2767fSMichael J. Spencer   // Ignore error here.  Indirect calls are ignored if this fails.
637bb2767fSMichael J. Spencer   (void)(bool) Symtab.create(M);
647bb2767fSMichael J. Spencer   for (auto &F : M) {
651fbb7194SZequan Wu     // Avoid extra cost of running passes for BFI when the function doesn't have
661fbb7194SZequan Wu     // entry count. Since LazyBlockFrequencyInfoPass only exists in LPM, check
671fbb7194SZequan Wu     // if using LazyBlockFrequencyInfoPass.
681fbb7194SZequan Wu     // TODO: Remove LazyBFI when LazyBlockFrequencyInfoPass is available in NPM.
691fbb7194SZequan Wu     if (F.isDeclaration() || (LazyBFI && !F.getEntryCount()))
707bb2767fSMichael J. Spencer       continue;
711fbb7194SZequan Wu     auto &BFI = GetBFI(F);
727bb2767fSMichael J. Spencer     if (BFI.getEntryFreq() == 0)
737bb2767fSMichael J. Spencer       continue;
741fbb7194SZequan Wu     TargetTransformInfo &TTI = GetTTI(F);
757bb2767fSMichael J. Spencer     for (auto &BB : F) {
767bb2767fSMichael J. Spencer       Optional<uint64_t> BBCount = BFI.getBlockProfileCount(&BB);
777bb2767fSMichael J. Spencer       if (!BBCount)
787bb2767fSMichael J. Spencer         continue;
797bb2767fSMichael J. Spencer       for (auto &I : BB) {
801b6b05a2SMircea Trofin         CallBase *CB = dyn_cast<CallBase>(&I);
811b6b05a2SMircea Trofin         if (!CB)
827bb2767fSMichael J. Spencer           continue;
831b6b05a2SMircea Trofin         if (CB->isIndirectCall()) {
847bb2767fSMichael J. Spencer           InstrProfValueData ValueData[8];
857bb2767fSMichael J. Spencer           uint32_t ActualNumValueData;
867bb2767fSMichael J. Spencer           uint64_t TotalC;
871b6b05a2SMircea Trofin           if (!getValueProfDataFromInst(*CB, IPVK_IndirectCallTarget, 8,
881b6b05a2SMircea Trofin                                         ValueData, ActualNumValueData, TotalC))
897bb2767fSMichael J. Spencer             continue;
907bb2767fSMichael J. Spencer           for (const auto &VD :
917bb2767fSMichael J. Spencer                ArrayRef<InstrProfValueData>(ValueData, ActualNumValueData)) {
927bb2767fSMichael J. Spencer             UpdateCounts(TTI, &F, Symtab.getFunction(VD.Value), VD.Count);
937bb2767fSMichael J. Spencer           }
947bb2767fSMichael J. Spencer           continue;
957bb2767fSMichael J. Spencer         }
961b6b05a2SMircea Trofin         UpdateCounts(TTI, &F, CB->getCalledFunction(), *BBCount);
977bb2767fSMichael J. Spencer       }
987bb2767fSMichael J. Spencer     }
997bb2767fSMichael J. Spencer   }
1007bb2767fSMichael J. Spencer 
1011fbb7194SZequan Wu   return addModuleFlags(M, Counts);
1021fbb7194SZequan Wu }
1031fbb7194SZequan Wu 
run(Module & M,ModuleAnalysisManager & MAM)1041fbb7194SZequan Wu PreservedAnalyses CGProfilePass::run(Module &M, ModuleAnalysisManager &MAM) {
1051fbb7194SZequan Wu   FunctionAnalysisManager &FAM =
1061fbb7194SZequan Wu       MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
1071fbb7194SZequan Wu   auto GetBFI = [&FAM](Function &F) -> BlockFrequencyInfo & {
1081fbb7194SZequan Wu     return FAM.getResult<BlockFrequencyAnalysis>(F);
1091fbb7194SZequan Wu   };
1101fbb7194SZequan Wu   auto GetTTI = [&FAM](Function &F) -> TargetTransformInfo & {
1111fbb7194SZequan Wu     return FAM.getResult<TargetIRAnalysis>(F);
1121fbb7194SZequan Wu   };
1131fbb7194SZequan Wu 
1141fbb7194SZequan Wu   runCGProfilePass(M, GetBFI, GetTTI, false);
1157bb2767fSMichael J. Spencer 
1167bb2767fSMichael J. Spencer   return PreservedAnalyses::all();
1177bb2767fSMichael J. Spencer }
118