1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
|
//===-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/StringSet.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/Support/CachePruning.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Target/TargetOptions.h"
#include <string>
namespace llvm {
class StringRef;
class LLVMContext;
class TargetMachine;
/// Wrapper around MemoryBufferRef, owning the identifier
class ThinLTOBuffer {
std::string OwnedIdentifier;
StringRef Buffer;
public:
ThinLTOBuffer(StringRef Buffer, StringRef Identifier)
: OwnedIdentifier(Identifier), Buffer(Buffer) {}
MemoryBufferRef getMemBuffer() const {
return MemoryBufferRef(Buffer,
{OwnedIdentifier.c_str(), OwnedIdentifier.size()});
}
StringRef getBuffer() const { return Buffer; }
StringRef getBufferIdentifier() const { return OwnedIdentifier; }
};
/// Helper to gather options relevant to the target machine creation
struct TargetMachineBuilder {
Triple TheTriple;
std::string MCpu;
std::string MAttr;
TargetOptions Options;
Optional<Reloc::Model> RelocModel;
CodeGenOpt::Level CGOptLevel = CodeGenOpt::Aggressive;
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(),
* unless setGeneratedObjectsDirectory() has been called, in which case
* results are available through getProducedBinaryFiles().
*/
void run();
/**
* Return the "in memory" binaries produced by the code generator. This is
* filled after run() unless setGeneratedObjectsDirectory() has been
* called, in which case results are available through
* getProducedBinaryFiles().
*/
std::vector<std::unique_ptr<MemoryBuffer>> &getProducedBinaries() {
return ProducedBinaries;
}
/**
* Return the "on-disk" binaries produced by the code generator. This is
* filled after run() when setGeneratedObjectsDirectory() has been
* called, in which case results are available through getProducedBinaries().
*/
std::vector<std::string> &getProducedBinaryFiles() {
return ProducedBinaryFiles;
}
/**
* \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). Setting to 0 will force
* pruning to occur.
* - 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; // Path to the cache, empty to disable.
CachePruningPolicy Policy;
};
/// 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 prunes of the cache. Set to a
/// negative value to disable pruning. A value of 0 will force pruning to
/// occur.
void setCachePruningInterval(int Interval) {
if(Interval < 0)
CacheOptions.Policy.Interval.reset();
else
CacheOptions.Policy.Interval = std::chrono::seconds(Interval);
}
/// Cache policy: expiration (in seconds) for an entry.
/// A value of 0 will be ignored.
void setCacheEntryExpiration(unsigned Expiration) {
if (Expiration)
CacheOptions.Policy.Expiration = std::chrono::seconds(Expiration);
}
/**
* Sets the maximum cache size that can be persistent across build, in terms
* of percentage of the available space on 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, and a
* value of 0 will be ignored.
*
*
* The formula looks like:
* AvailableSpace = FreeSpace + ExistingCacheSize
* NewCacheSize = AvailableSpace * P/100
*
*/
void setMaxCacheSizeRelativeToAvailableSpace(unsigned Percentage) {
if (Percentage)
CacheOptions.Policy.MaxSizePercentageOfAvailableSpace = Percentage;
}
/// Cache policy: the maximum size for the cache directory in bytes. A value
/// over the amount of available space on the disk will be reduced to the
/// amount of available space. A value of 0 will be ignored.
void setCacheMaxSizeBytes(unsigned MaxSizeBytes) {
if (MaxSizeBytes)
CacheOptions.Policy.MaxSizeBytes = MaxSizeBytes;
}
/// Cache policy: the maximum number of files in the cache directory. A value
/// of 0 will be ignored.
void setCacheMaxSizeFiles(unsigned MaxSizeFiles) {
if (MaxSizeFiles)
CacheOptions.Policy.MaxSizeFiles = MaxSizeFiles;
}
/**@}*/
/// 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); }
/// Set the path to a directory where to save generated object files. This
/// path can be used by a linker to request on-disk files instead of in-memory
/// buffers. When set, results are available through getProducedBinaryFiles()
/// instead of getProducedBinaries().
void setGeneratedObjectsDirectory(std::string Path) {
SavedObjectsDirectoryPath = 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);
}
/// Enable the Freestanding mode: indicate that the optimizer should not
/// assume builtins are present on the target.
void setFreestanding(bool Enabled) { Freestanding = Enabled; }
/// CodeModel
void setCodePICModel(Optional<Reloc::Model> Model) {
TMBuilder.RelocModel = Model;
}
/// CodeGen optimization level
void setCodeGenOptLevel(CodeGenOpt::Level CGOptLevel) {
TMBuilder.CGOptLevel = CGOptLevel;
}
/// IR optimization level: from 0 to 3.
void setOptLevel(unsigned NewOptLevel) {
OptLevel = (NewOptLevel > 3) ? 3 : NewOptLevel;
}
/// Disable CodeGen, only run the stages till codegen and stop. The output
/// will be bitcode.
void disableCodeGen(bool Disable) { DisableCodeGen = Disable; }
/// Perform CodeGen only: disable all other stages.
void setCodeGenOnly(bool CGOnly) { CodeGenOnly = CGOnly; }
/**@}*/
/**
* \defgroup Set of APIs to run individual stages in isolation.
* @{
*/
/**
* Produce the combined summary index from all the bitcode files:
* "thin-link".
*/
std::unique_ptr<ModuleSummaryIndex> linkCombinedIndex();
/**
* Perform promotion and renaming of exported internal functions,
* and additionally resolve weak and linkonce symbols.
* Index is updated to reflect linkage changes from weak resolution.
*/
void promote(Module &Module, ModuleSummaryIndex &Index);
/**
* Compute and emit the imported files for module at \p ModulePath.
*/
static void emitImports(StringRef ModulePath, StringRef OutputName,
ModuleSummaryIndex &Index);
/**
* Perform cross-module importing for the module identified by
* ModuleIdentifier.
*/
void crossModuleImport(Module &Module, ModuleSummaryIndex &Index);
/**
* Compute the list of summaries needed for importing into module.
*/
static void gatherImportedSummariesForModule(
StringRef ModulePath, ModuleSummaryIndex &Index,
std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex);
/**
* Perform internalization. Index is updated to reflect linkage changes.
*/
void internalize(Module &Module, ModuleSummaryIndex &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, when
/// SavedObjectsDirectoryPath isn't set.
std::vector<std::unique_ptr<MemoryBuffer>> ProducedBinaries;
/// Path to generated files in the supplied SavedObjectsDirectoryPath if any.
std::vector<std::string> ProducedBinaryFiles;
/// Vector holding the input buffers containing the bitcode modules to
/// process.
std::vector<ThinLTOBuffer> 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;
/// Path to a directory to save the generated object files.
std::string SavedObjectsDirectoryPath;
/// Flag to enable/disable CodeGen. When set to true, the process stops after
/// optimizations and a bitcode is produced.
bool DisableCodeGen = false;
/// Flag to indicate that only the CodeGen will be performed, no cross-module
/// importing or optimization.
bool CodeGenOnly = false;
/// Flag to indicate that the optimizer should not assume builtins are present
/// on the target.
bool Freestanding = false;
/// IR Optimization Level [0-3].
unsigned OptLevel = 3;
};
}
#endif
|