xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Instrumentation/CGProfile.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- CGProfile.cpp -----------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation/CGProfile.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "llvm/ADT/MapVector.h"
120b57cec5SDimitry Andric #include "llvm/Analysis/BlockFrequencyInfo.h"
135ffd83dbSDimitry Andric #include "llvm/Analysis/LazyBlockFrequencyInfo.h"
140b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
150b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
160b57cec5SDimitry Andric #include "llvm/IR/MDBuilder.h"
17*0fca6ea1SDimitry Andric #include "llvm/IR/Module.h"
180b57cec5SDimitry Andric #include "llvm/IR/PassManager.h"
190b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProf.h"
200b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation.h"
21bdd1243dSDimitry Andric #include <optional>
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric using namespace llvm;
240b57cec5SDimitry Andric 
255ffd83dbSDimitry Andric static bool
265ffd83dbSDimitry Andric addModuleFlags(Module &M,
275ffd83dbSDimitry Andric                MapVector<std::pair<Function *, Function *>, uint64_t> &Counts) {
280b57cec5SDimitry Andric   if (Counts.empty())
295ffd83dbSDimitry Andric     return false;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric   LLVMContext &Context = M.getContext();
320b57cec5SDimitry Andric   MDBuilder MDB(Context);
330b57cec5SDimitry Andric   std::vector<Metadata *> Nodes;
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric   for (auto E : Counts) {
360b57cec5SDimitry Andric     Metadata *Vals[] = {ValueAsMetadata::get(E.first.first),
370b57cec5SDimitry Andric                         ValueAsMetadata::get(E.first.second),
380b57cec5SDimitry Andric                         MDB.createConstant(ConstantInt::get(
390b57cec5SDimitry Andric                             Type::getInt64Ty(Context), E.second))};
400b57cec5SDimitry Andric     Nodes.push_back(MDNode::get(Context, Vals));
410b57cec5SDimitry Andric   }
420b57cec5SDimitry Andric 
43753f127fSDimitry Andric   M.addModuleFlag(Module::Append, "CG Profile",
44753f127fSDimitry Andric                   MDTuple::getDistinct(Context, Nodes));
455ffd83dbSDimitry Andric   return true;
465ffd83dbSDimitry Andric }
475ffd83dbSDimitry Andric 
487a6dacacSDimitry Andric static bool runCGProfilePass(Module &M, FunctionAnalysisManager &FAM,
497a6dacacSDimitry Andric                              bool InLTO) {
505ffd83dbSDimitry Andric   MapVector<std::pair<Function *, Function *>, uint64_t> Counts;
515ffd83dbSDimitry Andric   InstrProfSymtab Symtab;
525ffd83dbSDimitry Andric   auto UpdateCounts = [&](TargetTransformInfo &TTI, Function *F,
535ffd83dbSDimitry Andric                           Function *CalledF, uint64_t NewCount) {
54349cc55cSDimitry Andric     if (NewCount == 0)
55349cc55cSDimitry Andric       return;
56e8d8bef9SDimitry Andric     if (!CalledF || !TTI.isLoweredToCall(CalledF) ||
57e8d8bef9SDimitry Andric         CalledF->hasDLLImportStorageClass())
585ffd83dbSDimitry Andric       return;
595ffd83dbSDimitry Andric     uint64_t &Count = Counts[std::make_pair(F, CalledF)];
605ffd83dbSDimitry Andric     Count = SaturatingAdd(Count, NewCount);
615ffd83dbSDimitry Andric   };
625ffd83dbSDimitry Andric   // Ignore error here.  Indirect calls are ignored if this fails.
637a6dacacSDimitry Andric   (void)(bool)Symtab.create(M, InLTO);
645ffd83dbSDimitry Andric   for (auto &F : M) {
655ffd83dbSDimitry Andric     // Avoid extra cost of running passes for BFI when the function doesn't have
6606c3fb27SDimitry Andric     // entry count.
6706c3fb27SDimitry Andric     if (F.isDeclaration() || !F.getEntryCount())
685ffd83dbSDimitry Andric       continue;
6906c3fb27SDimitry Andric     auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);
705f757f3fSDimitry Andric     if (BFI.getEntryFreq() == BlockFrequency(0))
715ffd83dbSDimitry Andric       continue;
7206c3fb27SDimitry Andric     TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F);
735ffd83dbSDimitry Andric     for (auto &BB : F) {
74bdd1243dSDimitry Andric       std::optional<uint64_t> BBCount = BFI.getBlockProfileCount(&BB);
755ffd83dbSDimitry Andric       if (!BBCount)
765ffd83dbSDimitry Andric         continue;
775ffd83dbSDimitry Andric       for (auto &I : BB) {
785ffd83dbSDimitry Andric         CallBase *CB = dyn_cast<CallBase>(&I);
795ffd83dbSDimitry Andric         if (!CB)
805ffd83dbSDimitry Andric           continue;
815ffd83dbSDimitry Andric         if (CB->isIndirectCall()) {
825ffd83dbSDimitry Andric           uint64_t TotalC;
83*0fca6ea1SDimitry Andric           auto ValueData =
84*0fca6ea1SDimitry Andric               getValueProfDataFromInst(*CB, IPVK_IndirectCallTarget, 8, TotalC);
85*0fca6ea1SDimitry Andric           for (const auto &VD : ValueData)
865ffd83dbSDimitry Andric             UpdateCounts(TTI, &F, Symtab.getFunction(VD.Value), VD.Count);
875ffd83dbSDimitry Andric           continue;
885ffd83dbSDimitry Andric         }
895ffd83dbSDimitry Andric         UpdateCounts(TTI, &F, CB->getCalledFunction(), *BBCount);
905ffd83dbSDimitry Andric       }
915ffd83dbSDimitry Andric     }
925ffd83dbSDimitry Andric   }
935ffd83dbSDimitry Andric 
945ffd83dbSDimitry Andric   return addModuleFlags(M, Counts);
955ffd83dbSDimitry Andric }
965ffd83dbSDimitry Andric 
975ffd83dbSDimitry Andric PreservedAnalyses CGProfilePass::run(Module &M, ModuleAnalysisManager &MAM) {
985ffd83dbSDimitry Andric   FunctionAnalysisManager &FAM =
995ffd83dbSDimitry Andric       MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
1007a6dacacSDimitry Andric   runCGProfilePass(M, FAM, InLTO);
1015ffd83dbSDimitry Andric 
1025ffd83dbSDimitry Andric   return PreservedAnalyses::all();
1030b57cec5SDimitry Andric }
104