[llvm] r249270 - Support for function summary index bitcode sections and files.
Teresa Johnson via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 21 11:47:14 PDT 2015
Sorry about that, will do.
Thanks,
Teresa
On Wed, Oct 21, 2015 at 11:37 AM, Yaron Keren <yaron.keren at gmail.com> wrote:
> Hi Teresa,
>
> Visual C++ 2013 complains about BitcodeReader.cpp(5543): warning C4065:
> switch statement contains 'default' but no 'case' labels.
>
> switch (Stream.readRecord(Entry.ID, Record)) {
> default:
> return error("Invalid record");
> }
>
>
> To keep the build warning-free, could you silence it, maybe by adding a case
> something: statement just before the default:?
>
> Thanks, Yaron
>
>
>
> 2015-10-04 17:33 GMT+03:00 Teresa Johnson via llvm-commits
> <llvm-commits at lists.llvm.org>:
>>
>> Author: tejohnson
>> Date: Sun Oct 4 09:33:43 2015
>> New Revision: 249270
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=249270&view=rev
>> Log:
>> Support for function summary index bitcode sections and files.
>>
>> Summary:
>> The bitcode format is described in this document:
>> https://drive.google.com/file/d/0B036uwnWM6RWdnBLakxmeDdOeXc/view
>> For more info on ThinLTO see:
>> https://sites.google.com/site/llvmthinlto
>>
>> The first customer is ThinLTO, however the data structures are designed
>> and named more generally based on prior feedback. There are a few
>> comments regarding how certain interfaces are used by ThinLTO, and the
>> options added here to gold currently have ThinLTO-specific names as the
>> behavior they provoke is currently ThinLTO-specific.
>>
>> This patch includes support for generating per-module function indexes,
>> the combined index file via the gold plugin, and several tests
>> (more are included with the associated clang patch D11908).
>>
>> Reviewers: dexonsmith, davidxl, joker.eph
>>
>> Subscribers: llvm-commits
>>
>> Differential Revision: http://reviews.llvm.org/D13107
>>
>> Added:
>> llvm/trunk/include/llvm/IR/FunctionInfo.h
>> llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h
>> llvm/trunk/lib/IR/FunctionInfo.cpp
>> llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp
>> llvm/trunk/test/Bitcode/thinlto-function-summary.ll
>> llvm/trunk/test/tools/gold/X86/Inputs/thinlto.ll
>> llvm/trunk/test/tools/gold/X86/thinlto.ll
>> Modified:
>> llvm/trunk/include/llvm/Bitcode/BitcodeWriterPass.h
>> llvm/trunk/include/llvm/Bitcode/BitstreamWriter.h
>> llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
>> llvm/trunk/include/llvm/Bitcode/ReaderWriter.h
>> llvm/trunk/include/llvm/Object/Binary.h
>> llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
>> llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
>> llvm/trunk/lib/Bitcode/Writer/BitcodeWriterPass.cpp
>> llvm/trunk/lib/IR/CMakeLists.txt
>> llvm/trunk/lib/Object/CMakeLists.txt
>> llvm/trunk/tools/gold/gold-plugin.cpp
>> llvm/trunk/tools/llvm-as/llvm-as.cpp
>> llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
>>
>> Modified: llvm/trunk/include/llvm/Bitcode/BitcodeWriterPass.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/BitcodeWriterPass.h?rev=249270&r1=249269&r2=249270&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Bitcode/BitcodeWriterPass.h (original)
>> +++ llvm/trunk/include/llvm/Bitcode/BitcodeWriterPass.h Sun Oct 4
>> 09:33:43 2015
>> @@ -29,8 +29,12 @@ class PreservedAnalyses;
>> ///
>> /// If \c ShouldPreserveUseListOrder, encode use-list order so it can be
>> /// reproduced when deserialized.
>> +///
>> +/// If \c EmitFunctionSummary, emit the function summary index (currently
>> +/// for use in ThinLTO optimization).
>> ModulePass *createBitcodeWriterPass(raw_ostream &Str,
>> - bool ShouldPreserveUseListOrder =
>> false);
>> + bool ShouldPreserveUseListOrder =
>> false,
>> + bool EmitFunctionSummary = false);
>>
>> /// \brief Pass for writing a module of IR out to a bitcode file.
>> ///
>> @@ -39,15 +43,21 @@ ModulePass *createBitcodeWriterPass(raw_
>> class BitcodeWriterPass {
>> raw_ostream &OS;
>> bool ShouldPreserveUseListOrder;
>> + bool EmitFunctionSummary;
>>
>> public:
>> /// \brief Construct a bitcode writer pass around a particular output
>> stream.
>> ///
>> /// If \c ShouldPreserveUseListOrder, encode use-list order so it can
>> be
>> /// reproduced when deserialized.
>> + ///
>> + /// If \c EmitFunctionSummary, emit the function summary index
>> (currently
>> + /// for use in ThinLTO optimization).
>> explicit BitcodeWriterPass(raw_ostream &OS,
>> - bool ShouldPreserveUseListOrder = false)
>> - : OS(OS), ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {}
>> + bool ShouldPreserveUseListOrder = false,
>> + bool EmitFunctionSummary = false)
>> + : OS(OS), ShouldPreserveUseListOrder(ShouldPreserveUseListOrder),
>> + EmitFunctionSummary(EmitFunctionSummary) {}
>>
>> /// \brief Run the bitcode writer pass, and output the module to the
>> selected
>> /// output stream.
>>
>> Modified: llvm/trunk/include/llvm/Bitcode/BitstreamWriter.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/BitstreamWriter.h?rev=249270&r1=249269&r2=249270&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Bitcode/BitstreamWriter.h (original)
>> +++ llvm/trunk/include/llvm/Bitcode/BitstreamWriter.h Sun Oct 4 09:33:43
>> 2015
>> @@ -95,6 +95,9 @@ public:
>> /// \brief Retrieve the current position in the stream, in bits.
>> uint64_t GetCurrentBitNo() const { return GetBufferOffset() * 8 +
>> CurBit; }
>>
>> + /// \brief Retrieve the number of bits currently used to encode an
>> abbrev ID.
>> + unsigned GetAbbrevIDWidth() const { return CurCodeSize; }
>> +
>>
>> //===--------------------------------------------------------------------===//
>> // Basic Primitives for emitting bits to the stream.
>>
>> //===--------------------------------------------------------------------===//
>>
>> Modified: llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=249270&r1=249269&r2=249270&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)
>> +++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Sun Oct 4 09:33:43
>> 2015
>> @@ -150,6 +150,20 @@ namespace bitc {
>> VST_CODE_ENTRY = 1, // VST_ENTRY: [valueid, namechar x N]
>> VST_CODE_BBENTRY = 2, // VST_BBENTRY: [bbid, namechar x N]
>> VST_CODE_FNENTRY = 3, // VST_FNENTRY: [valueid, offset, namechar x
>> N]
>> + // VST_COMBINED_FNENTRY: [offset, namechar x N]
>> + VST_CODE_COMBINED_FNENTRY = 4
>> + };
>> +
>> + // The module path symbol table only has one code (MST_CODE_ENTRY).
>> + enum ModulePathSymtabCodes {
>> + MST_CODE_ENTRY = 1, // MST_ENTRY: [modid, namechar x N]
>> + };
>> +
>> + // The function summary section uses different codes in the per-module
>> + // and combined index cases.
>> + enum FunctionSummarySymtabCodes {
>> + FS_CODE_PERMODULE_ENTRY = 1, // FS_ENTRY: [valueid, islocal,
>> instcount]
>> + FS_CODE_COMBINED_ENTRY = 2, // FS_ENTRY: [modid, instcount]
>> };
>>
>> enum MetadataCodes {
>>
>> Modified: llvm/trunk/include/llvm/Bitcode/ReaderWriter.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/ReaderWriter.h?rev=249270&r1=249269&r2=249270&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Bitcode/ReaderWriter.h (original)
>> +++ llvm/trunk/include/llvm/Bitcode/ReaderWriter.h Sun Oct 4 09:33:43
>> 2015
>> @@ -15,6 +15,7 @@
>> #define LLVM_BITCODE_READERWRITER_H
>>
>> #include "llvm/IR/DiagnosticInfo.h"
>> +#include "llvm/IR/FunctionInfo.h"
>> #include "llvm/Support/Endian.h"
>> #include "llvm/Support/ErrorOr.h"
>> #include "llvm/Support/MemoryBuffer.h"
>> @@ -58,6 +59,30 @@ namespace llvm {
>> parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context,
>> DiagnosticHandlerFunction DiagnosticHandler =
>> nullptr);
>>
>> + /// Check if the given bitcode buffer contains a function summary
>> block.
>> + bool hasFunctionSummary(MemoryBufferRef Buffer, LLVMContext &Context,
>> + DiagnosticHandlerFunction DiagnosticHandler);
>> +
>> + /// Parse the specified bitcode buffer, returning the function info
>> index.
>> + /// If IsLazy is true, parse the entire function summary into
>> + /// the index. Otherwise skip the function summary section, and only
>> create
>> + /// an index object with a map from function name to function summary
>> offset.
>> + /// The index is used to perform lazy function summary reading later.
>> + ErrorOr<std::unique_ptr<FunctionInfoIndex>> getFunctionInfoIndex(
>> + MemoryBufferRef Buffer, LLVMContext &Context,
>> + DiagnosticHandlerFunction DiagnosticHandler, bool IsLazy = false);
>> +
>> + /// This method supports lazy reading of function summary data from the
>> + /// combined index during function importing. When reading the combined
>> index
>> + /// file, getFunctionInfoIndex is first invoked with IsLazy=true.
>> + /// Then this method is called for each function considered for
>> importing,
>> + /// to parse the summary information for the given function name into
>> + /// the index.
>> + std::error_code readFunctionSummary(
>> + MemoryBufferRef Buffer, LLVMContext &Context,
>> + DiagnosticHandlerFunction DiagnosticHandler, StringRef
>> FunctionName,
>> + std::unique_ptr<FunctionInfoIndex> Index);
>> +
>> /// \brief Write the specified module to the specified raw output
>> stream.
>> ///
>> /// For streams where it matters, the given stream should be in
>> "binary"
>> @@ -66,8 +91,18 @@ namespace llvm {
>> /// If \c ShouldPreserveUseListOrder, encode the use-list order for
>> each \a
>> /// Value in \c M. These will be reconstructed exactly when \a M is
>> /// deserialized.
>> + ///
>> + /// If \c EmitFunctionSummary, emit the function summary index
>> (currently
>> + /// for use in ThinLTO optimization).
>> void WriteBitcodeToFile(const Module *M, raw_ostream &Out,
>> - bool ShouldPreserveUseListOrder = false);
>> + bool ShouldPreserveUseListOrder = false,
>> + bool EmitFunctionSummary = false);
>> +
>> + /// Write the specified function 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 WriteFunctionSummaryToFile(const FunctionInfoIndex *Index,
>> + raw_ostream &Out);
>>
>> /// isBitcodeWrapper - Return true if the given bytes are the magic
>> bytes
>> /// for an LLVM IR bitcode wrapper.
>>
>> Added: llvm/trunk/include/llvm/IR/FunctionInfo.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/FunctionInfo.h?rev=249270&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/IR/FunctionInfo.h (added)
>> +++ llvm/trunk/include/llvm/IR/FunctionInfo.h Sun Oct 4 09:33:43 2015
>> @@ -0,0 +1,230 @@
>> +//===-- llvm/FunctionInfo.h - Function Info Index ---------------*- C++
>> -*-===//
>> +//
>> +// The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +/// @file
>> +/// FunctionInfo.h This file contains the declarations the classes that
>> hold
>> +/// the function info index and summary.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_IR_FUNCTIONINFO_H
>> +#define LLVM_IR_FUNCTIONINFO_H
>> +
>> +#include "llvm/ADT/SmallString.h"
>> +#include "llvm/ADT/StringMap.h"
>> +#include "llvm/IR/Module.h"
>> +#include "llvm/Support/MemoryBuffer.h"
>> +#include "llvm/Support/raw_ostream.h"
>> +
>> +namespace llvm {
>> +
>> +/// \brief Function summary information to aid decisions and
>> implementation of
>> +/// importing.
>> +///
>> +/// This is a separate class from FunctionInfo to enable lazy reading of
>> this
>> +/// function summary information from the combined index file during
>> imporing.
>> +class FunctionSummary {
>> + private:
>> + /// \brief Path of module containing function IR, used to locate module
>> when
>> + /// importing this function.
>> + ///
>> + /// This is only used during parsing of the combined function index, or
>> when
>> + /// parsing the per-module index for creation of the combined function
>> index,
>> + /// not during writing of the per-module index which doesn't contain a
>> + /// module path string table.
>> + StringRef ModulePath;
>> +
>> + /// \brief Used to flag functions that have local linkage types and
>> need to
>> + /// have module identifier appended before placing into the combined
>> + /// index, to disambiguate from other functions with the same name.
>> + ///
>> + /// This is only used in the per-module function index, as it is
>> consumed
>> + /// while creating the combined index.
>> + bool IsLocalFunction;
>> +
>> + // The rest of the information is used to help decide whether importing
>> + // is likely to be profitable.
>> + // Other information will be added as the importing is tuned, such
>> + // as hotness (when profile available), and other function
>> characteristics.
>> +
>> + /// Number of instructions (ignoring debug instructions, e.g.) computed
>> + /// during the initial compile step when the function index is first
>> built.
>> + unsigned InstCount;
>> +
>> + public:
>> + /// Construct a summary object from summary data expected for all
>> + /// summary records.
>> + FunctionSummary(unsigned NumInsts) : InstCount(NumInsts) {}
>> +
>> + /// Set the path to the module containing this function, for use in
>> + /// the combined index.
>> + void setModulePath(StringRef ModPath) { ModulePath = ModPath; }
>> +
>> + /// Get the path to the module containing this function.
>> + StringRef modulePath() const { return ModulePath; }
>> +
>> + /// Record whether this is a local function in the per-module index.
>> + void setLocalFunction(bool IsLocal) { IsLocalFunction = IsLocal; }
>> +
>> + /// Check whether this was a local function, for use in creating
>> + /// the combined index.
>> + bool isLocalFunction() const { return IsLocalFunction; }
>> +
>> + /// Get the instruction count recorded for this function.
>> + unsigned instCount() const { return InstCount; }
>> +};
>> +
>> +/// \brief Class to hold pointer to function summary and information
>> required
>> +/// for parsing it.
>> +///
>> +/// For the per-module index, this holds the bitcode offset
>> +/// of the corresponding function block. For the combined index,
>> +/// after parsing of the \a ValueSymbolTable, this initially
>> +/// holds the offset of the corresponding function summary bitcode
>> +/// record. After parsing the associated summary information from the
>> summary
>> +/// block the \a FunctionSummary is populated and stored here.
>> +class FunctionInfo {
>> + private:
>> + /// Function summary information used to help make ThinLTO importing
>> + /// decisions.
>> + std::unique_ptr<FunctionSummary> Summary;
>> +
>> + /// \brief The bitcode offset corresponding to either the associated
>> + /// function's function body record, or its function summary record,
>> + /// depending on whether this is a per-module or combined index.
>> + ///
>> + /// This bitcode offset is written to or read from the associated
>> + /// \a ValueSymbolTable entry for the function.
>> + /// For the per-module index this holds the bitcode offset of the
>> + /// function's body record within bitcode module block in its module,
>> + /// which is used during lazy function parsing or ThinLTO importing.
>> + /// For the combined index this holds the offset of the corresponding
>> + /// function summary record, to enable associating the combined index
>> + /// VST records with the summary records.
>> + uint64_t BitcodeIndex;
>> +
>> + public:
>> + /// Constructor used during parsing of VST entries.
>> + FunctionInfo(uint64_t FuncOffset)
>> + : Summary(nullptr), BitcodeIndex(FuncOffset) {}
>> +
>> + /// Constructor used for per-module index bitcode writing.
>> + FunctionInfo(uint64_t FuncOffset,
>> + std::unique_ptr<FunctionSummary> FuncSummary)
>> + : Summary(std::move(FuncSummary)), BitcodeIndex(FuncOffset) {}
>> +
>> + /// Record the function summary information parsed out of the function
>> + /// summary block during parsing or combined index creation.
>> + void setFunctionSummary(std::unique_ptr<FunctionSummary> FuncSummary) {
>> + Summary = std::move(FuncSummary);
>> + }
>> +
>> + /// Get the function summary recorded for this function.
>> + FunctionSummary *functionSummary() const { return Summary.get(); }
>> +
>> + /// Get the bitcode index recorded for this function, depending on
>> + /// the index type.
>> + uint64_t bitcodeIndex() const { return BitcodeIndex; }
>> +
>> + /// Record the bitcode index for this function, depending on
>> + /// the index type.
>> + void setBitcodeIndex(uint64_t FuncOffset) { BitcodeIndex = FuncOffset;
>> }
>> +};
>> +
>> +/// List of function info structures for a particular function name held
>> +/// in the FunctionMap. Requires a vector in the case of multiple
>> +/// COMDAT functions of the same name.
>> +typedef std::vector<std::unique_ptr<FunctionInfo>> FunctionInfoList;
>> +
>> +/// Map from function name to corresponding function info structures.
>> +typedef StringMap<FunctionInfoList> FunctionInfoMapTy;
>> +
>> +/// Type used for iterating through the function info map.
>> +typedef FunctionInfoMapTy::const_iterator const_funcinfo_iterator;
>> +typedef FunctionInfoMapTy::iterator funcinfo_iterator;
>> +
>> +/// String table to hold/own module path strings, which additionally
>> holds the
>> +/// module ID assigned to each module during the plugin step. The
>> StringMap
>> +/// makes a copy of and owns inserted strings.
>> +typedef StringMap<uint64_t> ModulePathStringTableTy;
>> +
>> +/// Class to hold module path string table and function map,
>> +/// and encapsulate methods for operating on them.
>> +class FunctionInfoIndex {
>> + private:
>> + /// Map from function name to list of function information instances
>> + /// for functions of that name (may be duplicates in the COMDAT case,
>> e.g.).
>> + FunctionInfoMapTy FunctionMap;
>> +
>> + /// Holds strings for combined index, mapping to the corresponding
>> module ID.
>> + ModulePathStringTableTy ModulePathStringTable;
>> +
>> + public:
>> + FunctionInfoIndex() = default;
>> + ~FunctionInfoIndex() = default;
>> +
>> + // Disable the copy constructor and assignment operators, so
>> + // no unexpected copying/moving occurs.
>> + FunctionInfoIndex(const FunctionInfoIndex &) = delete;
>> + void operator=(const FunctionInfoIndex &) = delete;
>> +
>> + funcinfo_iterator begin() { return FunctionMap.begin(); }
>> + const_funcinfo_iterator begin() const { return FunctionMap.begin(); }
>> + funcinfo_iterator end() { return FunctionMap.end(); }
>> + const_funcinfo_iterator end() const { return FunctionMap.end(); }
>> +
>> + /// Get the list of function info objects for a given function.
>> + const FunctionInfoList &getFunctionInfoList(StringRef FuncName) {
>> + return FunctionMap[FuncName];
>> + }
>> +
>> + /// Add a function info for a function of the given name.
>> + void addFunctionInfo(StringRef FuncName, std::unique_ptr<FunctionInfo>
>> Info) {
>> + FunctionMap[FuncName].push_back(std::move(Info));
>> + }
>> +
>> + /// Iterator to allow writer to walk through table during emission.
>> + iterator_range<StringMap<uint64_t>::const_iterator>
>> modPathStringEntries()
>> + const {
>> + return llvm::make_range(ModulePathStringTable.begin(),
>> + ModulePathStringTable.end());
>> + }
>> +
>> + /// Get the module ID recorded for the given module path.
>> + uint64_t getModuleId(const StringRef ModPath) const {
>> + return ModulePathStringTable.lookup(ModPath);
>> + }
>> +
>> + /// Add the given per-module index into this function index/summary,
>> + /// assigning it the given module ID. Each module merged in should have
>> + /// a unique ID, necessary for consistent renaming of promoted
>> + /// static (local) variables.
>> + void mergeFrom(std::unique_ptr<FunctionInfoIndex> Other,
>> + uint64_t NextModuleId);
>> +
>> + /// Convenience method for creating a promoted global name
>> + /// for the given value name of a local, and its original module's ID.
>> + static std::string getGlobalNameForLocal(StringRef Name, uint64_t
>> ModId) {
>> + SmallString<256> NewName(Name);
>> + NewName += ".llvm.";
>> + raw_svector_ostream(NewName) << ModId;
>> + return NewName.str();
>> + }
>> +
>> + /// Add a new module path, mapped to the given module Id, and return
>> StringRef
>> + /// owned by string table map.
>> + StringRef addModulePath(StringRef ModPath, uint64_t ModId) {
>> + return ModulePathStringTable.insert(std::make_pair(ModPath, ModId))
>> + .first->first();
>> + }
>> +};
>> +
>> +} // End llvm namespace
>> +
>> +#endif
>>
>> Modified: llvm/trunk/include/llvm/Object/Binary.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/Binary.h?rev=249270&r1=249269&r2=249270&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Object/Binary.h (original)
>> +++ llvm/trunk/include/llvm/Object/Binary.h Sun Oct 4 09:33:43 2015
>> @@ -43,6 +43,7 @@ protected:
>> ID_MachOUniversalBinary,
>> ID_COFFImportFile,
>> ID_IR, // LLVM IR
>> + ID_FunctionIndex, // Function summary index
>>
>> // Object and children.
>> ID_StartObjects,
>> @@ -122,6 +123,10 @@ public:
>> return TypeID == ID_IR;
>> }
>>
>> + bool isFunctionIndex() const {
>> + return TypeID == ID_FunctionIndex;
>> + }
>> +
>> bool isLittleEndian() const {
>> return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B ||
>> TypeID == ID_MachO32B || TypeID == ID_MachO64B);
>>
>> Added: llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h?rev=249270&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h (added)
>> +++ llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h Sun Oct 4
>> 09:33:43 2015
>> @@ -0,0 +1,99 @@
>> +//===- FunctionIndexObjectFile.h - Function index file implementation
>> -----===//
>> +//
>> +// The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// This file declares the FunctionIndexObjectFile template class.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_OBJECT_FUNCTIONINDEXOBJECTFILE_H
>> +#define LLVM_OBJECT_FUNCTIONINDEXOBJECTFILE_H
>> +
>> +#include "llvm/Object/SymbolicFile.h"
>> +
>> +namespace llvm {
>> +class FunctionInfoIndex;
>> +
>> +namespace object {
>> +class ObjectFile;
>> +
>> +/// This class is used to read just the function summary index related
>> +/// sections out of the given object (which may contain a single module's
>> +/// bitcode or be a combined index bitcode file). It builds a
>> FunctionInfoIndex
>> +/// object.
>> +class FunctionIndexObjectFile : public SymbolicFile {
>> + std::unique_ptr<FunctionInfoIndex> Index;
>> +
>> + public:
>> + FunctionIndexObjectFile(MemoryBufferRef Object,
>> + std::unique_ptr<FunctionInfoIndex> I);
>> + ~FunctionIndexObjectFile() override;
>> +
>> + // TODO: Walk through FunctionMap entries for function symbols.
>> + // However, currently these interfaces are not used by any consumers.
>> + void moveSymbolNext(DataRefImpl &Symb) const override {
>> + llvm_unreachable("not implemented");
>> + }
>> + std::error_code printSymbolName(raw_ostream &OS,
>> + DataRefImpl Symb) const override {
>> + llvm_unreachable("not implemented");
>> + return std::error_code();
>> + }
>> + uint32_t getSymbolFlags(DataRefImpl Symb) const override {
>> + llvm_unreachable("not implemented");
>> + return 0;
>> + }
>> + basic_symbol_iterator symbol_begin_impl() const override {
>> + llvm_unreachable("not implemented");
>> + return basic_symbol_iterator(BasicSymbolRef());
>> + }
>> + basic_symbol_iterator symbol_end_impl() const override {
>> + llvm_unreachable("not implemented");
>> + return basic_symbol_iterator(BasicSymbolRef());
>> + }
>> +
>> + const FunctionInfoIndex &getIndex() const {
>> + return const_cast<FunctionIndexObjectFile *>(this)->getIndex();
>> + }
>> + FunctionInfoIndex &getIndex() { return *Index; }
>> + std::unique_ptr<FunctionInfoIndex> takeIndex();
>> +
>> + static inline bool classof(const Binary *v) { return
>> v->isFunctionIndex(); }
>> +
>> + /// \brief Finds and returns bitcode embedded in the given object file,
>> or an
>> + /// error code if not found.
>> + static ErrorOr<MemoryBufferRef> findBitcodeInObject(const ObjectFile
>> &Obj);
>> +
>> + /// \brief Finds and returns bitcode in the given memory buffer (which
>> may
>> + /// be either a bitcode file or a native object file with embedded
>> bitcode),
>> + /// or an error code if not found.
>> + static ErrorOr<MemoryBufferRef> findBitcodeInMemBuffer(
>> + MemoryBufferRef Object);
>> +
>> + /// \brief Looks for function summary in the given memory buffer,
>> + /// returns true if found, else false.
>> + static bool hasFunctionSummaryInMemBuffer(MemoryBufferRef Object,
>> + LLVMContext &Context);
>> +
>> + /// \brief Parse function index in the given memory buffer.
>> + /// Return new FunctionIndexObjectFile instance containing parsed
>> function
>> + /// summary/index.
>> + static ErrorOr<std::unique_ptr<FunctionIndexObjectFile>> create(
>> + MemoryBufferRef Object, LLVMContext &Context, bool IsLazy = false);
>> +
>> + /// \brief Parse the function summary information for function with the
>> + /// given name out of the given buffer. Parsed information is
>> + /// stored on the index object saved in this object.
>> + std::error_code findFunctionSummaryInMemBuffer(MemoryBufferRef Object,
>> + LLVMContext &Context,
>> + StringRef FunctionName);
>> +};
>> +}
>> +}
>> +
>> +#endif
>>
>> Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=249270&r1=249269&r2=249270&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
>> +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Sun Oct 4 09:33:43
>> 2015
>> @@ -27,6 +27,7 @@
>> #include "llvm/IR/Module.h"
>> #include "llvm/IR/OperandTraits.h"
>> #include "llvm/IR/Operator.h"
>> +#include "llvm/IR/FunctionInfo.h"
>> #include "llvm/IR/ValueHandle.h"
>> #include "llvm/Support/DataStream.h"
>> #include "llvm/Support/ManagedStatic.h"
>> @@ -395,6 +396,96 @@ private:
>> Function *F,
>> DenseMap<Function *, uint64_t>::iterator
>> DeferredFunctionInfoIterator);
>> };
>> +
>> +/// Class to manage reading and parsing function summary index bitcode
>> +/// files/sections.
>> +class FunctionIndexBitcodeReader {
>> + LLVMContext &Context;
>> + DiagnosticHandlerFunction DiagnosticHandler;
>> +
>> + /// Eventually points to the function index built during parsing.
>> + FunctionInfoIndex *TheIndex = nullptr;
>> +
>> + std::unique_ptr<MemoryBuffer> Buffer;
>> + std::unique_ptr<BitstreamReader> StreamFile;
>> + BitstreamCursor Stream;
>> +
>> + /// \brief Used to indicate whether we are doing lazy parsing of
>> summary data.
>> + ///
>> + /// If false, the summary section is fully parsed into the index during
>> + /// the initial parse. Otherwise, if true, the caller is expected to
>> + /// invoke \a readFunctionSummary for each summary needed, and the
>> summary
>> + /// section is thus parsed lazily.
>> + bool IsLazy = false;
>> +
>> + /// Used to indicate whether caller only wants to check for the
>> presence
>> + /// of the function summary bitcode section. All blocks are skipped,
>> + /// but the SeenFuncSummary boolean is set.
>> + bool CheckFuncSummaryPresenceOnly = false;
>> +
>> + /// Indicates whether we have encountered a function summary section
>> + /// yet during parsing, used when checking if file contains function
>> + /// summary section.
>> + bool SeenFuncSummary = false;
>> +
>> + /// \brief Map populated during function summary section parsing, and
>> + /// consumed during ValueSymbolTable parsing.
>> + ///
>> + /// Used to correlate summary records with VST entries. For the
>> per-module
>> + /// index this maps the ValueID to the parsed function summary, and
>> + /// for the combined index this maps the summary record's bitcode
>> + /// offset to the function summary (since in the combined index the
>> + /// VST records do not hold value IDs but rather hold the function
>> + /// summary record offset).
>> + DenseMap<uint64_t, std::unique_ptr<FunctionSummary>> SummaryMap;
>> +
>> + /// Map populated during module path string table parsing, from the
>> + /// module ID to a string reference owned by the index's module
>> + /// path string table, used to correlate with combined index function
>> + /// summary records.
>> + DenseMap<uint64_t, StringRef> ModuleIdMap;
>> +
>> + public:
>> + std::error_code error(BitcodeError E, const Twine &Message);
>> + std::error_code error(BitcodeError E);
>> + std::error_code error(const Twine &Message);
>> +
>> + FunctionIndexBitcodeReader(MemoryBuffer *Buffer, LLVMContext &Context,
>> + DiagnosticHandlerFunction DiagnosticHandler,
>> + bool IsLazy = false,
>> + bool CheckFuncSummaryPresenceOnly = false);
>> + FunctionIndexBitcodeReader(LLVMContext &Context,
>> + DiagnosticHandlerFunction DiagnosticHandler,
>> + bool IsLazy = false,
>> + bool CheckFuncSummaryPresenceOnly = false);
>> + ~FunctionIndexBitcodeReader() { freeState(); }
>> +
>> + void freeState();
>> +
>> + void releaseBuffer();
>> +
>> + /// Check if the parser has encountered a function summary section.
>> + bool foundFuncSummary() { return SeenFuncSummary; }
>> +
>> + /// \brief Main interface to parsing a bitcode buffer.
>> + /// \returns true if an error occurred.
>> + std::error_code parseSummaryIndexInto(std::unique_ptr<DataStreamer>
>> Streamer,
>> + FunctionInfoIndex *I);
>> +
>> + /// \brief Interface for parsing a function summary lazily.
>> + std::error_code parseFunctionSummary(std::unique_ptr<DataStreamer>
>> Streamer,
>> + FunctionInfoIndex *I,
>> + size_t FunctionSummaryOffset);
>> +
>> + private:
>> + std::error_code parseModule();
>> + std::error_code parseValueSymbolTable();
>> + std::error_code parseEntireSummary();
>> + std::error_code parseModuleStringTable();
>> + std::error_code initStream(std::unique_ptr<DataStreamer> Streamer);
>> + std::error_code initStreamFromBuffer();
>> + std::error_code initLazyStream(std::unique_ptr<DataStreamer> Streamer);
>> +};
>> } // namespace
>>
>> BitcodeDiagnosticInfo::BitcodeDiagnosticInfo(std::error_code EC,
>> @@ -3377,6 +3468,19 @@ std::error_code BitcodeReader::parseModu
>> }
>> }
>>
>> +/// Helper to read the header common to all bitcode files.
>> +static bool hasValidBitcodeHeader(BitstreamCursor &Stream) {
>> + // Sniff for the signature.
>> + if (Stream.Read(8) != 'B' ||
>> + Stream.Read(8) != 'C' ||
>> + Stream.Read(4) != 0x0 ||
>> + Stream.Read(4) != 0xC ||
>> + Stream.Read(4) != 0xE ||
>> + Stream.Read(4) != 0xD)
>> + return false;
>> + return true;
>> +}
>> +
>> std::error_code
>> BitcodeReader::parseBitcodeInto(std::unique_ptr<DataStreamer> Streamer,
>> Module *M, bool ShouldLazyLoadMetadata) {
>> @@ -3386,13 +3490,7 @@ BitcodeReader::parseBitcodeInto(std::uni
>> return EC;
>>
>> // Sniff for the signature.
>> - if (Stream.Read(8) != 'B' ||
>> - Stream.Read(8) != 'C' ||
>> - Stream.Read(4) != 0x0 ||
>> - Stream.Read(4) != 0xC ||
>> - Stream.Read(4) != 0xE ||
>> - Stream.Read(4) != 0xD)
>> - return error("Invalid bitcode signature");
>> + if (!hasValidBitcodeHeader(Stream)) return error("Invalid bitcode
>> signature");
>>
>> // We expect a number of well-defined blocks, though we don't
>> necessarily
>> // need to understand them all.
>> @@ -3459,13 +3557,7 @@ ErrorOr<std::string> BitcodeReader::pars
>> return EC;
>>
>> // Sniff for the signature.
>> - if (Stream.Read(8) != 'B' ||
>> - Stream.Read(8) != 'C' ||
>> - Stream.Read(4) != 0x0 ||
>> - Stream.Read(4) != 0xC ||
>> - Stream.Read(4) != 0xE ||
>> - Stream.Read(4) != 0xD)
>> - return error("Invalid bitcode signature");
>> + if (!hasValidBitcodeHeader(Stream)) return error("Invalid bitcode
>> signature");
>>
>> // We expect a number of well-defined blocks, though we don't
>> necessarily
>> // need to understand them all.
>> @@ -5060,6 +5152,405 @@ BitcodeReader::initLazyStream(std::uniqu
>> return std::error_code();
>> }
>>
>> +std::error_code FunctionIndexBitcodeReader::error(BitcodeError E,
>> + const Twine &Message) {
>> + return ::error(DiagnosticHandler, make_error_code(E), Message);
>> +}
>> +
>> +std::error_code FunctionIndexBitcodeReader::error(const Twine &Message) {
>> + return ::error(DiagnosticHandler,
>> + make_error_code(BitcodeError::CorruptedBitcode),
>> Message);
>> +}
>> +
>> +std::error_code FunctionIndexBitcodeReader::error(BitcodeError E) {
>> + return ::error(DiagnosticHandler, make_error_code(E));
>> +}
>> +
>> +FunctionIndexBitcodeReader::FunctionIndexBitcodeReader(
>> + MemoryBuffer *Buffer, LLVMContext &Context,
>> + DiagnosticHandlerFunction DiagnosticHandler, bool IsLazy,
>> + bool CheckFuncSummaryPresenceOnly)
>> + : Context(Context),
>> + DiagnosticHandler(getDiagHandler(DiagnosticHandler, Context)),
>> + Buffer(Buffer),
>> + IsLazy(IsLazy),
>> + CheckFuncSummaryPresenceOnly(CheckFuncSummaryPresenceOnly) {}
>> +
>> +FunctionIndexBitcodeReader::FunctionIndexBitcodeReader(
>> + LLVMContext &Context, DiagnosticHandlerFunction DiagnosticHandler,
>> + bool IsLazy, bool CheckFuncSummaryPresenceOnly)
>> + : Context(Context),
>> + DiagnosticHandler(getDiagHandler(DiagnosticHandler, Context)),
>> + Buffer(nullptr),
>> + IsLazy(IsLazy),
>> + CheckFuncSummaryPresenceOnly(CheckFuncSummaryPresenceOnly) {}
>> +
>> +void FunctionIndexBitcodeReader::freeState() { Buffer = nullptr; }
>> +
>> +void FunctionIndexBitcodeReader::releaseBuffer() { Buffer.release(); }
>> +
>> +// Specialized value symbol table parser used when reading function index
>> +// blocks where we don't actually create global values.
>> +// At the end of this routine the function index is populated with a map
>> +// from function name to FunctionInfo. The function info contains
>> +// the function block's bitcode offset as well as the offset into the
>> +// function summary section.
>> +std::error_code FunctionIndexBitcodeReader::parseValueSymbolTable() {
>> + if (Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))
>> + return error("Invalid record");
>> +
>> + SmallVector<uint64_t, 64> Record;
>> +
>> + // Read all the records for this value table.
>> + SmallString<128> ValueName;
>> + while (1) {
>> + BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
>> +
>> + switch (Entry.Kind) {
>> + case BitstreamEntry::SubBlock: // Handled for us already.
>> + case BitstreamEntry::Error:
>> + return error("Malformed block");
>> + case BitstreamEntry::EndBlock:
>> + return std::error_code();
>> + case BitstreamEntry::Record:
>> + // The interesting case.
>> + break;
>> + }
>> +
>> + // Read a record.
>> + Record.clear();
>> + switch (Stream.readRecord(Entry.ID, Record)) {
>> + default: // Default behavior: ignore (e.g. VST_CODE_BBENTRY
>> records).
>> + break;
>> + case bitc::VST_CODE_FNENTRY: {
>> + // VST_FNENTRY: [valueid, offset, namechar x N]
>> + if (convertToString(Record, 2, ValueName))
>> + return error("Invalid record");
>> + unsigned ValueID = Record[0];
>> + uint64_t FuncOffset = Record[1];
>> + std::unique_ptr<FunctionInfo> FuncInfo =
>> + llvm::make_unique<FunctionInfo>(FuncOffset);
>> + if (foundFuncSummary() && !IsLazy) {
>> + DenseMap<uint64_t, std::unique_ptr<FunctionSummary>>::iterator
>> SMI =
>> + SummaryMap.find(ValueID);
>> + assert(SMI != SummaryMap.end() && "Summary info not found");
>> + FuncInfo->setFunctionSummary(std::move(SMI->second));
>> + }
>> + TheIndex->addFunctionInfo(ValueName, std::move(FuncInfo));
>> +
>> + ValueName.clear();
>> + break;
>> + }
>> + case bitc::VST_CODE_COMBINED_FNENTRY: {
>> + // VST_FNENTRY: [offset, namechar x N]
>> + if (convertToString(Record, 1, ValueName))
>> + return error("Invalid record");
>> + uint64_t FuncSummaryOffset = Record[0];
>> + std::unique_ptr<FunctionInfo> FuncInfo =
>> + llvm::make_unique<FunctionInfo>(FuncSummaryOffset);
>> + if (foundFuncSummary() && !IsLazy) {
>> + DenseMap<uint64_t, std::unique_ptr<FunctionSummary>>::iterator
>> SMI =
>> + SummaryMap.find(FuncSummaryOffset);
>> + assert(SMI != SummaryMap.end() && "Summary info not found");
>> + FuncInfo->setFunctionSummary(std::move(SMI->second));
>> + }
>> + TheIndex->addFunctionInfo(ValueName, std::move(FuncInfo));
>> +
>> + ValueName.clear();
>> + break;
>> + }
>> + }
>> + }
>> +}
>> +
>> +// Parse just the blocks needed for function index building out of the
>> module.
>> +// At the end of this routine the function Index is populated with a map
>> +// from function name to FunctionInfo. The function info contains
>> +// either the parsed function summary information (when parsing summaries
>> +// eagerly), or just to the function summary record's offset
>> +// if parsing lazily (IsLazy).
>> +std::error_code FunctionIndexBitcodeReader::parseModule() {
>> + if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
>> + return error("Invalid record");
>> +
>> + // Read the function index for this module.
>> + while (1) {
>> + BitstreamEntry Entry = Stream.advance();
>> +
>> + switch (Entry.Kind) {
>> + case BitstreamEntry::Error:
>> + return error("Malformed block");
>> + case BitstreamEntry::EndBlock:
>> + return std::error_code();
>> +
>> + case BitstreamEntry::SubBlock:
>> + if (CheckFuncSummaryPresenceOnly) {
>> + if (Entry.ID == bitc::FUNCTION_SUMMARY_BLOCK_ID)
>> + SeenFuncSummary = true;
>> + if (Stream.SkipBlock()) return error("Invalid record");
>> + // No need to parse the rest since we found the summary.
>> + return std::error_code();
>> + }
>> + switch (Entry.ID) {
>> + default: // Skip unknown content.
>> + if (Stream.SkipBlock()) return error("Invalid record");
>> + break;
>> + case bitc::BLOCKINFO_BLOCK_ID:
>> + // Need to parse these to get abbrev ids (e.g. for VST)
>> + if (Stream.ReadBlockInfoBlock()) return error("Malformed
>> block");
>> + break;
>> + case bitc::VALUE_SYMTAB_BLOCK_ID:
>> + if (std::error_code EC = parseValueSymbolTable()) return EC;
>> + break;
>> + case bitc::FUNCTION_SUMMARY_BLOCK_ID:
>> + SeenFuncSummary = true;
>> + if (IsLazy) {
>> + // Lazy parsing of summary info, skip it.
>> + if (Stream.SkipBlock()) return error("Invalid record");
>> + } else if (std::error_code EC = parseEntireSummary())
>> + return EC;
>> + break;
>> + case bitc::MODULE_STRTAB_BLOCK_ID:
>> + if (std::error_code EC = parseModuleStringTable()) return EC;
>> + break;
>> + }
>> + continue;
>> +
>> + case BitstreamEntry::Record:
>> + Stream.skipRecord(Entry.ID);
>> + continue;
>> + }
>> + }
>> +}
>> +
>> +// Eagerly parse the entire function summary block (i.e. for all
>> functions
>> +// in the index). This populates the FunctionSummary objects in
>> +// the index.
>> +std::error_code FunctionIndexBitcodeReader::parseEntireSummary() {
>> + if (Stream.EnterSubBlock(bitc::FUNCTION_SUMMARY_BLOCK_ID))
>> + return error("Invalid record");
>> +
>> + SmallVector<uint64_t, 64> Record;
>> +
>> + while (1) {
>> + BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
>> +
>> + switch (Entry.Kind) {
>> + case BitstreamEntry::SubBlock: // Handled for us already.
>> + case BitstreamEntry::Error:
>> + return error("Malformed block");
>> + case BitstreamEntry::EndBlock:
>> + return std::error_code();
>> + case BitstreamEntry::Record:
>> + // The interesting case.
>> + break;
>> + }
>> +
>> + // Read a record. The record format depends on whether this
>> + // is a per-module index or a combined index file. In the per-module
>> + // case the records contain the associated value's ID for correlation
>> + // with VST entries. In the combined index the correlation is done
>> + // via the bitcode offset of the summary records (which were saved
>> + // in the combined index VST entries). The records also contain
>> + // information used for ThinLTO renaming and importing.
>> + Record.clear();
>> + uint64_t CurRecordBit = Stream.GetCurrentBitNo();
>> + switch (Stream.readRecord(Entry.ID, Record)) {
>> + default: // Default behavior: ignore.
>> + break;
>> + // FS_PERMODULE_ENTRY: [valueid, islocal, instcount]
>> + case bitc::FS_CODE_PERMODULE_ENTRY: {
>> + unsigned ValueID = Record[0];
>> + bool IsLocal = Record[1];
>> + unsigned InstCount = Record[2];
>> + std::unique_ptr<FunctionSummary> FS =
>> + llvm::make_unique<FunctionSummary>(InstCount);
>> + FS->setLocalFunction(IsLocal);
>> + // The module path string ref set in the summary must be owned by
>> the
>> + // index's module string table. Since we don't have a module path
>> + // string table section in the per-module index, we create a
>> single
>> + // module path string table entry with an empty (0) ID to take
>> + // ownership.
>> + FS->setModulePath(
>> + TheIndex->addModulePath(Buffer->getBufferIdentifier(), 0));
>> + SummaryMap[ValueID] = std::move(FS);
>> + }
>> + // FS_COMBINED_ENTRY: [modid, instcount]
>> + case bitc::FS_CODE_COMBINED_ENTRY: {
>> + uint64_t ModuleId = Record[0];
>> + unsigned InstCount = Record[1];
>> + std::unique_ptr<FunctionSummary> FS =
>> + llvm::make_unique<FunctionSummary>(InstCount);
>> + FS->setModulePath(ModuleIdMap[ModuleId]);
>> + SummaryMap[CurRecordBit] = std::move(FS);
>> + }
>> + }
>> + }
>> + llvm_unreachable("Exit infinite loop");
>> +}
>> +
>> +// Parse the module string table block into the Index.
>> +// This populates the ModulePathStringTable map in the index.
>> +std::error_code FunctionIndexBitcodeReader::parseModuleStringTable() {
>> + if (Stream.EnterSubBlock(bitc::MODULE_STRTAB_BLOCK_ID))
>> + return error("Invalid record");
>> +
>> + SmallVector<uint64_t, 64> Record;
>> +
>> + SmallString<128> ModulePath;
>> + while (1) {
>> + BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
>> +
>> + switch (Entry.Kind) {
>> + case BitstreamEntry::SubBlock: // Handled for us already.
>> + case BitstreamEntry::Error:
>> + return error("Malformed block");
>> + case BitstreamEntry::EndBlock:
>> + return std::error_code();
>> + case BitstreamEntry::Record:
>> + // The interesting case.
>> + break;
>> + }
>> +
>> + Record.clear();
>> + switch (Stream.readRecord(Entry.ID, Record)) {
>> + default: // Default behavior: ignore.
>> + break;
>> + case bitc::MST_CODE_ENTRY: {
>> + // MST_ENTRY: [modid, namechar x N]
>> + if (convertToString(Record, 1, ModulePath))
>> + return error("Invalid record");
>> + uint64_t ModuleId = Record[0];
>> + StringRef ModulePathInMap =
>> + TheIndex->addModulePath(ModulePath, ModuleId);
>> + ModuleIdMap[ModuleId] = ModulePathInMap;
>> + ModulePath.clear();
>> + break;
>> + }
>> + }
>> + }
>> + llvm_unreachable("Exit infinite loop");
>> +}
>> +
>> +// Parse the function info index from the bitcode streamer into the given
>> index.
>> +std::error_code FunctionIndexBitcodeReader::parseSummaryIndexInto(
>> + std::unique_ptr<DataStreamer> Streamer, FunctionInfoIndex *I) {
>> + TheIndex = I;
>> +
>> + if (std::error_code EC = initStream(std::move(Streamer))) return EC;
>> +
>> + // Sniff for the signature.
>> + if (!hasValidBitcodeHeader(Stream)) return error("Invalid bitcode
>> signature");
>> +
>> + // We expect a number of well-defined blocks, though we don't
>> necessarily
>> + // need to understand them all.
>> + while (1) {
>> + if (Stream.AtEndOfStream()) {
>> + // We didn't really read a proper Module block.
>> + return error("Malformed block");
>> + }
>> +
>> + BitstreamEntry Entry =
>> + Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
>> +
>> + if (Entry.Kind != BitstreamEntry::SubBlock) return error("Malformed
>> block");
>> +
>> + // If we see a MODULE_BLOCK, parse it to find the blocks needed for
>> + // building the function summary index.
>> + if (Entry.ID == bitc::MODULE_BLOCK_ID) return parseModule();
>> +
>> + if (Stream.SkipBlock()) return error("Invalid record");
>> + }
>> +}
>> +
>> +// Parse the function information at the given offset in the buffer into
>> +// the index. Used to support lazy parsing of function summaries from the
>> +// combined index during importing.
>> +// TODO: This function is not yet complete as it won't have a consumer
>> +// until ThinLTO function importing is added.
>> +std::error_code FunctionIndexBitcodeReader::parseFunctionSummary(
>> + std::unique_ptr<DataStreamer> Streamer, FunctionInfoIndex *I,
>> + size_t FunctionSummaryOffset) {
>> + TheIndex = I;
>> +
>> + if (std::error_code EC = initStream(std::move(Streamer))) return EC;
>> +
>> + // Sniff for the signature.
>> + if (!hasValidBitcodeHeader(Stream)) return error("Invalid bitcode
>> signature");
>> +
>> + Stream.JumpToBit(FunctionSummaryOffset);
>> +
>> + BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
>> +
>> + switch (Entry.Kind) {
>> + default:
>> + return error("Malformed block");
>> + case BitstreamEntry::Record:
>> + // The expected case.
>> + break;
>> + }
>> +
>> + // TODO: Read a record. This interface will be completed when ThinLTO
>> + // importing is added so that it can be tested.
>> + SmallVector<uint64_t, 64> Record;
>> + switch (Stream.readRecord(Entry.ID, Record)) {
>> + default:
>> + return error("Invalid record");
>> + }
>> +
>> + return std::error_code();
>> +}
>> +
>> +std::error_code FunctionIndexBitcodeReader::initStream(
>> + std::unique_ptr<DataStreamer> Streamer) {
>> + if (Streamer) return initLazyStream(std::move(Streamer));
>> + return initStreamFromBuffer();
>> +}
>> +
>> +std::error_code FunctionIndexBitcodeReader::initStreamFromBuffer() {
>> + const unsigned char *BufPtr = (const unsigned char
>> *)Buffer->getBufferStart();
>> + const unsigned char *BufEnd = BufPtr + Buffer->getBufferSize();
>> +
>> + if (Buffer->getBufferSize() & 3) return error("Invalid bitcode
>> signature");
>> +
>> + // If we have a wrapper header, parse it and ignore the non-bc file
>> contents.
>> + // The magic number is 0x0B17C0DE stored in little endian.
>> + if (isBitcodeWrapper(BufPtr, BufEnd))
>> + if (SkipBitcodeWrapperHeader(BufPtr, BufEnd, true))
>> + return error("Invalid bitcode wrapper header");
>> +
>> + StreamFile.reset(new BitstreamReader(BufPtr, BufEnd));
>> + Stream.init(&*StreamFile);
>> +
>> + return std::error_code();
>> +}
>> +
>> +std::error_code FunctionIndexBitcodeReader::initLazyStream(
>> + std::unique_ptr<DataStreamer> Streamer) {
>> + // Check and strip off the bitcode wrapper; BitstreamReader expects
>> never to
>> + // see it.
>> + auto OwnedBytes =
>> + llvm::make_unique<StreamingMemoryObject>(std::move(Streamer));
>> + StreamingMemoryObject &Bytes = *OwnedBytes;
>> + StreamFile = llvm::make_unique<BitstreamReader>(std::move(OwnedBytes));
>> + Stream.init(&*StreamFile);
>> +
>> + unsigned char buf[16];
>> + if (Bytes.readBytes(buf, 16, 0) != 16)
>> + return error("Invalid bitcode signature");
>> +
>> + if (!isBitcode(buf, buf + 16)) return error("Invalid bitcode
>> signature");
>> +
>> + if (isBitcodeWrapper(buf, buf + 4)) {
>> + const unsigned char *bitcodeStart = buf;
>> + const unsigned char *bitcodeEnd = buf + 16;
>> + SkipBitcodeWrapperHeader(bitcodeStart, bitcodeEnd, false);
>> + Bytes.dropLeadingBytes(bitcodeStart - buf);
>> + Bytes.setKnownObjectSize(bitcodeEnd - bitcodeStart);
>> + }
>> + return std::error_code();
>> +}
>> +
>> namespace {
>> class BitcodeErrorCategoryType : public std::error_category {
>> const char *name() const LLVM_NOEXCEPT override {
>> @@ -5181,3 +5672,81 @@ llvm::getBitcodeTargetTriple(MemoryBuffe
>> return "";
>> return Triple.get();
>> }
>> +
>> +// Parse the specified bitcode buffer, returning the function info index.
>> +// If IsLazy is false, parse the entire function summary into
>> +// the index. Otherwise skip the function summary section, and only
>> create
>> +// an index object with a map from function name to function summary
>> offset.
>> +// The index is used to perform lazy function summary reading later.
>> +ErrorOr<std::unique_ptr<FunctionInfoIndex>> llvm::getFunctionInfoIndex(
>> + MemoryBufferRef Buffer, LLVMContext &Context,
>> + DiagnosticHandlerFunction DiagnosticHandler, bool IsLazy) {
>> + std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer,
>> false);
>> + FunctionIndexBitcodeReader R(Buf.get(), Context, DiagnosticHandler,
>> IsLazy);
>> +
>> + std::unique_ptr<FunctionInfoIndex> Index =
>> + llvm::make_unique<FunctionInfoIndex>();
>> +
>> + auto cleanupOnError = [&](std::error_code EC) {
>> + R.releaseBuffer(); // Never take ownership on error.
>> + return EC;
>> + };
>> +
>> + if (std::error_code EC = R.parseSummaryIndexInto(nullptr, Index.get()))
>> + return cleanupOnError(EC);
>> +
>> + Buf.release(); // The FunctionIndexBitcodeReader owns it now.
>> + return std::move(Index);
>> +}
>> +
>> +// Check if the given bitcode buffer contains a function summary block.
>> +bool llvm::hasFunctionSummary(MemoryBufferRef Buffer, LLVMContext
>> &Context,
>> + DiagnosticHandlerFunction
>> DiagnosticHandler) {
>> + std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer,
>> false);
>> + FunctionIndexBitcodeReader R(Buf.get(), Context, DiagnosticHandler,
>> false,
>> + true);
>> +
>> + auto cleanupOnError = [&](std::error_code EC) {
>> + R.releaseBuffer(); // Never take ownership on error.
>> + return false;
>> + };
>> +
>> + if (std::error_code EC = R.parseSummaryIndexInto(nullptr, nullptr))
>> + return cleanupOnError(EC);
>> +
>> + Buf.release(); // The FunctionIndexBitcodeReader owns it now.
>> + return R.foundFuncSummary();
>> +}
>> +
>> +// This method supports lazy reading of function summary data from the
>> combined
>> +// index during ThinLTO function importing. When reading the combined
>> index
>> +// file, getFunctionInfoIndex is first invoked with IsLazy=true.
>> +// Then this method is called for each function considered for importing,
>> +// to parse the summary information for the given function name into
>> +// the index.
>> +std::error_code llvm::readFunctionSummary(
>> + MemoryBufferRef Buffer, LLVMContext &Context,
>> + DiagnosticHandlerFunction DiagnosticHandler, StringRef FunctionName,
>> + std::unique_ptr<FunctionInfoIndex> Index) {
>> + std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer,
>> false);
>> + FunctionIndexBitcodeReader R(Buf.get(), Context, DiagnosticHandler);
>> +
>> + auto cleanupOnError = [&](std::error_code EC) {
>> + R.releaseBuffer(); // Never take ownership on error.
>> + return EC;
>> + };
>> +
>> + // Lookup the given function name in the FunctionMap, which may
>> + // contain a list of function infos in the case of a COMDAT. Walk
>> through
>> + // and parse each function summary info at the function summary offset
>> + // recorded when parsing the value symbol table.
>> + for (const auto &FI : Index->getFunctionInfoList(FunctionName)) {
>> + size_t FunctionSummaryOffset = FI->bitcodeIndex();
>> + if (std::error_code EC =
>> + R.parseFunctionSummary(nullptr, Index.get(),
>> FunctionSummaryOffset))
>> + return cleanupOnError(EC);
>> + }
>> +
>> + Buf.release(); // The FunctionIndexBitcodeReader owns it now.
>> + return std::error_code();
>> +}
>>
>> Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=249270&r1=249269&r2=249270&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
>> +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Sun Oct 4 09:33:43
>> 2015
>> @@ -13,6 +13,7 @@
>>
>> #include "llvm/Bitcode/ReaderWriter.h"
>> #include "ValueEnumerator.h"
>> +#include "llvm/ADT/STLExtras.h"
>> #include "llvm/ADT/Triple.h"
>> #include "llvm/Bitcode/BitstreamWriter.h"
>> #include "llvm/Bitcode/LLVMBitCodes.h"
>> @@ -23,6 +24,7 @@
>> #include "llvm/IR/InlineAsm.h"
>> #include "llvm/IR/Instructions.h"
>> #include "llvm/IR/LLVMContext.h"
>> +#include "llvm/IR/IntrinsicInst.h"
>> #include "llvm/IR/Module.h"
>> #include "llvm/IR/Operator.h"
>> #include "llvm/IR/UseListOrder.h"
>> @@ -2187,7 +2189,8 @@ static void WriteValueSymbolTable(
>> const ValueSymbolTable &VST, const ValueEnumerator &VE,
>> BitstreamWriter &Stream, uint64_t VSTOffsetPlaceholder = 0,
>> uint64_t BitcodeStartBit = 0,
>> - DenseMap<const Function *, uint64_t> *FunctionIndex = nullptr) {
>> + DenseMap<const Function *, std::unique_ptr<FunctionInfo>>
>> *FunctionIndex =
>> + nullptr) {
>> if (VST.empty()) {
>> // WriteValueSymbolTableForwardDecl should have returned early as
>> // well. Ensure this handling remains in sync by asserting that
>> @@ -2282,7 +2285,8 @@ static void WriteValueSymbolTable(
>> // Save the word offset of the function (from the start of the
>> // actual bitcode written to the stream).
>> assert(FunctionIndex->count(F) == 1);
>> - uint64_t BitcodeIndex = (*FunctionIndex)[F] - BitcodeStartBit;
>> + uint64_t BitcodeIndex =
>> + (*FunctionIndex)[F]->bitcodeIndex() - BitcodeStartBit;
>> assert((BitcodeIndex & 31) == 0 && "function block not 32-bit
>> aligned");
>> NameVals.push_back(BitcodeIndex / 32);
>>
>> @@ -2300,9 +2304,7 @@ static void WriteValueSymbolTable(
>> AbbrevToUse = VST_ENTRY_7_ABBREV;
>> }
>>
>> - for (const char *P = Name.getKeyData(),
>> - *E = Name.getKeyData()+Name.getKeyLength(); P != E; ++P)
>> - NameVals.push_back((unsigned char)*P);
>> + for (const auto P : Name.getKey()) NameVals.push_back((unsigned
>> char)P);
>>
>> // Emit the finished record.
>> Stream.EmitRecord(Code, NameVals, AbbrevToUse);
>> @@ -2311,6 +2313,68 @@ static void WriteValueSymbolTable(
>> Stream.ExitBlock();
>> }
>>
>> +/// Emit function names and summary offsets for the combined index
>> +/// used by ThinLTO.
>> +static void WriteCombinedValueSymbolTable(const FunctionInfoIndex *Index,
>> + BitstreamWriter &Stream) {
>> + Stream.EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 4);
>> +
>> + // 8-bit fixed-width VST_COMBINED_FNENTRY function strings.
>> + BitCodeAbbrev *Abbv = new BitCodeAbbrev();
>> + Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_COMBINED_FNENTRY));
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // funcoffset
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8));
>> + unsigned FnEntry8BitAbbrev = Stream.EmitAbbrev(Abbv);
>> +
>> + // 7-bit fixed width VST_COMBINED_FNENTRY function strings.
>> + Abbv = new BitCodeAbbrev();
>> + Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_COMBINED_FNENTRY));
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // funcoffset
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7));
>> + unsigned FnEntry7BitAbbrev = Stream.EmitAbbrev(Abbv);
>> +
>> + // 6-bit char6 VST_COMBINED_FNENTRY function strings.
>> + Abbv = new BitCodeAbbrev();
>> + Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_COMBINED_FNENTRY));
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // funcoffset
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
>> + unsigned FnEntry6BitAbbrev = Stream.EmitAbbrev(Abbv);
>> +
>> + // FIXME: We know if the type names can use 7-bit ascii.
>> + SmallVector<unsigned, 64> NameVals;
>> +
>> + for (const auto &FII : *Index) {
>> + for (const auto &FI : FII.getValue()) {
>> + NameVals.push_back(FI->bitcodeIndex());
>> +
>> + StringRef FuncName = FII.first();
>> +
>> + // Figure out the encoding to use for the name.
>> + StringEncoding Bits = getStringEncoding(FuncName.data(),
>> FuncName.size());
>> +
>> + // VST_COMBINED_FNENTRY: [funcsumoffset, namechar x N]
>> + unsigned AbbrevToUse = FnEntry8BitAbbrev;
>> + if (Bits == SE_Char6)
>> + AbbrevToUse = FnEntry6BitAbbrev;
>> + else if (Bits == SE_Fixed7)
>> + AbbrevToUse = FnEntry7BitAbbrev;
>> +
>> + for (const auto P : FuncName) NameVals.push_back((unsigned char)P);
>> +
>> + // Emit the finished record.
>> + Stream.EmitRecord(bitc::VST_CODE_COMBINED_FNENTRY, NameVals,
>> AbbrevToUse);
>> + NameVals.clear();
>> + }
>> + }
>> + Stream.ExitBlock();
>> +}
>> +
>> static void WriteUseList(ValueEnumerator &VE, UseListOrder &&Order,
>> BitstreamWriter &Stream) {
>> assert(Order.Shuffle.size() >= 2 && "Shuffle too small");
>> @@ -2345,14 +2409,33 @@ static void WriteUseListBlock(const Func
>> Stream.ExitBlock();
>> }
>>
>> -/// WriteFunction - Emit a function body to the module stream.
>> -static void WriteFunction(const Function &F, ValueEnumerator &VE,
>> - BitstreamWriter &Stream,
>> - DenseMap<const Function *, uint64_t>
>> &FunctionIndex) {
>> +/// \brief Save information for the given function into the function
>> index.
>> +///
>> +/// At a minimum this saves the bitcode index of the function record that
>> +/// was just written. However, if we are emitting function summary
>> information,
>> +/// for example for ThinLTO, then a \a FunctionSummary object is created
>> +/// to hold the provided summary information.
>> +static void SaveFunctionInfo(
>> + const Function &F,
>> + DenseMap<const Function *, std::unique_ptr<FunctionInfo>>
>> &FunctionIndex,
>> + unsigned NumInsts, uint64_t BitcodeIndex, bool EmitFunctionSummary) {
>> + std::unique_ptr<FunctionSummary> FuncSummary;
>> + if (EmitFunctionSummary) {
>> + FuncSummary = llvm::make_unique<FunctionSummary>(NumInsts);
>> + FuncSummary->setLocalFunction(F.hasLocalLinkage());
>> + }
>> + FunctionIndex[&F] =
>> + llvm::make_unique<FunctionInfo>(BitcodeIndex,
>> std::move(FuncSummary));
>> +}
>> +
>> +/// Emit a function body to the module stream.
>> +static void WriteFunction(
>> + const Function &F, ValueEnumerator &VE, BitstreamWriter &Stream,
>> + DenseMap<const Function *, std::unique_ptr<FunctionInfo>>
>> &FunctionIndex,
>> + bool EmitFunctionSummary) {
>> // Save the bitcode index of the start of this function block for
>> recording
>> // in the VST.
>> uint64_t BitcodeIndex = Stream.GetCurrentBitNo();
>> - FunctionIndex[&F] = BitcodeIndex;
>>
>> Stream.EnterSubblock(bitc::FUNCTION_BLOCK_ID, 4);
>> VE.incorporateFunction(F);
>> @@ -2379,6 +2462,7 @@ static void WriteFunction(const Function
>> bool NeedsMetadataAttachment = F.hasMetadata();
>>
>> DILocation *LastDL = nullptr;
>> + unsigned NumInsts = 0;
>>
>> // Finally, emit all the instructions, in order.
>> for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E;
>> ++BB)
>> @@ -2386,6 +2470,8 @@ static void WriteFunction(const Function
>> I != E; ++I) {
>> WriteInstruction(*I, InstID, VE, Stream, Vals);
>>
>> + if (!isa<DbgInfoIntrinsic>(I)) ++NumInsts;
>> +
>> if (!I->getType()->isVoidTy())
>> ++InstID;
>>
>> @@ -2422,6 +2508,9 @@ static void WriteFunction(const Function
>> WriteUseListBlock(&F, VE, Stream);
>> VE.purgeFunction();
>> Stream.ExitBlock();
>> +
>> + SaveFunctionInfo(F, FunctionIndex, NumInsts, BitcodeIndex,
>> + EmitFunctionSummary);
>> }
>>
>> // Emit blockinfo, which defines the standard abbreviations etc.
>> @@ -2599,10 +2688,155 @@ static void WriteBlockInfo(const ValueEn
>> Stream.ExitBlock();
>> }
>>
>> +/// Write the module path strings, currently only used when generating
>> +/// a combined index file.
>> +static void WriteModStrings(const FunctionInfoIndex *I,
>> + BitstreamWriter &Stream) {
>> + Stream.EnterSubblock(bitc::MODULE_STRTAB_BLOCK_ID, 3);
>> +
>> + // TODO: See which abbrev sizes we actually need to emit
>> +
>> + // 8-bit fixed-width MST_ENTRY strings.
>> + BitCodeAbbrev *Abbv = new BitCodeAbbrev();
>> + Abbv->Add(BitCodeAbbrevOp(bitc::MST_CODE_ENTRY));
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8));
>> + unsigned Abbrev8Bit = Stream.EmitAbbrev(Abbv);
>> +
>> + // 7-bit fixed width MST_ENTRY strings.
>> + Abbv = new BitCodeAbbrev();
>> + Abbv->Add(BitCodeAbbrevOp(bitc::MST_CODE_ENTRY));
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7));
>> + unsigned Abbrev7Bit = Stream.EmitAbbrev(Abbv);
>> +
>> + // 6-bit char6 MST_ENTRY strings.
>> + Abbv = new BitCodeAbbrev();
>> + Abbv->Add(BitCodeAbbrevOp(bitc::MST_CODE_ENTRY));
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
>> + unsigned Abbrev6Bit = Stream.EmitAbbrev(Abbv);
>> +
>> + SmallVector<unsigned, 64> NameVals;
>> + for (const StringMapEntry<uint64_t> &MPSE : I->modPathStringEntries())
>> {
>> + StringEncoding Bits =
>> + getStringEncoding(MPSE.getKey().data(), MPSE.getKey().size());
>> + unsigned AbbrevToUse = Abbrev8Bit;
>> + if (Bits == SE_Char6)
>> + AbbrevToUse = Abbrev6Bit;
>> + else if (Bits == SE_Fixed7)
>> + AbbrevToUse = Abbrev7Bit;
>> +
>> + NameVals.push_back(MPSE.getValue());
>> +
>> + for (const auto P : MPSE.getKey()) NameVals.push_back((unsigned
>> char)P);
>> +
>> + // Emit the finished record.
>> + Stream.EmitRecord(bitc::MST_CODE_ENTRY, NameVals, AbbrevToUse);
>> + NameVals.clear();
>> + }
>> + Stream.ExitBlock();
>> +}
>> +
>> +// Helper to emit a single function summary record.
>> +static void WritePerModuleFunctionSummaryRecord(
>> + SmallVector<unsigned, 64> &NameVals, FunctionSummary *FS, unsigned
>> ValueID,
>> + unsigned FSAbbrev, BitstreamWriter &Stream) {
>> + assert(FS);
>> + NameVals.push_back(ValueID);
>> + NameVals.push_back(FS->isLocalFunction());
>> + NameVals.push_back(FS->instCount());
>> +
>> + // Emit the finished record.
>> + Stream.EmitRecord(bitc::FS_CODE_PERMODULE_ENTRY, NameVals, FSAbbrev);
>> + NameVals.clear();
>> +}
>> +
>> +/// Emit the per-module function summary section alongside the rest of
>> +/// the module's bitcode.
>> +static void WritePerModuleFunctionSummary(
>> + DenseMap<const Function *, std::unique_ptr<FunctionInfo>>
>> &FunctionIndex,
>> + const Module *M, const ValueEnumerator &VE, BitstreamWriter &Stream)
>> {
>> + Stream.EnterSubblock(bitc::FUNCTION_SUMMARY_BLOCK_ID, 3);
>> +
>> + // Abbrev for FS_CODE_PERMODULE_ENTRY.
>> + BitCodeAbbrev *Abbv = new BitCodeAbbrev();
>> + Abbv->Add(BitCodeAbbrevOp(bitc::FS_CODE_PERMODULE_ENTRY));
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // valueid
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // islocal
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // instcount
>> + unsigned FSAbbrev = Stream.EmitAbbrev(Abbv);
>> +
>> + SmallVector<unsigned, 64> NameVals;
>> + for (auto &I : FunctionIndex) {
>> + // Skip anonymous functions. We will emit a function summary for
>> + // any aliases below.
>> + if (!I.first->hasName()) continue;
>> +
>> + WritePerModuleFunctionSummaryRecord(
>> + NameVals, I.second->functionSummary(),
>> +
>> VE.getValueID(M->getValueSymbolTable().lookup(I.first->getName())),
>> + FSAbbrev, Stream);
>> + }
>> +
>> + for (const GlobalAlias &A : M->aliases()) {
>> + if (!A.getBaseObject()) continue;
>> + const Function *F = dyn_cast<Function>(A.getBaseObject());
>> + if (!F || F->isDeclaration()) continue;
>> +
>> + assert(FunctionIndex.count(F) == 1);
>> + WritePerModuleFunctionSummaryRecord(
>> + NameVals, FunctionIndex[F]->functionSummary(),
>> + VE.getValueID(M->getValueSymbolTable().lookup(A.getName())),
>> FSAbbrev,
>> + Stream);
>> + }
>> +
>> + Stream.ExitBlock();
>> +}
>> +
>> +/// Emit the combined function summary section into the combined index
>> +/// file.
>> +static void WriteCombinedFunctionSummary(const FunctionInfoIndex *I,
>> + BitstreamWriter &Stream) {
>> + Stream.EnterSubblock(bitc::FUNCTION_SUMMARY_BLOCK_ID, 3);
>> +
>> + // Abbrev for FS_CODE_COMBINED_ENTRY.
>> + BitCodeAbbrev *Abbv = new BitCodeAbbrev();
>> + Abbv->Add(BitCodeAbbrevOp(bitc::FS_CODE_COMBINED_ENTRY));
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // modid
>> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // instcount
>> + unsigned FSAbbrev = Stream.EmitAbbrev(Abbv);
>> +
>> + SmallVector<unsigned, 64> NameVals;
>> + for (const auto &FII : *I) {
>> + for (auto &FI : FII.getValue()) {
>> + FunctionSummary *FS = FI->functionSummary();
>> + assert(FS);
>> +
>> + NameVals.push_back(I->getModuleId(FS->modulePath()));
>> + NameVals.push_back(FS->instCount());
>> +
>> + // Record the starting offset of this summary entry for use
>> + // in the VST entry. Add the current code size since the
>> + // reader will invoke readRecord after the abbrev id read.
>> + FI->setBitcodeIndex(Stream.GetCurrentBitNo() +
>> Stream.GetAbbrevIDWidth());
>> +
>> + // Emit the finished record.
>> + Stream.EmitRecord(bitc::FS_CODE_COMBINED_ENTRY, NameVals,
>> FSAbbrev);
>> + NameVals.clear();
>> + }
>> + }
>> +
>> + Stream.ExitBlock();
>> +}
>> +
>> /// WriteModule - Emit the specified module to the bitstream.
>> static void WriteModule(const Module *M, BitstreamWriter &Stream,
>> bool ShouldPreserveUseListOrder,
>> - uint64_t BitcodeStartBit) {
>> + uint64_t BitcodeStartBit, bool
>> EmitFunctionSummary) {
>> Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3);
>>
>> SmallVector<unsigned, 1> Vals;
>> @@ -2647,10 +2881,15 @@ static void WriteModule(const Module *M,
>> WriteOperandBundleTags(M, Stream);
>>
>> // Emit function bodies.
>> - DenseMap<const Function *, uint64_t> FunctionIndex;
>> + DenseMap<const Function *, std::unique_ptr<FunctionInfo>>
>> FunctionIndex;
>> for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F)
>> if (!F->isDeclaration())
>> - WriteFunction(*F, VE, Stream, FunctionIndex);
>> + WriteFunction(*F, VE, Stream, FunctionIndex, EmitFunctionSummary);
>> +
>> + // Need to write after the above call to WriteFunction which populates
>> + // the summary information in the index.
>> + if (EmitFunctionSummary)
>> + WritePerModuleFunctionSummary(FunctionIndex, M, VE, Stream);
>>
>> WriteValueSymbolTable(M->getValueSymbolTable(), VE, Stream,
>> VSTOffsetPlaceholder, BitcodeStartBit,
>> &FunctionIndex);
>> @@ -2728,10 +2967,22 @@ static void EmitDarwinBCHeaderAndTrailer
>> Buffer.push_back(0);
>> }
>>
>> +/// Helper to write the header common to all bitcode files.
>> +static void WriteBitcodeHeader(BitstreamWriter &Stream) {
>> + // Emit the file header.
>> + Stream.Emit((unsigned)'B', 8);
>> + Stream.Emit((unsigned)'C', 8);
>> + Stream.Emit(0x0, 4);
>> + Stream.Emit(0xC, 4);
>> + Stream.Emit(0xE, 4);
>> + Stream.Emit(0xD, 4);
>> +}
>> +
>> /// WriteBitcodeToFile - Write the specified module to the specified
>> output
>> /// stream.
>> void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out,
>> - bool ShouldPreserveUseListOrder) {
>> + bool ShouldPreserveUseListOrder,
>> + bool EmitFunctionSummary) {
>> SmallVector<char, 0> Buffer;
>> Buffer.reserve(256*1024);
>>
>> @@ -2751,15 +3002,11 @@ void llvm::WriteBitcodeToFile(const Modu
>> uint64_t BitcodeStartBit = Stream.GetCurrentBitNo();
>>
>> // Emit the file header.
>> - Stream.Emit((unsigned)'B', 8);
>> - Stream.Emit((unsigned)'C', 8);
>> - Stream.Emit(0x0, 4);
>> - Stream.Emit(0xC, 4);
>> - Stream.Emit(0xE, 4);
>> - Stream.Emit(0xD, 4);
>> + WriteBitcodeHeader(Stream);
>>
>> // Emit the module.
>> - WriteModule(M, Stream, ShouldPreserveUseListOrder, BitcodeStartBit);
>> + WriteModule(M, Stream, ShouldPreserveUseListOrder, BitcodeStartBit,
>> + EmitFunctionSummary);
>> }
>>
>> if (TT.isOSDarwin())
>> @@ -2768,3 +3015,38 @@ void llvm::WriteBitcodeToFile(const Modu
>> // Write the generated bitstream to "Out".
>> Out.write((char*)&Buffer.front(), Buffer.size());
>> }
>> +
>> +// Write the specified function 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::WriteFunctionSummaryToFile(const FunctionInfoIndex *Index,
>> + raw_ostream &Out) {
>> + SmallVector<char, 0> Buffer;
>> + Buffer.reserve(256 * 1024);
>> +
>> + BitstreamWriter Stream(Buffer);
>> +
>> + // Emit the bitcode header.
>> + WriteBitcodeHeader(Stream);
>> +
>> + Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3);
>> +
>> + SmallVector<unsigned, 1> Vals;
>> + unsigned CurVersion = 1;
>> + Vals.push_back(CurVersion);
>> + Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals);
>> +
>> + // Write the module paths in the combined index.
>> + WriteModStrings(Index, Stream);
>> +
>> + // Write the function summary combined index records.
>> + WriteCombinedFunctionSummary(Index, Stream);
>> +
>> + // Need a special VST writer for the combined index (we don't have a
>> + // real VST and real values when this is invoked).
>> + WriteCombinedValueSymbolTable(Index, Stream);
>> +
>> + Stream.ExitBlock();
>> +
>> + Out.write((char *)&Buffer.front(), Buffer.size());
>> +}
>>
>> Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriterPass.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriterPass.cpp?rev=249270&r1=249269&r2=249270&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriterPass.cpp (original)
>> +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriterPass.cpp Sun Oct 4
>> 09:33:43 2015
>> @@ -19,7 +19,7 @@
>> using namespace llvm;
>>
>> PreservedAnalyses BitcodeWriterPass::run(Module &M) {
>> - WriteBitcodeToFile(&M, OS, ShouldPreserveUseListOrder);
>> + WriteBitcodeToFile(&M, OS, ShouldPreserveUseListOrder,
>> EmitFunctionSummary);
>> return PreservedAnalyses::all();
>> }
>>
>> @@ -27,17 +27,21 @@ namespace {
>> class WriteBitcodePass : public ModulePass {
>> raw_ostream &OS; // raw_ostream to print on
>> bool ShouldPreserveUseListOrder;
>> + bool EmitFunctionSummary;
>>
>> public:
>> static char ID; // Pass identification, replacement for typeid
>> - explicit WriteBitcodePass(raw_ostream &o, bool
>> ShouldPreserveUseListOrder)
>> + explicit WriteBitcodePass(raw_ostream &o, bool
>> ShouldPreserveUseListOrder,
>> + bool EmitFunctionSummary)
>> : ModulePass(ID), OS(o),
>> - ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {}
>> + ShouldPreserveUseListOrder(ShouldPreserveUseListOrder),
>> + EmitFunctionSummary(EmitFunctionSummary) {}
>>
>> const char *getPassName() const override { return "Bitcode Writer"; }
>>
>> bool runOnModule(Module &M) override {
>> - WriteBitcodeToFile(&M, OS, ShouldPreserveUseListOrder);
>> + WriteBitcodeToFile(&M, OS, ShouldPreserveUseListOrder,
>> + EmitFunctionSummary);
>> return false;
>> }
>> };
>> @@ -46,6 +50,8 @@ namespace {
>> char WriteBitcodePass::ID = 0;
>>
>> ModulePass *llvm::createBitcodeWriterPass(raw_ostream &Str,
>> - bool
>> ShouldPreserveUseListOrder) {
>> - return new WriteBitcodePass(Str, ShouldPreserveUseListOrder);
>> + bool
>> ShouldPreserveUseListOrder,
>> + bool EmitFunctionSummary) {
>> + return new WriteBitcodePass(Str, ShouldPreserveUseListOrder,
>> + EmitFunctionSummary);
>> }
>>
>> Modified: llvm/trunk/lib/IR/CMakeLists.txt
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/CMakeLists.txt?rev=249270&r1=249269&r2=249270&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/IR/CMakeLists.txt (original)
>> +++ llvm/trunk/lib/IR/CMakeLists.txt Sun Oct 4 09:33:43 2015
>> @@ -39,6 +39,7 @@ add_llvm_library(LLVMCore
>> PassManager.cpp
>> PassRegistry.cpp
>> Statepoint.cpp
>> + FunctionInfo.cpp
>> Type.cpp
>> TypeFinder.cpp
>> Use.cpp
>>
>> Added: llvm/trunk/lib/IR/FunctionInfo.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/FunctionInfo.cpp?rev=249270&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/lib/IR/FunctionInfo.cpp (added)
>> +++ llvm/trunk/lib/IR/FunctionInfo.cpp Sun Oct 4 09:33:43 2015
>> @@ -0,0 +1,63 @@
>> +//===-- FunctionInfo.cpp - Function Info Index
>> ----------------------------===//
>> +//
>> +// The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// This file implements the function info index and summary classes for
>> the
>> +// IR library.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "llvm/IR/FunctionInfo.h"
>> +#include "llvm/ADT/StringMap.h"
>> +using namespace llvm;
>> +
>> +// Create the combined function index/summary from multiple
>> +// per-module instances.
>> +void FunctionInfoIndex::mergeFrom(std::unique_ptr<FunctionInfoIndex>
>> Other,
>> + uint64_t NextModuleId) {
>> +
>> + StringRef ModPath;
>> + for (auto &OtherFuncInfoLists : *Other) {
>> + StringRef FuncName = OtherFuncInfoLists.getKey();
>> + FunctionInfoList &List = OtherFuncInfoLists.second;
>> +
>> + // Assert that the func info list only has one entry, since we
>> shouldn't
>> + // have duplicate names within a single per-module index.
>> + assert(List.size() == 1);
>> + std::unique_ptr<FunctionInfo> Info = std::move(List.front());
>> +
>> + // Add the module path string ref for this module if we haven't
>> already
>> + // saved a reference to it.
>> + if (ModPath.empty())
>> + ModPath =
>> + addModulePath(Info->functionSummary()->modulePath(),
>> NextModuleId);
>> + else
>> + assert(ModPath == Info->functionSummary()->modulePath() &&
>> + "Each module in the combined map should have a unique ID");
>> +
>> + // Note the module path string ref was copied above and is still
>> owned by
>> + // the original per-module index. Reset it to the new module path
>> + // string reference owned by the combined index.
>> + Info->functionSummary()->setModulePath(ModPath);
>> +
>> + // If it is a local function, rename it.
>> + if (Info->functionSummary()->isLocalFunction()) {
>> + // Any local functions are virtually renamed when being added to
>> the
>> + // combined index map, to disambiguate from other functions with
>> + // the same name. The symbol table created for the combined index
>> + // file should contain the renamed symbols.
>> + FuncName =
>> + FunctionInfoIndex::getGlobalNameForLocal(FuncName,
>> NextModuleId);
>> + }
>> +
>> + // Add new function info to existing list. There may be duplicates
>> when
>> + // combining FunctionMap entries, due to COMDAT functions. Any local
>> + // functions were virtually renamed above.
>> + addFunctionInfo(FuncName, std::move(Info));
>> + }
>> +}
>>
>> Modified: llvm/trunk/lib/Object/CMakeLists.txt
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/CMakeLists.txt?rev=249270&r1=249269&r2=249270&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Object/CMakeLists.txt (original)
>> +++ llvm/trunk/lib/Object/CMakeLists.txt Sun Oct 4 09:33:43 2015
>> @@ -16,6 +16,7 @@ add_llvm_library(LLVMObject
>> RecordStreamer.cpp
>> SymbolicFile.cpp
>> SymbolSize.cpp
>> + FunctionIndexObjectFile.cpp
>>
>> ADDITIONAL_HEADER_DIRS
>> ${LLVM_MAIN_INCLUDE_DIR}/llvm/Object
>>
>> Added: llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp?rev=249270&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp (added)
>> +++ llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp Sun Oct 4 09:33:43
>> 2015
>> @@ -0,0 +1,114 @@
>> +//===- FunctionIndexObjectFile.cpp - Function index file implementation
>> ----===//
>> +//
>> +// The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// Part of the FunctionIndexObjectFile class implementation.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "llvm/Object/FunctionIndexObjectFile.h"
>> +#include "llvm/ADT/STLExtras.h"
>> +#include "llvm/Bitcode/ReaderWriter.h"
>> +#include "llvm/IR/FunctionInfo.h"
>> +#include "llvm/MC/MCStreamer.h"
>> +#include "llvm/Object/ObjectFile.h"
>> +#include "llvm/Support/MemoryBuffer.h"
>> +#include "llvm/Support/raw_ostream.h"
>> +using namespace llvm;
>> +using namespace object;
>> +
>> +FunctionIndexObjectFile::FunctionIndexObjectFile(
>> + MemoryBufferRef Object, std::unique_ptr<FunctionInfoIndex> I)
>> + : SymbolicFile(Binary::ID_FunctionIndex, Object), Index(std::move(I))
>> {}
>> +
>> +FunctionIndexObjectFile::~FunctionIndexObjectFile() {}
>> +
>> +std::unique_ptr<FunctionInfoIndex> FunctionIndexObjectFile::takeIndex() {
>> + return std::move(Index);
>> +}
>> +
>> +ErrorOr<MemoryBufferRef> FunctionIndexObjectFile::findBitcodeInObject(
>> + const ObjectFile &Obj) {
>> + for (const SectionRef &Sec : Obj.sections()) {
>> + StringRef SecName;
>> + if (std::error_code EC = Sec.getName(SecName)) return EC;
>> + if (SecName == ".llvmbc") {
>> + StringRef SecContents;
>> + if (std::error_code EC = Sec.getContents(SecContents)) return EC;
>> + return MemoryBufferRef(SecContents, Obj.getFileName());
>> + }
>> + }
>> +
>> + return object_error::bitcode_section_not_found;
>> +}
>> +
>> +ErrorOr<MemoryBufferRef> FunctionIndexObjectFile::findBitcodeInMemBuffer(
>> + MemoryBufferRef Object) {
>> + sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer());
>> + switch (Type) {
>> + case sys::fs::file_magic::bitcode:
>> + return Object;
>> + case sys::fs::file_magic::elf_relocatable:
>> + case sys::fs::file_magic::macho_object:
>> + case sys::fs::file_magic::coff_object: {
>> + ErrorOr<std::unique_ptr<ObjectFile>> ObjFile =
>> + ObjectFile::createObjectFile(Object, Type);
>> + if (!ObjFile) return ObjFile.getError();
>> + return findBitcodeInObject(*ObjFile->get());
>> + }
>> + default:
>> + return object_error::invalid_file_type;
>> + }
>> +}
>> +
>> +// Looks for function index in the given memory buffer.
>> +// returns true if found, else false.
>> +bool FunctionIndexObjectFile::hasFunctionSummaryInMemBuffer(
>> + MemoryBufferRef Object, LLVMContext &Context) {
>> + ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
>> + if (!BCOrErr) return false;
>> +
>> + return hasFunctionSummary(BCOrErr.get(), Context, nullptr);
>> +}
>> +
>> +// Parse function index in the given memory buffer.
>> +// Return new FunctionIndexObjectFile instance containing parsed
>> +// function summary/index.
>> +ErrorOr<std::unique_ptr<FunctionIndexObjectFile>>
>> +FunctionIndexObjectFile::create(MemoryBufferRef Object, LLVMContext
>> &Context,
>> + bool IsLazy) {
>> + std::unique_ptr<FunctionInfoIndex> Index;
>> +
>> + ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
>> + if (!BCOrErr) return BCOrErr.getError();
>> +
>> + ErrorOr<std::unique_ptr<FunctionInfoIndex>> IOrErr =
>> + getFunctionInfoIndex(BCOrErr.get(), Context, nullptr, IsLazy);
>> +
>> + if (std::error_code EC = IOrErr.getError()) return EC;
>> +
>> + Index = std::move(IOrErr.get());
>> +
>> + return llvm::make_unique<FunctionIndexObjectFile>(Object,
>> std::move(Index));
>> +}
>> +
>> +// Parse the function summary information for function with the
>> +// given name out of the given buffer. Parsed information is
>> +// stored on the index object saved in this object.
>> +std::error_code FunctionIndexObjectFile::findFunctionSummaryInMemBuffer(
>> + MemoryBufferRef Object, LLVMContext &Context, StringRef FunctionName)
>> {
>> + sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer());
>> + switch (Type) {
>> + case sys::fs::file_magic::bitcode: {
>> + return readFunctionSummary(Object, Context, nullptr, FunctionName,
>> + std::move(Index));
>> + }
>> + default:
>> + return object_error::invalid_file_type;
>> + }
>> +}
>>
>> Added: llvm/trunk/test/Bitcode/thinlto-function-summary.ll
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/thinlto-function-summary.ll?rev=249270&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/Bitcode/thinlto-function-summary.ll (added)
>> +++ llvm/trunk/test/Bitcode/thinlto-function-summary.ll Sun Oct 4
>> 09:33:43 2015
>> @@ -0,0 +1,45 @@
>> +; RUN: llvm-as -function-summary < %s | llvm-bcanalyzer -dump | FileCheck
>> %s -check-prefix=BC
>> +; Check for function summary block/records.
>> +
>> +; BC: <FUNCTION_SUMMARY_BLOCK
>> +; BC-NEXT: <PERMODULE_ENTRY
>> +; BC-NEXT: <PERMODULE_ENTRY
>> +; BC-NEXT: <PERMODULE_ENTRY
>> +; BC-NEXT: </FUNCTION_SUMMARY_BLOCK
>> +
>> +; RUN: llvm-as -function-summary < %s | llvm-dis | FileCheck %s
>> +; Check that this round-trips correctly.
>> +
>> +; ModuleID = '<stdin>'
>> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>> +target triple = "x86_64-unknown-linux-gnu"
>> +
>> +; CHECK: define i32 @foo()
>> +
>> +; Function Attrs: nounwind uwtable
>> +define i32 @foo() #0 {
>> +entry:
>> + ret i32 1
>> +}
>> +
>> +; CHECK: define i32 @bar(i32 %x)
>> +
>> +; Function Attrs: nounwind uwtable
>> +define i32 @bar(i32 %x) #0 {
>> +entry:
>> + ret i32 %x
>> +}
>> +
>> +; Check an anonymous function as well, since in that case only the alias
>> +; ends up in the value symbol table and having a summary.
>> + at f = alias void (), void ()* @0 ; <void ()*> [#uses=0]
>> + at h = external global void ()* ; <void ()*> [#uses=0]
>> +
>> +define internal void @0() nounwind {
>> +entry:
>> + store void()* @0, void()** @h
>> + br label %return
>> +
>> +return: ; preds = %entry
>> + ret void
>> +}
>>
>> Added: llvm/trunk/test/tools/gold/X86/Inputs/thinlto.ll
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/Inputs/thinlto.ll?rev=249270&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/tools/gold/X86/Inputs/thinlto.ll (added)
>> +++ llvm/trunk/test/tools/gold/X86/Inputs/thinlto.ll Sun Oct 4 09:33:43
>> 2015
>> @@ -0,0 +1,4 @@
>> +define void @g() {
>> +entry:
>> + ret void
>> +}
>>
>> Added: llvm/trunk/test/tools/gold/X86/thinlto.ll
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/thinlto.ll?rev=249270&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/tools/gold/X86/thinlto.ll (added)
>> +++ llvm/trunk/test/tools/gold/X86/thinlto.ll Sun Oct 4 09:33:43 2015
>> @@ -0,0 +1,22 @@
>> +; RUN: llvm-as -function-summary %s -o %t.o
>> +; RUN: llvm-as -function-summary %p/Inputs/thinlto.ll -o %t2.o
>> +
>> +; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \
>> +; RUN: --plugin-opt=thinlto \
>> +; RUN: -shared %t.o %t2.o -o %t3
>> +; RUN: llvm-bcanalyzer -dump %t3.thinlto.bc | FileCheck %s
>> --check-prefix=COMBINED
>> +; RUN: not test -e %t3
>> +
>> +; COMBINED: <MODULE_STRTAB_BLOCK
>> +; COMBINED-NEXT: <ENTRY
>> +; COMBINED-NEXT: <ENTRY
>> +; COMBINED-NEXT: </MODULE_STRTAB_BLOCK
>> +; COMBINED-NEXT: <FUNCTION_SUMMARY_BLOCK
>> +; COMBINED-NEXT: <COMBINED_ENTRY
>> +; COMBINED-NEXT: <COMBINED_ENTRY
>> +; COMBINED-NEXT: </FUNCTION_SUMMARY_BLOCK
>> +
>> +define void @f() {
>> +entry:
>> + ret void
>> +}
>>
>> Modified: llvm/trunk/tools/gold/gold-plugin.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/gold/gold-plugin.cpp?rev=249270&r1=249269&r2=249270&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/tools/gold/gold-plugin.cpp (original)
>> +++ llvm/trunk/tools/gold/gold-plugin.cpp Sun Oct 4 09:33:43 2015
>> @@ -32,6 +32,7 @@
>> #include "llvm/Linker/Linker.h"
>> #include "llvm/MC/SubtargetFeature.h"
>> #include "llvm/Object/IRObjectFile.h"
>> +#include "llvm/Object/FunctionIndexObjectFile.h"
>> #include "llvm/Support/raw_ostream.h"
>> #include "llvm/Support/Host.h"
>> #include "llvm/Support/ManagedStatic.h"
>> @@ -103,6 +104,10 @@ namespace options {
>> static std::string extra_library_path;
>> static std::string triple;
>> static std::string mcpu;
>> + // When the thinlto plugin option is specified, only read the function
>> + // the information from intermediate files and write a combined
>> + // global index for the ThinLTO backends.
>> + static bool thinlto = false;
>> // Additional options to pass into the code generator.
>> // Note: This array will contain all plugin options which are not
>> claimed
>> // as plugin exclusive to pass to the code generator.
>> @@ -132,6 +137,8 @@ namespace options {
>> TheOutputType = OT_SAVE_TEMPS;
>> } else if (opt == "disable-output") {
>> TheOutputType = OT_DISABLE;
>> + } else if (opt == "thinlto") {
>> + thinlto = true;
>> } else if (opt.size() == 2 && opt[0] == 'O') {
>> if (opt[1] < '0' || opt[1] > '3')
>> message(LDPL_FATAL, "Optimization level must be between 0 and
>> 3");
>> @@ -376,6 +383,10 @@ static ld_plugin_status claim_file_hook(
>>
>> cf.handle = file->handle;
>>
>> + // If we are doing ThinLTO compilation, don't need to process the
>> symbols.
>> + // Later we simply build a combined index file after all files are
>> claimed.
>> + if (options::thinlto) return LDPS_OK;
>> +
>> for (auto &Sym : Obj->symbols()) {
>> uint32_t Symflags = Sym.getFlags();
>> if (shouldSkip(Symflags))
>> @@ -591,6 +602,30 @@ static void freeSymName(ld_plugin_symbol
>> Sym.comdat_key = nullptr;
>> }
>>
>> +static std::unique_ptr<FunctionInfoIndex> getFunctionIndexForFile(
>> + LLVMContext &Context, claimed_file &F, ld_plugin_input_file &Info) {
>> +
>> + if (get_symbols(F.handle, F.syms.size(), &F.syms[0]) != LDPS_OK)
>> + message(LDPL_FATAL, "Failed to get symbol information");
>> +
>> + const void *View;
>> + if (get_view(F.handle, &View) != LDPS_OK)
>> + message(LDPL_FATAL, "Failed to get a view of file");
>> +
>> + MemoryBufferRef BufferRef(StringRef((const char *)View, Info.filesize),
>> + Info.name);
>> + ErrorOr<std::unique_ptr<object::FunctionIndexObjectFile>> ObjOrErr =
>> + object::FunctionIndexObjectFile::create(BufferRef, Context);
>> +
>> + if (std::error_code EC = ObjOrErr.getError())
>> + message(LDPL_FATAL, "Could not read function index bitcode from file
>> : %s",
>> + EC.message().c_str());
>> +
>> + object::FunctionIndexObjectFile &Obj = **ObjOrErr;
>> +
>> + return Obj.takeIndex();
>> +}
>> +
>> static std::unique_ptr<Module>
>> getModuleForFile(LLVMContext &Context, claimed_file &F,
>> ld_plugin_input_file &Info, raw_fd_ostream *ApiFile,
>> @@ -857,6 +892,35 @@ static ld_plugin_status allSymbolsReadHo
>> LLVMContext Context;
>> Context.setDiagnosticHandler(diagnosticHandler, nullptr, true);
>>
>> + // If we are doing ThinLTO compilation, simply build the combined
>> + // function index/summary and emit it. We don't need to parse the
>> modules
>> + // and link them in this case.
>> + if (options::thinlto) {
>> + std::unique_ptr<FunctionInfoIndex> CombinedIndex(new
>> FunctionInfoIndex());
>> + uint64_t NextModuleId = 0;
>> + for (claimed_file &F : Modules) {
>> + ld_plugin_input_file File;
>> + if (get_input_file(F.handle, &File) != LDPS_OK)
>> + message(LDPL_FATAL, "Failed to get file information");
>> +
>> + std::unique_ptr<FunctionInfoIndex> Index =
>> + getFunctionIndexForFile(Context, F, File);
>> + CombinedIndex->mergeFrom(std::move(Index), ++NextModuleId);
>> + }
>> +
>> + std::error_code EC;
>> + raw_fd_ostream OS(output_name + ".thinlto.bc", EC,
>> + sys::fs::OpenFlags::F_None);
>> + if (EC)
>> + message(LDPL_FATAL, "Unable to open %s.thinlto.bc for writing: %s",
>> + output_name.data(), EC.message().c_str());
>> + WriteFunctionSummaryToFile(CombinedIndex.get(), OS);
>> + OS.close();
>> +
>> + cleanup_hook();
>> + exit(0);
>> + }
>> +
>> std::unique_ptr<Module> Combined(new Module("ld-temp.o", Context));
>> Linker L(Combined.get());
>>
>>
>> Modified: llvm/trunk/tools/llvm-as/llvm-as.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-as/llvm-as.cpp?rev=249270&r1=249269&r2=249270&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/tools/llvm-as/llvm-as.cpp (original)
>> +++ llvm/trunk/tools/llvm-as/llvm-as.cpp Sun Oct 4 09:33:43 2015
>> @@ -45,6 +45,10 @@ static cl::opt<bool>
>> DisableOutput("disable-output", cl::desc("Disable output"),
>> cl::init(false));
>>
>> static cl::opt<bool>
>> +EmitFunctionSummary("function-summary", cl::desc("Emit function summary
>> index"),
>> + cl::init(false));
>> +
>> +static cl::opt<bool>
>> DumpAsm("d", cl::desc("Print assembly as parsed"), cl::Hidden);
>>
>> static cl::opt<bool>
>> @@ -77,7 +81,8 @@ static void WriteOutputFile(const Module
>> }
>>
>> if (Force || !CheckBitcodeOutputToConsole(Out->os(), true))
>> - WriteBitcodeToFile(M, Out->os(), PreserveBitcodeUseListOrder);
>> + WriteBitcodeToFile(M, Out->os(), PreserveBitcodeUseListOrder,
>> + EmitFunctionSummary);
>>
>> // Declare success.
>> Out->keep();
>>
>> Modified: llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp?rev=249270&r1=249269&r2=249270&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp (original)
>> +++ llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp Sun Oct 4
>> 09:33:43 2015
>> @@ -114,6 +114,9 @@ static const char *GetBlockName(unsigned
>> case bitc::METADATA_BLOCK_ID: return "METADATA_BLOCK";
>> case bitc::METADATA_ATTACHMENT_ID: return
>> "METADATA_ATTACHMENT_BLOCK";
>> case bitc::USELIST_BLOCK_ID: return "USELIST_BLOCK_ID";
>> + case bitc::FUNCTION_SUMMARY_BLOCK_ID:
>> + return "FUNCTION_SUMMARY_BLOCK";
>> + case bitc::MODULE_STRTAB_BLOCK_ID: return "MODULE_STRTAB_BLOCK";
>> }
>> }
>>
>> @@ -268,6 +271,18 @@ static const char *GetCodeName(unsigned
>> STRINGIFY_CODE(VST_CODE, ENTRY)
>> STRINGIFY_CODE(VST_CODE, BBENTRY)
>> STRINGIFY_CODE(VST_CODE, FNENTRY)
>> + STRINGIFY_CODE(VST_CODE, COMBINED_FNENTRY)
>> + }
>> + case bitc::MODULE_STRTAB_BLOCK_ID:
>> + switch (CodeID) {
>> + default: return nullptr;
>> + STRINGIFY_CODE(MST_CODE, ENTRY)
>> + }
>> + case bitc::FUNCTION_SUMMARY_BLOCK_ID:
>> + switch (CodeID) {
>> + default: return nullptr;
>> + STRINGIFY_CODE(FS_CODE, PERMODULE_ENTRY)
>> + STRINGIFY_CODE(FS_CODE, COMBINED_ENTRY)
>> }
>> case bitc::METADATA_ATTACHMENT_ID:
>> switch(CodeID) {
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
>
--
Teresa Johnson | Software Engineer | tejohnson at google.com | 408-460-2413
More information about the llvm-commits
mailing list