Index: llvm/include/llvm/IR/ModuleSummaryIndex.h =================================================================== --- llvm/include/llvm/IR/ModuleSummaryIndex.h +++ llvm/include/llvm/IR/ModuleSummaryIndex.h @@ -1036,6 +1036,9 @@ bool haveGVs() const { return HaveGVs; } + uint64_t getFlags() const; + void setFlags(uint64_t Flags); + gvsummary_iterator begin() { return GlobalValueMap.begin(); } const_gvsummary_iterator begin() const { return GlobalValueMap.begin(); } gvsummary_iterator end() { return GlobalValueMap.end(); } Index: llvm/lib/AsmParser/LLParser.h =================================================================== --- llvm/lib/AsmParser/LLParser.h +++ llvm/lib/AsmParser/LLParser.h @@ -347,6 +347,7 @@ bool ParseModuleEntry(unsigned ID); bool ParseModuleReference(StringRef &ModulePath); bool ParseGVReference(ValueInfo &VI, unsigned &GVId); + bool ParseSummaryIndexFlags(); bool ParseGVEntry(unsigned ID); bool ParseFunctionSummary(std::string Name, GlobalValue::GUID, unsigned ID); bool ParseVariableSummary(std::string Name, GlobalValue::GUID, unsigned ID); Index: llvm/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/lib/AsmParser/LLParser.cpp +++ llvm/lib/AsmParser/LLParser.cpp @@ -835,6 +835,9 @@ case lltok::kw_typeidCompatibleVTable: result = ParseTypeIdCompatibleVtableEntry(SummaryID); break; + case lltok::kw_flags: + result = ParseSummaryIndexFlags(); + break; default: result = Error(Lex.getLoc(), "unexpected summary kind"); break; @@ -7992,6 +7995,21 @@ } } +/// ParseSummaryIndexFlags +/// ::= 'flags' ':' UInt64 +bool LLParser::ParseSummaryIndexFlags() { + assert(Lex.getKind() == lltok::kw_flags); + Lex.Lex(); + + if (ParseToken(lltok::colon, "expected ':' here")) + return true; + uint64_t Flags; + if (ParseUInt64(Flags)) + return true; + Index->setFlags(Flags); + return false; +} + /// ParseGVEntry /// ::= 'gv' ':' '(' ('name' ':' STRINGCONSTANT | 'guid' ':' UInt64) /// [',' 'summaries' ':' Summary[',' Summary]* ]? ')' Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -5836,35 +5836,7 @@ default: // Default behavior: ignore. break; case bitc::FS_FLAGS: { // [flags] - uint64_t Flags = Record[0]; - // Scan flags. - assert(Flags <= 0x3f && "Unexpected bits in flag"); - - // 1 bit: WithGlobalValueDeadStripping flag. - // Set on combined index only. - if (Flags & 0x1) - TheIndex.setWithGlobalValueDeadStripping(); - // 1 bit: SkipModuleByDistributedBackend flag. - // Set on combined index only. - if (Flags & 0x2) - TheIndex.setSkipModuleByDistributedBackend(); - // 1 bit: HasSyntheticEntryCounts flag. - // Set on combined index only. - if (Flags & 0x4) - TheIndex.setHasSyntheticEntryCounts(); - // 1 bit: DisableSplitLTOUnit flag. - // Set on per module indexes. It is up to the client to validate - // the consistency of this flag across modules being linked. - if (Flags & 0x8) - TheIndex.setEnableSplitLTOUnit(); - // 1 bit: PartiallySplitLTOUnits flag. - // Set on combined index only. - if (Flags & 0x10) - TheIndex.setPartiallySplitLTOUnits(); - // 1 bit: WithAttributePropagation flag. - // Set on combined index only. - if (Flags & 0x20) - TheIndex.setWithAttributePropagation(); + TheIndex.setFlags(Record[0]); break; } case bitc::FS_VALUE_GUID: { // [valueid, refguid] Index: llvm/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -3898,20 +3898,7 @@ ArrayRef{ModuleSummaryIndex::BitcodeSummaryVersion}); // Write the index flags. - uint64_t Flags = 0; - if (Index.withGlobalValueDeadStripping()) - Flags |= 0x1; - if (Index.skipModuleByDistributedBackend()) - Flags |= 0x2; - if (Index.hasSyntheticEntryCounts()) - Flags |= 0x4; - if (Index.enableSplitLTOUnit()) - Flags |= 0x8; - if (Index.partiallySplitLTOUnits()) - Flags |= 0x10; - if (Index.withAttributePropagation()) - Flags |= 0x20; - Stream.EmitRecord(bitc::FS_FLAGS, ArrayRef{Flags}); + Stream.EmitRecord(bitc::FS_FLAGS, ArrayRef{Index.getFlags()}); for (const auto &GVI : valueIds()) { Stream.EmitRecord(bitc::FS_VALUE_GUID, Index: llvm/lib/IR/AsmWriter.cpp =================================================================== --- llvm/lib/IR/AsmWriter.cpp +++ llvm/lib/IR/AsmWriter.cpp @@ -747,6 +747,12 @@ int getModulePathSlot(StringRef Path); int getGUIDSlot(GlobalValue::GUID GUID); int getTypeIdSlot(StringRef Id); + int getNumSlots() const { + // For per-module summaries last records are typeidCompatibleVTable, + // which are enumerated by GUIDNext. For combined summaries those are + // typeid records enumerated by TypeIdNext. + return std::max(TypeIdNext, GUIDNext); + } /// If you'd like to deal with a function instead of just a module, use /// this method to get its data into the SlotTracker. @@ -2740,6 +2746,11 @@ printTypeIdCompatibleVtableSummary(TId.second); Out << ") ; guid = " << GUID << "\n"; } + + // Don't emit flags for per-module summaries. + if (TheIndex->getFlags()) + Out << "^" << Machine.getNumSlots() << " = flags: " << TheIndex->getFlags() + << "\n"; } static const char * Index: llvm/lib/IR/ModuleSummaryIndex.cpp =================================================================== --- llvm/lib/IR/ModuleSummaryIndex.cpp +++ llvm/lib/IR/ModuleSummaryIndex.cpp @@ -74,6 +74,52 @@ constexpr uint64_t ModuleSummaryIndex::BitcodeSummaryVersion; +uint64_t ModuleSummaryIndex::getFlags() const { + uint64_t Flags = 0; + if (withGlobalValueDeadStripping()) + Flags |= 0x1; + if (skipModuleByDistributedBackend()) + Flags |= 0x2; + if (hasSyntheticEntryCounts()) + Flags |= 0x4; + if (enableSplitLTOUnit()) + Flags |= 0x8; + if (partiallySplitLTOUnits()) + Flags |= 0x10; + if (withAttributePropagation()) + Flags |= 0x20; + return Flags; +} + +void ModuleSummaryIndex::setFlags(uint64_t Flags) { + assert(Flags <= 0x3f && "Unexpected bits in flag"); + // 1 bit: WithGlobalValueDeadStripping flag. + // Set on combined index only. + if (Flags & 0x1) + setWithGlobalValueDeadStripping(); + // 1 bit: SkipModuleByDistributedBackend flag. + // Set on combined index only. + if (Flags & 0x2) + setSkipModuleByDistributedBackend(); + // 1 bit: HasSyntheticEntryCounts flag. + // Set on combined index only. + if (Flags & 0x4) + setHasSyntheticEntryCounts(); + // 1 bit: DisableSplitLTOUnit flag. + // Set on per module indexes. It is up to the client to validate + // the consistency of this flag across modules being linked. + if (Flags & 0x8) + setEnableSplitLTOUnit(); + // 1 bit: PartiallySplitLTOUnits flag. + // Set on combined index only. + if (Flags & 0x10) + setPartiallySplitLTOUnits(); + // 1 bit: WithAttributePropagation flag. + // Set on combined index only. + if (Flags & 0x20) + setWithAttributePropagation(); +} + // Collect for the given module the list of function it defines // (GUID -> Summary). void ModuleSummaryIndex::collectDefinedFunctionsForModule( Index: llvm/test/Assembler/summary-flags.ll =================================================================== --- /dev/null +++ llvm/test/Assembler/summary-flags.ll @@ -0,0 +1,12 @@ +; ModuleID = 'tmp.bc' +source_filename = "tmp.bc" + +; Test parsing of summary flas. Expect that flags value is the same after round-trip through +; RUN: llvm-as %s -o - | llvm-dis -o - | FileCheck %s +; CHECK: ^0 = module +; CHECK-NEXT: ^1 = gv +; CHECK-NEXT: ^2 = flags: 33 + +^0 = module: (path: "main.bc", hash: (3499594384, 1671013073, 3271036935, 1830411232, 59290952)) +^1 = gv: (guid: 15822663052811949562, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0), insts: 2))) +^2 = flags: 33