File indexing completed on 2026-05-10 08:44:11
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_LTO_LTO_H
0016 #define LLVM_LTO_LTO_H
0017
0018 #include <memory>
0019
0020 #include "llvm/ADT/DenseMap.h"
0021 #include "llvm/ADT/MapVector.h"
0022 #include "llvm/Bitcode/BitcodeReader.h"
0023 #include "llvm/IR/ModuleSummaryIndex.h"
0024 #include "llvm/LTO/Config.h"
0025 #include "llvm/Object/IRSymtab.h"
0026 #include "llvm/Support/Caching.h"
0027 #include "llvm/Support/Error.h"
0028 #include "llvm/Support/StringSaver.h"
0029 #include "llvm/Support/ThreadPool.h"
0030 #include "llvm/Support/thread.h"
0031 #include "llvm/Transforms/IPO/FunctionAttrs.h"
0032 #include "llvm/Transforms/IPO/FunctionImport.h"
0033
0034 namespace llvm {
0035
0036 class Error;
0037 class IRMover;
0038 class LLVMContext;
0039 class MemoryBufferRef;
0040 class Module;
0041 class raw_pwrite_stream;
0042 class ToolOutputFile;
0043
0044
0045
0046
0047
0048
0049
0050 void thinLTOResolvePrevailingInIndex(
0051 const lto::Config &C, ModuleSummaryIndex &Index,
0052 function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
0053 isPrevailing,
0054 function_ref<void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)>
0055 recordNewLinkage,
0056 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols);
0057
0058
0059
0060
0061 void thinLTOInternalizeAndPromoteInIndex(
0062 ModuleSummaryIndex &Index,
0063 function_ref<bool(StringRef, ValueInfo)> isExported,
0064 function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
0065 isPrevailing);
0066
0067
0068
0069 std::string computeLTOCacheKey(
0070 const lto::Config &Conf, const ModuleSummaryIndex &Index,
0071 StringRef ModuleID, const FunctionImporter::ImportMapTy &ImportList,
0072 const FunctionImporter::ExportSetTy &ExportList,
0073 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
0074 const GVSummaryMapTy &DefinedGlobals,
0075 const DenseSet<GlobalValue::GUID> &CfiFunctionDefs = {},
0076 const DenseSet<GlobalValue::GUID> &CfiFunctionDecls = {});
0077
0078
0079 std::string recomputeLTOCacheKey(const std::string &Key, StringRef ExtraID);
0080
0081 namespace lto {
0082
0083 StringLiteral getThinLTODefaultCPU(const Triple &TheTriple);
0084
0085
0086
0087
0088 std::string getThinLTOOutputFile(StringRef Path, StringRef OldPrefix,
0089 StringRef NewPrefix);
0090
0091
0092 Expected<std::unique_ptr<ToolOutputFile>> setupLLVMOptimizationRemarks(
0093 LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses,
0094 StringRef RemarksFormat, bool RemarksWithHotness,
0095 std::optional<uint64_t> RemarksHotnessThreshold = 0, int Count = -1);
0096
0097
0098 Expected<std::unique_ptr<ToolOutputFile>>
0099 setupStatsFile(StringRef StatsFilename);
0100
0101
0102
0103 std::vector<int> generateModulesOrdering(ArrayRef<BitcodeModule *> R);
0104
0105
0106
0107
0108 void updateMemProfAttributes(Module &Mod, const ModuleSummaryIndex &Index);
0109
0110 class LTO;
0111 struct SymbolResolution;
0112
0113
0114
0115 class InputFile {
0116 public:
0117 struct Symbol;
0118
0119 private:
0120
0121 friend LTO;
0122 InputFile() = default;
0123
0124 std::vector<BitcodeModule> Mods;
0125 SmallVector<char, 0> Strtab;
0126 std::vector<Symbol> Symbols;
0127
0128
0129 std::vector<std::pair<size_t, size_t>> ModuleSymIndices;
0130
0131 StringRef TargetTriple, SourceFileName, COFFLinkerOpts;
0132 std::vector<StringRef> DependentLibraries;
0133 std::vector<std::pair<StringRef, Comdat::SelectionKind>> ComdatTable;
0134
0135 public:
0136 ~InputFile();
0137
0138
0139 static Expected<std::unique_ptr<InputFile>> create(MemoryBufferRef Object);
0140
0141
0142
0143 struct Symbol : irsymtab::Symbol {
0144 friend LTO;
0145
0146 public:
0147 Symbol(const irsymtab::Symbol &S) : irsymtab::Symbol(S) {}
0148
0149 using irsymtab::Symbol::isUndefined;
0150 using irsymtab::Symbol::isCommon;
0151 using irsymtab::Symbol::isWeak;
0152 using irsymtab::Symbol::isIndirect;
0153 using irsymtab::Symbol::getName;
0154 using irsymtab::Symbol::getIRName;
0155 using irsymtab::Symbol::getVisibility;
0156 using irsymtab::Symbol::canBeOmittedFromSymbolTable;
0157 using irsymtab::Symbol::isTLS;
0158 using irsymtab::Symbol::getComdatIndex;
0159 using irsymtab::Symbol::getCommonSize;
0160 using irsymtab::Symbol::getCommonAlignment;
0161 using irsymtab::Symbol::getCOFFWeakExternalFallback;
0162 using irsymtab::Symbol::getSectionName;
0163 using irsymtab::Symbol::isExecutable;
0164 using irsymtab::Symbol::isUsed;
0165 };
0166
0167
0168 ArrayRef<Symbol> symbols() const { return Symbols; }
0169
0170
0171 StringRef getCOFFLinkerOpts() const { return COFFLinkerOpts; }
0172
0173
0174 ArrayRef<StringRef> getDependentLibraries() const { return DependentLibraries; }
0175
0176
0177 StringRef getName() const;
0178
0179
0180 StringRef getTargetTriple() const { return TargetTriple; }
0181
0182
0183 StringRef getSourceFileName() const { return SourceFileName; }
0184
0185
0186 ArrayRef<std::pair<StringRef, Comdat::SelectionKind>> getComdatTable() const {
0187 return ComdatTable;
0188 }
0189
0190
0191 BitcodeModule &getSingleBitcodeModule();
0192
0193 private:
0194 ArrayRef<Symbol> module_symbols(unsigned I) const {
0195 const auto &Indices = ModuleSymIndices[I];
0196 return {Symbols.data() + Indices.first, Symbols.data() + Indices.second};
0197 }
0198 };
0199
0200 using IndexWriteCallback = std::function<void(const std::string &)>;
0201
0202
0203 class ThinBackendProc {
0204 protected:
0205 const Config &Conf;
0206 ModuleSummaryIndex &CombinedIndex;
0207 const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries;
0208 IndexWriteCallback OnWrite;
0209 bool ShouldEmitImportsFiles;
0210 DefaultThreadPool BackendThreadPool;
0211 std::optional<Error> Err;
0212 std::mutex ErrMu;
0213
0214 public:
0215 ThinBackendProc(
0216 const Config &Conf, ModuleSummaryIndex &CombinedIndex,
0217 const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
0218 lto::IndexWriteCallback OnWrite, bool ShouldEmitImportsFiles,
0219 ThreadPoolStrategy ThinLTOParallelism)
0220 : Conf(Conf), CombinedIndex(CombinedIndex),
0221 ModuleToDefinedGVSummaries(ModuleToDefinedGVSummaries),
0222 OnWrite(OnWrite), ShouldEmitImportsFiles(ShouldEmitImportsFiles),
0223 BackendThreadPool(ThinLTOParallelism) {}
0224
0225 virtual ~ThinBackendProc() = default;
0226 virtual Error start(
0227 unsigned Task, BitcodeModule BM,
0228 const FunctionImporter::ImportMapTy &ImportList,
0229 const FunctionImporter::ExportSetTy &ExportList,
0230 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
0231 MapVector<StringRef, BitcodeModule> &ModuleMap) = 0;
0232 Error wait() {
0233 BackendThreadPool.wait();
0234 if (Err)
0235 return std::move(*Err);
0236 return Error::success();
0237 }
0238 unsigned getThreadCount() { return BackendThreadPool.getMaxConcurrency(); }
0239 virtual bool isSensitiveToInputOrder() { return false; }
0240
0241
0242 Error emitFiles(const FunctionImporter::ImportMapTy &ImportList,
0243 llvm::StringRef ModulePath,
0244 const std::string &NewModulePath) const;
0245 };
0246
0247
0248
0249
0250
0251
0252
0253 using ThinBackendFunction = std::function<std::unique_ptr<ThinBackendProc>(
0254 const Config &C, ModuleSummaryIndex &CombinedIndex,
0255 const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
0256 AddStreamFn AddStream, FileCache Cache)>;
0257
0258
0259
0260
0261
0262
0263 struct ThinBackend {
0264 ThinBackend(ThinBackendFunction Func, ThreadPoolStrategy Parallelism)
0265 : Func(std::move(Func)), Parallelism(std::move(Parallelism)) {}
0266 ThinBackend() = default;
0267
0268 std::unique_ptr<ThinBackendProc> operator()(
0269 const Config &Conf, ModuleSummaryIndex &CombinedIndex,
0270 const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
0271 AddStreamFn AddStream, FileCache Cache) {
0272 assert(isValid() && "Invalid backend function");
0273 return Func(Conf, CombinedIndex, ModuleToDefinedGVSummaries,
0274 std::move(AddStream), std::move(Cache));
0275 }
0276 ThreadPoolStrategy getParallelism() const { return Parallelism; }
0277 bool isValid() const { return static_cast<bool>(Func); }
0278
0279 private:
0280 ThinBackendFunction Func = nullptr;
0281 ThreadPoolStrategy Parallelism;
0282 };
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292 ThinBackend createInProcessThinBackend(ThreadPoolStrategy Parallelism,
0293 IndexWriteCallback OnWrite = nullptr,
0294 bool ShouldEmitIndexFiles = false,
0295 bool ShouldEmitImportsFiles = false);
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312 ThinBackend createWriteIndexesThinBackend(ThreadPoolStrategy Parallelism,
0313 std::string OldPrefix,
0314 std::string NewPrefix,
0315 std::string NativeObjectPrefix,
0316 bool ShouldEmitImportsFiles,
0317 raw_fd_ostream *LinkedObjectsFile,
0318 IndexWriteCallback OnWrite);
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336 class LTO {
0337 friend InputFile;
0338
0339 public:
0340
0341 enum LTOKind {
0342
0343 LTOK_Default,
0344
0345
0346 LTOK_UnifiedRegular,
0347
0348
0349 LTOK_UnifiedThin,
0350 };
0351
0352
0353
0354
0355
0356
0357 LTO(Config Conf, ThinBackend Backend = {},
0358 unsigned ParallelCodeGenParallelismLevel = 1,
0359 LTOKind LTOMode = LTOK_Default);
0360 ~LTO();
0361
0362
0363
0364
0365 Error add(std::unique_ptr<InputFile> Obj, ArrayRef<SymbolResolution> Res);
0366
0367
0368
0369
0370 unsigned getMaxTasks() const;
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380 Error run(AddStreamFn AddStream, FileCache Cache = {});
0381
0382
0383
0384 static SmallVector<const char *> getRuntimeLibcallSymbols(const Triple &TT);
0385
0386 private:
0387 Config Conf;
0388
0389 struct RegularLTOState {
0390 RegularLTOState(unsigned ParallelCodeGenParallelismLevel,
0391 const Config &Conf);
0392 struct CommonResolution {
0393 uint64_t Size = 0;
0394 Align Alignment;
0395
0396 bool Prevailing = false;
0397 };
0398 std::map<std::string, CommonResolution> Commons;
0399
0400 unsigned ParallelCodeGenParallelismLevel;
0401 LTOLLVMContext Ctx;
0402 std::unique_ptr<Module> CombinedModule;
0403 std::unique_ptr<IRMover> Mover;
0404
0405
0406
0407
0408
0409 struct AddedModule {
0410 std::unique_ptr<Module> M;
0411 std::vector<GlobalValue *> Keep;
0412 };
0413 std::vector<AddedModule> ModsWithSummaries;
0414 bool EmptyCombinedModule = true;
0415 } RegularLTO;
0416
0417 using ModuleMapType = MapVector<StringRef, BitcodeModule>;
0418
0419 struct ThinLTOState {
0420 ThinLTOState(ThinBackend Backend);
0421
0422 ThinBackend Backend;
0423 ModuleSummaryIndex CombinedIndex;
0424
0425 ModuleMapType ModuleMap;
0426
0427 std::optional<ModuleMapType> ModulesToCompile;
0428 DenseMap<GlobalValue::GUID, StringRef> PrevailingModuleForGUID;
0429 } ThinLTO;
0430
0431
0432
0433
0434
0435
0436
0437
0438 struct GlobalResolution {
0439
0440 std::string IRName;
0441
0442
0443
0444
0445 bool VisibleOutsideSummary = false;
0446
0447
0448
0449 bool ExportDynamic = false;
0450
0451 bool UnnamedAddr = true;
0452
0453
0454 bool Prevailing = false;
0455
0456
0457
0458
0459 bool isPrevailingIRSymbol() const { return Prevailing && !IRName.empty(); }
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472 unsigned Partition = Unknown;
0473
0474
0475 enum : unsigned {
0476
0477 Unknown = -1u,
0478
0479
0480
0481 External = -2u,
0482
0483
0484 RegularLTO = 0,
0485 };
0486 };
0487
0488
0489 std::unique_ptr<llvm::BumpPtrAllocator> Alloc;
0490
0491
0492 std::unique_ptr<llvm::StringSaver> GlobalResolutionSymbolSaver;
0493
0494
0495
0496
0497 std::unique_ptr<llvm::DenseMap<StringRef, GlobalResolution>>
0498 GlobalResolutions;
0499
0500 void releaseGlobalResolutionsMemory();
0501
0502 void addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
0503 ArrayRef<SymbolResolution> Res, unsigned Partition,
0504 bool InSummary);
0505
0506
0507
0508
0509
0510 Error addModule(InputFile &Input, unsigned ModI,
0511 const SymbolResolution *&ResI, const SymbolResolution *ResE);
0512
0513 Expected<RegularLTOState::AddedModule>
0514 addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
0515 const SymbolResolution *&ResI, const SymbolResolution *ResE);
0516 Error linkRegularLTO(RegularLTOState::AddedModule Mod,
0517 bool LivenessFromIndex);
0518
0519 Error addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
0520 const SymbolResolution *&ResI, const SymbolResolution *ResE);
0521
0522 Error runRegularLTO(AddStreamFn AddStream);
0523 Error runThinLTO(AddStreamFn AddStream, FileCache Cache,
0524 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols);
0525
0526 Error checkPartiallySplit();
0527
0528 mutable bool CalledGetMaxTasks = false;
0529
0530
0531 LTOKind LTOMode;
0532
0533
0534 std::optional<bool> EnableSplitLTOUnit;
0535
0536
0537
0538 DenseSet<GlobalValue::GUID> DynamicExportSymbols;
0539
0540
0541 std::unique_ptr<ToolOutputFile> DiagnosticOutputFile;
0542 };
0543
0544
0545
0546 struct SymbolResolution {
0547 SymbolResolution()
0548 : Prevailing(0), FinalDefinitionInLinkageUnit(0), VisibleToRegularObj(0),
0549 ExportDynamic(0), LinkerRedefined(0) {}
0550
0551
0552 unsigned Prevailing : 1;
0553
0554
0555
0556 unsigned FinalDefinitionInLinkageUnit : 1;
0557
0558
0559 unsigned VisibleToRegularObj : 1;
0560
0561
0562
0563 unsigned ExportDynamic : 1;
0564
0565
0566
0567 unsigned LinkerRedefined : 1;
0568 };
0569
0570 }
0571 }
0572
0573 #endif