summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Bitcode
diff options
context:
space:
mode:
authorTeresa Johnson <tejohnson@google.com>2016-05-10 13:48:23 +0000
committerTeresa Johnson <tejohnson@google.com>2016-05-10 13:48:23 +0000
commit84174c3771e69214474b09e4afb26f10eef49245 (patch)
tree1b8f50c93464050b2cc1b8a81b0c9ada4d91c82b /llvm/lib/Bitcode
parent7189b0fdb2d06b4107185428aee8c31157ee9c9c (diff)
downloadbcm5719-llvm-84174c3771e69214474b09e4afb26f10eef49245.tar.gz
bcm5719-llvm-84174c3771e69214474b09e4afb26f10eef49245.zip
Restore "[ThinLTO] Emit individual index files for distributed backends"
This restores commit r268627: Summary: When launching ThinLTO backends in a distributed build (currently supported in gold via the thinlto-index-only plugin option), emit an individual index file for each backend process as described here: http://lists.llvm.org/pipermail/llvm-dev/2016-April/098272.html ... Differential Revision: http://reviews.llvm.org/D19556 Address msan failures by avoiding std::prev on map.end(), the theory is that this is causing issues due to some known UB problems in __tree. llvm-svn: 269059
Diffstat (limited to 'llvm/lib/Bitcode')
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp286
1 files changed, 215 insertions, 71 deletions
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 035e03e206e..64d3bd90dac 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -263,6 +263,10 @@ class IndexBitcodeWriter : public BitcodeWriter {
/// The combined index to write to bitcode.
const ModuleSummaryIndex &Index;
+ /// When writing a subset of the index for distributed backends, client
+ /// provides a map of modules to the corresponding GUIDs/summaries to write.
+ std::map<std::string, GVSummaryMapTy> *ModuleToSummariesForIndex;
+
/// Map that holds the correspondence between the GUID used in the combined
/// index and a value id generated by this class to use in references.
std::map<GlobalValue::GUID, unsigned> GUIDToValueIdMap;
@@ -272,17 +276,147 @@ class IndexBitcodeWriter : public BitcodeWriter {
public:
/// Constructs a IndexBitcodeWriter object for the given combined index,
- /// writing to the provided \p Buffer.
+ /// writing to the provided \p Buffer. When writing a subset of the index
+ /// for a distributed backend, provide a \p ModuleToSummariesForIndex map.
IndexBitcodeWriter(SmallVectorImpl<char> &Buffer,
- const ModuleSummaryIndex &Index)
- : BitcodeWriter(Buffer), Index(Index) {
- // Assign unique value ids to all functions in the index for use
+ const ModuleSummaryIndex &Index,
+ std::map<std::string, GVSummaryMapTy>
+ *ModuleToSummariesForIndex = nullptr)
+ : BitcodeWriter(Buffer), Index(Index),
+ ModuleToSummariesForIndex(ModuleToSummariesForIndex) {
+ // Assign unique value ids to all summaries to be written, for use
// in writing out the call graph edges. Save the mapping from GUID
// to the new global value id to use when writing those edges, which
// are currently saved in the index in terms of GUID.
- for (auto &II : Index)
- GUIDToValueIdMap[II.first] = ++GlobalValueId;
- }
+ for (const auto &I : *this)
+ GUIDToValueIdMap[I.first] = ++GlobalValueId;
+ }
+
+ /// The below iterator returns the GUID and associated summary.
+ typedef std::pair<GlobalValue::GUID, GlobalValueSummary *> GVInfo;
+
+ /// Iterator over the value GUID and summaries to be written to bitcode,
+ /// hides the details of whether they are being pulled from the entire
+ /// index or just those in a provided ModuleToSummariesForIndex map.
+ class iterator
+ : public llvm::iterator_facade_base<iterator, std::forward_iterator_tag,
+ GVInfo> {
+ /// Enables access to parent class.
+ const IndexBitcodeWriter &Writer;
+
+ // Iterators used when writing only those summaries in a provided
+ // ModuleToSummariesForIndex map:
+
+ /// Points to the last element in outer ModuleToSummariesForIndex map.
+ std::map<std::string, GVSummaryMapTy>::iterator ModuleSummariesBack;
+ /// Iterator on outer ModuleToSummariesForIndex map.
+ std::map<std::string, GVSummaryMapTy>::iterator ModuleSummariesIter;
+ /// Iterator on an inner global variable summary map.
+ GVSummaryMapTy::iterator ModuleGVSummariesIter;
+
+ // Iterators used when writing all summaries in the index:
+
+ /// Points to the last element in the Index outer GlobalValueMap.
+ const_gvsummary_iterator IndexSummariesBack;
+ /// Iterator on outer GlobalValueMap.
+ const_gvsummary_iterator IndexSummariesIter;
+ /// Iterator on an inner GlobalValueSummaryList.
+ GlobalValueSummaryList::const_iterator IndexGVSummariesIter;
+
+ public:
+ /// Construct iterator from parent \p Writer and indicate if we are
+ /// constructing the end iterator.
+ iterator(const IndexBitcodeWriter &Writer, bool IsAtEnd) : Writer(Writer) {
+ // Set up the appropriate set of iterators given whether we are writing
+ // the full index or just a subset.
+ // Can't setup the Back or inner iterators if the corresponding map
+ // is empty. This will be handled specially in operator== as well.
+ if (Writer.ModuleToSummariesForIndex &&
+ !Writer.ModuleToSummariesForIndex->empty()) {
+ ModuleSummariesIter = Writer.ModuleToSummariesForIndex->begin();
+ for (ModuleSummariesBack = Writer.ModuleToSummariesForIndex->begin();
+ std::next(ModuleSummariesBack) !=
+ Writer.ModuleToSummariesForIndex->end();
+ ModuleSummariesBack++)
+ ;
+ ModuleGVSummariesIter = !IsAtEnd ? ModuleSummariesIter->second.begin()
+ : ModuleSummariesBack->second.end();
+ } else if (!Writer.ModuleToSummariesForIndex &&
+ Writer.Index.begin() != Writer.Index.end()) {
+ IndexSummariesIter = Writer.Index.begin();
+ for (IndexSummariesBack = Writer.Index.begin();
+ std::next(IndexSummariesBack) != Writer.Index.end();
+ IndexSummariesBack++)
+ ;
+ IndexGVSummariesIter = !IsAtEnd ? IndexSummariesIter->second.begin()
+ : IndexSummariesBack->second.end();
+ }
+ }
+
+ /// Increment the appropriate set of iterators.
+ iterator &operator++() {
+ // First the inner iterator is incremented, then if it is at the end
+ // and there are more outer iterations to go, the inner is reset to
+ // the start of the next inner list.
+ if (Writer.ModuleToSummariesForIndex) {
+ ++ModuleGVSummariesIter;
+ if (ModuleGVSummariesIter == ModuleSummariesIter->second.end() &&
+ ModuleSummariesIter != ModuleSummariesBack) {
+ ++ModuleSummariesIter;
+ ModuleGVSummariesIter = ModuleSummariesIter->second.begin();
+ }
+ } else {
+ ++IndexGVSummariesIter;
+ if (IndexGVSummariesIter == IndexSummariesIter->second.end() &&
+ IndexSummariesIter != IndexSummariesBack) {
+ ++IndexSummariesIter;
+ IndexGVSummariesIter = IndexSummariesIter->second.begin();
+ }
+ }
+ return *this;
+ }
+
+ /// Access the <GUID,GlobalValueSummary*> pair corresponding to the current
+ /// outer and inner iterator positions.
+ GVInfo operator*() {
+ if (Writer.ModuleToSummariesForIndex)
+ return std::make_pair(ModuleGVSummariesIter->first,
+ ModuleGVSummariesIter->second);
+ return std::make_pair(IndexSummariesIter->first,
+ IndexGVSummariesIter->get());
+ }
+
+ /// Checks if the iterators are equal, with special handling for empty
+ /// indexes.
+ bool operator==(const iterator &RHS) const {
+ if (Writer.ModuleToSummariesForIndex) {
+ // First ensure that both are writing the same subset.
+ if (Writer.ModuleToSummariesForIndex !=
+ RHS.Writer.ModuleToSummariesForIndex)
+ return false;
+ // Already determined above that maps are the same, so if one is
+ // empty, they both are.
+ if (Writer.ModuleToSummariesForIndex->empty())
+ return true;
+ return ModuleGVSummariesIter == RHS.ModuleGVSummariesIter;
+ }
+ // First ensure RHS also writing the full index, and that both are
+ // writing the same full index.
+ if (RHS.Writer.ModuleToSummariesForIndex ||
+ &Writer.Index != &RHS.Writer.Index)
+ return false;
+ // Already determined above that maps are the same, so if one is
+ // empty, they both are.
+ if (Writer.Index.begin() == Writer.Index.end())
+ return true;
+ return IndexGVSummariesIter == RHS.IndexGVSummariesIter;
+ }
+ };
+
+ /// Obtain the start iterator over the summaries to be written.
+ iterator begin() { return iterator(*this, /*IsAtEnd=*/false); }
+ /// Obtain the end iterator over the summaries to be written.
+ iterator end() { return iterator(*this, /*IsAtEnd=*/true); }
private:
/// Main entry point for writing a combined index to bitcode, invoked by
@@ -294,6 +428,14 @@ private:
void writeCombinedValueSymbolTable();
void writeCombinedGlobalValueSummary();
+ /// Indicates whether the provided \p ModulePath should be written into
+ /// the module string table, e.g. if full index written or if it is in
+ /// the provided subset.
+ bool doIncludeModule(StringRef ModulePath) {
+ return !ModuleToSummariesForIndex ||
+ ModuleToSummariesForIndex->count(ModulePath);
+ }
+
bool hasValueId(GlobalValue::GUID ValGUID) {
const auto &VMI = GUIDToValueIdMap.find(ValGUID);
return VMI != GUIDToValueIdMap.end();
@@ -2964,6 +3106,8 @@ void IndexBitcodeWriter::writeModStrings() {
SmallVector<unsigned, 64> Vals;
for (const auto &MPSE : Index.modulePaths()) {
+ if (!doIncludeModule(MPSE.getKey()))
+ continue;
StringEncoding Bits =
getStringEncoding(MPSE.getKey().data(), MPSE.getKey().size());
unsigned AbbrevToUse = Abbrev8Bit;
@@ -3217,78 +3361,75 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
NameVals.clear();
};
- for (const auto &GSI : Index) {
- for (auto &SI : GSI.second) {
- GlobalValueSummary *S = SI.get();
- assert(S);
-
- assert(hasValueId(GSI.first));
- unsigned ValueId = getValueId(GSI.first);
- SummaryToValueIdMap[S] = ValueId;
-
- if (auto *AS = dyn_cast<AliasSummary>(S)) {
- // Will process aliases as a post-pass because the reader wants all
- // global to be loaded first.
- Aliases.push_back(AS);
- continue;
- }
+ for (const auto &I : *this) {
+ GlobalValueSummary *S = I.second;
+ assert(S);
- if (auto *VS = dyn_cast<GlobalVarSummary>(S)) {
- NameVals.push_back(ValueId);
- NameVals.push_back(Index.getModuleId(VS->modulePath()));
- NameVals.push_back(getEncodedGVSummaryFlags(VS->flags()));
- for (auto &RI : VS->refs()) {
- NameVals.push_back(getValueId(RI.getGUID()));
- }
+ assert(hasValueId(I.first));
+ unsigned ValueId = getValueId(I.first);
+ SummaryToValueIdMap[S] = ValueId;
- // Emit the finished record.
- Stream.EmitRecord(bitc::FS_COMBINED_GLOBALVAR_INIT_REFS, NameVals,
- FSModRefsAbbrev);
- NameVals.clear();
- MaybeEmitOriginalName(*S);
- continue;
- }
+ if (auto *AS = dyn_cast<AliasSummary>(S)) {
+ // Will process aliases as a post-pass because the reader wants all
+ // global to be loaded first.
+ Aliases.push_back(AS);
+ continue;
+ }
- auto *FS = cast<FunctionSummary>(S);
+ if (auto *VS = dyn_cast<GlobalVarSummary>(S)) {
NameVals.push_back(ValueId);
- NameVals.push_back(Index.getModuleId(FS->modulePath()));
- NameVals.push_back(getEncodedGVSummaryFlags(FS->flags()));
- NameVals.push_back(FS->instCount());
- NameVals.push_back(FS->refs().size());
-
- for (auto &RI : FS->refs()) {
+ NameVals.push_back(Index.getModuleId(VS->modulePath()));
+ NameVals.push_back(getEncodedGVSummaryFlags(VS->flags()));
+ for (auto &RI : VS->refs()) {
NameVals.push_back(getValueId(RI.getGUID()));
}
- bool HasProfileData = false;
- for (auto &EI : FS->calls()) {
- HasProfileData |= EI.second.ProfileCount != 0;
- if (HasProfileData)
- break;
- }
-
- for (auto &EI : FS->calls()) {
- // If this GUID doesn't have a value id, it doesn't have a function
- // summary and we don't need to record any calls to it.
- if (!hasValueId(EI.first.getGUID()))
- continue;
- NameVals.push_back(getValueId(EI.first.getGUID()));
- assert(EI.second.CallsiteCount > 0 && "Expected at least one callsite");
- NameVals.push_back(EI.second.CallsiteCount);
- if (HasProfileData)
- NameVals.push_back(EI.second.ProfileCount);
- }
-
- unsigned FSAbbrev =
- (HasProfileData ? FSCallsProfileAbbrev : FSCallsAbbrev);
- unsigned Code =
- (HasProfileData ? bitc::FS_COMBINED_PROFILE : bitc::FS_COMBINED);
-
// Emit the finished record.
- Stream.EmitRecord(Code, NameVals, FSAbbrev);
+ Stream.EmitRecord(bitc::FS_COMBINED_GLOBALVAR_INIT_REFS, NameVals,
+ FSModRefsAbbrev);
NameVals.clear();
MaybeEmitOriginalName(*S);
+ continue;
}
+
+ auto *FS = cast<FunctionSummary>(S);
+ NameVals.push_back(ValueId);
+ NameVals.push_back(Index.getModuleId(FS->modulePath()));
+ NameVals.push_back(getEncodedGVSummaryFlags(FS->flags()));
+ NameVals.push_back(FS->instCount());
+ NameVals.push_back(FS->refs().size());
+
+ for (auto &RI : FS->refs()) {
+ NameVals.push_back(getValueId(RI.getGUID()));
+ }
+
+ bool HasProfileData = false;
+ for (auto &EI : FS->calls()) {
+ HasProfileData |= EI.second.ProfileCount != 0;
+ if (HasProfileData)
+ break;
+ }
+
+ for (auto &EI : FS->calls()) {
+ // If this GUID doesn't have a value id, it doesn't have a function
+ // summary and we don't need to record any calls to it.
+ if (!hasValueId(EI.first.getGUID()))
+ continue;
+ NameVals.push_back(getValueId(EI.first.getGUID()));
+ assert(EI.second.CallsiteCount > 0 && "Expected at least one callsite");
+ NameVals.push_back(EI.second.CallsiteCount);
+ if (HasProfileData)
+ NameVals.push_back(EI.second.ProfileCount);
+ }
+
+ unsigned FSAbbrev = (HasProfileData ? FSCallsProfileAbbrev : FSCallsAbbrev);
+ unsigned Code =
+ (HasProfileData ? bitc::FS_COMBINED_PROFILE : bitc::FS_COMBINED);
+
+ // Emit the finished record.
+ Stream.EmitRecord(Code, NameVals, FSAbbrev);
+ NameVals.clear();
+ MaybeEmitOriginalName(*S);
}
for (auto *AS : Aliases) {
@@ -3562,12 +3703,15 @@ void IndexBitcodeWriter::writeIndex() {
// Write the specified module summary index to the given raw output stream,
// where it will be written in a new bitcode block. This is used when
-// writing the combined index file for ThinLTO.
-void llvm::WriteIndexToFile(const ModuleSummaryIndex &Index, raw_ostream &Out) {
+// writing the combined index file for ThinLTO. When writing a subset of the
+// index for a distributed backend, provide a \p ModuleToSummariesForIndex map.
+void llvm::WriteIndexToFile(
+ const ModuleSummaryIndex &Index, raw_ostream &Out,
+ std::map<std::string, GVSummaryMapTy> *ModuleToSummariesForIndex) {
SmallVector<char, 0> Buffer;
Buffer.reserve(256 * 1024);
- IndexBitcodeWriter IndexWriter(Buffer, Index);
+ IndexBitcodeWriter IndexWriter(Buffer, Index, ModuleToSummariesForIndex);
IndexWriter.write();
Out.write((char *)&Buffer.front(), Buffer.size());
OpenPOWER on IntegriCloud