ThinLTOCodeGenerator.h revision 341825
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
30namespace llvm {
31class StringRef;
32class LLVMContext;
33class TargetMachine;
34
35/// Wrapper around MemoryBufferRef, owning the identifier
36class ThinLTOBuffer {
37  std::string OwnedIdentifier;
38  StringRef Buffer;
39
40public:
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
53struct 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.
70class ThinLTOCodeGenerator {
71public:
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
309private:
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