Index: include/llvm/ProfileData/SampleProf.h =================================================================== --- include/llvm/ProfileData/SampleProf.h +++ include/llvm/ProfileData/SampleProf.h @@ -237,6 +237,14 @@ return T; } + ErrorOr + findCallTargetMapAt(uint32_t LineOffset, uint32_t Discriminator) const { + const auto &ret = BodySamples.find(LineLocation(LineOffset, Discriminator)); + if (ret == BodySamples.end()) + return std::error_code(); + return ret->second.getCallTargets(); + } + /// Return the function samples at the given callsite location. FunctionSamples &functionSamplesAt(const LineLocation &Loc) { return CallsiteSamples[Loc]; Index: lib/Transforms/IPO/SampleProfile.cpp =================================================================== --- lib/Transforms/IPO/SampleProfile.cpp +++ lib/Transforms/IPO/SampleProfile.cpp @@ -35,6 +35,7 @@ #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" +#include "llvm/IR/GlobalValue.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" @@ -43,6 +44,7 @@ #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/Pass.h" +#include "llvm/ProfileData/InstrProf.h" #include "llvm/ProfileData/SampleProfReader.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -992,6 +994,29 @@ } } +/// Sorts the CallTargetMap \p M by count in descending order and stores the +/// sorted result in \p Sorted. Returns the total counts. +static uint64_t +SortCallTargets(SmallVector, 2> &Sorted, + const SampleRecord::CallTargetMap &M) { + Sorted.clear(); + uint64_t Sum = 0; + for (auto I = M.begin(); I != M.end(); ++I) { + Sum += I->getValue(); + Sorted.push_back( + std::make_pair(Function::getGUID(I->getKey()), I->getValue())); + } + std::sort(Sorted.begin(), Sorted.end(), + [](const std::pair &L, + const std::pair &R) { + if (L.second == R.second) + return L.first > R.first; + else + return L.second > R.second; + }); + return Sum; +} + /// \brief Propagate weights into edges /// /// The following rules are applied to every block BB in the CFG: @@ -1069,13 +1094,49 @@ if (BlockWeights[BB]) { for (auto &I : BB->getInstList()) { - if (CallInst *CI = dyn_cast(&I)) { - if (!dyn_cast(&I)) { - SmallVector Weights; - Weights.push_back(BlockWeights[BB]); - CI->setMetadata(LLVMContext::MD_prof, - MDB.createBranchWeights(Weights)); + if (!isa(I) && !isa(I)) + continue; + CallSite CS(&I); + if (!CS.getCalledFunction()) { + const DebugLoc &DLoc = I.getDebugLoc(); + if (!DLoc) + continue; + const DILocation *DIL = DLoc; + unsigned Lineno = DLoc.getLine(); + unsigned HeaderLineno = DIL->getScope()->getSubprogram()->getLine(); + uint32_t LineOffset = getOffset(Lineno, HeaderLineno); + uint32_t Discriminator = DIL->getDiscriminator(); + + const FunctionSamples *FS = findFunctionSamples(I); + if (!FS) + continue; + auto T = FS->findCallTargetMapAt(LineOffset, Discriminator); + if (!T || T.get().size() == 0) + continue; + SmallVector, 2> SortedCallTargets; + uint64_t Sum = SortCallTargets(SortedCallTargets, T.get()); + LLVMContext &Ctx = I.getParent()->getParent()->getContext(); + MDBuilder MDHelper(Ctx); + SmallVector Vals; + // Tag + Vals.push_back(MDHelper.createString("VP")); + // Value Kind + Vals.push_back(MDHelper.createConstant(ConstantInt::get( + Type::getInt32Ty(Ctx), IPVK_IndirectCallTarget))); + // Total Count + Vals.push_back(MDHelper.createConstant( + ConstantInt::get(Type::getInt64Ty(Ctx), Sum))); + for (const auto &T_C : SortedCallTargets) { + Vals.push_back(MDHelper.createConstant( + ConstantInt::get(Type::getInt64Ty(Ctx), T_C.first))); + Vals.push_back(MDHelper.createConstant( + ConstantInt::get(Type::getInt64Ty(Ctx), T_C.second))); } + I.setMetadata(LLVMContext::MD_prof, MDNode::get(Ctx, Vals)); + } else if (!dyn_cast(&I)) { + SmallVector Weights; + Weights.push_back(BlockWeights[BB]); + I.setMetadata(LLVMContext::MD_prof, MDB.createBranchWeights(Weights)); } } } Index: test/Transforms/SampleProfile/Inputs/indirect-call.prof =================================================================== --- /dev/null +++ test/Transforms/SampleProfile/Inputs/indirect-call.prof @@ -0,0 +1,2 @@ +test:63067:0 + 4: 3345 _Z3foov:2059 _Z3barv:1398 Index: test/Transforms/SampleProfile/indirect-call.ll =================================================================== --- /dev/null +++ test/Transforms/SampleProfile/indirect-call.ll @@ -0,0 +1,20 @@ +; RUN: opt < %s -sample-profile -sample-profile-file=%S/Inputs/indirect-call.prof -S | FileCheck %s + +define void @test(void ()*) !dbg !3 { + %2 = alloca void ()* + store void ()* %0, void ()** %2 + %3 = load void ()*, void ()** %2 + ; CHECK: call {{.*}}, !prof ![[PROF:[0-9]+]] + call void %3(), !dbg !4 + ret void +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1) +!1 = !DIFile(filename: "test.cc", directory: "/") +!2 = !{i32 2, !"Debug Info Version", i32 3} +!3 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 1, unit: !0) +!4 = !DILocation(line: 5, scope: !3) +; CHECK: ![[PROF]] = !{!"VP", i32 0, i64 3457, i64 9191153033785521275, i64 2059, i64 -1069303473483922844, i64 1398}