xref: /llvm-project-15.0.7/lld/ELF/LTO.cpp (revision 928c8254)
1 //===- LTO.cpp ------------------------------------------------------------===//
2 //
3 //                             The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "LTO.h"
11 #include "Config.h"
12 #include "Error.h"
13 #include "InputFiles.h"
14 #include "Symbols.h"
15 #include "llvm/Analysis/TargetLibraryInfo.h"
16 #include "llvm/Analysis/TargetTransformInfo.h"
17 #include "llvm/Bitcode/ReaderWriter.h"
18 #include "llvm/CodeGen/CommandFlags.h"
19 #include "llvm/CodeGen/ParallelCG.h"
20 #include "llvm/IR/LegacyPassManager.h"
21 #include "llvm/Linker/IRMover.h"
22 #include "llvm/Support/StringSaver.h"
23 #include "llvm/Support/TargetRegistry.h"
24 #include "llvm/Target/TargetMachine.h"
25 #include "llvm/Transforms/IPO.h"
26 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
27 #include "llvm/Transforms/Utils/ModuleUtils.h"
28 
29 using namespace llvm;
30 using namespace llvm::object;
31 using namespace llvm::ELF;
32 
33 using namespace lld;
34 using namespace lld::elf;
35 
36 // This is for use when debugging LTO.
37 static void saveLtoObjectFile(StringRef Buffer, unsigned I, bool Many) {
38   SmallString<128> Filename = Config->OutputFile;
39   if (Many)
40     Filename += utostr(I);
41   Filename += ".lto.o";
42   std::error_code EC;
43   raw_fd_ostream OS(Filename, EC, sys::fs::OpenFlags::F_None);
44   check(EC);
45   OS << Buffer;
46 }
47 
48 // This is for use when debugging LTO.
49 static void saveBCFile(Module &M, StringRef Suffix) {
50   std::error_code EC;
51   raw_fd_ostream OS(Config->OutputFile.str() + Suffix.str(), EC,
52                     sys::fs::OpenFlags::F_None);
53   check(EC);
54   WriteBitcodeToFile(&M, OS, /* ShouldPreserveUseListOrder */ true);
55 }
56 
57 // Run LTO passes.
58 // Note that the gold plugin has a similar piece of code, so
59 // it is probably better to move this code to a common place.
60 static void runLTOPasses(Module &M, TargetMachine &TM) {
61   legacy::PassManager LtoPasses;
62   LtoPasses.add(createTargetTransformInfoWrapperPass(TM.getTargetIRAnalysis()));
63   PassManagerBuilder PMB;
64   PMB.LibraryInfo = new TargetLibraryInfoImpl(Triple(TM.getTargetTriple()));
65   PMB.Inliner = createFunctionInliningPass();
66   PMB.VerifyInput = PMB.VerifyOutput = !Config->DisableVerify;
67   PMB.LoopVectorize = true;
68   PMB.SLPVectorize = true;
69   PMB.OptLevel = Config->LtoO;
70   PMB.populateLTOPassManager(LtoPasses);
71   LtoPasses.run(M);
72 
73   if (Config->SaveTemps)
74     saveBCFile(M, ".lto.opt.bc");
75 }
76 
77 static bool shouldInternalize(const SmallPtrSet<GlobalValue *, 8> &Used,
78                               SymbolBody &B, GlobalValue *GV) {
79   if (B.Backref->IsUsedInRegularObj)
80     return false;
81 
82   if (Used.count(GV))
83     return false;
84 
85   return !B.Backref->includeInDynsym();
86 }
87 
88 BitcodeCompiler::BitcodeCompiler()
89     : Combined(new llvm::Module("ld-temp.o", Context)), Mover(*Combined) {
90   // This is a flag to discard all but GlobalValue names.
91   // We want to enable it by default because it saves memory.
92   // Disable it only when a developer option (-save-temps) is given.
93   Context.setDiscardValueNames(!Config->SaveTemps);
94 
95   Context.enableDebugTypeODRUniquing();
96 }
97 
98 void BitcodeCompiler::add(BitcodeFile &F) {
99   std::unique_ptr<IRObjectFile> Obj =
100       check(IRObjectFile::create(F.MB, Context));
101   std::vector<GlobalValue *> Keep;
102   unsigned BodyIndex = 0;
103   ArrayRef<SymbolBody *> Bodies = F.getSymbols();
104 
105   Module &M = Obj->getModule();
106   if (M.getDataLayoutStr().empty())
107     fatal("invalid bitcode file: " + F.getName() + " has no datalayout");
108 
109   // If a symbol appears in @llvm.used, the linker is required
110   // to treat the symbol as there is a reference to the symbol
111   // that it cannot see. Therefore, we can't internalize.
112   SmallPtrSet<GlobalValue *, 8> Used;
113   collectUsedGlobalVariables(M, Used, /* CompilerUsed */ false);
114 
115   for (const BasicSymbolRef &Sym : Obj->symbols()) {
116     GlobalValue *GV = Obj->getSymbolGV(Sym.getRawDataRefImpl());
117     // Ignore module asm symbols.
118     if (!GV)
119       continue;
120     if (GV->hasAppendingLinkage()) {
121       Keep.push_back(GV);
122       continue;
123     }
124     if (BitcodeFile::shouldSkip(Sym))
125       continue;
126     SymbolBody *B = Bodies[BodyIndex++];
127     if (!B || &B->repl() != B || !isa<DefinedBitcode>(B))
128       continue;
129     switch (GV->getLinkage()) {
130     default:
131       break;
132     case llvm::GlobalValue::LinkOnceAnyLinkage:
133       GV->setLinkage(GlobalValue::WeakAnyLinkage);
134       break;
135     case llvm::GlobalValue::LinkOnceODRLinkage:
136       GV->setLinkage(GlobalValue::WeakODRLinkage);
137       break;
138     }
139 
140     // We collect the set of symbols we want to internalize here
141     // and change the linkage after the IRMover executed, i.e. after
142     // we imported the symbols and satisfied undefined references
143     // to it. We can't just change linkage here because otherwise
144     // the IRMover will just rename the symbol.
145     if (shouldInternalize(Used, *B, GV))
146       InternalizedSyms.insert(GV->getName());
147 
148     Keep.push_back(GV);
149   }
150 
151   Mover.move(Obj->takeModule(), Keep,
152              [](GlobalValue &, IRMover::ValueAdder) {});
153 }
154 
155 static void internalize(GlobalValue &GV) {
156   assert(!GV.hasLocalLinkage() &&
157          "Trying to internalize a symbol with local linkage!");
158   GV.setLinkage(GlobalValue::InternalLinkage);
159 }
160 
161 std::vector<std::unique_ptr<InputFile>> BitcodeCompiler::runSplitCodegen(
162     const std::function<std::unique_ptr<TargetMachine>()> &TMFactory) {
163   unsigned NumThreads = Config->LtoJobs;
164   OwningData.resize(NumThreads);
165 
166   std::list<raw_svector_ostream> OSs;
167   std::vector<raw_pwrite_stream *> OSPtrs;
168   for (SmallString<0> &Obj : OwningData) {
169     OSs.emplace_back(Obj);
170     OSPtrs.push_back(&OSs.back());
171   }
172 
173   splitCodeGen(std::move(Combined), OSPtrs, {}, TMFactory);
174 
175   std::vector<std::unique_ptr<InputFile>> ObjFiles;
176   for (SmallString<0> &Obj : OwningData)
177     ObjFiles.push_back(createObjectFile(
178         MemoryBufferRef(Obj, "LLD-INTERNAL-combined-lto-object")));
179 
180   if (Config->SaveTemps)
181     for (unsigned I = 0; I < NumThreads; ++I)
182       saveLtoObjectFile(OwningData[I], I, NumThreads > 1);
183 
184   return ObjFiles;
185 }
186 
187 // Merge all the bitcode files we have seen, codegen the result
188 // and return the resulting ObjectFile.
189 std::vector<std::unique_ptr<InputFile>> BitcodeCompiler::compile() {
190   TheTriple = Combined->getTargetTriple();
191   for (const auto &Name : InternalizedSyms) {
192     GlobalValue *GV = Combined->getNamedValue(Name.first());
193     assert(GV);
194     internalize(*GV);
195   }
196 
197   if (Config->SaveTemps)
198     saveBCFile(*Combined, ".lto.bc");
199 
200   std::string Msg;
201   const Target *T = TargetRegistry::lookupTarget(TheTriple, Msg);
202   if (!T)
203     fatal("target not found: " + Msg);
204   TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
205   Reloc::Model R = Config->Pic ? Reloc::PIC_ : Reloc::Static;
206 
207   auto CreateTargetMachine = [&]() {
208     return std::unique_ptr<TargetMachine>(
209         T->createTargetMachine(TheTriple, "", "", Options, R));
210   };
211 
212   std::unique_ptr<TargetMachine> TM = CreateTargetMachine();
213   runLTOPasses(*Combined, *TM);
214 
215   return runSplitCodegen(CreateTargetMachine);
216 }
217