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