diff options
Diffstat (limited to 'include/llvm/LTO')
-rw-r--r-- | include/llvm/LTO/LTO.h | 74 | ||||
-rw-r--r-- | include/llvm/LTO/legacy/LTOCodeGenerator.h (renamed from include/llvm/LTO/LTOCodeGenerator.h) | 70 | ||||
-rw-r--r-- | include/llvm/LTO/legacy/LTOModule.h (renamed from include/llvm/LTO/LTOModule.h) | 28 | ||||
-rw-r--r-- | include/llvm/LTO/legacy/ThinLTOCodeGenerator.h | 276 | ||||
-rw-r--r-- | include/llvm/LTO/legacy/UpdateCompilerUsed.h | 32 |
5 files changed, 450 insertions, 30 deletions
diff --git a/include/llvm/LTO/LTO.h b/include/llvm/LTO/LTO.h new file mode 100644 index 0000000000000..5154c0007aaa5 --- /dev/null +++ b/include/llvm/LTO/LTO.h @@ -0,0 +1,74 @@ +//===-LTO.h - LLVM Link Time Optimizer ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares functions and classes used to support LTO. It is intended +// to be used both by LTO classes as well as by clients (gold-plugin) that +// don't utilize the LTO code generator interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LTO_LTO_H +#define LLVM_LTO_LTO_H + +#include "llvm/ADT/StringMap.h" +#include "llvm/IR/ModuleSummaryIndex.h" + +namespace llvm { + +class LLVMContext; +class MemoryBufferRef; +class Module; + +/// Helper to load a module from bitcode. +std::unique_ptr<Module> loadModuleFromBuffer(const MemoryBufferRef &Buffer, + LLVMContext &Context, bool Lazy); + +/// Provide a "loader" for the FunctionImporter to access function from other +/// modules. +class ModuleLoader { + /// The context that will be used for importing. + LLVMContext &Context; + + /// Map from Module identifier to MemoryBuffer. Used by clients like the + /// FunctionImported to request loading a Module. + StringMap<MemoryBufferRef> &ModuleMap; + +public: + ModuleLoader(LLVMContext &Context, StringMap<MemoryBufferRef> &ModuleMap) + : Context(Context), ModuleMap(ModuleMap) {} + + /// Load a module on demand. + std::unique_ptr<Module> operator()(StringRef Identifier) { + return loadModuleFromBuffer(ModuleMap[Identifier], Context, /*Lazy*/ true); + } +}; + + +/// Resolve Weak and LinkOnce values in the \p Index. Linkage changes recorded +/// in the index and the ThinLTO backends must apply the changes to the Module +/// via thinLTOResolveWeakForLinkerModule. +/// +/// This is done for correctness (if value exported, ensure we always +/// emit a copy), and compile-time optimization (allow drop of duplicates). +void thinLTOResolveWeakForLinkerInIndex( + ModuleSummaryIndex &Index, + function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)> + isPrevailing, + function_ref<void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)> + recordNewLinkage); + +/// Update the linkages in the given \p Index to mark exported values +/// as external and non-exported values as internal. The ThinLTO backends +/// must apply the changes to the Module via thinLTOInternalizeModule. +void thinLTOInternalizeAndPromoteInIndex( + ModuleSummaryIndex &Index, + function_ref<bool(StringRef, GlobalValue::GUID)> isExported); +} + +#endif diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/legacy/LTOCodeGenerator.h index 3820b211a381d..d083e37d75b88 100644 --- a/include/llvm/LTO/LTOCodeGenerator.h +++ b/include/llvm/LTO/legacy/LTOCodeGenerator.h @@ -36,18 +36,20 @@ #define LLVM_LTO_LTOCODEGENERATOR_H #include "llvm-c/lto.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/Module.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include <string> #include <vector> namespace llvm { +template <typename T> class ArrayRef; class LLVMContext; class DiagnosticInfo; - class GlobalValue; class Linker; class Mangler; class MemoryBuffer; @@ -66,17 +68,21 @@ struct LTOCodeGenerator { ~LTOCodeGenerator(); /// Merge given module. Return true on success. + /// + /// Resets \a HasVerifiedInput. bool addModule(struct LTOModule *); /// Set the destination module. + /// + /// Resets \a HasVerifiedInput. void setModule(std::unique_ptr<LTOModule> M); - void setTargetOptions(TargetOptions Options); + void setTargetOptions(const TargetOptions &Options); void setDebugInfo(lto_debug_model); - void setCodePICModel(Reloc::Model Model) { RelocModel = Model; } - + void setCodePICModel(Optional<Reloc::Model> Model) { RelocModel = Model; } + /// Set the file type to be emitted (assembly or object code). - /// The default is TargetMachine::CGFT_ObjectFile. + /// The default is TargetMachine::CGFT_ObjectFile. void setFileType(TargetMachine::CodeGenFileType FT) { FileType = FT; } void setCpu(const char *MCpu) { this->MCpu = MCpu; } @@ -86,6 +92,22 @@ struct LTOCodeGenerator { void setShouldInternalize(bool Value) { ShouldInternalize = Value; } void setShouldEmbedUselists(bool Value) { ShouldEmbedUselists = Value; } + /// Restore linkage of globals + /// + /// When set, the linkage of globals will be restored prior to code + /// generation. That is, a global symbol that had external linkage prior to + /// LTO will be emitted with external linkage again; and a local will remain + /// local. Note that this option only affects the end result - globals may + /// still be internalized in the process of LTO and may be modified and/or + /// deleted where legal. + /// + /// The default behavior will internalize globals (unless on the preserve + /// list) and, if parallel code generation is enabled, will externalize + /// all locals. + void setShouldRestoreGlobalsLinkage(bool Value) { + ShouldRestoreGlobalsLinkage = Value; + } + void addMustPreserveSymbol(StringRef Sym) { MustPreserveSymbols[Sym] = 1; } /// Pass options to the driver and optimization passes. @@ -105,6 +127,8 @@ struct LTOCodeGenerator { /// Write the merged module to the file specified by the given path. Return /// true on success. + /// + /// Calls \a verifyMergedModuleOnce(). bool writeMergedModules(const char *Path); /// Compile the merged module into a *single* output file; the path to output @@ -129,6 +153,8 @@ struct LTOCodeGenerator { bool DisableVectorization); /// Optimizes the merged module. Returns true on success. + /// + /// Calls \a verifyMergedModuleOnce(). bool optimize(bool DisableVerify, bool DisableInline, bool DisableGVNLoadPRE, bool DisableVectorization); @@ -142,6 +168,8 @@ struct LTOCodeGenerator { /// than one element, code generation is done in parallel with out.size() /// threads. Output files will be written to members of out. Returns true on /// success. + /// + /// Calls \a verifyMergedModuleOnce(). bool compileOptimized(ArrayRef<raw_pwrite_stream *> Out); void setDiagnosticHandler(lto_diagnostic_handler_t, void *); @@ -153,21 +181,28 @@ struct LTOCodeGenerator { private: void initializeLTOPasses(); + /// Verify the merged module on first call. + /// + /// Sets \a HasVerifiedInput on first call and doesn't run again on the same + /// input. + void verifyMergedModuleOnce(); + bool compileOptimizedToFile(const char **Name); + void restoreLinkageForExternals(); void applyScopeRestrictions(); - void applyRestriction(GlobalValue &GV, ArrayRef<StringRef> Libcalls, - std::vector<const char *> &MustPreserveList, - SmallPtrSetImpl<GlobalValue *> &AsmUsed, - Mangler &Mangler); + void preserveDiscardableGVs( + Module &TheModule, + llvm::function_ref<bool(const GlobalValue &)> mustPreserveGV); + bool determineTarget(); + std::unique_ptr<TargetMachine> createTargetMachine(); static void DiagnosticHandler(const DiagnosticInfo &DI, void *Context); void DiagnosticHandler2(const DiagnosticInfo &DI); void emitError(const std::string &ErrMsg); - - typedef StringMap<uint8_t> StringSet; + void emitWarning(const std::string &ErrMsg); LLVMContext &Context; std::unique_ptr<Module> MergedModule; @@ -175,9 +210,11 @@ private: std::unique_ptr<TargetMachine> TargetMach; bool EmitDwarfDebugInfo = false; bool ScopeRestrictionsDone = false; - Reloc::Model RelocModel = Reloc::Default; - StringSet MustPreserveSymbols; - StringSet AsmUndefinedRefs; + bool HasVerifiedInput = false; + Optional<Reloc::Model> RelocModel; + StringSet<> MustPreserveSymbols; + StringSet<> AsmUndefinedRefs; + StringMap<GlobalValue::LinkageTypes> ExternalSymbols; std::vector<std::string> CodegenOptions; std::string FeatureStr; std::string MCpu; @@ -185,11 +222,14 @@ private: std::string NativeObjectPath; TargetOptions Options; CodeGenOpt::Level CGOptLevel = CodeGenOpt::Default; + const Target *MArch = nullptr; + std::string TripleStr; unsigned OptLevel = 2; lto_diagnostic_handler_t DiagHandler = nullptr; void *DiagContext = nullptr; bool ShouldInternalize = true; bool ShouldEmbedUselists = false; + bool ShouldRestoreGlobalsLinkage = false; TargetMachine::CodeGenFileType FileType = TargetMachine::CGFT_ObjectFile; }; } diff --git a/include/llvm/LTO/LTOModule.h b/include/llvm/LTO/legacy/LTOModule.h index 97b5865bd47f8..2e46219be19e2 100644 --- a/include/llvm/LTO/LTOModule.h +++ b/include/llvm/LTO/legacy/LTOModule.h @@ -18,8 +18,6 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" #include "llvm/IR/Module.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/Object/IRObjectFile.h" #include "llvm/Target/TargetMachine.h" #include <string> @@ -59,8 +57,6 @@ private: std::vector<const char*> _asm_undefines; LTOModule(std::unique_ptr<object::IRObjectFile> Obj, TargetMachine *TM); - LTOModule(std::unique_ptr<object::IRObjectFile> Obj, TargetMachine *TM, - std::unique_ptr<LLVMContext> Context); public: ~LTOModule(); @@ -69,6 +65,9 @@ public: static bool isBitcodeFile(const void *mem, size_t length); static bool isBitcodeFile(const char *path); + /// Returns 'true' if the Module is produced for ThinLTO. + bool isThinLTO(); + /// Returns 'true' if the memory buffer is LLVM bitcode for the specified /// triple. static bool isBitcodeForTarget(MemoryBuffer *memBuffer, @@ -92,23 +91,22 @@ public: /// InitializeAllAsmPrinters(); /// InitializeAllAsmParsers(); static ErrorOr<std::unique_ptr<LTOModule>> - createFromFile(LLVMContext &Context, const char *path, TargetOptions options); + createFromFile(LLVMContext &Context, const char *path, + const TargetOptions &options); static ErrorOr<std::unique_ptr<LTOModule>> createFromOpenFile(LLVMContext &Context, int fd, const char *path, - size_t size, TargetOptions options); + size_t size, const TargetOptions &options); static ErrorOr<std::unique_ptr<LTOModule>> createFromOpenFileSlice(LLVMContext &Context, int fd, const char *path, - size_t map_size, off_t offset, TargetOptions options); + size_t map_size, off_t offset, + const TargetOptions &options); static ErrorOr<std::unique_ptr<LTOModule>> createFromBuffer(LLVMContext &Context, const void *mem, size_t length, - TargetOptions options, StringRef path = ""); - + const TargetOptions &options, StringRef path = ""); static ErrorOr<std::unique_ptr<LTOModule>> - createInLocalContext(const void *mem, size_t length, TargetOptions options, + createInLocalContext(std::unique_ptr<LLVMContext> Context, const void *mem, + size_t length, const TargetOptions &options, StringRef path); - static ErrorOr<std::unique_ptr<LTOModule>> - createInContext(const void *mem, size_t length, TargetOptions options, - StringRef path, LLVMContext *Context); const Module &getModule() const { return const_cast<LTOModule*>(this)->getModule(); @@ -207,8 +205,8 @@ private: /// Create an LTOModule (private version). static ErrorOr<std::unique_ptr<LTOModule>> - makeLTOModule(MemoryBufferRef Buffer, TargetOptions options, - LLVMContext *Context); + makeLTOModule(MemoryBufferRef Buffer, const TargetOptions &options, + LLVMContext &Context, bool ShouldBeLazy); }; } #endif diff --git a/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h b/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h new file mode 100644 index 0000000000000..539880e8d3a7a --- /dev/null +++ b/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h @@ -0,0 +1,276 @@ +//===-ThinLTOCodeGenerator.h - LLVM Link Time Optimizer -------------------===// +// +// 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 ThinLTOCodeGenerator class, similar to the +// LTOCodeGenerator but for the ThinLTO scheme. It provides an interface for +// linker plugin. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LTO_THINLTOCODEGENERATOR_H +#define LLVM_LTO_THINLTOCODEGENERATOR_H + +#include "llvm-c/lto.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/ADT/Triple.h" +#include "llvm/IR/ModuleSummaryIndex.h" +#include "llvm/Support/CodeGen.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Target/TargetOptions.h" + +#include <string> + +namespace llvm { +class StringRef; +class LLVMContext; +class TargetMachine; + +/// Helper to gather options relevant to the target machine creation +struct TargetMachineBuilder { + Triple TheTriple; + std::string MCpu; + std::string MAttr; + TargetOptions Options; + Optional<Reloc::Model> RelocModel; + CodeGenOpt::Level CGOptLevel = CodeGenOpt::Default; + + std::unique_ptr<TargetMachine> create() const; +}; + +/// This class define an interface similar to the LTOCodeGenerator, but adapted +/// for ThinLTO processing. +/// The ThinLTOCodeGenerator is not intended to be reuse for multiple +/// compilation: the model is that the client adds modules to the generator and +/// ask to perform the ThinLTO optimizations / codegen, and finally destroys the +/// codegenerator. +class ThinLTOCodeGenerator { +public: + /// Add given module to the code generator. + void addModule(StringRef Identifier, StringRef Data); + + /** + * Adds to a list of all global symbols that must exist in the final generated + * code. If a symbol is not listed there, it will be optimized away if it is + * inlined into every usage. + */ + void preserveSymbol(StringRef Name); + + /** + * Adds to a list of all global symbols that are cross-referenced between + * ThinLTO files. If the ThinLTO CodeGenerator can ensure that every + * references from a ThinLTO module to this symbol is optimized away, then + * the symbol can be discarded. + */ + void crossReferenceSymbol(StringRef Name); + + /** + * Process all the modules that were added to the code generator in parallel. + * + * Client can access the resulting object files using getProducedBinaries() + */ + void run(); + + /** + * Return the "in memory" binaries produced by the code generator. + */ + std::vector<std::unique_ptr<MemoryBuffer>> &getProducedBinaries() { + return ProducedBinaries; + } + + /** + * \defgroup Options setters + * @{ + */ + + /** + * \defgroup Cache controlling options + * + * These entry points control the ThinLTO cache. The cache is intended to + * support incremental build, and thus needs to be persistent accross build. + * The client enabled the cache by supplying a path to an existing directory. + * The code generator will use this to store objects files that may be reused + * during a subsequent build. + * To avoid filling the disk space, a few knobs are provided: + * - The pruning interval limit the frequency at which the garbage collector + * will try to scan the cache directory to prune it from expired entries. + * Setting to -1 disable the pruning (default). + * - The pruning expiration time indicates to the garbage collector how old + * an entry needs to be to be removed. + * - Finally, the garbage collector can be instructed to prune the cache till + * the occupied space goes below a threshold. + * @{ + */ + + struct CachingOptions { + std::string Path; // Path to the cache, empty to disable. + int PruningInterval = 1200; // seconds, -1 to disable pruning. + unsigned int Expiration = 7 * 24 * 3600; // seconds (1w default). + unsigned MaxPercentageOfAvailableSpace = 75; // percentage. + }; + + /// Provide a path to a directory where to store the cached files for + /// incremental build. + void setCacheDir(std::string Path) { CacheOptions.Path = std::move(Path); } + + /// Cache policy: interval (seconds) between two prune of the cache. Set to a + /// negative value (default) to disable pruning. A value of 0 will be ignored. + void setCachePruningInterval(int Interval) { + if (Interval) + CacheOptions.PruningInterval = Interval; + } + + /// Cache policy: expiration (in seconds) for an entry. + /// A value of 0 will be ignored. + void setCacheEntryExpiration(unsigned Expiration) { + if (Expiration) + CacheOptions.Expiration = Expiration; + } + + /** + * Sets the maximum cache size that can be persistent across build, in terms + * of percentage of the available space on the the disk. Set to 100 to + * indicate no limit, 50 to indicate that the cache size will not be left over + * half the available space. A value over 100 will be reduced to 100, and a + * value of 0 will be ignored. + * + * + * The formula looks like: + * AvailableSpace = FreeSpace + ExistingCacheSize + * NewCacheSize = AvailableSpace * P/100 + * + */ + void setMaxCacheSizeRelativeToAvailableSpace(unsigned Percentage) { + if (Percentage) + CacheOptions.MaxPercentageOfAvailableSpace = Percentage; + } + + /**@}*/ + + /// Set the path to a directory where to save temporaries at various stages of + /// the processing. + void setSaveTempsDir(std::string Path) { SaveTempsDir = std::move(Path); } + + /// CPU to use to initialize the TargetMachine + void setCpu(std::string Cpu) { TMBuilder.MCpu = std::move(Cpu); } + + /// Subtarget attributes + void setAttr(std::string MAttr) { TMBuilder.MAttr = std::move(MAttr); } + + /// TargetMachine options + void setTargetOptions(TargetOptions Options) { + TMBuilder.Options = std::move(Options); + } + + /// CodeModel + void setCodePICModel(Optional<Reloc::Model> Model) { + TMBuilder.RelocModel = Model; + } + + /// CodeGen optimization level + void setCodeGenOptLevel(CodeGenOpt::Level CGOptLevel) { + TMBuilder.CGOptLevel = CGOptLevel; + } + + /// Disable CodeGen, only run the stages till codegen and stop. The output + /// will be bitcode. + void disableCodeGen(bool Disable) { DisableCodeGen = Disable; } + + /// Perform CodeGen only: disable all other stages. + void setCodeGenOnly(bool CGOnly) { CodeGenOnly = CGOnly; } + + /**@}*/ + + /** + * \defgroup Set of APIs to run individual stages in isolation. + * @{ + */ + + /** + * Produce the combined summary index from all the bitcode files: + * "thin-link". + */ + std::unique_ptr<ModuleSummaryIndex> linkCombinedIndex(); + + /** + * Perform promotion and renaming of exported internal functions, + * and additionally resolve weak and linkonce symbols. + * Index is updated to reflect linkage changes from weak resolution. + */ + void promote(Module &Module, ModuleSummaryIndex &Index); + + /** + * Compute and emit the imported files for module at \p ModulePath. + */ + static void emitImports(StringRef ModulePath, StringRef OutputName, + ModuleSummaryIndex &Index); + + /** + * Perform cross-module importing for the module identified by + * ModuleIdentifier. + */ + void crossModuleImport(Module &Module, ModuleSummaryIndex &Index); + + /** + * Compute the list of summaries needed for importing into module. + */ + static void gatherImportedSummariesForModule( + StringRef ModulePath, ModuleSummaryIndex &Index, + std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex); + + /** + * Perform internalization. Index is updated to reflect linkage changes. + */ + void internalize(Module &Module, ModuleSummaryIndex &Index); + + /** + * Perform post-importing ThinLTO optimizations. + */ + void optimize(Module &Module); + + /** + * Perform ThinLTO CodeGen. + */ + std::unique_ptr<MemoryBuffer> codegen(Module &Module); + + /**@}*/ + +private: + /// Helper factory to build a TargetMachine + TargetMachineBuilder TMBuilder; + + /// Vector holding the in-memory buffer containing the produced binaries. + std::vector<std::unique_ptr<MemoryBuffer>> ProducedBinaries; + + /// Vector holding the input buffers containing the bitcode modules to + /// process. + std::vector<MemoryBufferRef> Modules; + + /// Set of symbols that need to be preserved outside of the set of bitcode + /// files. + StringSet<> PreservedSymbols; + + /// Set of symbols that are cross-referenced between bitcode files. + StringSet<> CrossReferencedSymbols; + + /// Control the caching behavior. + CachingOptions CacheOptions; + + /// Path to a directory to save the temporary bitcode files. + std::string SaveTempsDir; + + /// Flag to enable/disable CodeGen. When set to true, the process stops after + /// optimizations and a bitcode is produced. + bool DisableCodeGen = false; + + /// Flag to indicate that only the CodeGen will be performed, no cross-module + /// importing or optimization. + bool CodeGenOnly = false; +}; +} +#endif diff --git a/include/llvm/LTO/legacy/UpdateCompilerUsed.h b/include/llvm/LTO/legacy/UpdateCompilerUsed.h new file mode 100644 index 0000000000000..4be0027e97d7c --- /dev/null +++ b/include/llvm/LTO/legacy/UpdateCompilerUsed.h @@ -0,0 +1,32 @@ +//==------ UpdateCompilerUsed.h - LLVM Link Time Optimizer Utility --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares a helper class to update llvm.compiler_used metadata. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LTO_UPDATE_COMPILER_USED_H +#define LLVM_LTO_UPDATE_COMPILER_USED_H + +#include "llvm/ADT/StringSet.h" +#include "llvm/IR/GlobalValue.h" + +namespace llvm { +class Module; +class TargetMachine; + +/// Find all globals in \p TheModule that are referenced in +/// \p AsmUndefinedRefs, as well as the user-supplied functions definitions that +/// are also libcalls, and create or update the magic "llvm.compiler_used" +/// global in \p TheModule. +void updateCompilerUsed(Module &TheModule, const TargetMachine &TM, + const StringSet<> &AsmUndefinedRefs); +} + +#endif // LLVM_LTO_UPDATE_COMPILER_USED_H |