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, const 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 /// Monolithic LTO does not support caching (yet), this is a convenient wrapper 147 /// around AddOutput to workaround this. 148 static AddOutputFn getUncachedOutputWrapper(AddOutputFn &AddOutput, 149 unsigned Task) { 150 return [Task, &AddOutput](unsigned TaskId) { 151 auto Output = AddOutput(Task); 152 if (Output->isCachingEnabled() && Output->tryLoadFromCache("")) 153 report_fatal_error("Cache hit without a valid key?"); 154 errs() << Task << " == " << TaskId << "\n"; 155 assert(Task == TaskId && "Unexpexted TaskId mismatch"); 156 return Output; 157 }; 158 } 159 160 void codegen(Config &C, TargetMachine *TM, AddOutputFn AddOutput, unsigned Task, 161 Module &M) { 162 if (C.PreCodeGenModuleHook && !C.PreCodeGenModuleHook(Task, M)) 163 return; 164 165 auto Output = AddOutput(Task); 166 std::unique_ptr<raw_pwrite_stream> OS = Output->getStream(); 167 legacy::PassManager CodeGenPasses; 168 if (TM->addPassesToEmitFile(CodeGenPasses, *OS, 169 TargetMachine::CGFT_ObjectFile)) 170 report_fatal_error("Failed to setup codegen"); 171 CodeGenPasses.run(M); 172 } 173 174 void splitCodeGen(Config &C, TargetMachine *TM, AddOutputFn AddOutput, 175 unsigned ParallelCodeGenParallelismLevel, 176 std::unique_ptr<Module> M) { 177 ThreadPool CodegenThreadPool(ParallelCodeGenParallelismLevel); 178 unsigned ThreadCount = 0; 179 const Target *T = &TM->getTarget(); 180 181 SplitModule( 182 std::move(M), ParallelCodeGenParallelismLevel, 183 [&](std::unique_ptr<Module> MPart) { 184 // We want to clone the module in a new context to multi-thread the 185 // codegen. We do it by serializing partition modules to bitcode 186 // (while still on the main thread, in order to avoid data races) and 187 // spinning up new threads which deserialize the partitions into 188 // separate contexts. 189 // FIXME: Provide a more direct way to do this in LLVM. 190 SmallString<0> BC; 191 raw_svector_ostream BCOS(BC); 192 WriteBitcodeToFile(MPart.get(), BCOS); 193 194 // Enqueue the task 195 CodegenThreadPool.async( 196 [&](const SmallString<0> &BC, unsigned ThreadId) { 197 LTOLLVMContext Ctx(C); 198 ErrorOr<std::unique_ptr<Module>> MOrErr = parseBitcodeFile( 199 MemoryBufferRef(StringRef(BC.data(), BC.size()), "ld-temp.o"), 200 Ctx); 201 if (!MOrErr) 202 report_fatal_error("Failed to read bitcode"); 203 std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get()); 204 205 std::unique_ptr<TargetMachine> TM = 206 createTargetMachine(C, MPartInCtx->getTargetTriple(), T); 207 208 codegen(C, TM.get(), 209 getUncachedOutputWrapper(AddOutput, ThreadId), ThreadId, 210 *MPartInCtx); 211 }, 212 // Pass BC using std::move to ensure that it get moved rather than 213 // copied into the thread's context. 214 std::move(BC), ThreadCount++); 215 }, 216 false); 217 } 218 219 Expected<const Target *> initAndLookupTarget(Config &C, Module &M) { 220 if (!C.OverrideTriple.empty()) 221 M.setTargetTriple(C.OverrideTriple); 222 else if (M.getTargetTriple().empty()) 223 M.setTargetTriple(C.DefaultTriple); 224 225 std::string Msg; 226 const Target *T = TargetRegistry::lookupTarget(M.getTargetTriple(), Msg); 227 if (!T) 228 return make_error<StringError>(Msg, inconvertibleErrorCode()); 229 return T; 230 } 231 232 } 233 234 Error lto::backend(Config &C, AddOutputFn AddOutput, 235 unsigned ParallelCodeGenParallelismLevel, 236 std::unique_ptr<Module> M) { 237 Expected<const Target *> TOrErr = initAndLookupTarget(C, *M); 238 if (!TOrErr) 239 return TOrErr.takeError(); 240 241 std::unique_ptr<TargetMachine> TM = 242 createTargetMachine(C, M->getTargetTriple(), *TOrErr); 243 244 if (!C.CodeGenOnly) 245 if (!opt(C, TM.get(), 0, *M, /*IsThinLto=*/false)) 246 return Error(); 247 248 if (ParallelCodeGenParallelismLevel == 1) { 249 codegen(C, TM.get(), getUncachedOutputWrapper(AddOutput, 0), 0, *M); 250 } else { 251 splitCodeGen(C, TM.get(), AddOutput, ParallelCodeGenParallelismLevel, 252 std::move(M)); 253 } 254 return Error(); 255 } 256 257 Error lto::thinBackend(Config &Conf, unsigned Task, AddOutputFn AddOutput, 258 Module &Mod, ModuleSummaryIndex &CombinedIndex, 259 const FunctionImporter::ImportMapTy &ImportList, 260 const GVSummaryMapTy &DefinedGlobals, 261 MapVector<StringRef, MemoryBufferRef> &ModuleMap) { 262 Expected<const Target *> TOrErr = initAndLookupTarget(Conf, Mod); 263 if (!TOrErr) 264 return TOrErr.takeError(); 265 266 std::unique_ptr<TargetMachine> TM = 267 createTargetMachine(Conf, Mod.getTargetTriple(), *TOrErr); 268 269 if (Conf.CodeGenOnly) { 270 codegen(Conf, TM.get(), AddOutput, Task, Mod); 271 return Error(); 272 } 273 274 if (Conf.PreOptModuleHook && !Conf.PreOptModuleHook(Task, Mod)) 275 return Error(); 276 277 renameModuleForThinLTO(Mod, CombinedIndex); 278 279 thinLTOResolveWeakForLinkerModule(Mod, DefinedGlobals); 280 281 if (Conf.PostPromoteModuleHook && !Conf.PostPromoteModuleHook(Task, Mod)) 282 return Error(); 283 284 if (!DefinedGlobals.empty()) 285 thinLTOInternalizeModule(Mod, DefinedGlobals); 286 287 if (Conf.PostInternalizeModuleHook && 288 !Conf.PostInternalizeModuleHook(Task, Mod)) 289 return Error(); 290 291 auto ModuleLoader = [&](StringRef Identifier) { 292 assert(Mod.getContext().isODRUniquingDebugTypes() && 293 "ODR Type uniquing shoudl be enabled on the context"); 294 return std::move(getLazyBitcodeModule(MemoryBuffer::getMemBuffer( 295 ModuleMap[Identifier], false), 296 Mod.getContext(), 297 /*ShouldLazyLoadMetadata=*/true) 298 .get()); 299 }; 300 301 FunctionImporter Importer(CombinedIndex, ModuleLoader); 302 Importer.importFunctions(Mod, ImportList); 303 304 if (Conf.PostImportModuleHook && !Conf.PostImportModuleHook(Task, Mod)) 305 return Error(); 306 307 if (!opt(Conf, TM.get(), Task, Mod, /*IsThinLto=*/true)) 308 return Error(); 309 310 codegen(Conf, TM.get(), AddOutput, Task, Mod); 311 return Error(); 312 } 313