[llvm] r262977 - libLTO: add a ThinLTOCodeGenerator on the model of LTOCodeGenerator.
Mehdi Amini via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 18 18:30:06 PDT 2016
> On Mar 18, 2016, at 11:36 AM, Hal Finkel <hfinkel at anl.gov> wrote:
>
> ----- Original Message -----
>> From: "Mehdi Amini via llvm-commits" <llvm-commits at lists.llvm.org>
>> To: llvm-commits at lists.llvm.org
>> Sent: Tuesday, March 8, 2016 7:37:22 PM
>> Subject: [llvm] r262977 - libLTO: add a ThinLTOCodeGenerator on the model of LTOCodeGenerator.
>>
>> Author: mehdi_amini
>> Date: Tue Mar 8 19:37:22 2016
>> New Revision: 262977
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=262977&view=rev
>> Log:
>> libLTO: add a ThinLTOCodeGenerator on the model of LTOCodeGenerator.
>>
>> This is intended to provide a parallel (threaded) ThinLTO scheme
>> for linker plugin use through the libLTO C API.
>>
>> The intent of this patch is to provide a first implementation as a
>> proof-of-concept and allows linker to start supporting ThinLTO by
>> definiing the libLTO C API. Some part of the libLTO API are left
>> unimplemented yet. Following patches will add support for these.
>>
>> The current implementation can link all clang/llvm binaries.
>>
>> Differential Revision: http://reviews.llvm.org/D17066
>>
>> From: Mehdi Amini <mehdi.amini at apple.com>
>>
>> Added:
>> llvm/trunk/include/llvm/LTO/ThinLTOCodeGenerator.h
>> llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp
>> llvm/trunk/test/ThinLTO/
>> llvm/trunk/test/ThinLTO/Inputs/
>> llvm/trunk/test/ThinLTO/Inputs/funcimport.ll
>> llvm/trunk/test/ThinLTO/funcimport.ll
>> Modified:
>> llvm/trunk/include/llvm-c/lto.h
>> llvm/trunk/include/llvm/ADT/STLExtras.h
>> llvm/trunk/include/llvm/LTO/LTOModule.h
>> llvm/trunk/lib/LTO/CMakeLists.txt
>> llvm/trunk/lib/LTO/LLVMBuild.txt
>> llvm/trunk/lib/LTO/LTOModule.cpp
>> llvm/trunk/tools/llvm-lto/llvm-lto.cpp
>> llvm/trunk/tools/lto/lto.cpp
>> llvm/trunk/tools/lto/lto.exports
>>
>> Modified: llvm/trunk/include/llvm-c/lto.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/lto.h?rev=262977&r1=262976&r2=262977&view=diff
>> ==============================================================================
>> --- llvm/trunk/include/llvm-c/lto.h (original)
>> +++ llvm/trunk/include/llvm-c/lto.h Tue Mar 8 19:37:22 2016
>> @@ -40,8 +40,7 @@ typedef bool lto_bool_t;
>> * @{
>> */
>>
>> -#define LTO_API_VERSION 17
>> -
>> +#define LTO_API_VERSION 18
>> /**
>> * \since prior to LTO_API_VERSION=3
>> */
>> @@ -91,6 +90,9 @@ typedef struct LLVMOpaqueLTOModule *lto_
>> /** opaque reference to a code generator */
>> typedef struct LLVMOpaqueLTOCodeGenerator *lto_code_gen_t;
>>
>> +/** opaque reference to a thin code generator */
>> +typedef struct LLVMOpaqueThinLTOCodeGenerator *thinlto_code_gen_t;
>> +
>> #ifdef __cplusplus
>> extern "C" {
>> #endif
>> @@ -548,6 +550,221 @@ extern void
>> lto_codegen_set_should_embed_uselists(lto_code_gen_t cg,
>> lto_bool_t
>> ShouldEmbedUselists);
>>
>> +/**
>> + * @}
>> + * @defgroup LLVMCTLTO ThinLTO
>> + * @ingroup LLVMC
>> + *
>> + * @{
>> + */
>> +
>> +/**
>> + * Type to wrap a single object returned by ThinLTO.
>> + *
>> + * \since LTO_API_VERSION=18
>> + */
>> +typedef struct {
>> + void *Buffer;
>> + size_t Size;
>> +} LTOObjectBuffer;
>> +
>> +/**
>> + * Instantiates a ThinLTO code generator.
>> + * Returns NULL on error (check lto_get_error_message() for
>> details).
>> + *
>> + *
>> + * 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.
>> + *
>> + * \since LTO_API_VERSION=18
>> + */
>> +extern thinlto_code_gen_t thinlto_create_codegen();
>> +
>> +/**
>> + * Frees the generator and all memory it internally allocated.
>> + * Upon return the thinlto_code_gen_t is no longer valid.
>> + *
>> + * \since LTO_API_VERSION=18
>> + */
>> +extern void thinlto_codegen_dispose(thinlto_code_gen_t cg);
>> +
>> +/**
>> + * Add a module to a ThinLTO code generator. Identifier has to be
>> unique among
>> + * all the modules in a code generator. The data buffer stays owned
>> by the
>> + * client, and is expected to be available for the entire lifetime
>> of the
>> + * thinlto_code_gen_t it is added to.
>> + *
>> + * On failure, returns NULL (check lto_get_error_message() for
>> details).
>> + *
>> + *
>> + * \since LTO_API_VERSION=18
>> + */
>> +extern void thinlto_codegen_add_module(thinlto_code_gen_t cg,
>> + const char *identifier, const
>> char *data,
>> + int length);
>> +
>> +/**
>> + * Optimize and codegen all the modules added to the codegenerator
>> using
>> + * ThinLTO. Resulting objects are accessible using
>> thinlto_module_get_object().
>> + *
>> + * \since LTO_API_VERSION=18
>> + */
>> +extern void thinlto_codegen_process(thinlto_code_gen_t cg);
>> +
>> +/**
>> + * Returns the number of object files produced by the ThinLTO
>> CodeGenerator.
>> + *
>> + * It usually matches the number of input files, but this is not a
>> guarantee of
>> + * the API and may change in future implementation, so the client
>> should not
>> + * assume it.
>> + *
>> + * \since LTO_API_VERSION=18
>> + */
>> +extern unsigned int
>> thinlto_module_get_num_objects(thinlto_code_gen_t cg);
>> +
>> +/**
>> + * Returns a reference to the ith object file produced by the
>> ThinLTO
>> + * CodeGenerator.
>> + *
>> + * Client should use \p thinlto_module_get_num_objects() to get the
>> number of
>> + * available objects.
>> + *
>> + * \since LTO_API_VERSION=18
>> + */
>> +extern LTOObjectBuffer thinlto_module_get_object(thinlto_code_gen_t
>> cg,
>> + unsigned int
>> index);
>> +
>> +/**
>> + * Sets which PIC code model to generate.
>> + * Returns true on error (check lto_get_error_message() for
>> details).
>> + *
>> + * \since LTO_API_VERSION=18
>> + */
>> +extern lto_bool_t thinlto_codegen_set_pic_model(thinlto_code_gen_t
>> cg,
>> + lto_codegen_model);
>> +
>> +/**
>> + * @}
>> + * @defgroup LLVMCTLTO_CACHING ThinLTO Cache Control
>> + * @ingroup LLVMCTLTO
>> + *
>> + * 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.
>> + * @{
>> + */
>> +
>> +/**
>> + * Sets the path to a directory to use as a cache storage for
>> incremental build.
>> + *
>> + * \since LTO_API_VERSION=18
>> + */
>> +extern void thinlto_codegen_set_cache_dir(thinlto_code_gen_t cg,
>> + const char *cache_dir);
>> +
>> +/**
>> + * Sets the cache pruning interval (in seconds). A negative value
>> disable the
>> + * pruning (default).
>> + *
>> + * \since LTO_API_VERSION=18
>> + */
>> +extern void
>> thinlto_codegen_set_cache_pruning_interval(thinlto_code_gen_t cg,
>> + int
>> interval);
>> +
>> +/**
>> + * 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.
>> + *
>> + * The formula looks like:
>> + * AvailableSpace = FreeSpace + ExistingCacheSize
>> + * NewCacheSize = AvailableSpace * P/100
>> + *
>> + * \since LTO_API_VERSION=18
>> + */
>> +extern void
>> thinlto_codegen_set_final_cache_size_relative_to_available_space(
>> + thinlto_code_gen_t cg, unsigned percentage);
>> +
>> +/**
>> + * Sets the expiration (in seconds) for an entry in the cache.
>> + *
>> + * \since LTO_API_VERSION=18
>> + */
>> +extern void
>> thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg,
>> + unsigned
>> expiration);
>> +
>> +/**
>> + * @}
>> + */
>> +
>> +/**
>> + * Sets the path to a directory to use as a storage for temporary
>> bitcode files.
>> + * The intention is to make the bitcode files available for
>> debugging at various
>> + * stage of the pipeline.
>> + *
>> + * \since LTO_API_VERSION=18
>> + */
>> +extern void thinlto_codegen_set_savetemps_dir(thinlto_code_gen_t cg,
>> + const char
>> *save_temps_dir);
>> +
>> +/**
>> + * Sets the cpu to generate code for.
>> + *
>> + * \since LTO_API_VERSION=18
>> + */
>> +extern void thinlto_codegen_set_cpu(thinlto_code_gen_t cg, const
>> char *cpu);
>> +
>> +/**
>> + * Parse -mllvm style debug options.
>> + *
>> + * \since LTO_API_VERSION=18
>> + */
>> +extern void thinlto_debug_options(const char *const *options, int
>> number);
>> +
>> +/**
>> + * Test if a module has support for ThinLTO linking.
>> + *
>> + * \since LTO_API_VERSION=18
>> + */
>> +extern bool lto_module_is_thinlto(lto_module_t mod);
>> +
>> +/**
>> + * Adds a symbol to the list of global symbols that must exist in
>> the final
>> + * generated code. If a function is not listed there, it might be
>> inlined into
>> + * every usage and optimized away. For every single module, the
>> functions
>> + * referenced from code outside of the ThinLTO modules need to be
>> added here.
>> + *
>> + * \since LTO_API_VERSION=18
>> + */
>> +extern void
>> thinlto_codegen_add_must_preserve_symbol(thinlto_code_gen_t cg,
>> + const char
>> *name,
>> + int length);
>> +
>> +/**
>> + * Adds a symbol to the list of 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.
>> + *
>> + * \since LTO_API_VERSION=18
>> + */
>> +extern void
>> thinlto_codegen_add_cross_referenced_symbol(thinlto_code_gen_t cg,
>> + const char
>> *name,
>> + int length);
>> +
>> #ifdef __cplusplus
>> }
>> #endif
>>
>> Modified: llvm/trunk/include/llvm/ADT/STLExtras.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/STLExtras.h?rev=262977&r1=262976&r2=262977&view=diff
>> ==============================================================================
>> --- llvm/trunk/include/llvm/ADT/STLExtras.h (original)
>> +++ llvm/trunk/include/llvm/ADT/STLExtras.h Tue Mar 8 19:37:22 2016
>> @@ -386,6 +386,13 @@ auto find(R &&Range, const T &val) -> de
>> return std::find(Range.begin(), Range.end(), val);
>> }
>>
>> +/// Provide wrappers to std::find_if which take ranges instead of
>> having to pass
>> +/// begin/end explicitly.
>> +template <typename R, class T>
>> +auto find_if(R &&Range, const T &Pred) -> decltype(Range.begin()) {
>> + return std::find_if(Range.begin(), Range.end(), Pred);
>> +}
>> +
>> //===----------------------------------------------------------------------===//
>> // Extra additions to <memory>
>> //===----------------------------------------------------------------------===//
>>
>> Modified: llvm/trunk/include/llvm/LTO/LTOModule.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LTO/LTOModule.h?rev=262977&r1=262976&r2=262977&view=diff
>> ==============================================================================
>> --- llvm/trunk/include/llvm/LTO/LTOModule.h (original)
>> +++ llvm/trunk/include/llvm/LTO/LTOModule.h Tue Mar 8 19:37:22 2016
>> @@ -65,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,
>>
>> Added: llvm/trunk/include/llvm/LTO/ThinLTOCodeGenerator.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LTO/ThinLTOCodeGenerator.h?rev=262977&view=auto
>> ==============================================================================
>> --- llvm/trunk/include/llvm/LTO/ThinLTOCodeGenerator.h (added)
>> +++ llvm/trunk/include/llvm/LTO/ThinLTOCodeGenerator.h Tue Mar 8
>> 19:37:22 2016
>> @@ -0,0 +1,233 @@
>> +//===-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/StringRef.h"
>> +#include "llvm/ADT/StringSet.h"
>> +#include "llvm/ADT/Triple.h"
>> +#include "llvm/Support/CodeGen.h"
>> +#include "llvm/Support/MemoryBuffer.h"
>> +#include "llvm/Target/TargetOptions.h"
>> +
>> +#include <string>
>> +
>> +namespace llvm {
>> +class FunctionInfoIndex;
>> +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;
>> + Reloc::Model RelocModel = Reloc::Default;
>> + 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;
>> + int PruningInterval = -1; // seconds, -1 to
>> disable pruning
>> + unsigned int Expiration; // seconds.
>> + unsigned MaxPercentageOfAvailableSpace; // 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.
>> + void setCachePruningInterval(int Interval) {
>> + CacheOptions.PruningInterval = Interval;
>> + }
>> +
>> + /// Cache policy: expiration (in seconds) for an entry.
>> + void setCacheEntryExpiration(unsigned 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.
>> + *
>> + * The formula looks like:
>> + * AvailableSpace = FreeSpace + ExistingCacheSize
>> + * NewCacheSize = AvailableSpace * P/100
>> + *
>> + */
>> + void setMaxCacheSizeRelativeToAvailableSpace(unsigned 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(Reloc::Model Model) { TMBuilder.RelocModel =
>> Model; }
>> +
>> + /// CodeGen optimization level
>> + void setCodeGenOptLevel(CodeGenOpt::Level CGOptLevel) {
>> + TMBuilder.CGOptLevel = CGOptLevel;
>> + }
>> +
>> + /**@}*/
>> +
>> + /**
>> + * \defgroup Set of APIs to run individual stages in isolation.
>> + * @{
>> + */
>> +
>> + /**
>> + * Produce the combined function index from all the bitcode files:
>> + * "thin-link".
>> + */
>> + std::unique_ptr<FunctionInfoIndex> linkCombinedIndex();
>> +
>> + /**
>> + * Perform promotion and renaming of exported internal functions.
>> + */
>> + void promote(Module &Module, FunctionInfoIndex &Index);
>> +
>> + /**
>> + * Perform cross-module importing for the module identified by
>> + * ModuleIdentifier.
>> + */
>> + void crossModuleImport(Module &Module, FunctionInfoIndex &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;
>> +};
>> +}
>> +#endif
>>
>> Modified: llvm/trunk/lib/LTO/CMakeLists.txt
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/CMakeLists.txt?rev=262977&r1=262976&r2=262977&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/LTO/CMakeLists.txt (original)
>> +++ llvm/trunk/lib/LTO/CMakeLists.txt Tue Mar 8 19:37:22 2016
>> @@ -1,9 +1,10 @@
>> add_llvm_library(LLVMLTO
>> LTOModule.cpp
>> LTOCodeGenerator.cpp
>> + ThinLTOCodeGenerator.cpp
>>
>> ADDITIONAL_HEADER_DIRS
>> ${LLVM_MAIN_INCLUDE_DIR}/llvm/LTO
>> - )
>> +)
>>
>> add_dependencies(LLVMLTO intrinsics_gen)
>>
>> Modified: llvm/trunk/lib/LTO/LLVMBuild.txt
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LLVMBuild.txt?rev=262977&r1=262976&r2=262977&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/LTO/LLVMBuild.txt (original)
>> +++ llvm/trunk/lib/LTO/LLVMBuild.txt Tue Mar 8 19:37:22 2016
>> @@ -34,3 +34,4 @@ required_libraries =
>> Scalar
>> Support
>> Target
>> + TransformUtils
>> \ No newline at end of file
>>
>> Modified: llvm/trunk/lib/LTO/LTOModule.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTOModule.cpp?rev=262977&r1=262976&r2=262977&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/LTO/LTOModule.cpp (original)
>> +++ llvm/trunk/lib/LTO/LTOModule.cpp Tue Mar 8 19:37:22 2016
>> @@ -75,6 +75,18 @@ bool LTOModule::isBitcodeFile(const char
>> return bool(BCData);
>> }
>>
>> +bool LTOModule::isThinLTO() {
>> + // Right now the detection is only based on the summary presence.
>> We may want
>> + // to add a dedicated flag at some point.
>> + return hasFunctionSummary(IRFile->getMemoryBufferRef(),
>> + [](const DiagnosticInfo &DI) {
>> + DiagnosticPrinterRawOStream
>> DP(errs());
>> + DI.print(DP);
>> + errs() << '\n';
>> + return;
>> + });
>> +}
>> +
>> bool LTOModule::isBitcodeForTarget(MemoryBuffer *Buffer,
>> StringRef TriplePrefix) {
>> ErrorOr<MemoryBufferRef> BCOrErr =
>>
>> Added: llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp?rev=262977&view=auto
>> ==============================================================================
>> --- llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp (added)
>> +++ llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp Tue Mar 8 19:37:22
>> 2016
>> @@ -0,0 +1,384 @@
>> +//===-ThinLTOCodeGenerator.cpp - 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 implements the Thin Link Time Optimization library.
>> This library is
>> +// intended to be used by linker to optimize code at link time.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "llvm/LTO/ThinLTOCodeGenerator.h"
>> +
>> +#include "llvm/ADT/StringExtras.h"
>> +#include "llvm/ADT/Statistic.h"
>> +#include "llvm/Analysis/TargetLibraryInfo.h"
>> +#include "llvm/Analysis/TargetTransformInfo.h"
>> +#include "llvm/Bitcode/ReaderWriter.h"
>> +#include "llvm/Bitcode/BitcodeWriterPass.h"
>> +#include "llvm/ExecutionEngine/ObjectMemoryBuffer.h"
>> +#include "llvm/IR/LLVMContext.h"
>> +#include "llvm/IR/DiagnosticPrinter.h"
>> +#include "llvm/IR/LegacyPassManager.h"
>> +#include "llvm/IR/Mangler.h"
>> +#include "llvm/IRReader/IRReader.h"
>> +#include "llvm/Linker/Linker.h"
>> +#include "llvm/MC/SubtargetFeature.h"
>> +#include "llvm/Object/FunctionIndexObjectFile.h"
>> +#include "llvm/Support/SourceMgr.h"
>> +#include "llvm/Support/TargetRegistry.h"
>> +#include "llvm/Support/ThreadPool.h"
>> +#include "llvm/Target/TargetMachine.h"
>> +#include "llvm/Transforms/IPO.h"
>> +#include "llvm/Transforms/IPO/FunctionImport.h"
>> +#include "llvm/Transforms/IPO/PassManagerBuilder.h"
>> +#include "llvm/Transforms/ObjCARC.h"
>> +#include "llvm/Transforms/Utils/FunctionImportUtils.h"
>> +
>> +using namespace llvm;
>> +
>> +namespace {
>> +
>> +static cl::opt<int> ThreadCount("threads",
>> +
>> cl::init(std::thread::hardware_concurrency()));
>> +
>> +static void diagnosticHandler(const DiagnosticInfo &DI) {
>> + DiagnosticPrinterRawOStream DP(errs());
>> + DI.print(DP);
>> + errs() << '\n';
>> +}
>> +
>> +// Simple helper to load a module from bitcode
>> +static std::unique_ptr<Module>
>> +loadModuleFromBuffer(const MemoryBufferRef &Buffer, LLVMContext
>> &Context,
>> + bool Lazy) {
>> + SMDiagnostic Err;
>> + ErrorOr<std::unique_ptr<Module>> ModuleOrErr(nullptr);
>> + if (Lazy) {
>> + ModuleOrErr =
>> + getLazyBitcodeModule(MemoryBuffer::getMemBuffer(Buffer,
>> false), Context,
>> + /* ShouldLazyLoadMetadata */ Lazy);
>> + } else {
>> + ModuleOrErr = parseBitcodeFile(Buffer, Context);
>> + }
>> + if (std::error_code EC = ModuleOrErr.getError()) {
>> + Err = SMDiagnostic(Buffer.getBufferIdentifier(),
>> SourceMgr::DK_Error,
>> + EC.message());
>> + Err.print("ThinLTO", errs());
>> + report_fatal_error("Can't load module, abort.");
>> + }
>> + return std::move(ModuleOrErr.get());
>> +}
>> +
>> +// Simple helper to save temporary files for debug.
>> +static void saveTempBitcode(const Module &TheModule, StringRef
>> TempDir,
>> + unsigned count, StringRef Suffix) {
>> + if (TempDir.empty())
>> + return;
>> + // User asked to save temps, let dump the bitcode file after
>> import.
>> + auto SaveTempPath = TempDir + llvm::utostr(count) + Suffix;
>> + std::error_code EC;
>> + raw_fd_ostream OS(SaveTempPath.str(), EC, sys::fs::F_None);
>> + if (EC)
>> + report_fatal_error(Twine("Failed to open ") + SaveTempPath +
>> + " to save optimized bitcode\n");
>> + WriteBitcodeToFile(&TheModule, OS, true, false);
>> +}
>> +
>> +static StringMap<MemoryBufferRef>
>> +generateModuleMap(const std::vector<MemoryBufferRef> &Modules) {
>> + StringMap<MemoryBufferRef> ModuleMap;
>> + for (auto &ModuleBuffer : Modules) {
>> + assert(ModuleMap.find(ModuleBuffer.getBufferIdentifier()) ==
>> + ModuleMap.end() &&
>> + "Expect unique Buffer Identifier");
>> + ModuleMap[ModuleBuffer.getBufferIdentifier()] = ModuleBuffer;
>> + }
>> + return ModuleMap;
>> +}
>> +
>> +/// 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);
>> + }
>> +};
>> +
>> +static void promoteModule(Module &TheModule, const FunctionInfoIndex
>> &Index) {
>> + if (renameModuleForThinLTO(TheModule, Index))
>> + report_fatal_error("renameModuleForThinLTO failed");
>> +}
>> +
>> +static void crossImportIntoModule(Module &TheModule,
>> + const FunctionInfoIndex &Index,
>> + StringMap<MemoryBufferRef>
>> &ModuleMap) {
>> + ModuleLoader Loader(TheModule.getContext(), ModuleMap);
>> + FunctionImporter Importer(Index, Loader);
>> + Importer.importFunctions(TheModule);
>> +}
>> +
>> +static void optimizeModule(Module &TheModule, TargetMachine &TM) {
>> + // Populate the PassManager
>> + PassManagerBuilder PMB;
>> + PMB.LibraryInfo = new TargetLibraryInfoImpl(TM.getTargetTriple());
>> + PMB.Inliner = createFunctionInliningPass();
>> + // FIXME: should get it from the bitcode?
>> + PMB.OptLevel = 3;
>> + PMB.LoopVectorize = true;
>> + PMB.SLPVectorize = true;
>> + PMB.VerifyInput = true;
>> + PMB.VerifyOutput = false;
>> +
>> + legacy::PassManager PM;
>> +
>> + // Add the TTI (required to inform the vectorizer about register
>> size for
>> + // instance)
>> +
>> PM.add(createTargetTransformInfoWrapperPass(TM.getTargetIRAnalysis()));
>> +
>> + // Add optimizations
>> + PMB.populateThinLTOPassManager(PM);
>> + PM.add(createObjCARCContractPass());
>> +
>> + PM.run(TheModule);
>> +}
>> +
>> +std::unique_ptr<MemoryBuffer> codegenModule(Module &TheModule,
>> + TargetMachine &TM) {
>> + SmallVector<char, 128> OutputBuffer;
>> +
>> + // CodeGen
>> + {
>> + raw_svector_ostream OS(OutputBuffer);
>> + legacy::PassManager PM;
>> + if (TM.addPassesToEmitFile(PM, OS,
>> TargetMachine::CGFT_ObjectFile,
>> + /* DisableVerify */ true))
>> + report_fatal_error("Failed to setup codegen");
>> +
>> + // Run codegen now. resulting binary is in OutputBuffer.
>> + PM.run(TheModule);
>> + }
>> + return make_unique<ObjectMemoryBuffer>(std::move(OutputBuffer));
>> +}
>> +
>> +static std::unique_ptr<MemoryBuffer>
>> +ProcessThinLTOModule(Module &TheModule, const FunctionInfoIndex
>> &Index,
>> + StringMap<MemoryBufferRef> &ModuleMap,
>> TargetMachine &TM,
>> + ThinLTOCodeGenerator::CachingOptions
>> CacheOptions,
>> + StringRef SaveTempsDir, unsigned count) {
>> +
>> + // Save temps: after IPO.
>> + saveTempBitcode(TheModule, SaveTempsDir, count, ".1.IPO.bc");
>> +
>> + // "Benchmark"-like optimization: single-source case
>> + bool SingleModule = (ModuleMap.size() == 1);
>> +
>> + if (!SingleModule) {
>> + promoteModule(TheModule, Index);
>> +
>> + // Save temps: after promotion.
>> + saveTempBitcode(TheModule, SaveTempsDir, count,
>> ".2.promoted.bc");
>> +
>> + crossImportIntoModule(TheModule, Index, ModuleMap);
>> +
>> + // Save temps: after cross-module import.
>> + saveTempBitcode(TheModule, SaveTempsDir, count,
>> ".3.imported.bc");
>> + }
>> +
>> + optimizeModule(TheModule, TM);
>> +
>> + saveTempBitcode(TheModule, SaveTempsDir, count, ".3.opt.bc");
>> +
>> + return codegenModule(TheModule, TM);
>> +}
>> +
>> +// Initialize the TargetMachine builder for a given Triple
>> +static void initTMBuilder(TargetMachineBuilder &TMBuilder,
>> + const Triple &TheTriple) {
>> + // Set a default CPU for Darwin triples (copied from
>> LTOCodeGenerator).
>> + // FIXME this looks pretty terrible...
>> + if (TMBuilder.MCpu.empty() && TheTriple.isOSDarwin()) {
>> + if (TheTriple.getArch() == llvm::Triple::x86_64)
>> + TMBuilder.MCpu = "core2";
>> + else if (TheTriple.getArch() == llvm::Triple::x86)
>> + TMBuilder.MCpu = "yonah";
>> + else if (TheTriple.getArch() == llvm::Triple::aarch64)
>> + TMBuilder.MCpu = "cyclone";
>> + }
>> + TMBuilder.TheTriple = std::move(TheTriple);
>> +}
>> +
>> +} // end anonymous namespace
>> +
>> +void ThinLTOCodeGenerator::addModule(StringRef Identifier, StringRef
>> Data) {
>> + MemoryBufferRef Buffer(Data, Identifier);
>> + if (Modules.empty()) {
>> + // First module added, so initialize the triple and some options
>> + LLVMContext Context;
>> + Triple TheTriple(getBitcodeTargetTriple(Buffer, Context));
>> + initTMBuilder(TMBuilder, Triple(TheTriple));
>> + }
>> +#ifndef NDEBUG
>> + else {
>> + LLVMContext Context;
>> + assert(TMBuilder.TheTriple.str() ==
>> + getBitcodeTargetTriple(Buffer, Context) &&
>> + "ThinLTO modules with different triple not supported");
>> + }
>> +#endif
>> + Modules.push_back(Buffer);
>> +}
>> +
>> +void ThinLTOCodeGenerator::preserveSymbol(StringRef Name) {
>> + PreservedSymbols.insert(Name);
>> +}
>> +
>> +void ThinLTOCodeGenerator::crossReferenceSymbol(StringRef Name) {
>> + CrossReferencedSymbols.insert(Name);
>> +}
>> +
>> +// TargetMachine factory
>> +std::unique_ptr<TargetMachine> TargetMachineBuilder::create() const
>> {
>> + std::string ErrMsg;
>> + const Target *TheTarget =
>> + TargetRegistry::lookupTarget(TheTriple.str(), ErrMsg);
>> + if (!TheTarget) {
>> + report_fatal_error("Can't load target for this Triple: " +
>> ErrMsg);
>> + }
>> +
>> + // Use MAttr as the default set of features.
>> + SubtargetFeatures Features(MAttr);
>> + Features.getDefaultSubtargetFeatures(TheTriple);
>> + std::string FeatureStr = Features.getString();
>> + return
>> std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
>> + TheTriple.str(), MCpu, FeatureStr, Options, RelocModel,
>> + CodeModel::Default, CGOptLevel));
>> +}
>> +
>> +/**
>> + * Produce the combined function index from all the bitcode files:
>> + * "thin-link".
>> + */
>> +std::unique_ptr<FunctionInfoIndex>
>> ThinLTOCodeGenerator::linkCombinedIndex() {
>> + std::unique_ptr<FunctionInfoIndex> CombinedIndex;
>> + uint64_t NextModuleId = 0;
>> + for (auto &ModuleBuffer : Modules) {
>> + ErrorOr<std::unique_ptr<object::FunctionIndexObjectFile>>
>> ObjOrErr =
>> + object::FunctionIndexObjectFile::create(ModuleBuffer,
>> diagnosticHandler,
>> + false);
>> + if (std::error_code EC = ObjOrErr.getError()) {
>> + // FIXME diagnose
>> + errs() << "error: can't create FunctionIndexObjectFile for
>> buffer: "
>> + << EC.message() << "\n";
>> + return nullptr;
>> + }
>> + auto Index = (*ObjOrErr)->takeIndex();
>> + if (CombinedIndex) {
>> + CombinedIndex->mergeFrom(std::move(Index), ++NextModuleId);
>> + } else {
>> + CombinedIndex = std::move(Index);
>> + }
>> + }
>> + return CombinedIndex;
>> +}
>> +
>> +/**
>> + * Perform promotion and renaming of exported internal functions.
>> + */
>> +void ThinLTOCodeGenerator::promote(Module &TheModule,
>> + FunctionInfoIndex &Index) {
>> + promoteModule(TheModule, Index);
>> +}
>> +
>> +/**
>> + * Perform cross-module importing for the module identified by
>> ModuleIdentifier.
>> + */
>> +void ThinLTOCodeGenerator::crossModuleImport(Module &TheModule,
>> + FunctionInfoIndex
>> &Index) {
>> + auto ModuleMap = generateModuleMap(Modules);
>> + crossImportIntoModule(TheModule, Index, ModuleMap);
>> +}
>> +
>> +/**
>> + * Perform post-importing ThinLTO optimizations.
>> + */
>> +void ThinLTOCodeGenerator::optimize(Module &TheModule) {
>> + initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));
>> + optimizeModule(TheModule, *TMBuilder.create());
>> +}
>> +
>> +/**
>> + * Perform ThinLTO CodeGen.
>> + */
>> +std::unique_ptr<MemoryBuffer> ThinLTOCodeGenerator::codegen(Module
>> &TheModule) {
>> + initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));
>> + return codegenModule(TheModule, *TMBuilder.create());
>> +}
>> +
>> +// Main entry point for the ThinLTO processing
>> +void ThinLTOCodeGenerator::run() {
>> + // Sequential linking phase
>> + auto Index = linkCombinedIndex();
>> +
>> + // Save temps: index.
>> + if (!SaveTempsDir.empty()) {
>> + auto SaveTempPath = SaveTempsDir + "index.bc";
>> + std::error_code EC;
>> + raw_fd_ostream OS(SaveTempPath, EC, sys::fs::F_None);
>> + if (EC)
>> + report_fatal_error(Twine("Failed to open ") + SaveTempPath +
>> + " to save optimized bitcode\n");
>> + WriteFunctionSummaryToFile(*Index, OS);
>> + }
>> +
>> + // Prepare the resulting object vector
>> + assert(ProducedBinaries.empty() && "The generator should not be
>> reused");
>> + ProducedBinaries.resize(Modules.size());
>> +
>> + // Prepare the module map.
>> + auto ModuleMap = generateModuleMap(Modules);
>> +
>> + // Parallel optimizer + codegen
>> + {
>> + ThreadPool Pool(ThreadCount);
>> + int count = 0;
>> + for (auto &ModuleBuffer : Modules) {
>> + Pool.async([&](int count) {
>> + LLVMContext Context;
>> +
>> + // Parse module now
>> + auto TheModule = loadModuleFromBuffer(ModuleBuffer, Context,
>> false);
>> +
>> + // Save temps: original file.
>> + if (!SaveTempsDir.empty()) {
>> + saveTempBitcode(*TheModule, SaveTempsDir, count,
>> ".0.original.bc");
>> + }
>> +
>> + ProducedBinaries[count] = ProcessThinLTOModule(
>> + *TheModule, *Index, ModuleMap, *TMBuilder.create(),
>> CacheOptions,
>> + SaveTempsDir, count);
>> + }, count);
>> + count++;
>> + }
>> + }
>> +
>> + // If statistics were requested, print them out now.
>> + if (llvm::AreStatisticsEnabled())
>> + llvm::PrintStatistics();
>> +}
>>
>> Added: llvm/trunk/test/ThinLTO/Inputs/funcimport.ll
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ThinLTO/Inputs/funcimport.ll?rev=262977&view=auto
>> ==============================================================================
>> --- llvm/trunk/test/ThinLTO/Inputs/funcimport.ll (added)
>> +++ llvm/trunk/test/ThinLTO/Inputs/funcimport.ll Tue Mar 8 19:37:22
>> 2016
>> @@ -0,0 +1,32 @@
>> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
>> +target triple = "x86_64-apple-macosx10.11.0"
>> +
>> +
>> +define i32 @main() #0 {
>> +entry:
>> + call void (...) @weakalias()
>> + call void (...) @analias()
>> + %call = call i32 (...) @referencestatics()
>> + %call1 = call i32 (...) @referenceglobals()
>> + %call2 = call i32 (...) @referencecommon()
>> + call void (...) @setfuncptr()
>> + call void (...) @callfuncptr()
>> + call void (...) @callweakfunc()
>> + ret i32 0
>> +}
>> +
>> +declare void @weakalias(...) #1
>> +
>> +declare void @analias(...) #1
>> +
>> +declare i32 @referencestatics(...) #1
>> +
>> +declare i32 @referenceglobals(...) #1
>> +
>> +declare i32 @referencecommon(...) #1
>> +
>> +declare void @setfuncptr(...) #1
>> +
>> +declare void @callfuncptr(...) #1
>> +
>> +declare void @callweakfunc(...) #1
>>
>> Added: llvm/trunk/test/ThinLTO/funcimport.ll
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ThinLTO/funcimport.ll?rev=262977&view=auto
>> ==============================================================================
>> --- llvm/trunk/test/ThinLTO/funcimport.ll (added)
>> +++ llvm/trunk/test/ThinLTO/funcimport.ll Tue Mar 8 19:37:22 2016
>> @@ -0,0 +1,139 @@
>> +; Do setup work for all below tests: generate bitcode and combined
>> index
>> +; RUN: llvm-as -function-summary %s -o %t.bc
>> +; RUN: llvm-as -function-summary %p/Inputs/funcimport.ll -o %t2.bc
>> +; RUN: llvm-lto -thinlto-action=thinlink -o %t3.bc %t.bc %t2.bc
>> +
>> +; Ensure statics are promoted/renamed correctly from this file (all
>> but
>> +; constant variable need promotion).
>> +; RUN: llvm-lto -thinlto-action=promote %t.bc -thinlto-index=%t3.bc
>> -o - | llvm-dis -o - | FileCheck %s --check-prefix=EXPORTSTATIC
>> +; EXPORTSTATIC-DAG: @staticvar.llvm.0 = hidden global
>> +; EXPORTSTATIC-DAG: @staticconstvar = internal unnamed_addr constant
>> +; EXPORTSTATIC-DAG: @P.llvm.0 = hidden global void ()* null
>> +; EXPORTSTATIC-DAG: define hidden i32 @staticfunc.llvm.0
>> +; EXPORTSTATIC-DAG: define hidden void @staticfunc2.llvm.0
>> +
>> +; Ensure that both weak alias to an imported function and strong
>> alias to a
>> +; non-imported function are correctly turned into declarations.
>> +; Also ensures that alias to a linkonce function is turned into a
>> declaration
>> +; and that the associated linkonce function is not in the output, as
>> it is
>> +; lazily linked and never referenced/materialized.
>> +; RUN: llvm-lto -thinlto-action=import %t2.bc -thinlto-index=%t3.bc
>> -o - | llvm-dis -o - | FileCheck %s --check-prefix=IMPORTGLOB1
>> +; IMPORTGLOB1-DAG: define available_externally void @globalfunc1
>> +; IMPORTGLOB1-DAG: declare void @weakalias
>> +; IMPORTGLOB1-DAG: declare void @analias
>> +; IMPORTGLOB1-NOT: @linkoncealias
>> +; IMPORTGLOB1-NOT: @linkoncefunc
>> +; IMPORTGLOB1-NOT: declare void @globalfunc2
>> +
>> +; Verify that the optimizer run
>> +; RUN: llvm-lto -thinlto-action=optimize %t2.bc -o - | llvm-dis -o -
>> | FileCheck %s --check-prefix=OPTIMIZED
>> +; OPTIMIZED: define i32 @main()
>> +
>> +; Verify that the codegen run
>> +; RUN: llvm-lto -thinlto-action=codegen %t2.bc -o - | llvm-nm -o - |
>> FileCheck %s --check-prefix=CODEGEN
>> +; CODEGEN: T _main
>> +
>> +; Verify that all run together
>> +; RUN: llvm-lto -thinlto-action=run %t2.bc %t.bc
>> +; RUN: llvm-nm -o - < %t.bc.thinlto.o | FileCheck %s
>> --check-prefix=ALL
>> +; RUN: llvm-nm -o - < %t2.bc.thinlto.o | FileCheck %s
>> --check-prefix=ALL2
>> +; ALL: T _callfuncptr
>> +; ALL2: T _main
>> +
>> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
>> +target triple = "x86_64-apple-macosx10.11.0"
>> +
>> + at globalvar_in_section = global i32 1, align 4
>> + at globalvar = global i32 1, align 4
>> + at staticvar = internal global i32 1, align 4
>> + at staticvar2 = internal global i32 1, align 4
>> + at staticconstvar = internal unnamed_addr constant [2 x i32] [i32 10,
>> i32 20], align 4
>> + at commonvar = common global i32 0, align 4
>> + at P = internal global void ()* null, align 8
>> +
>> + at weakalias = weak alias void (...), bitcast (void ()* @globalfunc1
>> to void (...)*)
>> + at analias = alias void (...), bitcast (void ()* @globalfunc2 to void
>> (...)*)
>> + at linkoncealias = alias void (...), bitcast (void ()* @linkoncefunc
>> to void (...)*)
>> +
>> +define void @globalfunc1() #0 {
>> +entry:
>> + ret void
>> +}
>> +
>> +define void @globalfunc2() #0 {
>> +entry:
>> + ret void
>> +}
>> +
>> +define linkonce_odr void @linkoncefunc() #0 {
>> +entry:
>> + ret void
>> +}
>> +
>> +define i32 @referencestatics(i32 %i) #0 {
>> +entry:
>> + %i.addr = alloca i32, align 4
>> + store i32 %i, i32* %i.addr, align 4
>> + %call = call i32 @staticfunc()
>> + %0 = load i32, i32* @staticvar, align 4
>> + %add = add nsw i32 %call, %0
>> + %1 = load i32, i32* %i.addr, align 4
>> + %idxprom = sext i32 %1 to i64
>> + %arrayidx = getelementptr inbounds [2 x i32], [2 x i32]*
>> @staticconstvar, i64 0, i64 %idxprom
>> + %2 = load i32, i32* %arrayidx, align 4
>> + %add1 = add nsw i32 %add, %2
>> + ret i32 %add1
>> +}
>> +
>> +define i32 @referenceglobals(i32 %i) #0 {
>> +entry:
>> + %i.addr = alloca i32, align 4
>> + store i32 %i, i32* %i.addr, align 4
>> + call void @globalfunc1()
>> + %0 = load i32, i32* @globalvar, align 4
>> + ret i32 %0
>> +}
>> +
>> +define i32 @referencecommon(i32 %i) #0 {
>> +entry:
>> + %i.addr = alloca i32, align 4
>> + store i32 %i, i32* %i.addr, align 4
>> + %0 = load i32, i32* @commonvar, align 4
>> + ret i32 %0
>> +}
>> +
>> +define void @setfuncptr() #0 {
>> +entry:
>> + store void ()* @staticfunc2, void ()** @P, align 8
>> + ret void
>> +}
>> +
>> +define void @callfuncptr() #0 {
>> +entry:
>> + %0 = load void ()*, void ()** @P, align 8
>> + call void %0()
>> + ret void
>> +}
>> +
>> + at weakvar = weak global i32 1, align 4
>> +define weak void @weakfunc() #0 {
>> +entry:
>> + ret void
>> +}
>> +
>> +define void @callweakfunc() #0 {
>> +entry:
>> + call void @weakfunc()
>> + ret void
>> +}
>> +
>> +define internal i32 @staticfunc() #0 {
>> +entry:
>> + ret i32 1
>> +}
>> +
>> +define internal void @staticfunc2() #0 {
>> +entry:
>> + %0 = load i32, i32* @staticvar2, align 4
>> + ret void
>> +}
>>
>> Modified: llvm/trunk/tools/llvm-lto/llvm-lto.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-lto/llvm-lto.cpp?rev=262977&r1=262976&r2=262977&view=diff
>> ==============================================================================
>> --- llvm/trunk/tools/llvm-lto/llvm-lto.cpp (original)
>> +++ llvm/trunk/tools/llvm-lto/llvm-lto.cpp Tue Mar 8 19:37:22 2016
>> @@ -17,7 +17,9 @@
>> #include "llvm/CodeGen/CommandFlags.h"
>> #include "llvm/IR/DiagnosticPrinter.h"
>> #include "llvm/IR/LLVMContext.h"
>> +#include "llvm/IRReader/IRReader.h"
>> #include "llvm/LTO/LTOCodeGenerator.h"
>> +#include "llvm/LTO/ThinLTOCodeGenerator.h"
>> #include "llvm/LTO/LTOModule.h"
>> #include "llvm/Object/FunctionIndexObjectFile.h"
>> #include "llvm/Support/CommandLine.h"
>> @@ -25,6 +27,7 @@
>> #include "llvm/Support/ManagedStatic.h"
>> #include "llvm/Support/PrettyStackTrace.h"
>> #include "llvm/Support/Signals.h"
>> +#include "llvm/Support/SourceMgr.h"
>> #include "llvm/Support/TargetSelect.h"
>> #include "llvm/Support/ToolOutputFile.h"
>> #include "llvm/Support/raw_ostream.h"
>> @@ -64,6 +67,36 @@ static cl::opt<bool>
>> ThinLTO("thinlto", cl::init(false),
>> cl::desc("Only write combined global index for ThinLTO
>> backends"));
>>
>> +enum ThinLTOModes {
>> + THINLINK,
>> + THINPROMOTE,
>> + THINIMPORT,
>> + THINOPT,
>> + THINCODEGEN,
>> + THINALL
>> +};
>> +
>> +cl::opt<ThinLTOModes> ThinLTOMode(
>> + "thinlto-action", cl::desc("Perform a single ThinLTO stage:"),
>> + cl::values(
>> + clEnumValN(
>> + THINLINK, "thinlink",
>> + "ThinLink: produces the index by linking only the
>> summaries."),
>> + clEnumValN(THINPROMOTE, "promote",
>> + "Perform pre-import promotion (requires
>> -thinlto-index)."),
>> + clEnumValN(THINIMPORT, "import", "Perform both promotion and
>> "
>> + "cross-module importing
>> (requires "
>> + "-thinlto-index)."),
>> + clEnumValN(THINOPT, "optimize", "Perform ThinLTO
>> optimizations."),
>> + clEnumValN(THINCODEGEN, "codegen", "CodeGen (expected to
>> match llc)"),
>> + clEnumValN(THINALL, "run", "Perform ThinLTO end-to-end"),
>> + clEnumValEnd));
>> +
>> +static cl::opt<std::string>
>> + ThinLTOIndex("thinlto-index",
>> + cl::desc("Provide the index produced by a ThinLink,
>> required "
>> + "to perform the promotion and/or
>> importing."));
>> +
>> static cl::opt<bool>
>> SaveModuleFile("save-merged-module", cl::init(false),
>> cl::desc("Write merged LTO module to file before
>> CodeGen"));
>> @@ -241,6 +274,255 @@ static void createCombinedFunctionIndex(
>> OS.close();
>> }
>>
>> +namespace thinlto {
>> +
>> +std::vector<std::unique_ptr<MemoryBuffer>>
>> +loadAllFilesForIndex(const FunctionInfoIndex &Index) {
>> + std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
>> +
>> + for (auto &ModPath : Index.modPathStringEntries()) {
>> + const auto &Filename = ModPath.first();
>> + auto CurrentActivity = "loading file '" + Filename + "'";
>> + auto InputOrErr = MemoryBuffer::getFile(Filename);
>> + error(InputOrErr, "error " + CurrentActivity);
>> + InputBuffers.push_back(std::move(*InputOrErr));
>> + }
>> + return InputBuffers;
>> +}
>> +
>> +std::unique_ptr<FunctionInfoIndex> loadCombinedIndex() {
>> + if (ThinLTOIndex.empty())
>> + report_fatal_error("Missing -thinlto-index for ThinLTO promotion
>> stage");
>> + auto CurrentActivity = "loading file '" + ThinLTOIndex + "'";
>> + ErrorOr<std::unique_ptr<FunctionInfoIndex>> IndexOrErr =
>> + llvm::getFunctionIndexForFile(ThinLTOIndex,
>> diagnosticHandler);
>> + error(IndexOrErr, "error " + CurrentActivity);
>> + return std::move(IndexOrErr.get());
>> +}
>> +
>> +static std::unique_ptr<Module> loadModule(StringRef Filename,
>> + LLVMContext &Ctx) {
>> + SMDiagnostic Err;
>> + std::unique_ptr<Module> M(parseIRFile(Filename, Err, Ctx));
>> + if (!M) {
>> + Err.print("llvm-lto", errs());
>> + report_fatal_error("Can't load module for file " + Filename);
>> + }
>> + return M;
>> +}
>> +
>> +static void writeModuleToFile(Module &TheModule, StringRef Filename)
>> {
>> + std::error_code EC;
>> + raw_fd_ostream OS(Filename, EC, sys::fs::OpenFlags::F_None);
>> + error(EC, "error opening the file '" + Filename + "'");
>> + WriteBitcodeToFile(&TheModule, OS, true, false);
>> +}
>> +
>> +class ThinLTOProcessing {
>> +public:
>> + ThinLTOCodeGenerator ThinGenerator;
>> +
>> + ThinLTOProcessing(const TargetOptions &Options) {
>> + ThinGenerator.setCodePICModel(RelocModel);
>> + ThinGenerator.setTargetOptions(Options);
>> + }
>> +
>> + void run() {
>> + switch (ThinLTOMode) {
>> + case THINLINK:
>> + return thinLink();
>> + case THINPROMOTE:
>> + return promote();
>> + case THINIMPORT:
>> + return import();
>> + case THINOPT:
>> + return optimize();
>> + case THINCODEGEN:
>> + return codegen();
>> + case THINALL:
>> + return runAll();
>> + }
>> + }
>> +
>> +private:
>> + /// Load the input files, create the combined index, and write it
>> out.
>> + void thinLink() {
>> + // Perform "ThinLink": just produce the index
>> + if (OutputFilename.empty())
>> + report_fatal_error(
>> + "OutputFilename is necessary to store the combined
>> index.\n");
>> +
>> + LLVMContext Ctx;
>> + std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
>> + for (unsigned i = 0; i < InputFilenames.size(); ++i) {
>> + auto &Filename = InputFilenames[i];
>> + StringRef CurrentActivity = "loading file '" + Filename + "'";
>> + auto InputOrErr = MemoryBuffer::getFile(Filename);
>> + error(InputOrErr, "error " + CurrentActivity);
>> + InputBuffers.push_back(std::move(*InputOrErr));
>> + ThinGenerator.addModule(Filename,
>> InputBuffers.back()->getBuffer());
>> + }
>> +
>> + auto CombinedIndex = ThinGenerator.linkCombinedIndex();
>> + std::error_code EC;
>> + raw_fd_ostream OS(OutputFilename, EC,
>> sys::fs::OpenFlags::F_None);
>> + error(EC, "error opening the file '" + OutputFilename + "'");
>> + WriteFunctionSummaryToFile(*CombinedIndex, OS);
>> + return;
>> + }
>> +
>> + /// Load the combined index from disk, then load every file
>> referenced by
>> + /// the index and add them to the generator, finally perform the
>> promotion
>> + /// on the files mentioned on the command line (these must match
>> the index
>> + /// content).
>> + void promote() {
>> + if (InputFilenames.size() != 1 && !OutputFilename.empty())
>> + report_fatal_error("Can't handle a single output filename and
>> multiple "
>> + "input files, do not provide an output
>> filename and "
>> + "the output files will be suffixed from the
>> input "
>> + "ones.");
>> +
>> + auto Index = loadCombinedIndex();
>> + for (auto &Filename : InputFilenames) {
>> + LLVMContext Ctx;
>> + auto TheModule = loadModule(Filename, Ctx);
>> +
>> + ThinGenerator.promote(*TheModule, *Index);
>> +
>> + std::string OutputName = OutputFilename;
>> + if (OutputName.empty()) {
>> + OutputName = Filename + ".thinlto.promoted.bc";
>> + }
>> + writeModuleToFile(*TheModule, OutputName);
>> + }
>> + }
>> +
>> + /// Load the combined index from disk, then load every file
>> referenced by
>> + /// the index and add them to the generator, then performs the
>> promotion and
>> + /// cross module importing on the files mentioned on the command
>> line
>> + /// (these must match the index content).
>> + void import() {
>> + if (InputFilenames.size() != 1 && !OutputFilename.empty())
>> + report_fatal_error("Can't handle a single output filename and
>> multiple "
>> + "input files, do not provide an output
>> filename and "
>> + "the output files will be suffixed from the
>> input "
>> + "ones.");
>> +
>> + auto Index = loadCombinedIndex();
>> + auto InputBuffers = loadAllFilesForIndex(*Index);
>> + for (auto &MemBuffer : InputBuffers)
>> + ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
>> + MemBuffer->getBuffer());
>> +
>> + for (auto &Filename : InputFilenames) {
>> + LLVMContext Ctx;
>> + auto TheModule = loadModule(Filename, Ctx);
>> +
>> + ThinGenerator.crossModuleImport(*TheModule, *Index);
>> +
>> + std::string OutputName = OutputFilename;
>> + if (OutputName.empty()) {
>> + OutputName = Filename + ".thinlto.imported.bc";
>> + }
>> + writeModuleToFile(*TheModule, OutputName);
>> + }
>> + }
>> +
>> + void optimize() {
>> + if (InputFilenames.size() != 1 && !OutputFilename.empty())
>> + report_fatal_error("Can't handle a single output filename and
>> multiple "
>> + "input files, do not provide an output
>> filename and "
>> + "the output files will be suffixed from the
>> input "
>> + "ones.");
>> + if (!ThinLTOIndex.empty())
>> + errs() << "Warning: -thinlto-index ignored for optimize
>> stage";
>> +
>> + for (auto &Filename : InputFilenames) {
>> + LLVMContext Ctx;
>> + auto TheModule = loadModule(Filename, Ctx);
>> +
>> + ThinGenerator.optimize(*TheModule);
>> +
>> + std::string OutputName = OutputFilename;
>> + if (OutputName.empty()) {
>> + OutputName = Filename + ".thinlto.imported.bc";
>> + }
>> + writeModuleToFile(*TheModule, OutputName);
>> + }
>> + }
>> +
>> + void codegen() {
>> + if (InputFilenames.size() != 1 && !OutputFilename.empty())
>> + report_fatal_error("Can't handle a single output filename and
>> multiple "
>> + "input files, do not provide an output
>> filename and "
>> + "the output files will be suffixed from the
>> input "
>> + "ones.");
>> + if (!ThinLTOIndex.empty())
>> + errs() << "Warning: -thinlto-index ignored for codegen stage";
>> +
>> + for (auto &Filename : InputFilenames) {
>> + LLVMContext Ctx;
>> + auto TheModule = loadModule(Filename, Ctx);
>> +
>> + auto Buffer = ThinGenerator.codegen(*TheModule);
>> + std::string OutputName = OutputFilename;
>> + if (OutputName.empty()) {
>> + OutputName = Filename + ".thinlto.o";
>> + }
>> + if (OutputName == "-") {
>> + outs() << Buffer->getBuffer();
>> + return;
>> + }
>> +
>> + std::error_code EC;
>> + raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
>> + error(EC, "error opening the file '" + OutputName + "'");
>> + OS << Buffer->getBuffer();
>> + }
>> + }
>> +
>> + /// Full ThinLTO process
>> + void runAll() {
>> + if (!OutputFilename.empty())
>> + report_fatal_error("Do not provide an output filename for
>> ThinLTO "
>> + " processing, the output files will be
>> suffixed from "
>> + "the input ones.");
>> +
>> + if (!ThinLTOIndex.empty())
>> + errs() << "Warning: -thinlto-index ignored for full ThinLTO
>> process";
>> +
>> + LLVMContext Ctx;
>> + std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
>> + for (unsigned i = 0; i < InputFilenames.size(); ++i) {
>> + auto &Filename = InputFilenames[i];
>> + StringRef CurrentActivity = "loading file '" + Filename + "'";
>> + auto InputOrErr = MemoryBuffer::getFile(Filename);
>> + error(InputOrErr, "error " + CurrentActivity);
>> + InputBuffers.push_back(std::move(*InputOrErr));
>> + ThinGenerator.addModule(Filename,
>> InputBuffers.back()->getBuffer());
>> + }
>> +
>> + ThinGenerator.run();
>> +
>> + auto &Binaries = ThinGenerator.getProducedBinaries();
>> + if (Binaries.size() != InputFilenames.size())
>> + report_fatal_error("Number of output objects does not match
>> the number "
>> + "of inputs");
>> +
>> + for (unsigned BufID = 0; BufID < Binaries.size(); ++BufID) {
>> + auto OutputName = InputFilenames[BufID] + ".thinlto.o";
>> + std::error_code EC;
>> + raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
>> + error(EC, "error opening the file '" + OutputName + "'");
>> + OS << Binaries[BufID]->getBuffer();
>> + }
>> + }
>> +
>> + /// Load the combined index from disk, then load every file
>> referenced by
>> +};
>> +
>> +} // namespace thinlto
>> +
>> int main(int argc, char **argv) {
>> // Print a stack trace if we signal out.
>> sys::PrintStackTraceOnErrorSignal();
>> @@ -266,6 +548,14 @@ int main(int argc, char **argv) {
>> return 0;
>> }
>>
>> + if (ThinLTOMode.getNumOccurrences()) {
>> + if (ThinLTOMode.getNumOccurrences() > 1)
>> + report_fatal_error("You can't specify more than one
>> -thinlto-action");
>> + thinlto::ThinLTOProcessing ThinLTOProcessor(Options);
>> + ThinLTOProcessor.run();
>> + return 0;
>> + }
>> +
>> if (ThinLTO) {
>> createCombinedFunctionIndex();
>> return 0;
>>
>> Modified: llvm/trunk/tools/lto/lto.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lto/lto.cpp?rev=262977&r1=262976&r2=262977&view=diff
>> ==============================================================================
>> --- llvm/trunk/tools/lto/lto.cpp (original)
>> +++ llvm/trunk/tools/lto/lto.cpp Tue Mar 8 19:37:22 2016
>> @@ -20,6 +20,7 @@
>> #include "llvm/IR/LLVMContext.h"
>> #include "llvm/LTO/LTOCodeGenerator.h"
>> #include "llvm/LTO/LTOModule.h"
>> +#include "llvm/LTO/ThinLTOCodeGenerator.h"
>> #include "llvm/Support/MemoryBuffer.h"
>> #include "llvm/Support/Signals.h"
>> #include "llvm/Support/TargetSelect.h"
>> @@ -134,6 +135,7 @@ struct LibLTOCodeGenerator : LTOCodeGene
>> }
>>
>> DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LibLTOCodeGenerator,
>> lto_code_gen_t)
>> +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThinLTOCodeGenerator,
>> thinlto_code_gen_t)
>> DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOModule, lto_module_t)
>>
>> // Convert the subtarget features into a string to pass to
>> LTOCodeGenerator.
>> @@ -440,3 +442,106 @@ void lto_codegen_set_should_embed_uselis
>> lto_bool_t
>> ShouldEmbedUselists) {
>> unwrap(cg)->setShouldEmbedUselists(ShouldEmbedUselists);
>> }
>> +
>> +// ThinLTO API below
>> +
>> +thinlto_code_gen_t thinlto_create_codegen() {
>> + lto_initialize();
>> + ThinLTOCodeGenerator *CodeGen = new ThinLTOCodeGenerator();
>> + CodeGen->setTargetOptions(InitTargetOptionsFromCodeGenFlags());
>> +
>> + return wrap(CodeGen);
>> +}
>> +
>> +void thinlto_codegen_dispose(thinlto_code_gen_t cg) { delete
>> unwrap(cg); }
>> +
>> +void thinlto_codegen_add_module(thinlto_code_gen_t cg, const char
>> *Identifier,
>> + const char *Data, int Length) {
>> + unwrap(cg)->addModule(Identifier, StringRef(Data, Length));
>> +}
>> +
>> +void thinlto_codegen_process(thinlto_code_gen_t cg) {
>> unwrap(cg)->run(); }
>> +
>> +unsigned int thinlto_module_get_num_objects(thinlto_code_gen_t cg) {
>> + return unwrap(cg)->getProducedBinaries().size();
>> +}
>> +LTOObjectBuffer thinlto_module_get_object(thinlto_code_gen_t cg,
>> + unsigned int index) {
>> + assert(index < unwrap(cg)->getProducedBinaries().size() && "Index
>> overflow");
>> + auto &MemBuffer = unwrap(cg)->getProducedBinaries()[index];
>> + return LTOObjectBuffer{(void *)MemBuffer->getBufferStart(),
>
> GCC warns here:
>
> /src/llvm/tools/lto/lto.cpp:472:60: warning: cast from type ‘const char*’ to type ‘void*’ casts away qualifiers [-Wcast-qual]
> return LTOObjectBuffer{(void *)MemBuffer->getBufferStart(),
Thanks for the heads up, I tried to fix it in r263870, let me know if it is not enough.
--
Mehdi
>
> -Hal
>
>> + MemBuffer->getBufferSize()};
>> +}
>> +
>> +void thinlto_debug_options(const char *const *options, int number) {
>> + // if options were requested, set them
>> + if (number && options) {
>> + std::vector<const char *> CodegenArgv(1, "libLTO");
>> + for (auto Arg : ArrayRef<const char *>(options, number))
>> + CodegenArgv.push_back(Arg);
>> + cl::ParseCommandLineOptions(CodegenArgv.size(),
>> CodegenArgv.data());
>> + }
>> +}
>> +
>> +bool lto_module_is_thinlto(lto_module_t mod) {
>> + return unwrap(mod)->isThinLTO();
>> +}
>> +
>> +void thinlto_codegen_add_must_preserve_symbol(thinlto_code_gen_t cg,
>> + const char *Name, int
>> Length) {
>> + unwrap(cg)->preserveSymbol(StringRef(Name, Length));
>> +}
>> +
>> +void thinlto_codegen_add_cross_referenced_symbol(thinlto_code_gen_t
>> cg,
>> + const char *Name,
>> int Length) {
>> + unwrap(cg)->crossReferenceSymbol(StringRef(Name, Length));
>> +}
>> +
>> +void thinlto_codegen_set_cpu(thinlto_code_gen_t cg, const char *cpu)
>> {
>> + return unwrap(cg)->setCpu(cpu);
>> +}
>> +
>> +void thinlto_codegen_set_cache_dir(thinlto_code_gen_t cg,
>> + const char *cache_dir) {
>> + return unwrap(cg)->setCacheDir(cache_dir);
>> +}
>> +
>> +void thinlto_codegen_set_cache_pruning_interval(thinlto_code_gen_t
>> cg,
>> + int interval) {
>> + return unwrap(cg)->setCachePruningInterval(interval);
>> +}
>> +
>> +void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t
>> cg,
>> + unsigned expiration)
>> {
>> + return unwrap(cg)->setCacheEntryExpiration(expiration);
>> +}
>> +
>> +void
>> thinlto_codegen_set_final_cache_size_relative_to_available_space(
>> + thinlto_code_gen_t cg, unsigned Percentage) {
>> + return
>> unwrap(cg)->setMaxCacheSizeRelativeToAvailableSpace(Percentage);
>> +}
>> +
>> +void thinlto_codegen_set_savetemps_dir(thinlto_code_gen_t cg,
>> + const char *save_temps_dir) {
>> + return unwrap(cg)->setSaveTempsDir(save_temps_dir);
>> +}
>> +
>> +lto_bool_t thinlto_codegen_set_pic_model(thinlto_code_gen_t cg,
>> + lto_codegen_model model) {
>> + switch (model) {
>> + case LTO_CODEGEN_PIC_MODEL_STATIC:
>> + unwrap(cg)->setCodePICModel(Reloc::Static);
>> + return false;
>> + case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
>> + unwrap(cg)->setCodePICModel(Reloc::PIC_);
>> + return false;
>> + case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
>> + unwrap(cg)->setCodePICModel(Reloc::DynamicNoPIC);
>> + return false;
>> + case LTO_CODEGEN_PIC_MODEL_DEFAULT:
>> + unwrap(cg)->setCodePICModel(Reloc::Default);
>> + return false;
>> + }
>> + sLastErrorString = "Unknown PIC model";
>> + return true;
>> +}
>>
>> Modified: llvm/trunk/tools/lto/lto.exports
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lto/lto.exports?rev=262977&r1=262976&r2=262977&view=diff
>> ==============================================================================
>> --- llvm/trunk/tools/lto/lto.exports (original)
>> +++ llvm/trunk/tools/lto/lto.exports Tue Mar 8 19:37:22 2016
>> @@ -45,3 +45,20 @@ LLVMCreateDisasmCPU
>> LLVMDisasmDispose
>> LLVMDisasmInstruction
>> LLVMSetDisasmOptions
>> +thinlto_create_codegen
>> +thinlto_codegen_dispose
>> +thinlto_codegen_add_module
>> +thinlto_codegen_process
>> +thinlto_module_get_num_objects
>> +thinlto_module_get_object
>> +thinlto_codegen_set_pic_model
>> +thinlto_codegen_set_cache_dir
>> +thinlto_codegen_set_cache_pruning_interval
>> +thinlto_codegen_set_cache_entry_expiration
>> +thinlto_codegen_set_savetemps_dir
>> +thinlto_codegen_set_cpu
>> +thinlto_debug_options
>> +lto_module_is_thinlto
>> +thinlto_codegen_add_must_preserve_symbol
>> +thinlto_codegen_add_cross_referenced_symbol
>> +thinlto_codegen_set_final_cache_size_relative_to_available_space
>> \ No newline at end of file
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>
>
> --
> Hal Finkel
> Assistant Computational Scientist
> Leadership Computing Facility
> Argonne National Laboratory
More information about the llvm-commits
mailing list