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/StringSet.h" 17 #include "llvm/IR/AutoUpgrade.h" 18 #include "llvm/IR/DiagnosticPrinter.h" 19 #include "llvm/IR/IntrinsicInst.h" 20 #include "llvm/IR/Module.h" 21 #include "llvm/IRReader/IRReader.h" 22 #include "llvm/Linker/Linker.h" 23 #include "llvm/Object/FunctionIndexObjectFile.h" 24 #include "llvm/Support/CommandLine.h" 25 #include "llvm/Support/Debug.h" 26 #include "llvm/Support/SourceMgr.h" 27 using namespace llvm; 28 29 #define DEBUG_TYPE "function-import" 30 31 /// Limit on instruction count of imported functions. 32 static cl::opt<unsigned> ImportInstrLimit( 33 "import-instr-limit", cl::init(100), cl::Hidden, cl::value_desc("N"), 34 cl::desc("Only import functions with less than N instructions")); 35 36 // Load lazily a module from \p FileName in \p Context. 37 static std::unique_ptr<Module> loadFile(const std::string &FileName, 38 LLVMContext &Context) { 39 SMDiagnostic Err; 40 DEBUG(dbgs() << "Loading '" << FileName << "'\n"); 41 std::unique_ptr<Module> Result = getLazyIRFileModule(FileName, Err, Context); 42 if (!Result) { 43 Err.print("function-import", errs()); 44 return nullptr; 45 } 46 47 Result->materializeMetadata(); 48 UpgradeDebugInfo(*Result); 49 50 return Result; 51 } 52 53 /// Walk through the instructions in \p F looking for external 54 /// calls not already in the \p CalledFunctions set. If any are 55 /// found they are added to the \p Worklist for importing. 56 static void findExternalCalls(const Function &F, StringSet<> &CalledFunctions, 57 SmallVector<StringRef, 64> &Worklist) { 58 for (auto &BB : F) { 59 for (auto &I : BB) { 60 if (isa<CallInst>(I)) { 61 auto CalledFunction = cast<CallInst>(I).getCalledFunction(); 62 // Insert any new external calls that have not already been 63 // added to set/worklist. 64 if (CalledFunction && CalledFunction->hasName() && 65 CalledFunction->isDeclaration() && 66 !CalledFunctions.count(CalledFunction->getName())) { 67 CalledFunctions.insert(CalledFunction->getName()); 68 Worklist.push_back(CalledFunction->getName()); 69 } 70 } 71 } 72 } 73 } 74 75 // Helper function: given a worklist and an index, will process all the worklist 76 // and import them based on the summary information 77 static unsigned ProcessImportWorklist( 78 Module &DestModule, SmallVector<StringRef, 64> &Worklist, 79 StringSet<> &CalledFunctions, Linker &TheLinker, 80 const FunctionInfoIndex &Index, 81 std::function<std::unique_ptr<Module>(StringRef FileName)> & 82 LazyModuleLoader) { 83 unsigned ImportCount = 0; 84 while (!Worklist.empty()) { 85 auto CalledFunctionName = Worklist.pop_back_val(); 86 DEBUG(dbgs() << DestModule.getModuleIdentifier() << "Process import for " 87 << CalledFunctionName << "\n"); 88 89 // Try to get a summary for this function call. 90 auto InfoList = Index.findFunctionInfoList(CalledFunctionName); 91 if (InfoList == Index.end()) { 92 DEBUG(dbgs() << DestModule.getModuleIdentifier() << "No summary for " 93 << CalledFunctionName << " Ignoring.\n"); 94 continue; 95 } 96 assert(!InfoList->second.empty() && "No summary, error at import?"); 97 98 // Comdat can have multiple entries, FIXME: what do we do with them? 99 auto &Info = InfoList->second[0]; 100 assert(Info && "Nullptr in list, error importing summaries?\n"); 101 102 auto *Summary = Info->functionSummary(); 103 if (!Summary) { 104 // FIXME: in case we are lazyloading summaries, we can do it now. 105 DEBUG(dbgs() << DestModule.getModuleIdentifier() 106 << " Missing summary for " << CalledFunctionName 107 << ", error at import?\n"); 108 llvm_unreachable("Missing summary"); 109 } 110 111 if (Summary->instCount() > ImportInstrLimit) { 112 DEBUG(dbgs() << DestModule.getModuleIdentifier() << " Skip import of " 113 << CalledFunctionName << " with " << Summary->instCount() 114 << " instructions (limit " << ImportInstrLimit << ")\n"); 115 continue; 116 } 117 118 // Get the module path from the summary. 119 auto FileName = Summary->modulePath(); 120 DEBUG(dbgs() << "Importing " << CalledFunctionName << " from " << FileName 121 << "\n"); 122 123 // Get the module for the import 124 auto SrcModule = LazyModuleLoader(FileName); 125 assert(&SrcModule->getContext() == &DestModule.getContext()); 126 127 // The function that we will import! 128 GlobalValue *SGV = SrcModule->getNamedValue(CalledFunctionName); 129 StringRef ImportFunctionName = CalledFunctionName; 130 if (!SGV) { 131 // Might be local in source Module, promoted/renamed in DestModule. 132 std::pair<StringRef, StringRef> Split = 133 CalledFunctionName.split(".llvm."); 134 SGV = SrcModule->getNamedValue(Split.first); 135 #ifndef NDEBUG 136 // Assert that Split.second is module id 137 uint64_t ModuleId; 138 assert(!Split.second.getAsInteger(10, ModuleId)); 139 assert(ModuleId == Index.getModuleId(FileName)); 140 #endif 141 } 142 Function *F = dyn_cast<Function>(SGV); 143 if (!F && isa<GlobalAlias>(SGV)) { 144 auto *SGA = dyn_cast<GlobalAlias>(SGV); 145 F = dyn_cast<Function>(SGA->getBaseObject()); 146 ImportFunctionName = F->getName(); 147 } 148 if (!F) { 149 errs() << "Can't load function '" << CalledFunctionName << "' in Module '" 150 << FileName << "', error in the summary?\n"; 151 llvm_unreachable("Can't load function in Module"); 152 } 153 154 // We cannot import weak_any functions/aliases without possibly affecting 155 // the order they are seen and selected by the linker, changing program 156 // semantics. 157 if (SGV->hasWeakAnyLinkage()) { 158 DEBUG(dbgs() << DestModule.getModuleIdentifier() 159 << " Ignoring import request for weak-any " 160 << (isa<Function>(SGV) ? "function " : "alias ") 161 << CalledFunctionName << " from " << FileName << "\n"); 162 continue; 163 } 164 165 // Link in the specified function. 166 DenseSet<const GlobalValue *> FunctionsToImport; 167 FunctionsToImport.insert(F); 168 if (TheLinker.linkInModule(*SrcModule, Linker::Flags::None, &Index, 169 &FunctionsToImport)) 170 report_fatal_error("Function Import: link error"); 171 172 // Process the newly imported function and add callees to the worklist. 173 GlobalValue *NewGV = DestModule.getNamedValue(ImportFunctionName); 174 assert(NewGV); 175 Function *NewF = dyn_cast<Function>(NewGV); 176 assert(NewF); 177 findExternalCalls(*NewF, CalledFunctions, Worklist); 178 ++ImportCount; 179 } 180 return ImportCount; 181 } 182 183 // Automatically import functions in Module \p DestModule based on the summaries 184 // index. 185 // 186 // The current implementation imports every called functions that exists in the 187 // summaries index. 188 bool FunctionImporter::importFunctions(Module &DestModule) { 189 DEBUG(dbgs() << "Starting import for Module " 190 << DestModule.getModuleIdentifier() << "\n"); 191 unsigned ImportedCount = 0; 192 193 /// First step is collecting the called external functions. 194 StringSet<> CalledFunctions; 195 SmallVector<StringRef, 64> Worklist; 196 for (auto &F : DestModule) { 197 if (F.isDeclaration() || F.hasFnAttribute(Attribute::OptimizeNone)) 198 continue; 199 findExternalCalls(F, CalledFunctions, Worklist); 200 } 201 if (Worklist.empty()) 202 return false; 203 204 /// Second step: for every call to an external function, try to import it. 205 206 // Linker that will be used for importing function 207 Linker TheLinker(DestModule, DiagnosticHandler); 208 209 ImportedCount += ProcessImportWorklist(DestModule, Worklist, CalledFunctions, 210 TheLinker, Index, ModuleLoader); 211 212 DEBUG(errs() << "Imported " << ImportedCount << " functions for Module " 213 << DestModule.getModuleIdentifier() << "\n"); 214 return ImportedCount; 215 } 216 217 /// Summary file to use for function importing when using -function-import from 218 /// the command line. 219 static cl::opt<std::string> 220 SummaryFile("summary-file", 221 cl::desc("The summary file to use for function importing.")); 222 223 static void diagnosticHandler(const DiagnosticInfo &DI) { 224 raw_ostream &OS = errs(); 225 DiagnosticPrinterRawOStream DP(OS); 226 DI.print(DP); 227 OS << '\n'; 228 } 229 230 /// Parse the function index out of an IR file and return the function 231 /// index object if found, or nullptr if not. 232 static std::unique_ptr<FunctionInfoIndex> 233 getFunctionIndexForFile(StringRef Path, std::string &Error, 234 DiagnosticHandlerFunction DiagnosticHandler) { 235 std::unique_ptr<MemoryBuffer> Buffer; 236 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = 237 MemoryBuffer::getFile(Path); 238 if (std::error_code EC = BufferOrErr.getError()) { 239 Error = EC.message(); 240 return nullptr; 241 } 242 Buffer = std::move(BufferOrErr.get()); 243 ErrorOr<std::unique_ptr<object::FunctionIndexObjectFile>> ObjOrErr = 244 object::FunctionIndexObjectFile::create(Buffer->getMemBufferRef(), 245 DiagnosticHandler); 246 if (std::error_code EC = ObjOrErr.getError()) { 247 Error = EC.message(); 248 return nullptr; 249 } 250 return (*ObjOrErr)->takeIndex(); 251 } 252 253 /// Pass that performs cross-module function import provided a summary file. 254 class FunctionImportPass : public ModulePass { 255 /// Optional function summary index to use for importing, otherwise 256 /// the summary-file option must be specified. 257 FunctionInfoIndex *Index; 258 259 public: 260 /// Pass identification, replacement for typeid 261 static char ID; 262 263 /// Specify pass name for debug output 264 const char *getPassName() const override { 265 return "Function Importing"; 266 } 267 268 explicit FunctionImportPass(FunctionInfoIndex *Index = nullptr) 269 : ModulePass(ID), Index(Index) {} 270 271 bool runOnModule(Module &M) override { 272 if (SummaryFile.empty() && !Index) 273 report_fatal_error("error: -function-import requires -summary-file or " 274 "file from frontend\n"); 275 std::unique_ptr<FunctionInfoIndex> IndexPtr; 276 if (!SummaryFile.empty()) { 277 if (Index) 278 report_fatal_error("error: -summary-file and index from frontend\n"); 279 std::string Error; 280 IndexPtr = getFunctionIndexForFile(SummaryFile, Error, diagnosticHandler); 281 if (!IndexPtr) { 282 errs() << "Error loading file '" << SummaryFile << "': " << Error 283 << "\n"; 284 return false; 285 } 286 Index = IndexPtr.get(); 287 } 288 289 // Perform the import now. 290 auto ModuleLoader = [&M](StringRef Identifier) { 291 return loadFile(Identifier, M.getContext()); 292 }; 293 FunctionImporter Importer(*Index, diagnosticHandler, ModuleLoader); 294 return Importer.importFunctions(M); 295 296 return false; 297 } 298 }; 299 300 char FunctionImportPass::ID = 0; 301 INITIALIZE_PASS_BEGIN(FunctionImportPass, "function-import", 302 "Summary Based Function Import", false, false) 303 INITIALIZE_PASS_END(FunctionImportPass, "function-import", 304 "Summary Based Function Import", false, false) 305 306 namespace llvm { 307 Pass *createFunctionImportPass(FunctionInfoIndex *Index = nullptr) { 308 return new FunctionImportPass(Index); 309 } 310 } 311