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).
    135    *  - The pruning expiration time indicates to the garbage collector how old
    136    *    an entry needs to be to be removed.
    137    *  - Finally, the garbage collector can be instructed to prune the cache till
    138    *    the occupied space goes below a threshold.
    139    * @{
    140    */
    141 
    142   struct CachingOptions {
    143     std::string Path;                    // Path to the cache, empty to disable.
    144     CachePruningPolicy Policy;
    145   };
    146 
    147   /// Provide a path to a directory where to store the cached files for
    148   /// incremental build.
    149   void setCacheDir(std::string Path) { CacheOptions.Path = std::move(Path); }
    150 
    151   /// Cache policy: interval (seconds) between two prune of the cache. Set to a
    152   /// negative value (default) to disable pruning. A value of 0 will be ignored.
    153   void setCachePruningInterval(int Interval) {
    154     if (Interval)
    155       CacheOptions.Policy.Interval = std::chrono::seconds(Interval);
    156   }
    157 
    158   /// Cache policy: expiration (in seconds) for an entry.
    159   /// A value of 0 will be ignored.
    160   void setCacheEntryExpiration(unsigned Expiration) {
    161     if (Expiration)
    162       CacheOptions.Policy.Expiration = std::chrono::seconds(Expiration);
    163   }
    164 
    165   /**
    166    * Sets the maximum cache size that can be persistent across build, in terms
    167    * of percentage of the available space on the the disk. Set to 100 to
    168    * indicate no limit, 50 to indicate that the cache size will not be left over
    169    * half the available space. A value over 100 will be reduced to 100, and a
    170    * value of 0 will be ignored.
    171    *
    172    *
    173    * The formula looks like:
    174    *  AvailableSpace = FreeSpace + ExistingCacheSize
    175    *  NewCacheSize = AvailableSpace * P/100
    176    *
    177    */
    178   void setMaxCacheSizeRelativeToAvailableSpace(unsigned Percentage) {
    179     if (Percentage)
    180       CacheOptions.Policy.MaxSizePercentageOfAvailableSpace = Percentage;
    181   }
    182 
    183   /**@}*/
    184 
    185   /// Set the path to a directory where to save temporaries at various stages of
    186   /// the processing.
    187   void setSaveTempsDir(std::string Path) { SaveTempsDir = std::move(Path); }
    188 
    189   /// Set the path to a directory where to save generated object files. This
    190   /// path can be used by a linker to request on-disk files instead of in-memory
    191   /// buffers. When set, results are available through getProducedBinaryFiles()
    192   /// instead of getProducedBinaries().
    193   void setGeneratedObjectsDirectory(std::string Path) {
    194     SavedObjectsDirectoryPath = std::move(Path);
    195   }
    196 
    197   /// CPU to use to initialize the TargetMachine
    198   void setCpu(std::string Cpu) { TMBuilder.MCpu = std::move(Cpu); }
    199 
    200   /// Subtarget attributes
    201   void setAttr(std::string MAttr) { TMBuilder.MAttr = std::move(MAttr); }
    202 
    203   /// TargetMachine options
    204   void setTargetOptions(TargetOptions Options) {
    205     TMBuilder.Options = std::move(Options);
    206   }
    207 
    208   /// Enable the Freestanding mode: indicate that the optimizer should not
    209   /// assume builtins are present on the target.
    210   void setFreestanding(bool Enabled) { Freestanding = Enabled; }
    211 
    212   /// CodeModel
    213   void setCodePICModel(Optional<Reloc::Model> Model) {
    214     TMBuilder.RelocModel = Model;
    215   }
    216 
    217   /// CodeGen optimization level
    218   void setCodeGenOptLevel(CodeGenOpt::Level CGOptLevel) {
    219     TMBuilder.CGOptLevel = CGOptLevel;
    220   }
    221 
    222   /// IR optimization level: from 0 to 3.
    223   void setOptLevel(unsigned NewOptLevel) {
    224     OptLevel = (NewOptLevel > 3) ? 3 : NewOptLevel;
    225   }
    226 
    227   /// Disable CodeGen, only run the stages till codegen and stop. The output
    228   /// will be bitcode.
    229   void disableCodeGen(bool Disable) { DisableCodeGen = Disable; }
    230 
    231   /// Perform CodeGen only: disable all other stages.
    232   void setCodeGenOnly(bool CGOnly) { CodeGenOnly = CGOnly; }
    233 
    234   /**@}*/
    235 
    236   /**
    237    * \defgroup Set of APIs to run individual stages in isolation.
    238    * @{
    239    */
    240 
    241   /**
    242    * Produce the combined summary index from all the bitcode files:
    243    * "thin-link".
    244    */
    245   std::unique_ptr<ModuleSummaryIndex> linkCombinedIndex();
    246 
    247   /**
    248    * Perform promotion and renaming of exported internal functions,
    249    * and additionally resolve weak and linkonce symbols.
    250    * Index is updated to reflect linkage changes from weak resolution.
    251    */
    252   void promote(Module &Module, ModuleSummaryIndex &Index);
    253 
    254   /**
    255    * Compute and emit the imported files for module at \p ModulePath.
    256    */
    257   static void emitImports(StringRef ModulePath, StringRef OutputName,
    258                           ModuleSummaryIndex &Index);
    259 
    260   /**
    261    * Perform cross-module importing for the module identified by
    262    * ModuleIdentifier.
    263    */
    264   void crossModuleImport(Module &Module, ModuleSummaryIndex &Index);
    265 
    266   /**
    267    * Compute the list of summaries needed for importing into module.
    268    */
    269   static void gatherImportedSummariesForModule(
    270       StringRef ModulePath, ModuleSummaryIndex &Index,
    271       std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex);
    272 
    273   /**
    274    * Perform internalization. Index is updated to reflect linkage changes.
    275    */
    276   void internalize(Module &Module, ModuleSummaryIndex &Index);
    277 
    278   /**
    279    * Perform post-importing ThinLTO optimizations.
    280    */
    281   void optimize(Module &Module);
    282 
    283   /**
    284    * Perform ThinLTO CodeGen.
    285    */
    286   std::unique_ptr<MemoryBuffer> codegen(Module &Module);
    287 
    288   /**@}*/
    289 
    290 private:
    291   /// Helper factory to build a TargetMachine
    292   TargetMachineBuilder TMBuilder;
    293 
    294   /// Vector holding the in-memory buffer containing the produced binaries, when
    295   /// SavedObjectsDirectoryPath isn't set.
    296   std::vector<std::unique_ptr<MemoryBuffer>> ProducedBinaries;
    297 
    298   /// Path to generated files in the supplied SavedObjectsDirectoryPath if any.
    299   std::vector<std::string> ProducedBinaryFiles;
    300 
    301   /// Vector holding the input buffers containing the bitcode modules to
    302   /// process.
    303   std::vector<ThinLTOBuffer> Modules;
    304 
    305   /// Set of symbols that need to be preserved outside of the set of bitcode
    306   /// files.
    307   StringSet<> PreservedSymbols;
    308 
    309   /// Set of symbols that are cross-referenced between bitcode files.
    310   StringSet<> CrossReferencedSymbols;
    311 
    312   /// Control the caching behavior.
    313   CachingOptions CacheOptions;
    314 
    315   /// Path to a directory to save the temporary bitcode files.
    316   std::string SaveTempsDir;
    317 
    318   /// Path to a directory to save the generated object files.
    319   std::string SavedObjectsDirectoryPath;
    320 
    321   /// Flag to enable/disable CodeGen. When set to true, the process stops after
    322   /// optimizations and a bitcode is produced.
    323   bool DisableCodeGen = false;
    324 
    325   /// Flag to indicate that only the CodeGen will be performed, no cross-module
    326   /// importing or optimization.
    327   bool CodeGenOnly = false;
    328 
    329   /// Flag to indicate that the optimizer should not assume builtins are present
    330   /// on the target.
    331   bool Freestanding = false;
    332 
    333   /// IR Optimization Level [0-3].
    334   unsigned OptLevel = 3;
    335 };
    336 }
    337 #endif
    338