Index: llvm/include/llvm/CodeGen/AsmPrinter.h =================================================================== --- llvm/include/llvm/CodeGen/AsmPrinter.h +++ llvm/include/llvm/CodeGen/AsmPrinter.h @@ -388,6 +388,9 @@ /// runOnMachineFunction. virtual void SetupMachineFunction(MachineFunction &MF); + /// This method computes and updates a functions instruction counts + void UpdateFunctionInstructionCounts(Function &F); + /// This method emits the body and trailer for a function. void emitFunctionBody(); Index: llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h =================================================================== --- llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h +++ llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h @@ -102,7 +102,7 @@ template Error mapInteger(T &Value, const Twine &Comment = "") { if (isStreaming()) { emitComment(Comment); - Streamer->emitIntValue((int)Value, sizeof(T)); + Streamer->emitIntValue((uint64_t)Value, sizeof(T)); incrStreamedLen(sizeof(T)); return Error::success(); } Index: llvm/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def =================================================================== --- llvm/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def +++ llvm/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def @@ -171,7 +171,6 @@ CV_SYMBOL(S_DEFRANGE_DPC_PTR_TAG, 0x1157) CV_SYMBOL(S_DPC_SYM_TAG_MAP, 0x1158) CV_SYMBOL(S_ARMSWITCHTABLE , 0x1159) -CV_SYMBOL(S_POGODATA , 0x115c) CV_SYMBOL(S_INLINESITE2 , 0x115d) CV_SYMBOL(S_MOD_TYPEREF , 0x115f) CV_SYMBOL(S_REF_MINIPDB , 0x1160) @@ -201,6 +200,7 @@ SYMBOL_RECORD_ALIAS(S_GPROC32_ID , 0x1147, GlobalProcIdSym, ProcSym) SYMBOL_RECORD_ALIAS(S_LPROC32_DPC , 0x1155, DPCProcSym, ProcSym) SYMBOL_RECORD_ALIAS(S_LPROC32_DPC_ID , 0x1156, DPCProcIdSym, ProcSym) +SYMBOL_RECORD(S_POGODATA , 0x115c, PgoSym) SYMBOL_RECORD(S_REGISTER , 0x1106, RegisterSym) SYMBOL_RECORD(S_PUB32 , 0x110e, PublicSym32) Index: llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h =================================================================== --- llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -797,6 +797,24 @@ private: }; +// S_POGODATA +class PgoSym : public SymbolRecord { +public: + explicit PgoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit PgoSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::PgoSym), + RecordOffset(RecordOffset) {} + + uint32_t FunctionEntryCount = 0; + uint64_t DynamicInstrCount = 0; + uint32_t StaticInstrCount = 0; + uint32_t LiveInstrCount = 0; + + uint32_t RecordOffset = 0; + +private: +}; + // S_CALLSITEINFO class CallSiteInfoSym : public SymbolRecord { static constexpr uint32_t RelocationOffset = 4; Index: llvm/include/llvm/IR/FixedMetadataKinds.def =================================================================== --- llvm/include/llvm/IR/FixedMetadataKinds.def +++ llvm/include/llvm/IR/FixedMetadataKinds.def @@ -45,3 +45,4 @@ LLVM_FIXED_MD_KIND(MD_nosanitize, "nosanitize", 31) LLVM_FIXED_MD_KIND(MD_func_sanitize, "func_sanitize", 32) LLVM_FIXED_MD_KIND(MD_exclude, "exclude", 33) +LLVM_FIXED_MD_KIND(MD_instrcount, "instrcount", 34) Index: llvm/include/llvm/IR/Function.h =================================================================== --- llvm/include/llvm/IR/Function.h +++ llvm/include/llvm/IR/Function.h @@ -170,7 +170,7 @@ /// This is equivalent to the sum of the sizes of each basic block contained /// within this function. unsigned getInstructionCount() const; - + /// Returns the FunctionType for me. FunctionType *getFunctionType() const { return cast(getValueType()); @@ -263,6 +263,36 @@ bool isSynthetic() const { return PCT == PCT_Synthetic; } }; + /// Class to represent function instruction counts. + /// + /// This class owns the state and values for the + /// dynamic, static and live instruction of a function. + class FunctionInstructionCounts { + private: + uint64_t DynInstCount = 0; + uint32_t LiveInstCount = 0; + uint32_t StaticInstCount = 0; + public: + FunctionInstructionCounts(uint64_t DynInstCount, uint32_t LiveInstCount, + uint32_t StaticInstCount) + : DynInstCount(DynInstCount), LiveInstCount(LiveInstCount), + StaticInstCount(StaticInstCount) {} + uint64_t getDynInstCount() const { return DynInstCount; } + uint32_t getLiveInstCount() const { return LiveInstCount; } + uint32_t getStaticInstCount() const { return StaticInstCount; } + }; + + /// Set the various function instruction counts. + /// + /// This invloves setting the dynamic, static and + /// live instruction counts per function. + void setFunctionInstructionCounts(uint64_t DynInstCount, + uint32_t LiveInstCount, + uint32_t StaticInstCount); + + /// Get the various function instruction counts. + Optional getFunctionInstructionCounts() const; + /// Set the entry count for this function. /// /// Entry count is the number of times this function was executed based on Index: llvm/include/llvm/IR/MDBuilder.h =================================================================== --- llvm/include/llvm/IR/MDBuilder.h +++ llvm/include/llvm/IR/MDBuilder.h @@ -73,6 +73,12 @@ MDNode *createFunctionEntryCount(uint64_t Count, bool Synthetic, const DenseSet *Imports); + /// Return metadata containing a function's instruction counts: Dynamic + /// Instruction Count, Live Instruction Count and Static Instruction Count. + MDNode *createFunctionInstructionCounts(uint64_t DynInstCount, + uint32_t LiveInstCount, + uint32_t StaticInstCount); + /// Return metadata containing the section prefix for a function. MDNode *createFunctionSectionPrefix(StringRef Prefix); Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -67,6 +67,9 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Dominators.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/BranchProbabilityInfo.h" #include "llvm/IR/Function.h" #include "llvm/IR/GCStrategy.h" #include "llvm/IR/GlobalAlias.h" @@ -2181,10 +2184,39 @@ return Res.first->second; } + +void AsmPrinter::UpdateFunctionInstructionCounts(Function &F) { + uint32_t StaticInstCount = 0; + uint32_t LiveInstCount = 0; + uint64_t DynInstCount = 0; + uint32_t BlockInstrCount = 0; + + /// Attempting to retrive machine block frequency using + /// LazyMachineBlockFrequencyInfo from getAnalysis API results in some + /// functions not holding any valid MBFI value. + /// TODO:Implement means to compute instruction count and frequency at the + /// Machine Basic Block level to account for lowered instruction count diff. + + LoopInfo LI{DominatorTree(F)}; + BranchProbabilityInfo NBPI(F, LI); + BlockFrequencyInfo NBFI(F, NBPI, LI); + for (auto &BB : F) { + auto BFICount = NBFI.getBlockProfileCount(&BB); + BlockInstrCount = std::distance(BB.instructionsWithoutDebug().begin(), + BB.instructionsWithoutDebug().end()); + if (BFICount.hasValue() && BFICount.getValue() > 0) { + DynInstCount += BlockInstrCount * BFICount.getValue(); + LiveInstCount += BlockInstrCount; + } + StaticInstCount += BlockInstrCount; + } + F.setFunctionInstructionCounts(DynInstCount, LiveInstCount, StaticInstCount); +} + void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { this->MF = &MF; const Function &F = MF.getFunction(); - + UpdateFunctionInstructionCounts(MF.getFunction()); // Record that there are split-stack functions, so we will emit a special // section to tell the linker. if (MF.shouldSplitStack()) { Index: llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -1164,6 +1164,23 @@ emitNullTerminatedSymbolName(OS, FuncName); endSymbolRecord(ProcRecordEnd); + // Only display S_POGODATA if entry count or DnyCounts are non 0 + if (GV->getFunctionInstructionCounts().hasValue() && + GV->getFunctionInstructionCounts().getValue().getDynInstCount() > 0) { + MCSymbol *PgoEnd = beginSymbolRecord(SymbolKind::S_POGODATA); + OS.AddComment("Function Entry Count"); + OS.emitInt32(GV->getEntryCount()->getCount()); + OS.AddComment("Dynamic Instruction Count"); + OS.emitInt64( + GV->getFunctionInstructionCounts().getValue().getDynInstCount()); + OS.AddComment("Static Instruction Count"); + OS.emitInt32( + GV->getFunctionInstructionCounts().getValue().getStaticInstCount()); + OS.AddComment("Live Instruction Count"); + OS.emitInt32( + GV->getFunctionInstructionCounts().getValue().getLiveInstCount()); + endSymbolRecord(PgoEnd); + } MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC); // Subtract out the CSR size since MSVC excludes that and we include it. OS.AddComment("FrameSize"); Index: llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp =================================================================== --- llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -430,6 +430,14 @@ return Error::success(); } +Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, PgoSym &Pgo) { + W.printHex("FunctionEntryCount", Pgo.FunctionEntryCount); + W.printHex("DynamicInstrCount", Pgo.DynamicInstrCount); + W.printHex("StaticInstrCount", Pgo.StaticInstrCount); + W.printHex("LiveInstrCount", Pgo.LiveInstrCount); + return Error::success(); +} + Error CVSymbolDumperImpl::visitKnownRecord( CVSymbol &CVR, HeapAllocationSiteSym &HeapAllocSite) { StringRef LinkageName; Index: llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp =================================================================== --- llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp +++ llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp @@ -325,6 +325,14 @@ return Error::success(); } +Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, PgoSym &Pgo) { + error(IO.mapInteger(Pgo.FunctionEntryCount)); + error(IO.mapInteger(Pgo.DynamicInstrCount)); + error(IO.mapInteger(Pgo.StaticInstrCount)); + error(IO.mapInteger(Pgo.LiveInstrCount)); + return Error::success(); +} + Error SymbolRecordMapping::visitKnownRecord( CVSymbol &CVR, HeapAllocationSiteSym &HeapAllocSite) { Index: llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp =================================================================== --- llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp +++ llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp @@ -439,6 +439,7 @@ case SymbolKind::S_ENVBLOCK: case SymbolKind::S_BLOCK32: case SymbolKind::S_FRAMEPROC: + case SymbolKind::S_POGODATA: case SymbolKind::S_THUNK32: case SymbolKind::S_FRAMECOOKIE: case SymbolKind::S_UNAMESPACE: Index: llvm/lib/IR/Function.cpp =================================================================== --- llvm/lib/IR/Function.cpp +++ llvm/lib/IR/Function.cpp @@ -71,7 +71,7 @@ using namespace llvm; using ProfileCount = Function::ProfileCount; - +using FunctionInstructionCounts = Function::FunctionInstructionCounts; // Explicit instantiations of SymbolTableListTraits since some of the methods // are not in the public header file... template class llvm::SymbolTableListTraits; @@ -1968,6 +1968,34 @@ setValueSubclassData(getSubclassDataFromValue() & ~(1 << Bit)); } +void Function::setFunctionInstructionCounts(uint64_t DynInstCount, + uint32_t LiveInstCount, + uint32_t StaticInstCount) { + MDBuilder MDB(getContext()); + setMetadata(LLVMContext::MD_instrcount, + MDB.createFunctionInstructionCounts(DynInstCount, LiveInstCount, + StaticInstCount)); + } + +Optional + Function::getFunctionInstructionCounts() const { + MDNode *MD = getMetadata(LLVMContext::MD_instrcount); + if (MD && MD->getOperand(0)) + if (MDString *MDS = dyn_cast(MD->getOperand(0))) { + if (MDS->getString().equals("function_instruction_counts")) { + ConstantInt *CIDIC = mdconst::extract(MD->getOperand(1)); + uint64_t DynInstCount = CIDIC->getValue().getZExtValue(); + ConstantInt *CILIC = mdconst::extract(MD->getOperand(2)); + uint32_t LiveInstCount = CILIC->getValue().getZExtValue(); + ConstantInt *CISIC = mdconst::extract(MD->getOperand(3)); + uint32_t StaticInstCount = CISIC->getValue().getZExtValue(); + return FunctionInstructionCounts(DynInstCount, LiveInstCount, + StaticInstCount); + } + } + return None; + } + void Function::setEntryCount(ProfileCount Count, const DenseSet *S) { #if !defined(NDEBUG) Index: llvm/lib/IR/MDBuilder.cpp =================================================================== --- llvm/lib/IR/MDBuilder.cpp +++ llvm/lib/IR/MDBuilder.cpp @@ -75,6 +75,20 @@ return MDNode::get(Context, Ops); } +MDNode *MDBuilder::createFunctionInstructionCounts(uint64_t DynInstCount, + uint32_t LiveInstCount, + uint32_t StaticInstCount) { + SmallVector Ops; + Type *Int64Ty = Type::getInt64Ty(Context); + Ops.push_back(createString("function_instruction_counts")); + Ops.push_back(createConstant(ConstantInt::get(Int64Ty, DynInstCount))); + Type *Int32Ty = Type::getInt32Ty(Context); + Ops.push_back(createConstant(ConstantInt::get(Int32Ty, LiveInstCount))); + Ops.push_back(createConstant(ConstantInt::get(Int32Ty, StaticInstCount))); + + return MDNode::get(Context, Ops); +} + MDNode *MDBuilder::createFunctionSectionPrefix(StringRef Prefix) { return MDNode::get(Context, {createString("function_section_prefix"), Index: llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp =================================================================== --- llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp +++ llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp @@ -501,6 +501,13 @@ IO.mapRequired("Flags", Symbol.Flags); } +template <> void SymbolRecordImpl::map(IO &IO) { + IO.mapRequired("FunctionEntryCount", Symbol.FunctionEntryCount); + IO.mapRequired("DynamicInstrCount", Symbol.DynamicInstrCount); + IO.mapRequired("StaticInstrCount", Symbol.StaticInstrCount); + IO.mapRequired("LiveInstrCount", Symbol.LiveInstrCount); +} + template <> void SymbolRecordImpl::map(IO &IO) { IO.mapOptional("Offset", Symbol.CodeOffset, 0U); IO.mapOptional("Segment", Symbol.Segment, uint16_t(0)); Index: llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp =================================================================== --- llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp +++ llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp @@ -675,6 +675,15 @@ return Error::success(); } +Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, PgoSym &PGO) { + AutoIndent Indent(P, 7); + P.formatLine("Call Count = {0}, Dynamic Instruction Count = {1}", + PGO.FunctionEntryCount, PGO.DynamicInstrCount); + P.formatLine("Live Instruction Count = {0}, Static Instruction Count = {1}", + PGO.LiveInstrCount, PGO.StaticInstrCount); + return Error::success(); +} + Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, HeapAllocationSiteSym &HAS) { AutoIndent Indent(P, 7);