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