LLVM API Documentation
00001 //===- CGSCCPassManager.h - Call graph pass management ----------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 /// \file 00010 /// 00011 /// This header provides classes for managing passes over SCCs of the call 00012 /// graph. These passes form an important component of LLVM's interprocedural 00013 /// optimizations. Because they operate on the SCCs of the call graph, and they 00014 /// wtraverse the graph in post order, they can effectively do pair-wise 00015 /// interprocedural optimizations for all call edges in the program. At each 00016 /// call site edge, the callee has already been optimized as much as is 00017 /// possible. This in turn allows very accurate analysis of it for IPO. 00018 /// 00019 //===----------------------------------------------------------------------===// 00020 00021 #ifndef LLVM_ANALYSIS_CGSCCPASSMANAGER_H 00022 #define LLVM_ANALYSIS_CGSCCPASSMANAGER_H 00023 00024 #include "llvm/IR/PassManager.h" 00025 #include "llvm/Analysis/LazyCallGraph.h" 00026 00027 namespace llvm { 00028 00029 class CGSCCAnalysisManager; 00030 00031 class CGSCCPassManager { 00032 public: 00033 // We have to explicitly define all the special member functions because MSVC 00034 // refuses to generate them. 00035 CGSCCPassManager() {} 00036 CGSCCPassManager(CGSCCPassManager &&Arg) : Passes(std::move(Arg.Passes)) {} 00037 CGSCCPassManager &operator=(CGSCCPassManager &&RHS) { 00038 Passes = std::move(RHS.Passes); 00039 return *this; 00040 } 00041 00042 /// \brief Run all of the CGSCC passes in this pass manager over a SCC. 00043 PreservedAnalyses run(LazyCallGraph::SCC *C, 00044 CGSCCAnalysisManager *AM = nullptr); 00045 00046 template <typename CGSCCPassT> void addPass(CGSCCPassT Pass) { 00047 Passes.emplace_back(new CGSCCPassModel<CGSCCPassT>(std::move(Pass))); 00048 } 00049 00050 static StringRef name() { return "CGSCCPassManager"; } 00051 00052 private: 00053 // Pull in the concept type and model template specialized for SCCs. 00054 typedef detail::PassConcept<LazyCallGraph::SCC *, CGSCCAnalysisManager> 00055 CGSCCPassConcept; 00056 template <typename PassT> 00057 struct CGSCCPassModel 00058 : detail::PassModel<LazyCallGraph::SCC *, CGSCCAnalysisManager, PassT> { 00059 CGSCCPassModel(PassT Pass) 00060 : detail::PassModel<LazyCallGraph::SCC *, CGSCCAnalysisManager, PassT>( 00061 std::move(Pass)) {} 00062 }; 00063 00064 CGSCCPassManager(const CGSCCPassManager &) LLVM_DELETED_FUNCTION; 00065 CGSCCPassManager &operator=(const CGSCCPassManager &) LLVM_DELETED_FUNCTION; 00066 00067 std::vector<std::unique_ptr<CGSCCPassConcept>> Passes; 00068 }; 00069 00070 /// \brief A function analysis manager to coordinate and cache analyses run over 00071 /// a module. 00072 class CGSCCAnalysisManager : public detail::AnalysisManagerBase< 00073 CGSCCAnalysisManager, LazyCallGraph::SCC *> { 00074 friend class detail::AnalysisManagerBase<CGSCCAnalysisManager, 00075 LazyCallGraph::SCC *>; 00076 typedef detail::AnalysisManagerBase<CGSCCAnalysisManager, 00077 LazyCallGraph::SCC *> BaseT; 00078 typedef BaseT::ResultConceptT ResultConceptT; 00079 typedef BaseT::PassConceptT PassConceptT; 00080 00081 public: 00082 // Most public APIs are inherited from the CRTP base class. 00083 00084 // We have to explicitly define all the special member functions because MSVC 00085 // refuses to generate them. 00086 CGSCCAnalysisManager() {} 00087 CGSCCAnalysisManager(CGSCCAnalysisManager &&Arg) 00088 : BaseT(std::move(static_cast<BaseT &>(Arg))), 00089 CGSCCAnalysisResults(std::move(Arg.CGSCCAnalysisResults)) {} 00090 CGSCCAnalysisManager &operator=(CGSCCAnalysisManager &&RHS) { 00091 BaseT::operator=(std::move(static_cast<BaseT &>(RHS))); 00092 CGSCCAnalysisResults = std::move(RHS.CGSCCAnalysisResults); 00093 return *this; 00094 } 00095 00096 /// \brief Returns true if the analysis manager has an empty results cache. 00097 bool empty() const; 00098 00099 /// \brief Clear the function analysis result cache. 00100 /// 00101 /// This routine allows cleaning up when the set of functions itself has 00102 /// potentially changed, and thus we can't even look up a a result and 00103 /// invalidate it directly. Notably, this does *not* call invalidate 00104 /// functions as there is nothing to be done for them. 00105 void clear(); 00106 00107 private: 00108 CGSCCAnalysisManager(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION; 00109 CGSCCAnalysisManager & 00110 operator=(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION; 00111 00112 /// \brief Get a function pass result, running the pass if necessary. 00113 ResultConceptT &getResultImpl(void *PassID, LazyCallGraph::SCC *C); 00114 00115 /// \brief Get a cached function pass result or return null. 00116 ResultConceptT *getCachedResultImpl(void *PassID, 00117 LazyCallGraph::SCC *C) const; 00118 00119 /// \brief Invalidate a function pass result. 00120 void invalidateImpl(void *PassID, LazyCallGraph::SCC *C); 00121 00122 /// \brief Invalidate the results for a function.. 00123 void invalidateImpl(LazyCallGraph::SCC *C, const PreservedAnalyses &PA); 00124 00125 /// \brief List of function analysis pass IDs and associated concept pointers. 00126 /// 00127 /// Requires iterators to be valid across appending new entries and arbitrary 00128 /// erases. Provides both the pass ID and concept pointer such that it is 00129 /// half of a bijection and provides storage for the actual result concept. 00130 typedef std::list< 00131 std::pair<void *, std::unique_ptr<detail::AnalysisResultConcept< 00132 LazyCallGraph::SCC *>>>> CGSCCAnalysisResultListT; 00133 00134 /// \brief Map type from function pointer to our custom list type. 00135 typedef DenseMap<LazyCallGraph::SCC *, CGSCCAnalysisResultListT> 00136 CGSCCAnalysisResultListMapT; 00137 00138 /// \brief Map from function to a list of function analysis results. 00139 /// 00140 /// Provides linear time removal of all analysis results for a function and 00141 /// the ultimate storage for a particular cached analysis result. 00142 CGSCCAnalysisResultListMapT CGSCCAnalysisResultLists; 00143 00144 /// \brief Map type from a pair of analysis ID and function pointer to an 00145 /// iterator into a particular result list. 00146 typedef DenseMap<std::pair<void *, LazyCallGraph::SCC *>, 00147 CGSCCAnalysisResultListT::iterator> CGSCCAnalysisResultMapT; 00148 00149 /// \brief Map from an analysis ID and function to a particular cached 00150 /// analysis result. 00151 CGSCCAnalysisResultMapT CGSCCAnalysisResults; 00152 }; 00153 00154 /// \brief A module analysis which acts as a proxy for a CGSCC analysis 00155 /// manager. 00156 /// 00157 /// This primarily proxies invalidation information from the module analysis 00158 /// manager and module pass manager to a CGSCC analysis manager. You should 00159 /// never use a CGSCC analysis manager from within (transitively) a module 00160 /// pass manager unless your parent module pass has received a proxy result 00161 /// object for it. 00162 class CGSCCAnalysisManagerModuleProxy { 00163 public: 00164 class Result { 00165 public: 00166 explicit Result(CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} 00167 // We have to explicitly define all the special member functions because 00168 // MSVC refuses to generate them. 00169 Result(const Result &Arg) : CGAM(Arg.CGAM) {} 00170 Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {} 00171 Result &operator=(Result RHS) { 00172 std::swap(CGAM, RHS.CGAM); 00173 return *this; 00174 } 00175 ~Result(); 00176 00177 /// \brief Accessor for the \c CGSCCAnalysisManager. 00178 CGSCCAnalysisManager &getManager() { return *CGAM; } 00179 00180 /// \brief Handler for invalidation of the module. 00181 /// 00182 /// If this analysis itself is preserved, then we assume that the call 00183 /// graph of the module hasn't changed and thus we don't need to invalidate 00184 /// *all* cached data associated with a \c SCC* in the \c 00185 /// CGSCCAnalysisManager. 00186 /// 00187 /// Regardless of whether this analysis is marked as preserved, all of the 00188 /// analyses in the \c CGSCCAnalysisManager are potentially invalidated 00189 /// based on the set of preserved analyses. 00190 bool invalidate(Module *M, const PreservedAnalyses &PA); 00191 00192 private: 00193 CGSCCAnalysisManager *CGAM; 00194 }; 00195 00196 static void *ID() { return (void *)&PassID; } 00197 00198 explicit CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManager &CGAM) 00199 : CGAM(&CGAM) {} 00200 // We have to explicitly define all the special member functions because MSVC 00201 // refuses to generate them. 00202 CGSCCAnalysisManagerModuleProxy( 00203 const CGSCCAnalysisManagerModuleProxy &Arg) 00204 : CGAM(Arg.CGAM) {} 00205 CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManagerModuleProxy &&Arg) 00206 : CGAM(std::move(Arg.CGAM)) {} 00207 CGSCCAnalysisManagerModuleProxy & 00208 operator=(CGSCCAnalysisManagerModuleProxy RHS) { 00209 std::swap(CGAM, RHS.CGAM); 00210 return *this; 00211 } 00212 00213 /// \brief Run the analysis pass and create our proxy result object. 00214 /// 00215 /// This doesn't do any interesting work, it is primarily used to insert our 00216 /// proxy result object into the module analysis cache so that we can proxy 00217 /// invalidation to the CGSCC analysis manager. 00218 /// 00219 /// In debug builds, it will also assert that the analysis manager is empty 00220 /// as no queries should arrive at the CGSCC analysis manager prior to 00221 /// this analysis being requested. 00222 Result run(Module *M); 00223 00224 private: 00225 static char PassID; 00226 00227 CGSCCAnalysisManager *CGAM; 00228 }; 00229 00230 /// \brief A CGSCC analysis which acts as a proxy for a module analysis 00231 /// manager. 00232 /// 00233 /// This primarily provides an accessor to a parent module analysis manager to 00234 /// CGSCC passes. Only the const interface of the module analysis manager is 00235 /// provided to indicate that once inside of a CGSCC analysis pass you 00236 /// cannot request a module analysis to actually run. Instead, the user must 00237 /// rely on the \c getCachedResult API. 00238 /// 00239 /// This proxy *doesn't* manage the invalidation in any way. That is handled by 00240 /// the recursive return path of each layer of the pass manager and the 00241 /// returned PreservedAnalysis set. 00242 class ModuleAnalysisManagerCGSCCProxy { 00243 public: 00244 /// \brief Result proxy object for \c ModuleAnalysisManagerCGSCCProxy. 00245 class Result { 00246 public: 00247 explicit Result(const ModuleAnalysisManager &MAM) : MAM(&MAM) {} 00248 // We have to explicitly define all the special member functions because 00249 // MSVC refuses to generate them. 00250 Result(const Result &Arg) : MAM(Arg.MAM) {} 00251 Result(Result &&Arg) : MAM(std::move(Arg.MAM)) {} 00252 Result &operator=(Result RHS) { 00253 std::swap(MAM, RHS.MAM); 00254 return *this; 00255 } 00256 00257 const ModuleAnalysisManager &getManager() const { return *MAM; } 00258 00259 /// \brief Handle invalidation by ignoring it, this pass is immutable. 00260 bool invalidate(LazyCallGraph::SCC *) { return false; } 00261 00262 private: 00263 const ModuleAnalysisManager *MAM; 00264 }; 00265 00266 static void *ID() { return (void *)&PassID; } 00267 00268 ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManager &MAM) 00269 : MAM(&MAM) {} 00270 // We have to explicitly define all the special member functions because MSVC 00271 // refuses to generate them. 00272 ModuleAnalysisManagerCGSCCProxy( 00273 const ModuleAnalysisManagerCGSCCProxy &Arg) 00274 : MAM(Arg.MAM) {} 00275 ModuleAnalysisManagerCGSCCProxy(ModuleAnalysisManagerCGSCCProxy &&Arg) 00276 : MAM(std::move(Arg.MAM)) {} 00277 ModuleAnalysisManagerCGSCCProxy & 00278 operator=(ModuleAnalysisManagerCGSCCProxy RHS) { 00279 std::swap(MAM, RHS.MAM); 00280 return *this; 00281 } 00282 00283 /// \brief Run the analysis pass and create our proxy result object. 00284 /// Nothing to see here, it just forwards the \c MAM reference into the 00285 /// result. 00286 Result run(LazyCallGraph::SCC *) { return Result(*MAM); } 00287 00288 private: 00289 static char PassID; 00290 00291 const ModuleAnalysisManager *MAM; 00292 }; 00293 00294 /// \brief The core module pass which does a post-order walk of the SCCs and 00295 /// runs a CGSCC pass over each one. 00296 /// 00297 /// Designed to allow composition of a CGSCCPass(Manager) and 00298 /// a ModulePassManager. Note that this pass must be run with a module analysis 00299 /// manager as it uses the LazyCallGraph analysis. It will also run the 00300 /// \c CGSCCAnalysisManagerModuleProxy analysis prior to running the CGSCC 00301 /// pass over the module to enable a \c FunctionAnalysisManager to be used 00302 /// within this run safely. 00303 template <typename CGSCCPassT> class ModuleToPostOrderCGSCCPassAdaptor { 00304 public: 00305 explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) 00306 : Pass(std::move(Pass)) {} 00307 // We have to explicitly define all the special member functions because MSVC 00308 // refuses to generate them. 00309 ModuleToPostOrderCGSCCPassAdaptor( 00310 const ModuleToPostOrderCGSCCPassAdaptor &Arg) 00311 : Pass(Arg.Pass) {} 00312 ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg) 00313 : Pass(std::move(Arg.Pass)) {} 00314 friend void swap(ModuleToPostOrderCGSCCPassAdaptor &LHS, 00315 ModuleToPostOrderCGSCCPassAdaptor &RHS) { 00316 using std::swap; 00317 swap(LHS.Pass, RHS.Pass); 00318 } 00319 ModuleToPostOrderCGSCCPassAdaptor & 00320 operator=(ModuleToPostOrderCGSCCPassAdaptor RHS) { 00321 swap(*this, RHS); 00322 return *this; 00323 } 00324 00325 /// \brief Runs the CGSCC pass across every SCC in the module. 00326 PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { 00327 assert(AM && "We need analyses to compute the call graph!"); 00328 00329 // Setup the CGSCC analysis manager from its proxy. 00330 CGSCCAnalysisManager &CGAM = 00331 AM->getResult<CGSCCAnalysisManagerModuleProxy>(M).getManager(); 00332 00333 // Get the call graph for this module. 00334 LazyCallGraph &CG = AM->getResult<LazyCallGraphAnalysis>(M); 00335 00336 PreservedAnalyses PA = PreservedAnalyses::all(); 00337 for (LazyCallGraph::SCC &C : CG.postorder_sccs()) { 00338 PreservedAnalyses PassPA = Pass.run(&C, &CGAM); 00339 00340 // We know that the CGSCC pass couldn't have invalidated any other 00341 // SCC's analyses (that's the contract of a CGSCC pass), so 00342 // directly handle the CGSCC analysis manager's invalidation here. 00343 // FIXME: This isn't quite correct. We need to handle the case where the 00344 // pass updated the CG, particularly some child of the current SCC, and 00345 // invalidate its analyses. 00346 CGAM.invalidate(&C, PassPA); 00347 00348 // Then intersect the preserved set so that invalidation of module 00349 // analyses will eventually occur when the module pass completes. 00350 PA.intersect(std::move(PassPA)); 00351 } 00352 00353 // By definition we preserve the proxy. This precludes *any* invalidation 00354 // of CGSCC analyses by the proxy, but that's OK because we've taken 00355 // care to invalidate analyses in the CGSCC analysis manager 00356 // incrementally above. 00357 PA.preserve<CGSCCAnalysisManagerModuleProxy>(); 00358 return PA; 00359 } 00360 00361 static StringRef name() { return "ModuleToPostOrderCGSCCPassAdaptor"; } 00362 00363 private: 00364 CGSCCPassT Pass; 00365 }; 00366 00367 /// \brief A function to deduce a function pass type and wrap it in the 00368 /// templated adaptor. 00369 template <typename CGSCCPassT> 00370 ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT> 00371 createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) { 00372 return std::move( 00373 ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass))); 00374 } 00375 00376 /// \brief A CGSCC analysis which acts as a proxy for a function analysis 00377 /// manager. 00378 /// 00379 /// This primarily proxies invalidation information from the CGSCC analysis 00380 /// manager and CGSCC pass manager to a function analysis manager. You should 00381 /// never use a function analysis manager from within (transitively) a CGSCC 00382 /// pass manager unless your parent CGSCC pass has received a proxy result 00383 /// object for it. 00384 class FunctionAnalysisManagerCGSCCProxy { 00385 public: 00386 class Result { 00387 public: 00388 explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {} 00389 // We have to explicitly define all the special member functions because 00390 // MSVC refuses to generate them. 00391 Result(const Result &Arg) : FAM(Arg.FAM) {} 00392 Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {} 00393 Result &operator=(Result RHS) { 00394 std::swap(FAM, RHS.FAM); 00395 return *this; 00396 } 00397 ~Result(); 00398 00399 /// \brief Accessor for the \c FunctionAnalysisManager. 00400 FunctionAnalysisManager &getManager() { return *FAM; } 00401 00402 /// \brief Handler for invalidation of the SCC. 00403 /// 00404 /// If this analysis itself is preserved, then we assume that the set of \c 00405 /// Function objects in the \c SCC hasn't changed and thus we don't need 00406 /// to invalidate *all* cached data associated with a \c Function* in the \c 00407 /// FunctionAnalysisManager. 00408 /// 00409 /// Regardless of whether this analysis is marked as preserved, all of the 00410 /// analyses in the \c FunctionAnalysisManager are potentially invalidated 00411 /// based on the set of preserved analyses. 00412 bool invalidate(LazyCallGraph::SCC *C, const PreservedAnalyses &PA); 00413 00414 private: 00415 FunctionAnalysisManager *FAM; 00416 }; 00417 00418 static void *ID() { return (void *)&PassID; } 00419 00420 explicit FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager &FAM) 00421 : FAM(&FAM) {} 00422 // We have to explicitly define all the special member functions because MSVC 00423 // refuses to generate them. 00424 FunctionAnalysisManagerCGSCCProxy( 00425 const FunctionAnalysisManagerCGSCCProxy &Arg) 00426 : FAM(Arg.FAM) {} 00427 FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManagerCGSCCProxy &&Arg) 00428 : FAM(std::move(Arg.FAM)) {} 00429 FunctionAnalysisManagerCGSCCProxy & 00430 operator=(FunctionAnalysisManagerCGSCCProxy RHS) { 00431 std::swap(FAM, RHS.FAM); 00432 return *this; 00433 } 00434 00435 /// \brief Run the analysis pass and create our proxy result object. 00436 /// 00437 /// This doesn't do any interesting work, it is primarily used to insert our 00438 /// proxy result object into the module analysis cache so that we can proxy 00439 /// invalidation to the function analysis manager. 00440 /// 00441 /// In debug builds, it will also assert that the analysis manager is empty 00442 /// as no queries should arrive at the function analysis manager prior to 00443 /// this analysis being requested. 00444 Result run(LazyCallGraph::SCC *C); 00445 00446 private: 00447 static char PassID; 00448 00449 FunctionAnalysisManager *FAM; 00450 }; 00451 00452 /// \brief A function analysis which acts as a proxy for a CGSCC analysis 00453 /// manager. 00454 /// 00455 /// This primarily provides an accessor to a parent CGSCC analysis manager to 00456 /// function passes. Only the const interface of the CGSCC analysis manager is 00457 /// provided to indicate that once inside of a function analysis pass you 00458 /// cannot request a CGSCC analysis to actually run. Instead, the user must 00459 /// rely on the \c getCachedResult API. 00460 /// 00461 /// This proxy *doesn't* manage the invalidation in any way. That is handled by 00462 /// the recursive return path of each layer of the pass manager and the 00463 /// returned PreservedAnalysis set. 00464 class CGSCCAnalysisManagerFunctionProxy { 00465 public: 00466 /// \brief Result proxy object for \c ModuleAnalysisManagerFunctionProxy. 00467 class Result { 00468 public: 00469 explicit Result(const CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} 00470 // We have to explicitly define all the special member functions because 00471 // MSVC refuses to generate them. 00472 Result(const Result &Arg) : CGAM(Arg.CGAM) {} 00473 Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {} 00474 Result &operator=(Result RHS) { 00475 std::swap(CGAM, RHS.CGAM); 00476 return *this; 00477 } 00478 00479 const CGSCCAnalysisManager &getManager() const { return *CGAM; } 00480 00481 /// \brief Handle invalidation by ignoring it, this pass is immutable. 00482 bool invalidate(Function *) { return false; } 00483 00484 private: 00485 const CGSCCAnalysisManager *CGAM; 00486 }; 00487 00488 static void *ID() { return (void *)&PassID; } 00489 00490 CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager &CGAM) 00491 : CGAM(&CGAM) {} 00492 // We have to explicitly define all the special member functions because MSVC 00493 // refuses to generate them. 00494 CGSCCAnalysisManagerFunctionProxy( 00495 const CGSCCAnalysisManagerFunctionProxy &Arg) 00496 : CGAM(Arg.CGAM) {} 00497 CGSCCAnalysisManagerFunctionProxy(CGSCCAnalysisManagerFunctionProxy &&Arg) 00498 : CGAM(std::move(Arg.CGAM)) {} 00499 CGSCCAnalysisManagerFunctionProxy & 00500 operator=(CGSCCAnalysisManagerFunctionProxy RHS) { 00501 std::swap(CGAM, RHS.CGAM); 00502 return *this; 00503 } 00504 00505 /// \brief Run the analysis pass and create our proxy result object. 00506 /// Nothing to see here, it just forwards the \c CGAM reference into the 00507 /// result. 00508 Result run(Function *) { return Result(*CGAM); } 00509 00510 private: 00511 static char PassID; 00512 00513 const CGSCCAnalysisManager *CGAM; 00514 }; 00515 00516 /// \brief Adaptor that maps from a SCC to its functions. 00517 /// 00518 /// Designed to allow composition of a FunctionPass(Manager) and 00519 /// a CGSCCPassManager. Note that if this pass is constructed with a pointer 00520 /// to a \c CGSCCAnalysisManager it will run the 00521 /// \c FunctionAnalysisManagerCGSCCProxy analysis prior to running the function 00522 /// pass over the SCC to enable a \c FunctionAnalysisManager to be used 00523 /// within this run safely. 00524 template <typename FunctionPassT> class CGSCCToFunctionPassAdaptor { 00525 public: 00526 explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass) 00527 : Pass(std::move(Pass)) {} 00528 // We have to explicitly define all the special member functions because MSVC 00529 // refuses to generate them. 00530 CGSCCToFunctionPassAdaptor(const CGSCCToFunctionPassAdaptor &Arg) 00531 : Pass(Arg.Pass) {} 00532 CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg) 00533 : Pass(std::move(Arg.Pass)) {} 00534 friend void swap(CGSCCToFunctionPassAdaptor &LHS, CGSCCToFunctionPassAdaptor &RHS) { 00535 using std::swap; 00536 swap(LHS.Pass, RHS.Pass); 00537 } 00538 CGSCCToFunctionPassAdaptor &operator=(CGSCCToFunctionPassAdaptor RHS) { 00539 swap(*this, RHS); 00540 return *this; 00541 } 00542 00543 /// \brief Runs the function pass across every function in the module. 00544 PreservedAnalyses run(LazyCallGraph::SCC *C, CGSCCAnalysisManager *AM) { 00545 FunctionAnalysisManager *FAM = nullptr; 00546 if (AM) 00547 // Setup the function analysis manager from its proxy. 00548 FAM = &AM->getResult<FunctionAnalysisManagerCGSCCProxy>(C).getManager(); 00549 00550 PreservedAnalyses PA = PreservedAnalyses::all(); 00551 for (LazyCallGraph::Node *N : *C) { 00552 PreservedAnalyses PassPA = Pass.run(&N->getFunction(), FAM); 00553 00554 // We know that the function pass couldn't have invalidated any other 00555 // function's analyses (that's the contract of a function pass), so 00556 // directly handle the function analysis manager's invalidation here. 00557 if (FAM) 00558 FAM->invalidate(&N->getFunction(), PassPA); 00559 00560 // Then intersect the preserved set so that invalidation of module 00561 // analyses will eventually occur when the module pass completes. 00562 PA.intersect(std::move(PassPA)); 00563 } 00564 00565 // By definition we preserve the proxy. This precludes *any* invalidation 00566 // of function analyses by the proxy, but that's OK because we've taken 00567 // care to invalidate analyses in the function analysis manager 00568 // incrementally above. 00569 // FIXME: We need to update the call graph here to account for any deleted 00570 // edges! 00571 PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 00572 return PA; 00573 } 00574 00575 static StringRef name() { return "CGSCCToFunctionPassAdaptor"; } 00576 00577 private: 00578 FunctionPassT Pass; 00579 }; 00580 00581 /// \brief A function to deduce a function pass type and wrap it in the 00582 /// templated adaptor. 00583 template <typename FunctionPassT> 00584 CGSCCToFunctionPassAdaptor<FunctionPassT> 00585 createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) { 00586 return std::move(CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass))); 00587 } 00588 00589 } 00590 00591 #endif