Index: llvm/include/llvm/CodeGen/AsmPrinter.h =================================================================== --- llvm/include/llvm/CodeGen/AsmPrinter.h +++ llvm/include/llvm/CodeGen/AsmPrinter.h @@ -400,0 +401,3 @@ + /// This method computes and updates a functions instruction counts + void UpdateFunctionInstructionCounts(Function &F); + Index: llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h =================================================================== --- llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h +++ llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h @@ -105 +105 @@ - Streamer->emitIntValue((int)Value, sizeof(T)); + Streamer->emitIntValue((uint64_t)Value, sizeof(T)); Index: llvm/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def =================================================================== --- llvm/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def +++ llvm/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def @@ -174 +173,0 @@ -CV_SYMBOL(S_POGODATA , 0x115c) @@ -203,0 +203 @@ +SYMBOL_RECORD(S_POGODATA , 0x115c, PgoSym) Index: llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h =================================================================== --- llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -799,0 +800,18 @@ +// 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: +}; + Index: llvm/include/llvm/IR/FixedMetadataKinds.def =================================================================== --- llvm/include/llvm/IR/FixedMetadataKinds.def +++ llvm/include/llvm/IR/FixedMetadataKinds.def @@ -52,0 +53 @@ +LLVM_FIXED_MD_KIND(MD_instrcount, "instrcount", 39) \ No newline at end of file Index: llvm/include/llvm/IR/Function.h =================================================================== --- llvm/include/llvm/IR/Function.h +++ llvm/include/llvm/IR/Function.h @@ -265,0 +266,30 @@ + /// 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; + Index: llvm/include/llvm/IR/MDBuilder.h =================================================================== --- llvm/include/llvm/IR/MDBuilder.h +++ llvm/include/llvm/IR/MDBuilder.h @@ -76,0 +77,6 @@ + /// 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); + Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -69,0 +70,3 @@ +#include "llvm/IR/Dominators.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/BranchProbabilityInfo.h" @@ -2311,0 +2315,29 @@ + +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); +} + @@ -2315 +2347 @@ - + UpdateFunctionInstructionCounts(MF.getFunction()); Index: llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -1169,0 +1170,17 @@ + // 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); + } Index: llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp =================================================================== --- llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -432,0 +433,8 @@ +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(); +} + Index: llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp =================================================================== --- llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp +++ llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp @@ -327,0 +328,8 @@ +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(); +} + Index: llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp =================================================================== --- llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp +++ llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp @@ -441,0 +442 @@ + case SymbolKind::S_POGODATA: Index: llvm/lib/IR/Function.cpp =================================================================== --- llvm/lib/IR/Function.cpp +++ llvm/lib/IR/Function.cpp @@ -75 +75 @@ - +using FunctionInstructionCounts = Function::FunctionInstructionCounts; @@ -2031,0 +2032,28 @@ +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; + } + Index: llvm/lib/IR/MDBuilder.cpp =================================================================== --- llvm/lib/IR/MDBuilder.cpp +++ llvm/lib/IR/MDBuilder.cpp @@ -77,0 +78,14 @@ +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); +} + Index: llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp =================================================================== --- llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp +++ llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp @@ -504,0 +505,7 @@ +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); +} + Index: llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp =================================================================== --- llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp +++ llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp @@ -677,0 +678,9 @@ +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(); +} +