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