diff options
Diffstat (limited to 'lib/Bitcode/Writer/BitcodeWriter.cpp')
-rw-r--r-- | lib/Bitcode/Writer/BitcodeWriter.cpp | 155 |
1 files changed, 111 insertions, 44 deletions
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index ebb2022551f7..043441bac4de 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -108,6 +108,14 @@ class ModuleBitcodeWriter : public BitcodeWriterBase { /// True if a module hash record should be written. bool GenerateHash; + /// If non-null, when GenerateHash is true, the resulting hash is written + /// into ModHash. When GenerateHash is false, that specified value + /// is used as the hash instead of computing from the generated bitcode. + /// Can be used to produce the same module hash for a minimized bitcode + /// used just for the thin link as in the regular full bitcode that will + /// be used in the backend. + ModuleHash *ModHash; + /// The start bit of the identification block. uint64_t BitcodeStartBit; @@ -124,10 +132,12 @@ public: /// writing to the provided \p Buffer. ModuleBitcodeWriter(const Module *M, SmallVectorImpl<char> &Buffer, BitstreamWriter &Stream, bool ShouldPreserveUseListOrder, - const ModuleSummaryIndex *Index, bool GenerateHash) + const ModuleSummaryIndex *Index, bool GenerateHash, + ModuleHash *ModHash = nullptr) : BitcodeWriterBase(Stream), Buffer(Buffer), M(*M), VE(*M, ShouldPreserveUseListOrder), Index(Index), - GenerateHash(GenerateHash), BitcodeStartBit(Stream.GetCurrentBitNo()) { + GenerateHash(GenerateHash), ModHash(ModHash), + BitcodeStartBit(Stream.GetCurrentBitNo()) { // Assign ValueIds to any callee values in the index that came from // indirect call profiles and were recorded as a GUID not a Value* // (which would have been assigned an ID by the ValueEnumerator). @@ -466,7 +476,6 @@ public: void write(); private: - void writeIndex(); void writeModStrings(); void writeCombinedValueSymbolTable(); void writeCombinedGlobalValueSummary(); @@ -709,22 +718,22 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { } void ModuleBitcodeWriter::writeAttributeGroupTable() { - const std::vector<AttributeSet> &AttrGrps = VE.getAttributeGroups(); + const std::vector<AttributeList> &AttrGrps = VE.getAttributeGroups(); if (AttrGrps.empty()) return; Stream.EnterSubblock(bitc::PARAMATTR_GROUP_BLOCK_ID, 3); SmallVector<uint64_t, 64> Record; for (unsigned i = 0, e = AttrGrps.size(); i != e; ++i) { - AttributeSet AS = AttrGrps[i]; + AttributeList AS = AttrGrps[i]; for (unsigned i = 0, e = AS.getNumSlots(); i != e; ++i) { - AttributeSet A = AS.getSlotAttributes(i); + AttributeList A = AS.getSlotAttributes(i); Record.push_back(VE.getAttributeGroupID(A)); Record.push_back(AS.getSlotIndex(i)); - for (AttributeSet::iterator I = AS.begin(0), E = AS.end(0); - I != E; ++I) { + for (AttributeList::iterator I = AS.begin(0), E = AS.end(0); I != E; + ++I) { Attribute Attr = *I; if (Attr.isEnumAttribute()) { Record.push_back(0); @@ -756,14 +765,14 @@ void ModuleBitcodeWriter::writeAttributeGroupTable() { } void ModuleBitcodeWriter::writeAttributeTable() { - const std::vector<AttributeSet> &Attrs = VE.getAttributes(); + const std::vector<AttributeList> &Attrs = VE.getAttributes(); if (Attrs.empty()) return; Stream.EnterSubblock(bitc::PARAMATTR_BLOCK_ID, 3); SmallVector<uint64_t, 64> Record; for (unsigned i = 0, e = Attrs.size(); i != e; ++i) { - const AttributeSet &A = Attrs[i]; + const AttributeList &A = Attrs[i]; for (unsigned i = 0, e = A.getNumSlots(); i != e; ++i) Record.push_back(VE.getAttributeGroupID(A.getSlotAttributes(i))); @@ -1326,6 +1335,8 @@ static uint64_t getOptimizationFlags(const Value *V) { Flags |= FastMathFlags::NoSignedZeros; if (FPMO->hasAllowReciprocal()) Flags |= FastMathFlags::AllowReciprocal; + if (FPMO->hasAllowContract()) + Flags |= FastMathFlags::AllowContract; } return Flags; @@ -1473,6 +1484,13 @@ void ModuleBitcodeWriter::writeDIDerivedType(const DIDerivedType *N, Record.push_back(N->getFlags()); Record.push_back(VE.getMetadataOrNullID(N->getExtraData())); + // DWARF address space is encoded as N->getDWARFAddressSpace() + 1. 0 means + // that there is no DWARF address space associated with DIDerivedType. + if (const auto &DWARFAddressSpace = N->getDWARFAddressSpace()) + Record.push_back(*DWARFAddressSpace + 1); + else + Record.push_back(0); + Stream.EmitRecord(bitc::METADATA_DERIVED_TYPE, Record, Abbrev); Record.clear(); } @@ -1549,6 +1567,7 @@ void ModuleBitcodeWriter::writeDICompileUnit(const DICompileUnit *N, Record.push_back(N->getDWOId()); Record.push_back(VE.getMetadataOrNullID(N->getMacros().get())); Record.push_back(N->getSplitDebugInlining()); + Record.push_back(N->getDebugInfoForProfiling()); Stream.EmitRecord(bitc::METADATA_COMPILE_UNIT, Record, Abbrev); Record.clear(); @@ -2559,7 +2578,7 @@ void ModuleBitcodeWriter::writeInstruction(const Instruction &I, Vals.push_back(VE.getTypeID(SI.getCondition()->getType())); pushValue(SI.getCondition(), InstID, Vals); Vals.push_back(VE.getValueID(SI.getDefaultDest())); - for (SwitchInst::ConstCaseIt Case : SI.cases()) { + for (auto Case : SI.cases()) { Vals.push_back(VE.getValueID(Case.getCaseValue())); Vals.push_back(VE.getValueID(Case.getCaseSuccessor())); } @@ -2905,13 +2924,6 @@ void ModuleBitcodeWriter::writeValueSymbolTable( NameVals.push_back(VE.getValueID(Name.getValue())); Function *F = dyn_cast<Function>(Name.getValue()); - if (!F) { - // If value is an alias, need to get the aliased base object to - // see if it is a function. - auto *GA = dyn_cast<GlobalAlias>(Name.getValue()); - if (GA && GA->getBaseObject()) - F = dyn_cast<Function>(GA->getBaseObject()); - } // VST_CODE_ENTRY: [valueid, namechar x N] // VST_CODE_FNENTRY: [valueid, funcoffset, namechar x N] @@ -3367,6 +3379,49 @@ void IndexBitcodeWriter::writeModStrings() { Stream.ExitBlock(); } +/// Write the function type metadata related records that need to appear before +/// a function summary entry (whether per-module or combined). +static void writeFunctionTypeMetadataRecords(BitstreamWriter &Stream, + FunctionSummary *FS) { + if (!FS->type_tests().empty()) + Stream.EmitRecord(bitc::FS_TYPE_TESTS, FS->type_tests()); + + SmallVector<uint64_t, 64> Record; + + auto WriteVFuncIdVec = [&](uint64_t Ty, + ArrayRef<FunctionSummary::VFuncId> VFs) { + if (VFs.empty()) + return; + Record.clear(); + for (auto &VF : VFs) { + Record.push_back(VF.GUID); + Record.push_back(VF.Offset); + } + Stream.EmitRecord(Ty, Record); + }; + + WriteVFuncIdVec(bitc::FS_TYPE_TEST_ASSUME_VCALLS, + FS->type_test_assume_vcalls()); + WriteVFuncIdVec(bitc::FS_TYPE_CHECKED_LOAD_VCALLS, + FS->type_checked_load_vcalls()); + + auto WriteConstVCallVec = [&](uint64_t Ty, + ArrayRef<FunctionSummary::ConstVCall> VCs) { + for (auto &VC : VCs) { + Record.clear(); + Record.push_back(VC.VFunc.GUID); + Record.push_back(VC.VFunc.Offset); + Record.insert(Record.end(), VC.Args.begin(), VC.Args.end()); + Stream.EmitRecord(Ty, Record); + } + }; + + WriteConstVCallVec(bitc::FS_TYPE_TEST_ASSUME_CONST_VCALL, + FS->type_test_assume_const_vcalls()); + WriteConstVCallVec(bitc::FS_TYPE_CHECKED_LOAD_CONST_VCALL, + FS->type_checked_load_const_vcalls()); +} + // Helper to emit a single function summary record. void ModuleBitcodeWriter::writePerModuleFunctionSummaryRecord( SmallVector<uint64_t, 64> &NameVals, GlobalValueSummary *Summary, @@ -3375,8 +3430,7 @@ void ModuleBitcodeWriter::writePerModuleFunctionSummaryRecord( NameVals.push_back(ValueID); FunctionSummary *FS = cast<FunctionSummary>(Summary); - if (!FS->type_tests().empty()) - Stream.EmitRecord(bitc::FS_TYPE_TESTS, FS->type_tests()); + writeFunctionTypeMetadataRecords(Stream, FS); NameVals.push_back(getEncodedGVSummaryFlags(FS->flags())); NameVals.push_back(FS->instCount()); @@ -3636,8 +3690,7 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() { } auto *FS = cast<FunctionSummary>(S); - if (!FS->type_tests().empty()) - Stream.EmitRecord(bitc::FS_TYPE_TESTS, FS->type_tests()); + writeFunctionTypeMetadataRecords(Stream, FS); NameVals.push_back(ValueId); NameVals.push_back(Index.getModuleId(FS->modulePath())); @@ -3659,9 +3712,16 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() { 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())); + GlobalValue::GUID GUID = EI.first.getGUID(); + if (!hasValueId(GUID)) { + // For SamplePGO, the indirect call targets for local functions will + // have its original name annotated in profile. We try to find the + // corresponding PGOFuncName as the GUID. + GUID = Index.getGUIDFromOriginalID(GUID); + if (GUID == 0 || !hasValueId(GUID)) + continue; + } + NameVals.push_back(getValueId(GUID)); if (HasProfileData) NameVals.push_back(static_cast<uint8_t>(EI.second.Hotness)); } @@ -3697,7 +3757,7 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() { /// Create the "IDENTIFICATION_BLOCK_ID" containing a single string with the /// current llvm version, and a record for the epoch number. -void writeIdentificationBlock(BitstreamWriter &Stream) { +static void writeIdentificationBlock(BitstreamWriter &Stream) { Stream.EnterSubblock(bitc::IDENTIFICATION_BLOCK_ID, 5); // Write the "user readable" string identifying the bitcode producer @@ -3722,17 +3782,24 @@ void writeIdentificationBlock(BitstreamWriter &Stream) { void ModuleBitcodeWriter::writeModuleHash(size_t BlockStartPos) { // Emit the module's hash. // MODULE_CODE_HASH: [5*i32] - SHA1 Hasher; - Hasher.update(ArrayRef<uint8_t>((const uint8_t *)&(Buffer)[BlockStartPos], - Buffer.size() - BlockStartPos)); - StringRef Hash = Hasher.result(); - uint32_t Vals[5]; - for (int Pos = 0; Pos < 20; Pos += 4) { - Vals[Pos / 4] = support::endian::read32be(Hash.data() + Pos); - } + if (GenerateHash) { + SHA1 Hasher; + uint32_t Vals[5]; + Hasher.update(ArrayRef<uint8_t>((const uint8_t *)&(Buffer)[BlockStartPos], + Buffer.size() - BlockStartPos)); + StringRef Hash = Hasher.result(); + for (int Pos = 0; Pos < 20; Pos += 4) { + Vals[Pos / 4] = support::endian::read32be(Hash.data() + Pos); + } - // Emit the finished record. - Stream.EmitRecord(bitc::MODULE_CODE_HASH, Vals); + // Emit the finished record. + Stream.EmitRecord(bitc::MODULE_CODE_HASH, Vals); + + if (ModHash) + // Save the written hash value. + std::copy(std::begin(Vals), std::end(Vals), std::begin(*ModHash)); + } else if (ModHash) + Stream.EmitRecord(bitc::MODULE_CODE_HASH, ArrayRef<uint32_t>(*ModHash)); } void ModuleBitcodeWriter::write() { @@ -3793,9 +3860,7 @@ void ModuleBitcodeWriter::write() { writeValueSymbolTable(M.getValueSymbolTable(), /* IsModuleLevel */ true, &FunctionToBitcodeIndex); - if (GenerateHash) { - writeModuleHash(BlockStartPos); - } + writeModuleHash(BlockStartPos); Stream.ExitBlock(); } @@ -3886,9 +3951,10 @@ BitcodeWriter::~BitcodeWriter() = default; void BitcodeWriter::writeModule(const Module *M, bool ShouldPreserveUseListOrder, const ModuleSummaryIndex *Index, - bool GenerateHash) { - ModuleBitcodeWriter ModuleWriter( - M, Buffer, *Stream, ShouldPreserveUseListOrder, Index, GenerateHash); + bool GenerateHash, ModuleHash *ModHash) { + ModuleBitcodeWriter ModuleWriter(M, Buffer, *Stream, + ShouldPreserveUseListOrder, Index, + GenerateHash, ModHash); ModuleWriter.write(); } @@ -3897,7 +3963,7 @@ void BitcodeWriter::writeModule(const Module *M, void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out, bool ShouldPreserveUseListOrder, const ModuleSummaryIndex *Index, - bool GenerateHash) { + bool GenerateHash, ModuleHash *ModHash) { SmallVector<char, 0> Buffer; Buffer.reserve(256*1024); @@ -3908,7 +3974,8 @@ void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out, Buffer.insert(Buffer.begin(), BWH_HeaderSize, 0); BitcodeWriter Writer(Buffer); - Writer.writeModule(M, ShouldPreserveUseListOrder, Index, GenerateHash); + Writer.writeModule(M, ShouldPreserveUseListOrder, Index, GenerateHash, + ModHash); if (TT.isOSDarwin() || TT.isOSBinFormatMachO()) emitDarwinBCHeaderAndTrailer(Buffer, TT); |