diff options
Diffstat (limited to 'clang/lib/CodeGen/CodeGenPGO.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CodeGenPGO.cpp | 85 |
1 files changed, 81 insertions, 4 deletions
diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp index 2c0d93b394a..df043537dd4 100644 --- a/clang/lib/CodeGen/CodeGenPGO.cpp +++ b/clang/lib/CodeGen/CodeGenPGO.cpp @@ -18,11 +18,14 @@ #include "clang/AST/StmtVisitor.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/MDBuilder.h" -#include "llvm/ProfileData/InstrProfReader.h" #include "llvm/Support/Endian.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MD5.h" +static llvm::cl::opt<bool> EnableValueProfiling( + "enable-value-profiling", llvm::cl::ZeroOrMore, + llvm::cl::desc("Enable value profiling"), llvm::cl::init(false)); + using namespace clang; using namespace CodeGen; @@ -740,12 +743,83 @@ void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S) { Builder.getInt32(Counter)}); } +// This method either inserts a call to the profile run-time during +// instrumentation or puts profile data into metadata for PGO use. +void CodeGenPGO::valueProfile(CGBuilderTy &Builder, uint32_t ValueKind, + llvm::Instruction *ValueSite, llvm::Value *ValuePtr) { + + if (!EnableValueProfiling) + return; + + if (!ValuePtr || !ValueSite || !Builder.GetInsertBlock()) + return; + + bool InstrumentValueSites = CGM.getCodeGenOpts().ProfileInstrGenerate; + if (InstrumentValueSites && RegionCounterMap) { + llvm::LLVMContext &Ctx = CGM.getLLVMContext(); + auto *I8PtrTy = llvm::Type::getInt8PtrTy(Ctx); + llvm::Value *Args[5] = { + llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy), + Builder.getInt64(FunctionHash), + Builder.CreatePtrToInt(ValuePtr, Builder.getInt64Ty()), + Builder.getInt32(ValueKind), + Builder.getInt32(NumValueSites[ValueKind]++) + }; + Builder.CreateCall( + CGM.getIntrinsic(llvm::Intrinsic::instrprof_value_profile), Args); + return; + } + + llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader(); + if (PGOReader && haveRegionCounts()) { + // We record the top most called three functions at each call site. + // Profile metadata contains "VP" string identifying this metadata + // as value profiling data, then a uint32_t value for the value profiling + // kind, a uint64_t value for the total number of times the call is + // executed, followed by the function hash and execution count (uint64_t) + // pairs for each function. + if (NumValueSites[ValueKind] >= ProfRecord->getNumValueSites(ValueKind)) + return; + uint32_t NV = ProfRecord->getNumValueDataForSite(ValueKind, + NumValueSites[ValueKind]); + std::unique_ptr<InstrProfValueData[]> VD = + ProfRecord->getValueForSite(ValueKind, NumValueSites[ValueKind]); + + uint64_t Sum = 0; + for (uint32_t I = 0; I < NV; ++I) + Sum += VD[I].Count; + + llvm::LLVMContext &Ctx = CGM.getLLVMContext(); + llvm::MDBuilder MDHelper(Ctx); + SmallVector<llvm::Metadata*, 3> Vals; + Vals.push_back(MDHelper.createString("VP")); + Vals.push_back(MDHelper.createConstant( + llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx), ValueKind))); + Vals.push_back(MDHelper.createConstant( + llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), Sum))); + + uint32_t MDCount = 3; + for (uint32_t I = 0; I < NV; ++I) { + Vals.push_back(MDHelper.createConstant( + llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), VD[I].Value))); + Vals.push_back(MDHelper.createConstant( + llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), VD[I].Count))); + if (--MDCount == 0) + break; + } + ValueSite->setMetadata( + llvm::LLVMContext::MD_prof, llvm::MDNode::get(Ctx, Vals)); + NumValueSites[ValueKind]++; + } +} + void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader, bool IsInMainFile) { CGM.getPGOStats().addVisited(IsInMainFile); RegionCounts.clear(); - if (std::error_code EC = - PGOReader->getFunctionCounts(FuncName, FunctionHash, RegionCounts)) { + llvm::ErrorOr<llvm::InstrProfRecord> RecordErrorOr = + PGOReader->getInstrProfRecord(FuncName, FunctionHash); + if (std::error_code EC = RecordErrorOr.getError()) { if (EC == llvm::instrprof_error::unknown_function) CGM.getPGOStats().addMissing(IsInMainFile); else if (EC == llvm::instrprof_error::hash_mismatch) @@ -753,8 +827,11 @@ void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader, else if (EC == llvm::instrprof_error::malformed) // TODO: Consider a more specific warning for this case. CGM.getPGOStats().addMismatched(IsInMainFile); - RegionCounts.clear(); + return; } + ProfRecord = + llvm::make_unique<llvm::InstrProfRecord>(std::move(RecordErrorOr.get())); + RegionCounts = ProfRecord->Counts; } /// \brief Calculate what to divide by to scale weights. |

