Index: include/llvm/IR/ThinLTOInfo.h =================================================================== --- /dev/null +++ include/llvm/IR/ThinLTOInfo.h @@ -0,0 +1,219 @@ +//===-- llvm/ThinLTOInfo.h - ThinLTO Index and Summary ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// ThinLtoInfo.h This file contains the declarations the classes that hold +// the ThinLTO function index and summary. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_THINLTOINFO_H +#define LLVM_IR_THINLTOINFO_H + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/MemoryBuffer.h" + +namespace llvm { + +// Function summary information to aid decisions and implementation of +// importing. This is a separate class from ThinLTOFunctionInfo to +// enable lazy reading of this function summary information from the +// combined index file during imporing. +class ThinLTOFunctionSummary { + private: + // Path of module containing function IR, used to locate module when + // importing this function. + StringRef ModulePath; + // Index of function within bitcode module block in its module, used + // to quickly import this function. + uint64_t BitcodeIndex; + + // 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: + ThinLTOFunctionSummary(StringRef ModPath, uint64_t BitcodeIdx, + unsigned NumInsts) : + ModulePath(ModPath), + BitcodeIndex(BitcodeIdx), + InstCount(NumInsts) { } + + StringRef modulePath() const { + return ModulePath; + } + + uint64_t bitcodeIndex() const { + return BitcodeIndex; + } + + unsigned instCount() { + return InstCount; + } +}; + +// Class to hold pointer to function summary and information required +// for parsing it. After parsing of the ThinLTO symtab, this initially +// holds the offset into the corresponding ThinLTO function summary bitcode +// block. After parsing the associated summary information from the summary +// block the FunctionSummary is populated and stored here. +class ThinLTOFunctionInfo { + private: + // Function summary information used to help make importing decisions. + ThinLTOFunctionSummary *FunctionSummary; + // Used during bitcode parsing and writing to hold the offset of the + // corresponding function summary in the function summary section. + uint64_t FunctionSummarySecOffset; + // True if we are still parsing into this instance. + bool Parsing; + // Used to flag functions that have local linkage types and need to + // have module identifier appended before placing into the combined + // index, to disambiguiate from other functions with the same name. + bool IsLocalFunction; + + public: + // Constructed during parsing + ThinLTOFunctionInfo(uint64_t SecOffset) : + FunctionSummary(nullptr), + FunctionSummarySecOffset(SecOffset), + Parsing(true), + IsLocalFunction(false) { } + + ~ThinLTOFunctionInfo() { + // Support sharing FunctionSummary object between per-module and + // combined indexes. + if (FunctionSummary) + delete FunctionSummary; + } + + // Use the default copy constructor (when creating combined index), + // which will cause the same ThinLTOFunctionSummary object to be shared. + + // Record the function information parsed out of the function + // summary block. + void recordParsedInfo(ThinLTOFunctionSummary *FuncSummary) { + assert(Parsing); + Parsing = false; + FunctionSummary = FuncSummary; + } + + ThinLTOFunctionSummary *functionSummary() const { + assert(!Parsing); + return FunctionSummary; + } + + void isLocalFunction(bool Local) { + IsLocalFunction = Local; + } + bool isLocalFunction() const { + return IsLocalFunction; + } +}; + +// List of function info structures for a particular function name held +// in the ThinLTOFunctionMap. Requires a vector in the case of multiple +// COMDAT functions of the same name. +typedef std::vector ThinLTOFunctionInfoList; +// Map from function name to corresponding function info structures. +typedef StringMap ThinLTOFunctionMap; + +// 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 ThinLTOModulePathStringTable; + +// Class to hold module path string table and ThinLTOFunctionMap, +// and encapsulate methods for operating on them. +class ThinLTOFunctionSummaryIndex { + public: + typedef ThinLTOFunctionMap::const_iterator const_funcinfo_iterator; + + 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.). + ThinLTOFunctionMap FunctionMap; + + // Holds strings for combined index, mapping to the corresponding module ID. + ThinLTOModulePathStringTable ModulePathStringTable; + + // Used for assigning module ids when per-module index structures merged + // to form combined index, necessary for consistent renaming of promoted + // static (local) variables. + static uint64_t NextModuleId; + + public: + ThinLTOFunctionSummaryIndex() { } + + // Use default copy constructor. For the StringMaps this will + // call std::swap during the assignment. + + // Use when the ThinLTOFunctionMap has already been created + // (e.g. from a native object wrapped bitcode file's symtab). + void setFunctionMap(ThinLTOFunctionMap &&FuncMap) { + FunctionMap = std::move(FuncMap); + } + + const_funcinfo_iterator funcinfo_begin() const { + return FunctionMap.begin(); + } + const_funcinfo_iterator funcinfo_end() const { + return FunctionMap.end(); + } + + // Return the list of function info objects for a given function. + ThinLTOFunctionInfoList getFunctionInfoList(StringRef FuncName) const { + return FunctionMap.lookup(FuncName); + } + + // Add a function info for a function of the given name. + void addFunctionInfo(StringRef FuncName, + ThinLTOFunctionInfo &Info) { + if (FunctionMap.count(FuncName)) + FunctionMap.lookup(FuncName).push_back(Info); + else + FunctionMap.insert(std::make_pair(FuncName, + ThinLTOFunctionInfoList(1, Info))); + } + + // 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(); + } + + // Iterator to allow writer to walk through table during emission. + iterator_range::const_iterator> + modPathStringEntries() const { + return llvm::make_range(ModulePathStringTable.begin(), + ModulePathStringTable.end()); + } + + // Used to create the combined function index/summary from multiple + // per-module instances. + void mergeFrom(ThinLTOFunctionSummaryIndex *Other); + + static std::string getGlobalThinLTONameForLocal(StringRef Name, + uint64_t ModId) { + SmallString<256> NewName(Name); + NewName += ".llvm."; + NewName += ModId; + return NewName.str(); + } +}; + +} // End llvm namespace + +#endif Index: lib/IR/CMakeLists.txt =================================================================== --- lib/IR/CMakeLists.txt +++ lib/IR/CMakeLists.txt @@ -39,6 +39,7 @@ PassManager.cpp PassRegistry.cpp Statepoint.cpp + ThinLTOInfo.cpp Type.cpp TypeFinder.cpp Use.cpp Index: lib/IR/ThinLTOInfo.cpp =================================================================== --- /dev/null +++ lib/IR/ThinLTOInfo.cpp @@ -0,0 +1,65 @@ +//===-- ThinLTOInfo.cpp - ThinLTO Index and Summary -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements ThinLTO function index and summary classes for the +// IR library. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/ThinLTOInfo.h" +#include "llvm/ADT/StringMap.h" +using namespace llvm; + +uint64_t ThinLTOFunctionSummaryIndex::NextModuleId = 0; + +// Used to create the combined function index/summary from multiple +// per-module instances. +void ThinLTOFunctionSummaryIndex::mergeFrom( + ThinLTOFunctionSummaryIndex *Other) { + + ++NextModuleId; + + const_funcinfo_iterator OtherFuncInfoLists = Other->funcinfo_begin(); + StringRef ModPath; + for (; OtherFuncInfoLists != Other->funcinfo_end(); OtherFuncInfoLists++) { + StringRef FuncName = OtherFuncInfoLists->getKey(); + ThinLTOFunctionInfoList List = OtherFuncInfoLists->second; + + // Assert that the func info list only has one entry. + assert(List.size() == 1); + // Note the module path string ref is copied and still owned by the + // original per-module ThinLTOFunctionInfo. This should be ok, we + // just need to keep those around until the combined index is written. + ThinLTOFunctionInfo Info = List.front(); + + // Get the module path string ref for this module if we haven't already + // saved a reference to it. + if (ModPath.empty()) { + ModPath = Info.functionSummary()->modulePath(); + addModulePath(ModPath, NextModuleId); + } + else + assert(ModPath == Info.functionSummary()->modulePath()); + + // If it is a local function, rename it. + if (Info.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 compiled index + // file should contain the renamed symbols. + FuncName = ThinLTOFunctionSummaryIndex::getGlobalThinLTONameForLocal( + FuncName, NextModuleId); + } + + // Add func info to existing list. + // There may be duplicates when combining ThinLTOFunctionMap entries, + // due to COMDAT functions. Any local functions are virtually renamed + addFunctionInfo(FuncName, Info); + } +}