betulb updated this revision to Diff 45550. betulb added a comment. In this revision:
- Clang no longer attaches function names as metadata. - Bug fixed in checking the getNumValueSites return value. - Addressed review comments. http://reviews.llvm.org/D8940 Files: lib/CodeGen/CGCall.cpp lib/CodeGen/CodeGenPGO.cpp lib/CodeGen/CodeGenPGO.h test/Profile/c-indirect-call.c
Index: test/Profile/c-indirect-call.c =================================================================== --- /dev/null +++ test/Profile/c-indirect-call.c @@ -0,0 +1,15 @@ +// Check the data structures emitted by instrumentation. +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-indirect-call.c %s -o - -emit-llvm -fprofile-instr-generate -mllvm -enable-value-profiling | FileCheck %s + +void (*foo)(void); + +int main(void) { +// CHECK: [[REG1:%[0-9]+]] = load void ()*, void ()** @foo, align 8 +// CHECK-NEXT: call void [[REG1]]() +// CHECK-NEXT: [[REG2:%[0-9]+]] = ptrtoint void ()* [[REG1]] to i64 +// CHECK-NEXT: call void @__llvm_profile_instrument_target(i64 [[REG2]], i8* bitcast ({ i32, i32, i64, i8*, i64*, i8*, i8*, [1 x i16] }* @__profd_main to i8*), i32 0) + foo(); + return 0; +} + +// CHECK: declare void @__llvm_profile_instrument_target(i64, i8*, i32) Index: lib/CodeGen/CodeGenPGO.h =================================================================== --- lib/CodeGen/CodeGenPGO.h +++ lib/CodeGen/CodeGenPGO.h @@ -19,6 +19,7 @@ #include "CodeGenTypes.h" #include "clang/Frontend/CodeGenOptions.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ProfileData/InstrProfReader.h" #include "llvm/Support/MemoryBuffer.h" #include <memory> @@ -32,20 +33,22 @@ std::string FuncName; llvm::GlobalVariable *FuncNameVar; + unsigned NumValueSites[llvm::IPVK_Last + 1]; unsigned NumRegionCounters; uint64_t FunctionHash; std::unique_ptr<llvm::DenseMap<const Stmt *, unsigned>> RegionCounterMap; std::unique_ptr<llvm::DenseMap<const Stmt *, uint64_t>> StmtCountMap; + std::unique_ptr<llvm::InstrProfRecord> ProfRecord; std::vector<uint64_t> RegionCounts; uint64_t CurrentRegionCount; /// \brief A flag that is set to true when this function doesn't need /// to have coverage mapping data. bool SkipCoverageMapping; public: CodeGenPGO(CodeGenModule &CGM) - : CGM(CGM), NumRegionCounters(0), FunctionHash(0), CurrentRegionCount(0), - SkipCoverageMapping(false) {} + : CGM(CGM), NumValueSites{0}, NumRegionCounters(0), + FunctionHash(0), CurrentRegionCount(0), SkipCoverageMapping(false) {} /// Whether or not we have PGO region data for the current function. This is /// false both when we have no data at all and when our data has been @@ -87,6 +90,9 @@ /// for an unused declaration. void emitEmptyCounterMapping(const Decl *D, StringRef FuncName, llvm::GlobalValue::LinkageTypes Linkage); + // Insert instrumentation or attach profile metadata at value sites + void valueProfile(CGBuilderTy &Builder, uint32_t ValueKind, + llvm::Instruction *ValueSite, llvm::Value *ValuePtr); private: void setFuncName(llvm::Function *Fn); void setFuncName(StringRef Name, llvm::GlobalValue::LinkageTypes Linkage); Index: lib/CodeGen/CodeGenPGO.cpp =================================================================== --- lib/CodeGen/CodeGenPGO.cpp +++ 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,21 +743,95 @@ 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) CGM.getPGOStats().addMismatched(IsInMainFile); 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. Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -3539,6 +3539,11 @@ CS.setAttributes(Attrs); CS.setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv)); + // Insert instrumentation or attach profile metadata at indirect call sites + if (!CS.getCalledFunction()) + PGO.valueProfile(Builder, llvm::IPVK_IndirectCallTarget, + CS.getInstruction(), Callee); + // In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC // optimizer it can aggressively ignore unwind edges. if (CGM.getLangOpts().ObjCAutoRefCount)
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits