Index: lib/Transforms/Instrumentation/PGOInstrumentation.cpp =================================================================== --- lib/Transforms/Instrumentation/PGOInstrumentation.cpp +++ lib/Transforms/Instrumentation/PGOInstrumentation.cpp @@ -53,6 +53,7 @@ #include "llvm/Analysis/BlockFrequencyInfo.h" #include "llvm/Analysis/BranchProbabilityInfo.h" #include "llvm/Analysis/CFG.h" +#include "llvm/IR/CallSite.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstIterator.h" @@ -81,6 +82,7 @@ STATISTIC(NumOfPGOFunc, "Number of functions having valid profile counts."); STATISTIC(NumOfPGOMismatch, "Number of functions having mismatch profile."); STATISTIC(NumOfPGOMissing, "Number of functions without profile."); +STATISTIC(NumOfPGOICall, "Number of indirect call value instrumentation."); // Command line option to specify the file to read profile from. This is // mainly used for testing. @@ -90,6 +92,12 @@ cl::desc("Specify the path of profile data file. This is" "mainly for test purpose.")); +// Command line options to disable value profiling. The default is false: +// i.e. vaule profiling is enabled by default. This is for debug purpose. +static cl::opt +DisableValueProfiling("disable-vp", cl::init(false), cl::Hidden, + cl::desc("Disable Value Profiling")); + namespace { class PGOInstrumentationGen : public ModulePass { public: @@ -305,7 +313,7 @@ return InstrBB; } -// Visit all edge and instrument the edges not in MST. +// Visit all edge and instrument the edges not in MST, and do value profiling. // Critical edges will be split. static void instrumentOneFunc(Function &F, Module *M, BranchProbabilityInfo *BPI, @@ -318,6 +326,7 @@ } uint32_t I = 0; + Type *I8PtrTy = Type::getInt8PtrTy(M->getContext()); for (auto &E : FuncInfo.MST.AllEdges) { BasicBlock *InstrBB = FuncInfo.getInstrBB(E.get()); if (!InstrBB) @@ -326,13 +335,38 @@ IRBuilder<> Builder(InstrBB, InstrBB->getFirstInsertionPt()); assert(Builder.GetInsertPoint() != InstrBB->end() && "Cannot get the Instrumentation point"); - Type *I8PtrTy = Type::getInt8PtrTy(M->getContext()); Builder.CreateCall( Intrinsic::getDeclaration(M, Intrinsic::instrprof_increment), {llvm::ConstantExpr::getBitCast(FuncInfo.FuncNameVar, I8PtrTy), Builder.getInt64(FuncInfo.FunctionHash), Builder.getInt32(NumCounters), Builder.getInt32(I++)}); } + + if (DisableValueProfiling) return; + + unsigned NumIndirectCallSites = 0; + for (auto &BB : F) { + for (auto &Inst : BB) { + CallSite CS(&Inst); + if (!CS || CS.getCalledFunction()) continue; + Value *Callee = CS.getCalledValue(); + if (!Callee) continue; + + DEBUG(dbgs() << "Instrument one indirect call: CallSite Index = " + << NumIndirectCallSites<<"\n"); + IRBuilder<> Builder(&Inst); + assert(Builder.GetInsertPoint() != BB.end() && + "Cannot get the Instrumentation point"); + Builder.CreateCall( + Intrinsic::getDeclaration(M, Intrinsic::instrprof_value_profile), + {llvm::ConstantExpr::getBitCast(FuncInfo.FuncNameVar, I8PtrTy), + Builder.getInt64(FuncInfo.FunctionHash), + Builder.CreatePtrToInt(Callee, Builder.getInt64Ty()), + Builder.getInt32(llvm::InstrProfValueKind::IPVK_IndirectCallTarget), + Builder.getInt32(NumIndirectCallSites++)}); + } + } + NumOfPGOICall += NumIndirectCallSites; } // This class represents a CFG edge in profile use compilation.