diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h b/llvm/include/llvm/IR/ModuleSummaryIndex.h --- a/llvm/include/llvm/IR/ModuleSummaryIndex.h +++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h @@ -1037,6 +1037,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(); } diff --git a/llvm/lib/AsmParser/LLParser.h b/llvm/lib/AsmParser/LLParser.h --- a/llvm/lib/AsmParser/LLParser.h +++ b/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); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/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; @@ -7995,6 +7998,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]* ]? ')' diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/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] diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/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, diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -783,7 +783,7 @@ /// These functions do the actual initialization. inline void initializeIfNeeded(); - void initializeIndexIfNeeded(); + int initializeIndexIfNeeded(); // Implementation Details private: @@ -806,7 +806,8 @@ /// Add all of the module level global variables (and their initializers) /// and function declarations, but not the contents of those functions. void processModule(); - void processIndex(); + // Returns number of allocated slots + int processIndex(); /// Add all of the functions arguments, basic blocks, and instructions. void processFunction(); @@ -920,11 +921,12 @@ processFunction(); } -void SlotTracker::initializeIndexIfNeeded() { +int SlotTracker::initializeIndexIfNeeded() { if (!TheIndex) - return; - processIndex(); + return 0; + int NumSlots = processIndex(); TheIndex = nullptr; ///< Prevent re-processing next time we're called. + return NumSlots; } // Iterate through all the global variables, functions, and global @@ -1019,7 +1021,7 @@ } // Iterate through all the GUID in the index and create slots for them. -void SlotTracker::processIndex() { +int SlotTracker::processIndex() { ST_DEBUG("begin processIndex!\n"); assert(TheIndex); @@ -1038,17 +1040,17 @@ for (auto &GlobalList : *TheIndex) CreateGUIDSlot(GlobalList.first); + for (auto &TId : TheIndex->typeIdCompatibleVtableMap()) + CreateGUIDSlot(GlobalValue::getGUID(TId.first)); + // Start numbering the TypeIds after the GUIDs. TypeIdNext = GUIDNext; - for (auto TidIter = TheIndex->typeIds().begin(); TidIter != TheIndex->typeIds().end(); TidIter++) CreateTypeIdSlot(TidIter->second.first); - for (auto &TId : TheIndex->typeIdCompatibleVtableMap()) - CreateGUIDSlot(GlobalValue::getGUID(TId.first)); - ST_DEBUG("end processIndex!\n"); + return TypeIdNext; } void SlotTracker::processGlobalObjectMetadata(const GlobalObject &GO) { @@ -2678,7 +2680,7 @@ void AssemblyWriter::printModuleSummaryIndex() { assert(TheIndex); - Machine.initializeIndexIfNeeded(); + int NumSlots = Machine.initializeIndexIfNeeded(); Out << "\n"; @@ -2740,6 +2742,10 @@ printTypeIdCompatibleVtableSummary(TId.second); Out << ") ; guid = " << GUID << "\n"; } + + // Don't emit flags when it's not really needed (value is zero by default). + if (TheIndex->getFlags()) + Out << "^" << NumSlots << " = flags: " << TheIndex->getFlags() << "\n"; } static const char * diff --git a/llvm/lib/IR/ModuleSummaryIndex.cpp b/llvm/lib/IR/ModuleSummaryIndex.cpp --- a/llvm/lib/IR/ModuleSummaryIndex.cpp +++ b/llvm/lib/IR/ModuleSummaryIndex.cpp @@ -72,6 +72,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( diff --git a/llvm/test/Assembler/summary-flags.ll b/llvm/test/Assembler/summary-flags.ll new file mode 100644 --- /dev/null +++ b/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