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; 62 if (Task != 0) 63 PathPrefix += "." + utostr(Task); 64 } else 65 PathPrefix = M.getModuleIdentifier(); 66 std::string Path = PathPrefix + "." + PathSuffix + ".bc"; 67 std::error_code EC; 68 raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None); 69 if (EC) { 70 // Because -save-temps is a debugging feature, we report the error 71 // directly and exit. 72 llvm::errs() << "failed to open " << Path << ": " << EC.message() 73 << '\n'; 74 exit(1); 75 } 76 WriteBitcodeToFile(&M, OS, /*ShouldPreserveUseListOrder=*/false); 77 return true; 78 }; 79 }; 80 81 setHook("0.preopt", PreOptModuleHook); 82 setHook("1.promote", PostPromoteModuleHook); 83 setHook("2.internalize", PostInternalizeModuleHook); 84 setHook("3.import", PostImportModuleHook); 85 setHook("4.opt", PostOptModuleHook); 86 setHook("5.precodegen", PreCodeGenModuleHook); 87 88 CombinedIndexHook = [=](const ModuleSummaryIndex &Index) { 89 std::string Path = OutputFileName + ".index.bc"; 90 std::error_code EC; 91 raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None); 92 if (EC) { 93 // Because -save-temps is a debugging feature, we report the error 94 // directly and exit. 95 llvm::errs() << "failed to open " << Path << ": " << EC.message() << '\n'; 96 exit(1); 97 } 98 WriteIndexToFile(Index, OS); 99 return true; 100 }; 101 102 return Error(); 103 } 104 105 namespace { 106 107 std::unique_ptr<TargetMachine> 108 createTargetMachine(Config &C, StringRef TheTriple, const Target *TheTarget) { 109 SubtargetFeatures Features; 110 Features.getDefaultSubtargetFeatures(Triple(TheTriple)); 111 for (const std::string &A : C.MAttrs) 112 Features.AddFeature(A); 113 114 return std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine( 115 TheTriple, C.CPU, Features.getString(), C.Options, C.RelocModel, 116 C.CodeModel, C.CGOptLevel)); 117 } 118 119 bool opt(Config &C, TargetMachine *TM, unsigned Task, Module &M, 120 bool IsThinLto) { 121 M.setDataLayout(TM->createDataLayout()); 122 123 legacy::PassManager passes; 124 passes.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis())); 125 126 PassManagerBuilder PMB; 127 PMB.LibraryInfo = new TargetLibraryInfoImpl(Triple(TM->getTargetTriple())); 128 PMB.Inliner = createFunctionInliningPass(); 129 // Unconditionally verify input since it is not verified before this 130 // point and has unknown origin. 131 PMB.VerifyInput = true; 132 PMB.VerifyOutput = !C.DisableVerify; 133 PMB.LoopVectorize = true; 134 PMB.SLPVectorize = true; 135 PMB.OptLevel = C.OptLevel; 136 if (IsThinLto) 137 PMB.populateThinLTOPassManager(passes); 138 else 139 PMB.populateLTOPassManager(passes); 140 passes.run(M); 141 142 if (C.PostOptModuleHook && !C.PostOptModuleHook(Task, M)) 143 return false; 144 145 return true; 146 } 147 148 void codegen(Config &C, TargetMachine *TM, AddOutputFn AddOutput, unsigned Task, 149 Module &M) { 150 if (C.PreCodeGenModuleHook && !C.PreCodeGenModuleHook(Task, M)) 151 return; 152 153 auto Output = AddOutput(Task); 154 std::unique_ptr<raw_pwrite_stream> OS = Output->getStream(); 155 legacy::PassManager CodeGenPasses; 156 if (TM->addPassesToEmitFile(CodeGenPasses, *OS, 157 TargetMachine::CGFT_ObjectFile)) 158 report_fatal_error("Failed to setup codegen"); 159 CodeGenPasses.run(M); 160 } 161 162 void splitCodeGen(Config &C, TargetMachine *TM, AddOutputFn AddOutput, 163 unsigned ParallelCodeGenParallelismLevel, 164 std::unique_ptr<Module> M) { 165 ThreadPool CodegenThreadPool(ParallelCodeGenParallelismLevel); 166 unsigned ThreadCount = 0; 167 const Target *T = &TM->getTarget(); 168 169 SplitModule( 170 std::move(M), ParallelCodeGenParallelismLevel, 171 [&](std::unique_ptr<Module> MPart) { 172 // We want to clone the module in a new context to multi-thread the 173 // codegen. We do it by serializing partition modules to bitcode 174 // (while still on the main thread, in order to avoid data races) and 175 // spinning up new threads which deserialize the partitions into 176 // separate contexts. 177 // FIXME: Provide a more direct way to do this in LLVM. 178 SmallString<0> BC; 179 raw_svector_ostream BCOS(BC); 180 WriteBitcodeToFile(MPart.get(), BCOS); 181 182 // Enqueue the task 183 CodegenThreadPool.async( 184 [&](const SmallString<0> &BC, unsigned ThreadId) { 185 LTOLLVMContext Ctx(C); 186 ErrorOr<std::unique_ptr<Module>> MOrErr = parseBitcodeFile( 187 MemoryBufferRef(StringRef(BC.data(), BC.size()), "ld-temp.o"), 188 Ctx); 189 if (!MOrErr) 190 report_fatal_error("Failed to read bitcode"); 191 std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get()); 192 193 std::unique_ptr<TargetMachine> TM = 194 createTargetMachine(C, MPartInCtx->getTargetTriple(), T); 195 codegen(C, TM.get(), AddOutput, ThreadId, *MPartInCtx); 196 }, 197 // Pass BC using std::move to ensure that it get moved rather than 198 // copied into the thread's context. 199 std::move(BC), ThreadCount++); 200 }, 201 false); 202 } 203 204 Expected<const Target *> initAndLookupTarget(Config &C, Module &M) { 205 if (!C.OverrideTriple.empty()) 206 M.setTargetTriple(C.OverrideTriple); 207 else if (M.getTargetTriple().empty()) 208 M.setTargetTriple(C.DefaultTriple); 209 210 std::string Msg; 211 const Target *T = TargetRegistry::lookupTarget(M.getTargetTriple(), Msg); 212 if (!T) 213 return make_error<StringError>(Msg, inconvertibleErrorCode()); 214 return T; 215 } 216 217 } 218 219 Error lto::backend(Config &C, AddOutputFn AddOutput, 220 unsigned ParallelCodeGenParallelismLevel, 221 std::unique_ptr<Module> M) { 222 Expected<const Target *> TOrErr = initAndLookupTarget(C, *M); 223 if (!TOrErr) 224 return TOrErr.takeError(); 225 226 std::unique_ptr<TargetMachine> TM = 227 createTargetMachine(C, M->getTargetTriple(), *TOrErr); 228 229 if (!opt(C, TM.get(), 0, *M, /*IsThinLto=*/false)) 230 return Error(); 231 232 if (ParallelCodeGenParallelismLevel == 1) 233 codegen(C, TM.get(), AddOutput, 0, *M); 234 else 235 splitCodeGen(C, TM.get(), AddOutput, ParallelCodeGenParallelismLevel, 236 std::move(M)); 237 return Error(); 238 } 239 240 Error lto::thinBackend(Config &Conf, unsigned Task, AddOutputFn AddOutput, 241 Module &Mod, ModuleSummaryIndex &CombinedIndex, 242 const FunctionImporter::ImportMapTy &ImportList, 243 const GVSummaryMapTy &DefinedGlobals, 244 MapVector<StringRef, MemoryBufferRef> &ModuleMap) { 245 Expected<const Target *> TOrErr = initAndLookupTarget(Conf, Mod); 246 if (!TOrErr) 247 return TOrErr.takeError(); 248 249 std::unique_ptr<TargetMachine> TM = 250 createTargetMachine(Conf, Mod.getTargetTriple(), *TOrErr); 251 252 if (Conf.PreOptModuleHook && !Conf.PreOptModuleHook(Task, Mod)) 253 return Error(); 254 255 thinLTOResolveWeakForLinkerModule(Mod, DefinedGlobals); 256 257 renameModuleForThinLTO(Mod, CombinedIndex); 258 259 if (Conf.PostPromoteModuleHook && !Conf.PostPromoteModuleHook(Task, Mod)) 260 return Error(); 261 262 if (!DefinedGlobals.empty()) 263 thinLTOInternalizeModule(Mod, DefinedGlobals); 264 265 if (Conf.PostInternalizeModuleHook && 266 !Conf.PostInternalizeModuleHook(Task, Mod)) 267 return Error(); 268 269 auto ModuleLoader = [&](StringRef Identifier) { 270 return std::move(getLazyBitcodeModule(MemoryBuffer::getMemBuffer( 271 ModuleMap[Identifier], false), 272 Mod.getContext(), 273 /*ShouldLazyLoadMetadata=*/true) 274 .get()); 275 }; 276 277 FunctionImporter Importer(CombinedIndex, ModuleLoader); 278 Importer.importFunctions(Mod, ImportList); 279 280 if (Conf.PostImportModuleHook && !Conf.PostImportModuleHook(Task, Mod)) 281 return Error(); 282 283 if (!opt(Conf, TM.get(), Task, Mod, /*IsThinLto=*/true)) 284 return Error(); 285 286 codegen(Conf, TM.get(), AddOutput, Task, Mod); 287 return Error(); 288 } 289