1 //===-LTOBackend.cpp - LLVM Link Time Optimizer Backend -------------------===// 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 implements the "backend" phase of LTO, i.e. it performs 11 // optimization and code generation on a loaded module. It is generally used 12 // internally by the LTO class but can also be used independently, for example 13 // to implement a standalone ThinLTO backend. 14 // 15 //===----------------------------------------------------------------------===// 16 17 #include "llvm/LTO/LTOBackend.h" 18 #include "llvm/Analysis/TargetLibraryInfo.h" 19 #include "llvm/Analysis/TargetTransformInfo.h" 20 #include "llvm/Bitcode/ReaderWriter.h" 21 #include "llvm/IR/LegacyPassManager.h" 22 #include "llvm/LTO/LTO.h" 23 #include "llvm/MC/SubtargetFeature.h" 24 #include "llvm/Support/Error.h" 25 #include "llvm/Support/FileSystem.h" 26 #include "llvm/Support/TargetRegistry.h" 27 #include "llvm/Support/ThreadPool.h" 28 #include "llvm/Target/TargetMachine.h" 29 #include "llvm/Transforms/IPO.h" 30 #include "llvm/Transforms/IPO/PassManagerBuilder.h" 31 #include "llvm/Transforms/Utils/FunctionImportUtils.h" 32 #include "llvm/Transforms/Utils/SplitModule.h" 33 34 using namespace llvm; 35 using namespace lto; 36 37 Error Config::addSaveTemps(std::string OutputFileName, 38 bool UseInputModulePath) { 39 ShouldDiscardValueNames = false; 40 41 std::error_code EC; 42 ResolutionFile = llvm::make_unique<raw_fd_ostream>( 43 OutputFileName + "resolution.txt", EC, sys::fs::OpenFlags::F_Text); 44 if (EC) 45 return errorCodeToError(EC); 46 47 auto setHook = [&](std::string PathSuffix, ModuleHookFn &Hook) { 48 // Keep track of the hook provided by the linker, which also needs to run. 49 ModuleHookFn LinkerHook = Hook; 50 Hook = [=](unsigned Task, Module &M) { 51 // If the linker's hook returned false, we need to pass that result 52 // through. 53 if (LinkerHook && !LinkerHook(Task, M)) 54 return false; 55 56 std::string PathPrefix; 57 // If this is the combined module (not a ThinLTO backend compile) or the 58 // user hasn't requested using the input module's path, emit to a file 59 // named from the provided OutputFileName with the Task ID appended. 60 if (M.getModuleIdentifier() == "ld-temp.o" || !UseInputModulePath) { 61 PathPrefix = OutputFileName + utostr(Task); 62 } else 63 PathPrefix = M.getModuleIdentifier(); 64 std::string Path = PathPrefix + "." + PathSuffix + ".bc"; 65 std::error_code EC; 66 raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None); 67 if (EC) { 68 // Because -save-temps is a debugging feature, we report the error 69 // directly and exit. 70 llvm::errs() << "failed to open " << Path << ": " << EC.message() 71 << '\n'; 72 exit(1); 73 } 74 WriteBitcodeToFile(&M, OS, /*ShouldPreserveUseListOrder=*/false); 75 return true; 76 }; 77 }; 78 79 setHook("0.preopt", PreOptModuleHook); 80 setHook("1.promote", PostPromoteModuleHook); 81 setHook("2.internalize", PostInternalizeModuleHook); 82 setHook("3.import", PostImportModuleHook); 83 setHook("4.opt", PostOptModuleHook); 84 setHook("5.precodegen", PreCodeGenModuleHook); 85 86 CombinedIndexHook = [=](const ModuleSummaryIndex &Index) { 87 std::string Path = OutputFileName + "index.bc"; 88 std::error_code EC; 89 raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None); 90 if (EC) { 91 // Because -save-temps is a debugging feature, we report the error 92 // directly and exit. 93 llvm::errs() << "failed to open " << Path << ": " << EC.message() << '\n'; 94 exit(1); 95 } 96 WriteIndexToFile(Index, OS); 97 return true; 98 }; 99 100 return Error(); 101 } 102 103 namespace { 104 105 std::unique_ptr<TargetMachine> 106 createTargetMachine(Config &C, StringRef TheTriple, const Target *TheTarget) { 107 SubtargetFeatures Features; 108 Features.getDefaultSubtargetFeatures(Triple(TheTriple)); 109 for (const std::string &A : C.MAttrs) 110 Features.AddFeature(A); 111 112 return std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine( 113 TheTriple, C.CPU, Features.getString(), C.Options, C.RelocModel, 114 C.CodeModel, C.CGOptLevel)); 115 } 116 117 bool opt(Config &C, TargetMachine *TM, unsigned Task, Module &M, 118 bool IsThinLto) { 119 M.setDataLayout(TM->createDataLayout()); 120 121 legacy::PassManager passes; 122 passes.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis())); 123 124 PassManagerBuilder PMB; 125 PMB.LibraryInfo = new TargetLibraryInfoImpl(Triple(TM->getTargetTriple())); 126 PMB.Inliner = createFunctionInliningPass(); 127 // Unconditionally verify input since it is not verified before this 128 // point and has unknown origin. 129 PMB.VerifyInput = true; 130 PMB.VerifyOutput = !C.DisableVerify; 131 PMB.LoopVectorize = true; 132 PMB.SLPVectorize = true; 133 PMB.OptLevel = C.OptLevel; 134 if (IsThinLto) 135 PMB.populateThinLTOPassManager(passes); 136 else 137 PMB.populateLTOPassManager(passes); 138 passes.run(M); 139 140 if (C.PostOptModuleHook && !C.PostOptModuleHook(Task, M)) 141 return false; 142 143 return true; 144 } 145 146 void codegen(Config &C, TargetMachine *TM, AddOutputFn AddOutput, unsigned Task, 147 Module &M) { 148 if (C.PreCodeGenModuleHook && !C.PreCodeGenModuleHook(Task, M)) 149 return; 150 151 auto Output = AddOutput(Task); 152 std::unique_ptr<raw_pwrite_stream> OS = Output->getStream(); 153 legacy::PassManager CodeGenPasses; 154 if (TM->addPassesToEmitFile(CodeGenPasses, *OS, 155 TargetMachine::CGFT_ObjectFile)) 156 report_fatal_error("Failed to setup codegen"); 157 CodeGenPasses.run(M); 158 } 159 160 void splitCodeGen(Config &C, TargetMachine *TM, AddOutputFn AddOutput, 161 unsigned ParallelCodeGenParallelismLevel, 162 std::unique_ptr<Module> M) { 163 ThreadPool CodegenThreadPool(ParallelCodeGenParallelismLevel); 164 unsigned ThreadCount = 0; 165 const Target *T = &TM->getTarget(); 166 167 SplitModule( 168 std::move(M), ParallelCodeGenParallelismLevel, 169 [&](std::unique_ptr<Module> MPart) { 170 // We want to clone the module in a new context to multi-thread the 171 // codegen. We do it by serializing partition modules to bitcode 172 // (while still on the main thread, in order to avoid data races) and 173 // spinning up new threads which deserialize the partitions into 174 // separate contexts. 175 // FIXME: Provide a more direct way to do this in LLVM. 176 SmallString<0> BC; 177 raw_svector_ostream BCOS(BC); 178 WriteBitcodeToFile(MPart.get(), BCOS); 179 180 // Enqueue the task 181 CodegenThreadPool.async( 182 [&](const SmallString<0> &BC, unsigned ThreadId) { 183 LTOLLVMContext Ctx(C); 184 ErrorOr<std::unique_ptr<Module>> MOrErr = parseBitcodeFile( 185 MemoryBufferRef(StringRef(BC.data(), BC.size()), "ld-temp.o"), 186 Ctx); 187 if (!MOrErr) 188 report_fatal_error("Failed to read bitcode"); 189 std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get()); 190 191 std::unique_ptr<TargetMachine> TM = 192 createTargetMachine(C, MPartInCtx->getTargetTriple(), T); 193 codegen(C, TM.get(), AddOutput, ThreadId, *MPartInCtx); 194 }, 195 // Pass BC using std::move to ensure that it get moved rather than 196 // copied into the thread's context. 197 std::move(BC), ThreadCount++); 198 }, 199 false); 200 } 201 202 Expected<const Target *> initAndLookupTarget(Config &C, Module &M) { 203 if (!C.OverrideTriple.empty()) 204 M.setTargetTriple(C.OverrideTriple); 205 else if (M.getTargetTriple().empty()) 206 M.setTargetTriple(C.DefaultTriple); 207 208 std::string Msg; 209 const Target *T = TargetRegistry::lookupTarget(M.getTargetTriple(), Msg); 210 if (!T) 211 return make_error<StringError>(Msg, inconvertibleErrorCode()); 212 return T; 213 } 214 215 } 216 217 Error lto::backend(Config &C, AddOutputFn AddOutput, 218 unsigned ParallelCodeGenParallelismLevel, 219 std::unique_ptr<Module> M) { 220 Expected<const Target *> TOrErr = initAndLookupTarget(C, *M); 221 if (!TOrErr) 222 return TOrErr.takeError(); 223 224 std::unique_ptr<TargetMachine> TM = 225 createTargetMachine(C, M->getTargetTriple(), *TOrErr); 226 227 if (!opt(C, TM.get(), 0, *M, /*IsThinLto=*/false)) 228 return Error(); 229 230 if (ParallelCodeGenParallelismLevel == 1) 231 codegen(C, TM.get(), AddOutput, 0, *M); 232 else 233 splitCodeGen(C, TM.get(), AddOutput, ParallelCodeGenParallelismLevel, 234 std::move(M)); 235 return Error(); 236 } 237 238 Error lto::thinBackend(Config &Conf, unsigned Task, AddOutputFn AddOutput, 239 Module &Mod, ModuleSummaryIndex &CombinedIndex, 240 const FunctionImporter::ImportMapTy &ImportList, 241 const GVSummaryMapTy &DefinedGlobals, 242 MapVector<StringRef, MemoryBufferRef> &ModuleMap) { 243 Expected<const Target *> TOrErr = initAndLookupTarget(Conf, Mod); 244 if (!TOrErr) 245 return TOrErr.takeError(); 246 247 std::unique_ptr<TargetMachine> TM = 248 createTargetMachine(Conf, Mod.getTargetTriple(), *TOrErr); 249 250 if (Conf.PreOptModuleHook && !Conf.PreOptModuleHook(Task, Mod)) 251 return Error(); 252 253 renameModuleForThinLTO(Mod, CombinedIndex); 254 255 thinLTOResolveWeakForLinkerModule(Mod, DefinedGlobals); 256 257 if (Conf.PostPromoteModuleHook && !Conf.PostPromoteModuleHook(Task, Mod)) 258 return Error(); 259 260 if (!DefinedGlobals.empty()) 261 thinLTOInternalizeModule(Mod, DefinedGlobals); 262 263 if (Conf.PostInternalizeModuleHook && 264 !Conf.PostInternalizeModuleHook(Task, Mod)) 265 return Error(); 266 267 auto ModuleLoader = [&](StringRef Identifier) { 268 return std::move(getLazyBitcodeModule(MemoryBuffer::getMemBuffer( 269 ModuleMap[Identifier], false), 270 Mod.getContext(), 271 /*ShouldLazyLoadMetadata=*/true) 272 .get()); 273 }; 274 275 FunctionImporter Importer(CombinedIndex, ModuleLoader); 276 Importer.importFunctions(Mod, ImportList); 277 278 if (Conf.PostImportModuleHook && !Conf.PostImportModuleHook(Task, Mod)) 279 return Error(); 280 281 if (!opt(Conf, TM.get(), Task, Mod, /*IsThinLto=*/true)) 282 return Error(); 283 284 codegen(Conf, TM.get(), AddOutput, Task, Mod); 285 return Error(); 286 } 287