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