Holman created this revision. Herald added subscribers: dexonsmith, wenlei, hiraditya. Holman requested review of this revision. Herald added projects: clang, LLVM. Herald added subscribers: llvm-commits, cfe-commits.
This change adds debug information about whether PGO is being used or not. Microsoft performance tooling (e.g. xperf, WPA) uses this information to show whether functions are optimized with PGO or not, as well as whether PGO information is invalid. This information is useful for validating whether training scenarios are providing good coverage of real world scenarios, showing if profile data is out of date, etc. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D99994 Files: clang/lib/CodeGen/CGDebugInfo.cpp llvm/include/llvm/IR/DIBuilder.h llvm/include/llvm/IR/DebugInfoMetadata.h llvm/lib/AsmParser/LLParser.cpp llvm/lib/Bitcode/Reader/MetadataLoader.cpp llvm/lib/Bitcode/Writer/BitcodeWriter.cpp llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp llvm/lib/IR/DIBuilder.cpp llvm/lib/IR/DebugInfo.cpp llvm/lib/IR/DebugInfoMetadata.cpp llvm/unittests/IR/MetadataTest.cpp
Index: llvm/unittests/IR/MetadataTest.cpp =================================================================== --- llvm/unittests/IR/MetadataTest.cpp +++ llvm/unittests/IR/MetadataTest.cpp @@ -97,7 +97,7 @@ Context, 1, getFile(), "clang", false, "-g", 2, "", DICompileUnit::FullDebug, getTuple(), getTuple(), getTuple(), getTuple(), getTuple(), 0, true, false, - DICompileUnit::DebugNameTableKind::Default, false, "/", ""); + DICompileUnit::DebugNameTableKind::Default, false, "/", "", false); } DIType *getBasicType(StringRef Name) { return DIBasicType::get(Context, dwarf::DW_TAG_unspecified_type, Name); @@ -2110,11 +2110,13 @@ MDTuple *Macros = getTuple(); StringRef SysRoot = "/"; StringRef SDK = "MacOSX.sdk"; + bool HasPGO = false; auto *N = DICompileUnit::getDistinct( Context, SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, true, - false, DICompileUnit::DebugNameTableKind::Default, false, SysRoot, SDK); + false, DICompileUnit::DebugNameTableKind::Default, false, SysRoot, SDK, + HasPGO); EXPECT_EQ(dwarf::DW_TAG_compile_unit, N->getTag()); EXPECT_EQ(SourceLanguage, N->getSourceLanguage()); @@ -2133,6 +2135,7 @@ EXPECT_EQ(DWOId, N->getDWOId()); EXPECT_EQ(SysRoot, N->getSysRoot()); EXPECT_EQ(SDK, N->getSDK()); + EXPECT_EQ(HasPGO, N->hasPGO()); TempDICompileUnit Temp = N->clone(); EXPECT_EQ(dwarf::DW_TAG_compile_unit, Temp->getTag()); @@ -2151,6 +2154,7 @@ EXPECT_EQ(Macros, Temp->getMacros().get()); EXPECT_EQ(SysRoot, Temp->getSysRoot()); EXPECT_EQ(SDK, Temp->getSDK()); + EXPECT_EQ(HasPGO, Temp->hasPGO()); auto *TempAddress = Temp.get(); auto *Clone = MDNode::replaceWithPermanent(std::move(Temp)); @@ -2173,11 +2177,12 @@ uint64_t DWOId = 0xc0ffee; StringRef SysRoot = "/"; StringRef SDK = "MacOSX.sdk"; + bool HasPGO = false; auto *N = DICompileUnit::getDistinct( Context, SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, nullptr, ImportedEntities, nullptr, DWOId, true, false, - DICompileUnit::DebugNameTableKind::Default, false, SysRoot, SDK); + DICompileUnit::DebugNameTableKind::Default, false, SysRoot, SDK, HasPGO); auto *GlobalVariables = MDTuple::getDistinct(Context, None); EXPECT_EQ(nullptr, N->getGlobalVariables().get()); Index: llvm/lib/IR/DebugInfoMetadata.cpp =================================================================== --- llvm/lib/IR/DebugInfoMetadata.cpp +++ llvm/lib/IR/DebugInfoMetadata.cpp @@ -736,7 +736,7 @@ Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, - MDString *SDK, StorageType Storage, bool ShouldCreate) { + MDString *SDK, bool HasPGO, StorageType Storage, bool ShouldCreate) { assert(Storage != Uniqued && "Cannot unique DICompileUnit"); assert(isCanonical(Producer) && "Expected canonical MDString"); assert(isCanonical(Flags) && "Expected canonical MDString"); @@ -757,7 +757,7 @@ Context, Storage, SourceLanguage, IsOptimized, RuntimeVersion, EmissionKind, DWOId, SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress, - Ops), + HasPGO, Ops), Storage); } Index: llvm/lib/IR/DebugInfo.cpp =================================================================== --- llvm/lib/IR/DebugInfo.cpp +++ llvm/lib/IR/DebugInfo.cpp @@ -491,7 +491,8 @@ RetainedTypes, GlobalVariables, ImportedEntities, CU->getMacros(), CU->getDWOId(), CU->getSplitDebugInlining(), CU->getDebugInfoForProfiling(), CU->getNameTableKind(), - CU->getRangesBaseAddress(), CU->getSysRoot(), CU->getSDK()); + CU->getRangesBaseAddress(), CU->getSysRoot(), CU->getSDK(), + CU->hasPGO()); } DILocation *getReplacementMDLocation(DILocation *MLD) { Index: llvm/lib/IR/DIBuilder.cpp =================================================================== --- llvm/lib/IR/DIBuilder.cpp +++ llvm/lib/IR/DIBuilder.cpp @@ -141,7 +141,7 @@ DICompileUnit::DebugEmissionKind Kind, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling, DICompileUnit::DebugNameTableKind NameTableKind, bool RangesBaseAddress, - StringRef SysRoot, StringRef SDK) { + StringRef SysRoot, StringRef SDK, bool HasPGO) { assert(((Lang <= dwarf::DW_LANG_Fortran08 && Lang >= dwarf::DW_LANG_C89) || (Lang <= dwarf::DW_LANG_hi_user && Lang >= dwarf::DW_LANG_lo_user)) && @@ -152,7 +152,7 @@ VMContext, Lang, File, Producer, isOptimized, Flags, RunTimeVer, SplitName, Kind, nullptr, nullptr, nullptr, nullptr, nullptr, DWOId, SplitDebugInlining, DebugInfoForProfiling, NameTableKind, - RangesBaseAddress, SysRoot, SDK); + RangesBaseAddress, SysRoot, SDK, HasPGO); // Create a named metadata so that it is easier to find cu in a module. NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu"); Index: llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -804,6 +804,9 @@ // The low byte of the flags indicates the source language. Flags = MapDWLangToCVLang(CU->getSourceLanguage()); // TODO: Figure out which other flags need to be set. + if (CU->hasPGO()) { + Flags |= static_cast<uint32_t>(CompileSym3Flags::PGO); + } OS.AddComment("Flags and language"); OS.emitInt32(Flags); @@ -1428,6 +1431,10 @@ if (Asm->TM.getOptLevel() != CodeGenOpt::None && !GV.hasOptSize() && !GV.hasOptNone()) FPO |= FrameProcedureOptions::OptimizedForSpeed; + if (GV.getEntryCount().hasValue()) { + FPO |= FrameProcedureOptions::ValidProfileCounts; + FPO |= FrameProcedureOptions::ProfileGuidedOptimization; + } // FIXME: Set GuardCfg when it is implemented. CurFn->FrameProcOpts = FPO; Index: llvm/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1762,6 +1762,7 @@ Record.push_back(N->getRangesBaseAddress()); Record.push_back(VE.getMetadataOrNullID(N->getRawSysRoot())); Record.push_back(VE.getMetadataOrNullID(N->getRawSDK())); + Record.push_back(N->hasPGO()); Stream.EmitRecord(bitc::METADATA_COMPILE_UNIT, Record, Abbrev); Record.clear(); Index: llvm/lib/Bitcode/Reader/MetadataLoader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1608,7 +1608,7 @@ break; } case bitc::METADATA_COMPILE_UNIT: { - if (Record.size() < 14 || Record.size() > 22) + if (Record.size() < 14 || Record.size() > 23) return error("Invalid record"); // Ignore Record[0], which indicates whether this compile unit is @@ -1626,7 +1626,8 @@ Record.size() <= 18 ? 0 : Record[18], Record.size() <= 19 ? 0 : Record[19], Record.size() <= 20 ? nullptr : getMDString(Record[20]), - Record.size() <= 21 ? nullptr : getMDString(Record[21])); + Record.size() <= 21 ? nullptr : getMDString(Record[21]), + Record.size() <= 22 ? false : Record[22]); MetadataList.assignValue(CU, NextMetadataNo); NextMetadataNo++; Index: llvm/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/lib/AsmParser/LLParser.cpp +++ llvm/lib/AsmParser/LLParser.cpp @@ -5001,7 +5001,8 @@ OPTIONAL(nameTableKind, NameTableKindField, ); \ OPTIONAL(rangesBaseAddress, MDBoolField, = false); \ OPTIONAL(sysroot, MDStringField, ); \ - OPTIONAL(sdk, MDStringField, ); + OPTIONAL(sdk, MDStringField, ); \ + OPTIONAL(hasPGO, MDBoolField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS @@ -5010,7 +5011,7 @@ runtimeVersion.Val, splitDebugFilename.Val, emissionKind.Val, enums.Val, retainedTypes.Val, globals.Val, imports.Val, macros.Val, dwoId.Val, splitDebugInlining.Val, debugInfoForProfiling.Val, nameTableKind.Val, - rangesBaseAddress.Val, sysroot.Val, sdk.Val); + rangesBaseAddress.Val, sysroot.Val, sdk.Val, hasPGO.Val); return false; } Index: llvm/include/llvm/IR/DebugInfoMetadata.h =================================================================== --- llvm/include/llvm/IR/DebugInfoMetadata.h +++ llvm/include/llvm/IR/DebugInfoMetadata.h @@ -1333,6 +1333,7 @@ private: unsigned SourceLanguage; bool IsOptimized; + bool HasPGO; unsigned RuntimeVersion; unsigned EmissionKind; uint64_t DWOId; @@ -1345,13 +1346,14 @@ bool IsOptimized, unsigned RuntimeVersion, unsigned EmissionKind, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, - bool RangesBaseAddress, ArrayRef<Metadata *> Ops) + bool RangesBaseAddress, bool HasPGO, ArrayRef<Metadata *> Ops) : DIScope(C, DICompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops), SourceLanguage(SourceLanguage), IsOptimized(IsOptimized), RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind), DWOId(DWOId), SplitDebugInlining(SplitDebugInlining), DebugInfoForProfiling(DebugInfoForProfiling), - NameTableKind(NameTableKind), RangesBaseAddress(RangesBaseAddress) { + NameTableKind(NameTableKind), RangesBaseAddress(RangesBaseAddress), + HasPGO(HasPGO) { assert(Storage != Uniqued); } ~DICompileUnit() = default; @@ -1366,7 +1368,8 @@ DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, StringRef SysRoot, - StringRef SDK, StorageType Storage, bool ShouldCreate = true) { + StringRef SDK, bool HasPGO, StorageType Storage, + bool ShouldCreate = true) { return getImpl( Context, SourceLanguage, File, getCanonicalMDString(Context, Producer), IsOptimized, getCanonicalMDString(Context, Flags), RuntimeVersion, @@ -1375,7 +1378,7 @@ ImportedEntities.get(), Macros.get(), DWOId, SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress, getCanonicalMDString(Context, SysRoot), - getCanonicalMDString(Context, SDK), Storage, ShouldCreate); + getCanonicalMDString(Context, SDK), HasPGO, Storage, ShouldCreate); } static DICompileUnit * getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, @@ -1385,7 +1388,7 @@ Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, - bool RangesBaseAddress, MDString *SysRoot, MDString *SDK, + bool RangesBaseAddress, MDString *SysRoot, MDString *SDK, bool HasPGO, StorageType Storage, bool ShouldCreate = true); TempDICompileUnit cloneImpl() const { @@ -1395,7 +1398,7 @@ getEmissionKind(), getEnumTypes(), getRetainedTypes(), getGlobalVariables(), getImportedEntities(), getMacros(), DWOId, getSplitDebugInlining(), getDebugInfoForProfiling(), getNameTableKind(), - getRangesBaseAddress(), getSysRoot(), getSDK()); + getRangesBaseAddress(), getSysRoot(), getSDK(), hasPGO()); } public: @@ -1412,12 +1415,12 @@ DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling, DebugNameTableKind NameTableKind, bool RangesBaseAddress, - StringRef SysRoot, StringRef SDK), + StringRef SysRoot, StringRef SDK, bool HasPGO), (SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress, - SysRoot, SDK)) + SysRoot, SDK, HasPGO)) DEFINE_MDNODE_GET_DISTINCT_TEMPORARY( DICompileUnit, (unsigned SourceLanguage, Metadata *File, MDString *Producer, @@ -1427,16 +1430,18 @@ Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, - MDString *SDK), + MDString *SDK, bool HasPGO), (SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining, - DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot, SDK)) + DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot, SDK, + HasPGO)) TempDICompileUnit clone() const { return cloneImpl(); } unsigned getSourceLanguage() const { return SourceLanguage; } bool isOptimized() const { return IsOptimized; } + bool hasPGO() const { return HasPGO; } unsigned getRuntimeVersion() const { return RuntimeVersion; } DebugEmissionKind getEmissionKind() const { return (DebugEmissionKind)EmissionKind; Index: llvm/include/llvm/IR/DIBuilder.h =================================================================== --- llvm/include/llvm/IR/DIBuilder.h +++ llvm/include/llvm/IR/DIBuilder.h @@ -138,6 +138,8 @@ /// \param SysRoot The clang system root (value of -isysroot). /// \param SDK The SDK name. On Darwin, this is the last component /// of the sysroot. + /// \param HasPGO A boolean flag which indicates whether PGO data + /// is available or not DICompileUnit * createCompileUnit(unsigned Lang, DIFile *File, StringRef Producer, bool isOptimized, StringRef Flags, unsigned RV, @@ -149,7 +151,7 @@ DICompileUnit::DebugNameTableKind NameTableKind = DICompileUnit::DebugNameTableKind::Default, bool RangesBaseAddress = false, StringRef SysRoot = {}, - StringRef SDK = {}); + StringRef SDK = {}, bool HasPGO = false); /// Create a file descriptor to hold debugging information for a file. /// \param Filename File name. Index: clang/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- clang/lib/CodeGen/CGDebugInfo.cpp +++ clang/lib/CodeGen/CGDebugInfo.cpp @@ -642,7 +642,8 @@ ? llvm::DICompileUnit::DebugNameTableKind::None : static_cast<llvm::DICompileUnit::DebugNameTableKind>( CGOpts.DebugNameTable), - CGOpts.DebugRangesBaseAddress, remapDIPath(Sysroot), SDK); + CGOpts.DebugRangesBaseAddress, remapDIPath(Sysroot), SDK, + CGOpts.hasProfileIRUse()); } llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits