1 //===- FunctionImport.cpp - ThinLTO Summary-based Function Import ---------===// 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 Function import based on summaries. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/Transforms/IPO/FunctionImport.h" 15 16 #include "llvm/ADT/SmallVector.h" 17 #include "llvm/ADT/Statistic.h" 18 #include "llvm/ADT/StringSet.h" 19 #include "llvm/IR/AutoUpgrade.h" 20 #include "llvm/IR/DiagnosticPrinter.h" 21 #include "llvm/IR/IntrinsicInst.h" 22 #include "llvm/IR/Module.h" 23 #include "llvm/IRReader/IRReader.h" 24 #include "llvm/Linker/Linker.h" 25 #include "llvm/Object/ModuleSummaryIndexObjectFile.h" 26 #include "llvm/Support/CommandLine.h" 27 #include "llvm/Support/Debug.h" 28 #include "llvm/Support/SourceMgr.h" 29 #include "llvm/Transforms/Utils/FunctionImportUtils.h" 30 31 #define DEBUG_TYPE "function-import" 32 33 using namespace llvm; 34 35 STATISTIC(NumImported, "Number of functions imported"); 36 37 /// Limit on instruction count of imported functions. 38 static cl::opt<unsigned> ImportInstrLimit( 39 "import-instr-limit", cl::init(100), cl::Hidden, cl::value_desc("N"), 40 cl::desc("Only import functions with less than N instructions")); 41 42 static cl::opt<float> 43 ImportInstrFactor("import-instr-evolution-factor", cl::init(0.7), 44 cl::Hidden, cl::value_desc("x"), 45 cl::desc("As we import functions, multiply the " 46 "`import-instr-limit` threshold by this factor " 47 "before processing newly imported functions")); 48 49 static cl::opt<bool> PrintImports("print-imports", cl::init(false), cl::Hidden, 50 cl::desc("Print imported functions")); 51 52 // Load lazily a module from \p FileName in \p Context. 53 static std::unique_ptr<Module> loadFile(const std::string &FileName, 54 LLVMContext &Context) { 55 SMDiagnostic Err; 56 DEBUG(dbgs() << "Loading '" << FileName << "'\n"); 57 // Metadata isn't loaded until functions are imported, to minimize 58 // the memory overhead. 59 std::unique_ptr<Module> Result = 60 getLazyIRFileModule(FileName, Err, Context, 61 /* ShouldLazyLoadMetadata = */ true); 62 if (!Result) { 63 Err.print("function-import", errs()); 64 return nullptr; 65 } 66 67 return Result; 68 } 69 70 namespace { 71 72 /// Given a list of possible callee implementation for a call site, select one 73 /// that fits the \p Threshold. 74 /// 75 /// FIXME: select "best" instead of first that fits. But what is "best"? 76 /// - The smallest: more likely to be inlined. 77 /// - The one with the least outgoing edges (already well optimized). 78 /// - One from a module already being imported from in order to reduce the 79 /// number of source modules parsed/linked. 80 /// - One that has PGO data attached. 81 /// - [insert you fancy metric here] 82 static const FunctionSummary * 83 selectCallee(const GlobalValueInfoList &CalleeInfoList, unsigned Threshold) { 84 auto It = llvm::find_if( 85 CalleeInfoList, [&](const std::unique_ptr<GlobalValueInfo> &GlobInfo) { 86 assert(GlobInfo->summary() && 87 "We should not have a Global Info without summary"); 88 auto *Summary = cast<FunctionSummary>(GlobInfo->summary()); 89 90 if (GlobalValue::isWeakAnyLinkage(Summary->linkage())) 91 return false; 92 93 if (Summary->instCount() > Threshold) 94 return false; 95 96 return true; 97 }); 98 if (It == CalleeInfoList.end()) 99 return nullptr; 100 101 return cast<FunctionSummary>((*It)->summary()); 102 } 103 104 /// Return the summary for the function \p GUID that fits the \p Threshold, or 105 /// null if there's no match. 106 static const FunctionSummary *selectCallee(uint64_t GUID, unsigned Threshold, 107 const ModuleSummaryIndex &Index) { 108 auto CalleeInfoList = Index.findGlobalValueInfoList(GUID); 109 if (CalleeInfoList == Index.end()) { 110 return nullptr; // This function does not have a summary 111 } 112 return selectCallee(CalleeInfoList->second, Threshold); 113 } 114 115 /// Return true if the global \p GUID is exported by module \p ExportModulePath. 116 static bool isGlobalExported(const ModuleSummaryIndex &Index, 117 StringRef ExportModulePath, uint64_t GUID) { 118 auto CalleeInfoList = Index.findGlobalValueInfoList(GUID); 119 if (CalleeInfoList == Index.end()) 120 // This global does not have a summary, it is not part of the ThinLTO 121 // process 122 return false; 123 auto DefinedInCalleeModule = llvm::find_if( 124 CalleeInfoList->second, 125 [&](const std::unique_ptr<GlobalValueInfo> &GlobInfo) { 126 auto *Summary = GlobInfo->summary(); 127 assert(Summary && "Unexpected GlobalValueInfo without summary"); 128 return Summary->modulePath() == ExportModulePath; 129 }); 130 return (DefinedInCalleeModule != CalleeInfoList->second.end()); 131 } 132 133 using EdgeInfo = std::pair<const FunctionSummary *, unsigned /* Threshold */>; 134 135 /// Compute the list of functions to import for a given caller. Mark these 136 /// imported functions and the symbols they reference in their source module as 137 /// exported from their source module. 138 static void computeImportForFunction( 139 StringRef ModulePath, const FunctionSummary &Summary, 140 const ModuleSummaryIndex &Index, unsigned Threshold, 141 const std::map<uint64_t, FunctionSummary *> &DefinedFunctions, 142 SmallVectorImpl<EdgeInfo> &Worklist, 143 FunctionImporter::ImportMapTy &ImportsForModule, 144 StringMap<FunctionImporter::ExportSetTy> &ExportLists) { 145 for (auto &Edge : Summary.calls()) { 146 auto GUID = Edge.first; 147 DEBUG(dbgs() << " edge -> " << GUID << " Threshold:" << Threshold << "\n"); 148 149 if (DefinedFunctions.count(GUID)) { 150 DEBUG(dbgs() << "ignored! Target already in destination module.\n"); 151 continue; 152 } 153 154 auto *CalleeSummary = selectCallee(GUID, Threshold, Index); 155 if (!CalleeSummary) { 156 DEBUG(dbgs() << "ignored! No qualifying callee with summary found.\n"); 157 continue; 158 } 159 assert(CalleeSummary->instCount() <= Threshold && 160 "selectCallee() didn't honor the threshold"); 161 162 auto &ProcessedThreshold = 163 ImportsForModule[CalleeSummary->modulePath()][GUID]; 164 /// Since the traversal of the call graph is DFS, we can revisit a function 165 /// a second time with a higher threshold. In this case, it is added back to 166 /// the worklist with the new threshold. 167 if (ProcessedThreshold && ProcessedThreshold > Threshold) { 168 DEBUG(dbgs() << "ignored! Target was already seen with Threshold " 169 << ProcessedThreshold << "\n"); 170 continue; 171 } 172 // Mark this function as imported in this module, with the current Threshold 173 ProcessedThreshold = Threshold; 174 175 // Make exports in the source module. 176 auto ExportModulePath = CalleeSummary->modulePath(); 177 auto ExportList = ExportLists[ExportModulePath]; 178 ExportList.insert(GUID); 179 // Mark all functions and globals referenced by this function as exported to 180 // the outside if they are defined in the same source module. 181 for (auto &Edge : CalleeSummary->calls()) { 182 auto CalleeGUID = Edge.first; 183 if (isGlobalExported(Index, ExportModulePath, CalleeGUID)) 184 ExportList.insert(CalleeGUID); 185 } 186 for (auto &GUID : CalleeSummary->refs()) { 187 if (isGlobalExported(Index, ExportModulePath, GUID)) 188 ExportList.insert(GUID); 189 } 190 191 // Insert the newly imported function to the worklist. 192 Worklist.push_back(std::make_pair(CalleeSummary, Threshold)); 193 } 194 } 195 196 /// Given the list of globals defined in a module, compute the list of imports 197 /// as well as the list of "exports", i.e. the list of symbols referenced from 198 /// another module (that may require promotion). 199 static void ComputeImportForModule( 200 StringRef ModulePath, 201 const std::map<uint64_t, FunctionSummary *> &DefinedFunctions, 202 const ModuleSummaryIndex &Index, 203 FunctionImporter::ImportMapTy &ImportsForModule, 204 StringMap<FunctionImporter::ExportSetTy> &ExportLists) { 205 // Worklist contains the list of function imported in this module, for which 206 // we will analyse the callees and may import further down the callgraph. 207 SmallVector<EdgeInfo, 128> Worklist; 208 209 // Populate the worklist with the import for the functions in the current 210 // module 211 for (auto &FuncInfo : DefinedFunctions) { 212 auto *Summary = FuncInfo.second; 213 DEBUG(dbgs() << "Initalize import for " << FuncInfo.first << "\n"); 214 computeImportForFunction(ModulePath, *Summary, Index, ImportInstrLimit, 215 DefinedFunctions, Worklist, ImportsForModule, 216 ExportLists); 217 } 218 219 while (!Worklist.empty()) { 220 auto FuncInfo = Worklist.pop_back_val(); 221 auto *Summary = FuncInfo.first; 222 auto Threshold = FuncInfo.second; 223 224 // Process the newly imported functions and add callees to the worklist. 225 // Adjust the threshold 226 Threshold = Threshold * ImportInstrFactor; 227 228 computeImportForFunction(ModulePath, *Summary, Index, Threshold, 229 DefinedFunctions, Worklist, ImportsForModule, 230 ExportLists); 231 } 232 } 233 234 } // anonymous namespace 235 236 /// Compute all the import and export for every module in the Index. 237 void llvm::ComputeCrossModuleImport( 238 const ModuleSummaryIndex &Index, 239 StringMap<FunctionImporter::ImportMapTy> &ImportLists, 240 StringMap<FunctionImporter::ExportSetTy> &ExportLists) { 241 auto ModuleCount = Index.modulePaths().size(); 242 243 // Collect for each module the list of function it defines. 244 // GUID -> Summary 245 StringMap<std::map<uint64_t, FunctionSummary *>> Module2FunctionInfoMap( 246 ModuleCount); 247 248 for (auto &GlobalList : Index) { 249 auto GUID = GlobalList.first; 250 for (auto &GlobInfo : GlobalList.second) { 251 auto *Summary = dyn_cast_or_null<FunctionSummary>(GlobInfo->summary()); 252 if (!Summary) 253 /// Ignore global variable, focus on functions 254 continue; 255 DEBUG(dbgs() << "Adding definition: Module '" << Summary->modulePath() 256 << "' defines '" << GUID << "'\n"); 257 Module2FunctionInfoMap[Summary->modulePath()][GUID] = Summary; 258 } 259 } 260 261 // For each module that has function defined, compute the import/export lists. 262 for (auto &DefinedFunctions : Module2FunctionInfoMap) { 263 auto &ImportsForModule = ImportLists[DefinedFunctions.first()]; 264 DEBUG(dbgs() << "Computing import for Module '" << DefinedFunctions.first() 265 << "'\n"); 266 ComputeImportForModule(DefinedFunctions.first(), DefinedFunctions.second, 267 Index, ImportsForModule, ExportLists); 268 } 269 270 #ifndef NDEBUG 271 DEBUG(dbgs() << "Import/Export lists for " << ImportLists.size() 272 << " modules:\n"); 273 for (auto &ModuleImports : ImportLists) { 274 auto ModName = ModuleImports.first(); 275 auto &Exports = ExportLists[ModName]; 276 DEBUG(dbgs() << "* Module " << ModName << " exports " << Exports.size() 277 << " functions. Imports from " << ModuleImports.second.size() 278 << " modules.\n"); 279 for (auto &Src : ModuleImports.second) { 280 auto SrcModName = Src.first(); 281 DEBUG(dbgs() << " - " << Src.second.size() << " functions imported from " 282 << SrcModName << "\n"); 283 } 284 } 285 #endif 286 } 287 288 // Automatically import functions in Module \p DestModule based on the summaries 289 // index. 290 // 291 bool FunctionImporter::importFunctions( 292 Module &DestModule, const FunctionImporter::ImportMapTy &ImportList) { 293 DEBUG(dbgs() << "Starting import for Module " 294 << DestModule.getModuleIdentifier() << "\n"); 295 unsigned ImportedCount = 0; 296 297 // Linker that will be used for importing function 298 Linker TheLinker(DestModule); 299 // Do the actual import of functions now, one Module at a time 300 std::set<StringRef> ModuleNameOrderedList; 301 for (auto &FunctionsToImportPerModule : ImportList) { 302 ModuleNameOrderedList.insert(FunctionsToImportPerModule.first()); 303 } 304 for (auto &Name : ModuleNameOrderedList) { 305 // Get the module for the import 306 const auto &FunctionsToImportPerModule = ImportList.find(Name); 307 assert(FunctionsToImportPerModule != ImportList.end()); 308 std::unique_ptr<Module> SrcModule = ModuleLoader(Name); 309 assert(&DestModule.getContext() == &SrcModule->getContext() && 310 "Context mismatch"); 311 312 // If modules were created with lazy metadata loading, materialize it 313 // now, before linking it (otherwise this will be a noop). 314 SrcModule->materializeMetadata(); 315 UpgradeDebugInfo(*SrcModule); 316 317 auto &ImportGUIDs = FunctionsToImportPerModule->second; 318 // Find the globals to import 319 DenseSet<const GlobalValue *> GlobalsToImport; 320 for (auto &GV : *SrcModule) { 321 if (GV.hasName() && ImportGUIDs.count(GV.getGUID())) { 322 GV.materialize(); 323 GlobalsToImport.insert(&GV); 324 } 325 } 326 for (auto &GV : SrcModule->aliases()) { 327 if (!GV.hasName()) 328 continue; 329 auto GUID = GV.getGUID(); 330 if (ImportGUIDs.count(GUID)) { 331 // Alias can't point to "available_externally". However when we import 332 // linkOnceODR the linkage does not change. So we import the alias 333 // and aliasee only in this case. 334 const GlobalObject *GO = GV.getBaseObject(); 335 if (!GO->hasLinkOnceODRLinkage()) 336 continue; 337 GV.materialize(); 338 GlobalsToImport.insert(&GV); 339 GlobalsToImport.insert(GO); 340 } 341 } 342 for (auto &GV : SrcModule->globals()) { 343 if (!GV.hasName()) 344 continue; 345 auto GUID = Function::getGUID(Function::getGlobalIdentifier( 346 GV.getName(), GV.getLinkage(), SrcModule->getModuleIdentifier())); 347 if (ImportGUIDs.count(GUID)) { 348 GV.materialize(); 349 GlobalsToImport.insert(&GV); 350 } 351 } 352 353 // Link in the specified functions. 354 if (renameModuleForThinLTO(*SrcModule, Index, &GlobalsToImport)) 355 return true; 356 357 if (PrintImports) { 358 for (const auto *GV : GlobalsToImport) 359 dbgs() << DestModule.getSourceFileName() << ": Import " << GV->getName() 360 << " from " << SrcModule->getSourceFileName() << "\n"; 361 } 362 363 if (TheLinker.linkInModule(std::move(SrcModule), Linker::Flags::None, 364 &GlobalsToImport)) 365 report_fatal_error("Function Import: link error"); 366 367 ImportedCount += GlobalsToImport.size(); 368 } 369 370 NumImported += ImportedCount; 371 372 DEBUG(dbgs() << "Imported " << ImportedCount << " functions for Module " 373 << DestModule.getModuleIdentifier() << "\n"); 374 return ImportedCount; 375 } 376 377 /// Summary file to use for function importing when using -function-import from 378 /// the command line. 379 static cl::opt<std::string> 380 SummaryFile("summary-file", 381 cl::desc("The summary file to use for function importing.")); 382 383 static void diagnosticHandler(const DiagnosticInfo &DI) { 384 raw_ostream &OS = errs(); 385 DiagnosticPrinterRawOStream DP(OS); 386 DI.print(DP); 387 OS << '\n'; 388 } 389 390 /// Parse the summary index out of an IR file and return the summary 391 /// index object if found, or nullptr if not. 392 static std::unique_ptr<ModuleSummaryIndex> 393 getModuleSummaryIndexForFile(StringRef Path, std::string &Error, 394 DiagnosticHandlerFunction DiagnosticHandler) { 395 std::unique_ptr<MemoryBuffer> Buffer; 396 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = 397 MemoryBuffer::getFile(Path); 398 if (std::error_code EC = BufferOrErr.getError()) { 399 Error = EC.message(); 400 return nullptr; 401 } 402 Buffer = std::move(BufferOrErr.get()); 403 ErrorOr<std::unique_ptr<object::ModuleSummaryIndexObjectFile>> ObjOrErr = 404 object::ModuleSummaryIndexObjectFile::create(Buffer->getMemBufferRef(), 405 DiagnosticHandler); 406 if (std::error_code EC = ObjOrErr.getError()) { 407 Error = EC.message(); 408 return nullptr; 409 } 410 return (*ObjOrErr)->takeIndex(); 411 } 412 413 namespace { 414 /// Pass that performs cross-module function import provided a summary file. 415 class FunctionImportPass : public ModulePass { 416 /// Optional module summary index to use for importing, otherwise 417 /// the summary-file option must be specified. 418 const ModuleSummaryIndex *Index; 419 420 public: 421 /// Pass identification, replacement for typeid 422 static char ID; 423 424 /// Specify pass name for debug output 425 const char *getPassName() const override { 426 return "Function Importing"; 427 } 428 429 explicit FunctionImportPass(const ModuleSummaryIndex *Index = nullptr) 430 : ModulePass(ID), Index(Index) {} 431 432 bool runOnModule(Module &M) override { 433 if (SummaryFile.empty() && !Index) 434 report_fatal_error("error: -function-import requires -summary-file or " 435 "file from frontend\n"); 436 std::unique_ptr<ModuleSummaryIndex> IndexPtr; 437 if (!SummaryFile.empty()) { 438 if (Index) 439 report_fatal_error("error: -summary-file and index from frontend\n"); 440 std::string Error; 441 IndexPtr = 442 getModuleSummaryIndexForFile(SummaryFile, Error, diagnosticHandler); 443 if (!IndexPtr) { 444 errs() << "Error loading file '" << SummaryFile << "': " << Error 445 << "\n"; 446 return false; 447 } 448 Index = IndexPtr.get(); 449 } 450 451 // First step is collecting the import/export lists 452 // The export list is not used yet, but could limit the amount of renaming 453 // performed in renameModuleForThinLTO() 454 StringMap<FunctionImporter::ImportMapTy> ImportLists; 455 StringMap<FunctionImporter::ExportSetTy> ExportLists; 456 ComputeCrossModuleImport(*Index, ImportLists, ExportLists); 457 auto &ImportList = ImportLists[M.getModuleIdentifier()]; 458 459 // Next we need to promote to global scope and rename any local values that 460 // are potentially exported to other modules. 461 if (renameModuleForThinLTO(M, *Index, nullptr)) { 462 errs() << "Error renaming module\n"; 463 return false; 464 } 465 466 // Perform the import now. 467 auto ModuleLoader = [&M](StringRef Identifier) { 468 return loadFile(Identifier, M.getContext()); 469 }; 470 FunctionImporter Importer(*Index, ModuleLoader); 471 return Importer.importFunctions(M, ImportList); 472 } 473 }; 474 } // anonymous namespace 475 476 char FunctionImportPass::ID = 0; 477 INITIALIZE_PASS_BEGIN(FunctionImportPass, "function-import", 478 "Summary Based Function Import", false, false) 479 INITIALIZE_PASS_END(FunctionImportPass, "function-import", 480 "Summary Based Function Import", false, false) 481 482 namespace llvm { 483 Pass *createFunctionImportPass(const ModuleSummaryIndex *Index = nullptr) { 484 return new FunctionImportPass(Index); 485 } 486 } 487