Home | History | Annotate | Download | only in legacy
      1 //===-ThinLTOCodeGenerator.h - LLVM Link Time Optimizer -------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file declares the ThinLTOCodeGenerator class, similar to the
     11 // LTOCodeGenerator but for the ThinLTO scheme. It provides an interface for
     12 // linker plugin.
     13 //
     14 //===----------------------------------------------------------------------===//
     15 
     16 #ifndef LLVM_LTO_THINLTOCODEGENERATOR_H
     17 #define LLVM_LTO_THINLTOCODEGENERATOR_H
     18 
     19 #include "llvm-c/lto.h"
     20 #include "llvm/ADT/StringSet.h"
     21 #include "llvm/ADT/Triple.h"
     22 #include "llvm/IR/ModuleSummaryIndex.h"
     23 #include "llvm/Support/CachePruning.h"
     24 #include "llvm/Support/CodeGen.h"
     25 #include "llvm/Support/MemoryBuffer.h"
     26 #include "llvm/Target/TargetOptions.h"
     27 
     28 #include <string>
     29 
     30 namespace llvm {
     31 class StringRef;
     32 class LLVMContext;
     33 class TargetMachine;
     34 
     35 /// Wrapper around MemoryBufferRef, owning the identifier
     36 class ThinLTOBuffer {
     37   std::string OwnedIdentifier;
     38   StringRef Buffer;
     39 
     40 public:
     41   ThinLTOBuffer(StringRef Buffer, StringRef Identifier)
     42       : OwnedIdentifier(Identifier), Buffer(Buffer) {}
     43 
     44   MemoryBufferRef getMemBuffer() const {
     45     return MemoryBufferRef(Buffer,
     46                            {OwnedIdentifier.c_str(), OwnedIdentifier.size()});
     47   }
     48   StringRef getBuffer() const { return Buffer; }
     49   StringRef getBufferIdentifier() const { return OwnedIdentifier; }
     50 };
     51 
     52 /// Helper to gather options relevant to the target machine creation
     53 struct TargetMachineBuilder {
     54   Triple TheTriple;
     55   std::string MCpu;
     56   std::string MAttr;
     57   TargetOptions Options;
     58   Optional<Reloc::Model> RelocModel;
     59   CodeGenOpt::Level CGOptLevel = CodeGenOpt::Aggressive;
     60 
     61   std::unique_ptr<TargetMachine> create() const;
     62 };
     63 
     64 /// This class define an interface similar to the LTOCodeGenerator, but adapted
     65 /// for ThinLTO processing.
     66 /// The ThinLTOCodeGenerator is not intended to be reuse for multiple
     67 /// compilation: the model is that the client adds modules to the generator and
     68 /// ask to perform the ThinLTO optimizations / codegen, and finally destroys the
     69 /// codegenerator.
     70 class ThinLTOCodeGenerator {
     71 public:
     72   /// Add given module to the code generator.
     73   void addModule(StringRef Identifier, StringRef Data);
     74 
     75   /**
     76    * Adds to a list of all global symbols that must exist in the final generated
     77    * code. If a symbol is not listed there, it will be optimized away if it is
     78    * inlined into every usage.
     79    */
     80   void preserveSymbol(StringRef Name);
     81 
     82   /**
     83    * Adds to a list of all global symbols that are cross-referenced between
     84    * ThinLTO files. If the ThinLTO CodeGenerator can ensure that every
     85    * references from a ThinLTO module to this symbol is optimized away, then
     86    * the symbol can be discarded.
     87    */
     88   void crossReferenceSymbol(StringRef Name);
     89 
     90   /**
     91    * Process all the modules that were added to the code generator in parallel.
     92    *
     93    * Client can access the resulting object files using getProducedBinaries(),
     94    * unless setGeneratedObjectsDirectory() has been called, in which case
     95    * results are available through getProducedBinaryFiles().
     96    */
     97   void run();
     98 
     99   /**
    100    * Return the "in memory" binaries produced by the code generator. This is
    101    * filled after run() unless setGeneratedObjectsDirectory() has been
    102    * called, in which case results are available through
    103    * getProducedBinaryFiles().
    104    */
    105   std::vector<std::unique_ptr<MemoryBuffer>> &getProducedBinaries() {
    106     return ProducedBinaries;
    107   }
    108 
    109   /**
    110    * Return the "on-disk" binaries produced by the code generator. This is
    111    * filled after run() when setGeneratedObjectsDirectory() has been
    112    * called, in which case results are available through getProducedBinaries().
    113    */
    114   std::vector<std::string> &getProducedBinaryFiles() {
    115     return ProducedBinaryFiles;
    116   }
    117 
    118   /**
    119    * \defgroup Options setters
    120    * @{
    121    */
    122 
    123   /**
    124    * \defgroup Cache controlling options
    125    *
    126    * These entry points control the ThinLTO cache. The cache is intended to
    127    * support incremental build, and thus needs to be persistent accross build.
    128    * The client enabled the cache by supplying a path to an existing directory.
    129    * The code generator will use this to store objects files that may be reused
    130    * during a subsequent build.
    131    * To avoid filling the disk space, a few knobs are provided:
    132    *  - The pruning interval limit the frequency at which the garbage collector
    133    *    will try to scan the cache directory to prune it from expired entries.
    134    *    Setting to -1 disable the pruning (default). Setting to 0 will force
    135    *    pruning to occur.
    136    *  - The pruning expiration time indicates to the garbage collector how old
    137    *    an entry needs to be to be removed.
    138    *  - Finally, the garbage collector can be instructed to prune the cache till
    139    *    the occupied space goes below a threshold.
    140    * @{
    141    */
    142 
    143   struct CachingOptions {
    144     std::string Path;                    // Path to the cache, empty to disable.
    145     CachePruningPolicy Policy;
    146   };
    147 
    148   /// Provide a path to a directory where to store the cached files for
    149   /// incremental build.
    150   void setCacheDir(std::string Path) { CacheOptions.Path = std::move(Path); }
    151 
    152   /// Cache policy: interval (seconds) between two prunes of the cache. Set to a
    153   /// negative value to disable pruning. A value of 0 will force pruning to
    154   /// occur.
    155   void setCachePruningInterval(int Interval) {
    156     if(Interval < 0)
    157       CacheOptions.Policy.Interval.reset();
    158     else
    159       CacheOptions.Policy.Interval = std::chrono::seconds(Interval);
    160   }
    161 
    162   /// Cache policy: expiration (in seconds) for an entry.
    163   /// A value of 0 will be ignored.
    164   void setCacheEntryExpiration(unsigned Expiration) {
    165     if (Expiration)
    166       CacheOptions.Policy.Expiration = std::chrono::seconds(Expiration);
    167   }
    168 
    169   /**
    170    * Sets the maximum cache size that can be persistent across build, in terms
    171    * of percentage of the available space on the disk. Set to 100 to indicate
    172    * no limit, 50 to indicate that the cache size will not be left over
    173    * half the available space. A value over 100 will be reduced to 100, and a
    174    * value of 0 will be ignored.
    175    *
    176    *
    177    * The formula looks like:
    178    *  AvailableSpace = FreeSpace + ExistingCacheSize
    179    *  NewCacheSize = AvailableSpace * P/100
    180    *
    181    */
    182   void setMaxCacheSizeRelativeToAvailableSpace(unsigned Percentage) {
    183     if (Percentage)
    184       CacheOptions.Policy.MaxSizePercentageOfAvailableSpace = Percentage;
    185   }
    186 
    187   /// Cache policy: the maximum size for the cache directory in bytes. A value
    188   /// over the amount of available space on the disk will be reduced to the
    189   /// amount of available space. A value of 0 will be ignored.
    190   void setCacheMaxSizeBytes(unsigned MaxSizeBytes) {
    191     if (MaxSizeBytes)
    192       CacheOptions.Policy.MaxSizeBytes = MaxSizeBytes;
    193   }
    194 
    195   /// Cache policy: the maximum number of files in the cache directory. A value
    196   /// of 0 will be ignored.
    197   void setCacheMaxSizeFiles(unsigned MaxSizeFiles) {
    198     if (MaxSizeFiles)
    199       CacheOptions.Policy.MaxSizeFiles = MaxSizeFiles;
    200   }
    201 
    202   /**@}*/
    203 
    204   /// Set the path to a directory where to save temporaries at various stages of
    205   /// the processing.
    206   void setSaveTempsDir(std::string Path) { SaveTempsDir = std::move(Path); }
    207 
    208   /// Set the path to a directory where to save generated object files. This
    209   /// path can be used by a linker to request on-disk files instead of in-memory
    210   /// buffers. When set, results are available through getProducedBinaryFiles()
    211   /// instead of getProducedBinaries().
    212   void setGeneratedObjectsDirectory(std::string Path) {
    213     SavedObjectsDirectoryPath = std::move(Path);
    214   }
    215 
    216   /// CPU to use to initialize the TargetMachine
    217   void setCpu(std::string Cpu) { TMBuilder.MCpu = std::move(Cpu); }
    218 
    219   /// Subtarget attributes
    220   void setAttr(std::string MAttr) { TMBuilder.MAttr = std::move(MAttr); }
    221 
    222   /// TargetMachine options
    223   void setTargetOptions(TargetOptions Options) {
    224     TMBuilder.Options = std::move(Options);
    225   }
    226 
    227   /// Enable the Freestanding mode: indicate that the optimizer should not
    228   /// assume builtins are present on the target.
    229   void setFreestanding(bool Enabled) { Freestanding = Enabled; }
    230 
    231   /// CodeModel
    232   void setCodePICModel(Optional<Reloc::Model> Model) {
    233     TMBuilder.RelocModel = Model;
    234   }
    235 
    236   /// CodeGen optimization level
    237   void setCodeGenOptLevel(CodeGenOpt::Level CGOptLevel) {
    238     TMBuilder.CGOptLevel = CGOptLevel;
    239   }
    240 
    241   /// IR optimization level: from 0 to 3.
    242   void setOptLevel(unsigned NewOptLevel) {
    243     OptLevel = (NewOptLevel > 3) ? 3 : NewOptLevel;
    244   }
    245 
    246   /// Disable CodeGen, only run the stages till codegen and stop. The output
    247   /// will be bitcode.
    248   void disableCodeGen(bool Disable) { DisableCodeGen = Disable; }
    249 
    250   /// Perform CodeGen only: disable all other stages.
    251   void setCodeGenOnly(bool CGOnly) { CodeGenOnly = CGOnly; }
    252 
    253   /**@}*/
    254 
    255   /**
    256    * \defgroup Set of APIs to run individual stages in isolation.
    257    * @{
    258    */
    259 
    260   /**
    261    * Produce the combined summary index from all the bitcode files:
    262    * "thin-link".
    263    */
    264   std::unique_ptr<ModuleSummaryIndex> linkCombinedIndex();
    265 
    266   /**
    267    * Perform promotion and renaming of exported internal functions,
    268    * and additionally resolve weak and linkonce symbols.
    269    * Index is updated to reflect linkage changes from weak resolution.
    270    */
    271   void promote(Module &Module, ModuleSummaryIndex &Index);
    272 
    273   /**
    274    * Compute and emit the imported files for module at \p ModulePath.
    275    */
    276   static void emitImports(StringRef ModulePath, StringRef OutputName,
    277                           ModuleSummaryIndex &Index);
    278 
    279   /**
    280    * Perform cross-module importing for the module identified by
    281    * ModuleIdentifier.
    282    */
    283   void crossModuleImport(Module &Module, ModuleSummaryIndex &Index);
    284 
    285   /**
    286    * Compute the list of summaries needed for importing into module.
    287    */
    288   static void gatherImportedSummariesForModule(
    289       StringRef ModulePath, ModuleSummaryIndex &Index,
    290       std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex);
    291 
    292   /**
    293    * Perform internalization. Index is updated to reflect linkage changes.
    294    */
    295   void internalize(Module &Module, ModuleSummaryIndex &Index);
    296 
    297   /**
    298    * Perform post-importing ThinLTO optimizations.
    299    */
    300   void optimize(Module &Module);
    301 
    302   /**
    303    * Perform ThinLTO CodeGen.
    304    */
    305   std::unique_ptr<MemoryBuffer> codegen(Module &Module);
    306 
    307   /**@}*/
    308 
    309 private:
    310   /// Helper factory to build a TargetMachine
    311   TargetMachineBuilder TMBuilder;
    312 
    313   /// Vector holding the in-memory buffer containing the produced binaries, when
    314   /// SavedObjectsDirectoryPath isn't set.
    315   std::vector<std::unique_ptr<MemoryBuffer>> ProducedBinaries;
    316 
    317   /// Path to generated files in the supplied SavedObjectsDirectoryPath if any.
    318   std::vector<std::string> ProducedBinaryFiles;
    319 
    320   /// Vector holding the input buffers containing the bitcode modules to
    321   /// process.
    322   std::vector<ThinLTOBuffer> Modules;
    323 
    324   /// Set of symbols that need to be preserved outside of the set of bitcode
    325   /// files.
    326   StringSet<> PreservedSymbols;
    327 
    328   /// Set of symbols that are cross-referenced between bitcode files.
    329   StringSet<> CrossReferencedSymbols;
    330 
    331   /// Control the caching behavior.
    332   CachingOptions CacheOptions;
    333 
    334   /// Path to a directory to save the temporary bitcode files.
    335   std::string SaveTempsDir;
    336 
    337   /// Path to a directory to save the generated object files.
    338   std::string SavedObjectsDirectoryPath;
    339 
    340   /// Flag to enable/disable CodeGen. When set to true, the process stops after
    341   /// optimizations and a bitcode is produced.
    342   bool DisableCodeGen = false;
    343 
    344   /// Flag to indicate that only the CodeGen will be performed, no cross-module
    345   /// importing or optimization.
    346   bool CodeGenOnly = false;
    347 
    348   /// Flag to indicate that the optimizer should not assume builtins are present
    349   /// on the target.
    350   bool Freestanding = false;
    351 
    352   /// IR Optimization Level [0-3].
    353   unsigned OptLevel = 3;
    354 };
    355 }
    356 #endif
    357