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/TargetTransformInfo.h" 14 #include "llvm/IR/Constants.h" 15 #include "llvm/IR/Instructions.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 21 #include <array> 22 23 using namespace llvm; 24 25 PreservedAnalyses CGProfilePass::run(Module &M, ModuleAnalysisManager &MAM) { 26 MapVector<std::pair<Function *, Function *>, uint64_t> Counts; 27 FunctionAnalysisManager &FAM = 28 MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 29 InstrProfSymtab Symtab; 30 auto UpdateCounts = [&](TargetTransformInfo &TTI, Function *F, 31 Function *CalledF, uint64_t NewCount) { 32 if (!CalledF || !TTI.isLoweredToCall(CalledF)) 33 return; 34 uint64_t &Count = Counts[std::make_pair(F, CalledF)]; 35 Count = SaturatingAdd(Count, NewCount); 36 }; 37 // Ignore error here. Indirect calls are ignored if this fails. 38 (void)(bool)Symtab.create(M); 39 for (auto &F : M) { 40 if (F.isDeclaration()) 41 continue; 42 auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F); 43 if (BFI.getEntryFreq() == 0) 44 continue; 45 TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F); 46 for (auto &BB : F) { 47 Optional<uint64_t> BBCount = BFI.getBlockProfileCount(&BB); 48 if (!BBCount) 49 continue; 50 for (auto &I : BB) { 51 CallBase *CB = dyn_cast<CallBase>(&I); 52 if (!CB) 53 continue; 54 if (CB->isIndirectCall()) { 55 InstrProfValueData ValueData[8]; 56 uint32_t ActualNumValueData; 57 uint64_t TotalC; 58 if (!getValueProfDataFromInst(*CB, IPVK_IndirectCallTarget, 8, 59 ValueData, ActualNumValueData, TotalC)) 60 continue; 61 for (const auto &VD : 62 ArrayRef<InstrProfValueData>(ValueData, ActualNumValueData)) { 63 UpdateCounts(TTI, &F, Symtab.getFunction(VD.Value), VD.Count); 64 } 65 continue; 66 } 67 UpdateCounts(TTI, &F, CB->getCalledFunction(), *BBCount); 68 } 69 } 70 } 71 72 addModuleFlags(M, Counts); 73 74 return PreservedAnalyses::all(); 75 } 76 77 void CGProfilePass::addModuleFlags( 78 Module &M, 79 MapVector<std::pair<Function *, Function *>, uint64_t> &Counts) const { 80 if (Counts.empty()) 81 return; 82 83 LLVMContext &Context = M.getContext(); 84 MDBuilder MDB(Context); 85 std::vector<Metadata *> Nodes; 86 87 for (auto E : Counts) { 88 Metadata *Vals[] = {ValueAsMetadata::get(E.first.first), 89 ValueAsMetadata::get(E.first.second), 90 MDB.createConstant(ConstantInt::get( 91 Type::getInt64Ty(Context), E.second))}; 92 Nodes.push_back(MDNode::get(Context, Vals)); 93 } 94 95 M.addModuleFlag(Module::Append, "CG Profile", MDNode::get(Context, Nodes)); 96 } 97