CGSCCPassManager.h revision dce4a407a24b04eebc6a376f8e62b41aaa7b071f
1//===- CGSCCPassManager.h - Call graph pass management ----------*- C++ -*-===// 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/// \file 10/// 11/// This header provides classes for managing passes over SCCs of the call 12/// graph. These passes form an important component of LLVM's interprocedural 13/// optimizations. Because they operate on the SCCs of the call graph, and they 14/// wtraverse the graph in post order, they can effectively do pair-wise 15/// interprocedural optimizations for all call edges in the program. At each 16/// call site edge, the callee has already been optimized as much as is 17/// possible. This in turn allows very accurate analysis of it for IPO. 18/// 19//===----------------------------------------------------------------------===// 20 21#ifndef LLVM_ANALYSIS_CGSCC_PASS_MANAGER_H 22#define LLVM_ANALYSIS_CGSCC_PASS_MANAGER_H 23 24#include "llvm/IR/PassManager.h" 25#include "llvm/Analysis/LazyCallGraph.h" 26 27namespace llvm { 28 29class CGSCCAnalysisManager; 30 31class CGSCCPassManager { 32public: 33 // We have to explicitly define all the special member functions because MSVC 34 // refuses to generate them. 35 CGSCCPassManager() {} 36 CGSCCPassManager(CGSCCPassManager &&Arg) : Passes(std::move(Arg.Passes)) {} 37 CGSCCPassManager &operator=(CGSCCPassManager &&RHS) { 38 Passes = std::move(RHS.Passes); 39 return *this; 40 } 41 42 /// \brief Run all of the CGSCC passes in this pass manager over a SCC. 43 PreservedAnalyses run(LazyCallGraph::SCC *C, 44 CGSCCAnalysisManager *AM = nullptr); 45 46 template <typename CGSCCPassT> void addPass(CGSCCPassT Pass) { 47 Passes.emplace_back(new CGSCCPassModel<CGSCCPassT>(std::move(Pass))); 48 } 49 50 static StringRef name() { return "CGSCCPassManager"; } 51 52private: 53 // Pull in the concept type and model template specialized for SCCs. 54 typedef detail::PassConcept<LazyCallGraph::SCC *, CGSCCAnalysisManager> 55 CGSCCPassConcept; 56 template <typename PassT> 57 struct CGSCCPassModel 58 : detail::PassModel<LazyCallGraph::SCC *, CGSCCAnalysisManager, PassT> { 59 CGSCCPassModel(PassT Pass) 60 : detail::PassModel<LazyCallGraph::SCC *, CGSCCAnalysisManager, PassT>( 61 std::move(Pass)) {} 62 }; 63 64 CGSCCPassManager(const CGSCCPassManager &) LLVM_DELETED_FUNCTION; 65 CGSCCPassManager &operator=(const CGSCCPassManager &) LLVM_DELETED_FUNCTION; 66 67 std::vector<std::unique_ptr<CGSCCPassConcept>> Passes; 68}; 69 70/// \brief A function analysis manager to coordinate and cache analyses run over 71/// a module. 72class CGSCCAnalysisManager : public detail::AnalysisManagerBase< 73 CGSCCAnalysisManager, LazyCallGraph::SCC *> { 74 friend class detail::AnalysisManagerBase<CGSCCAnalysisManager, 75 LazyCallGraph::SCC *>; 76 typedef detail::AnalysisManagerBase<CGSCCAnalysisManager, 77 LazyCallGraph::SCC *> BaseT; 78 typedef BaseT::ResultConceptT ResultConceptT; 79 typedef BaseT::PassConceptT PassConceptT; 80 81public: 82 // Most public APIs are inherited from the CRTP base class. 83 84 // We have to explicitly define all the special member functions because MSVC 85 // refuses to generate them. 86 CGSCCAnalysisManager() {} 87 CGSCCAnalysisManager(CGSCCAnalysisManager &&Arg) 88 : BaseT(std::move(static_cast<BaseT &>(Arg))), 89 CGSCCAnalysisResults(std::move(Arg.CGSCCAnalysisResults)) {} 90 CGSCCAnalysisManager &operator=(CGSCCAnalysisManager &&RHS) { 91 BaseT::operator=(std::move(static_cast<BaseT &>(RHS))); 92 CGSCCAnalysisResults = std::move(RHS.CGSCCAnalysisResults); 93 return *this; 94 } 95 96 /// \brief Returns true if the analysis manager has an empty results cache. 97 bool empty() const; 98 99 /// \brief Clear the function analysis result cache. 100 /// 101 /// This routine allows cleaning up when the set of functions itself has 102 /// potentially changed, and thus we can't even look up a a result and 103 /// invalidate it directly. Notably, this does *not* call invalidate 104 /// functions as there is nothing to be done for them. 105 void clear(); 106 107private: 108 CGSCCAnalysisManager(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION; 109 CGSCCAnalysisManager & 110 operator=(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION; 111 112 /// \brief Get a function pass result, running the pass if necessary. 113 ResultConceptT &getResultImpl(void *PassID, LazyCallGraph::SCC *C); 114 115 /// \brief Get a cached function pass result or return null. 116 ResultConceptT *getCachedResultImpl(void *PassID, 117 LazyCallGraph::SCC *C) const; 118 119 /// \brief Invalidate a function pass result. 120 void invalidateImpl(void *PassID, LazyCallGraph::SCC *C); 121 122 /// \brief Invalidate the results for a function.. 123 void invalidateImpl(LazyCallGraph::SCC *C, const PreservedAnalyses &PA); 124 125 /// \brief List of function analysis pass IDs and associated concept pointers. 126 /// 127 /// Requires iterators to be valid across appending new entries and arbitrary 128 /// erases. Provides both the pass ID and concept pointer such that it is 129 /// half of a bijection and provides storage for the actual result concept. 130 typedef std::list< 131 std::pair<void *, std::unique_ptr<detail::AnalysisResultConcept< 132 LazyCallGraph::SCC *>>>> CGSCCAnalysisResultListT; 133 134 /// \brief Map type from function pointer to our custom list type. 135 typedef DenseMap<LazyCallGraph::SCC *, CGSCCAnalysisResultListT> 136 CGSCCAnalysisResultListMapT; 137 138 /// \brief Map from function to a list of function analysis results. 139 /// 140 /// Provides linear time removal of all analysis results for a function and 141 /// the ultimate storage for a particular cached analysis result. 142 CGSCCAnalysisResultListMapT CGSCCAnalysisResultLists; 143 144 /// \brief Map type from a pair of analysis ID and function pointer to an 145 /// iterator into a particular result list. 146 typedef DenseMap<std::pair<void *, LazyCallGraph::SCC *>, 147 CGSCCAnalysisResultListT::iterator> CGSCCAnalysisResultMapT; 148 149 /// \brief Map from an analysis ID and function to a particular cached 150 /// analysis result. 151 CGSCCAnalysisResultMapT CGSCCAnalysisResults; 152}; 153 154/// \brief A module analysis which acts as a proxy for a CGSCC analysis 155/// manager. 156/// 157/// This primarily proxies invalidation information from the module analysis 158/// manager and module pass manager to a CGSCC analysis manager. You should 159/// never use a CGSCC analysis manager from within (transitively) a module 160/// pass manager unless your parent module pass has received a proxy result 161/// object for it. 162class CGSCCAnalysisManagerModuleProxy { 163public: 164 class Result { 165 public: 166 explicit Result(CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} 167 // We have to explicitly define all the special member functions because 168 // MSVC refuses to generate them. 169 Result(const Result &Arg) : CGAM(Arg.CGAM) {} 170 Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {} 171 Result &operator=(Result RHS) { 172 std::swap(CGAM, RHS.CGAM); 173 return *this; 174 } 175 ~Result(); 176 177 /// \brief Accessor for the \c CGSCCAnalysisManager. 178 CGSCCAnalysisManager &getManager() { return *CGAM; } 179 180 /// \brief Handler for invalidation of the module. 181 /// 182 /// If this analysis itself is preserved, then we assume that the call 183 /// graph of the module hasn't changed and thus we don't need to invalidate 184 /// *all* cached data associated with a \c SCC* in the \c 185 /// CGSCCAnalysisManager. 186 /// 187 /// Regardless of whether this analysis is marked as preserved, all of the 188 /// analyses in the \c CGSCCAnalysisManager are potentially invalidated 189 /// based on the set of preserved analyses. 190 bool invalidate(Module *M, const PreservedAnalyses &PA); 191 192 private: 193 CGSCCAnalysisManager *CGAM; 194 }; 195 196 static void *ID() { return (void *)&PassID; } 197 198 explicit CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManager &CGAM) 199 : CGAM(&CGAM) {} 200 // We have to explicitly define all the special member functions because MSVC 201 // refuses to generate them. 202 CGSCCAnalysisManagerModuleProxy( 203 const CGSCCAnalysisManagerModuleProxy &Arg) 204 : CGAM(Arg.CGAM) {} 205 CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManagerModuleProxy &&Arg) 206 : CGAM(std::move(Arg.CGAM)) {} 207 CGSCCAnalysisManagerModuleProxy & 208 operator=(CGSCCAnalysisManagerModuleProxy RHS) { 209 std::swap(CGAM, RHS.CGAM); 210 return *this; 211 } 212 213 /// \brief Run the analysis pass and create our proxy result object. 214 /// 215 /// This doesn't do any interesting work, it is primarily used to insert our 216 /// proxy result object into the module analysis cache so that we can proxy 217 /// invalidation to the CGSCC analysis manager. 218 /// 219 /// In debug builds, it will also assert that the analysis manager is empty 220 /// as no queries should arrive at the CGSCC analysis manager prior to 221 /// this analysis being requested. 222 Result run(Module *M); 223 224private: 225 static char PassID; 226 227 CGSCCAnalysisManager *CGAM; 228}; 229 230/// \brief A CGSCC analysis which acts as a proxy for a module analysis 231/// manager. 232/// 233/// This primarily provides an accessor to a parent module analysis manager to 234/// CGSCC passes. Only the const interface of the module analysis manager is 235/// provided to indicate that once inside of a CGSCC analysis pass you 236/// cannot request a module analysis to actually run. Instead, the user must 237/// rely on the \c getCachedResult API. 238/// 239/// This proxy *doesn't* manage the invalidation in any way. That is handled by 240/// the recursive return path of each layer of the pass manager and the 241/// returned PreservedAnalysis set. 242class ModuleAnalysisManagerCGSCCProxy { 243public: 244 /// \brief Result proxy object for \c ModuleAnalysisManagerCGSCCProxy. 245 class Result { 246 public: 247 explicit Result(const ModuleAnalysisManager &MAM) : MAM(&MAM) {} 248 // We have to explicitly define all the special member functions because 249 // MSVC refuses to generate them. 250 Result(const Result &Arg) : MAM(Arg.MAM) {} 251 Result(Result &&Arg) : MAM(std::move(Arg.MAM)) {} 252 Result &operator=(Result RHS) { 253 std::swap(MAM, RHS.MAM); 254 return *this; 255 } 256 257 const ModuleAnalysisManager &getManager() const { return *MAM; } 258 259 /// \brief Handle invalidation by ignoring it, this pass is immutable. 260 bool invalidate(LazyCallGraph::SCC *) { return false; } 261 262 private: 263 const ModuleAnalysisManager *MAM; 264 }; 265 266 static void *ID() { return (void *)&PassID; } 267 268 ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManager &MAM) 269 : MAM(&MAM) {} 270 // We have to explicitly define all the special member functions because MSVC 271 // refuses to generate them. 272 ModuleAnalysisManagerCGSCCProxy( 273 const ModuleAnalysisManagerCGSCCProxy &Arg) 274 : MAM(Arg.MAM) {} 275 ModuleAnalysisManagerCGSCCProxy(ModuleAnalysisManagerCGSCCProxy &&Arg) 276 : MAM(std::move(Arg.MAM)) {} 277 ModuleAnalysisManagerCGSCCProxy & 278 operator=(ModuleAnalysisManagerCGSCCProxy RHS) { 279 std::swap(MAM, RHS.MAM); 280 return *this; 281 } 282 283 /// \brief Run the analysis pass and create our proxy result object. 284 /// Nothing to see here, it just forwards the \c MAM reference into the 285 /// result. 286 Result run(LazyCallGraph::SCC *) { return Result(*MAM); } 287 288private: 289 static char PassID; 290 291 const ModuleAnalysisManager *MAM; 292}; 293 294/// \brief The core module pass which does a post-order walk of the SCCs and 295/// runs a CGSCC pass over each one. 296/// 297/// Designed to allow composition of a CGSCCPass(Manager) and 298/// a ModulePassManager. Note that this pass must be run with a module analysis 299/// manager as it uses the LazyCallGraph analysis. It will also run the 300/// \c CGSCCAnalysisManagerModuleProxy analysis prior to running the CGSCC 301/// pass over the module to enable a \c FunctionAnalysisManager to be used 302/// within this run safely. 303template <typename CGSCCPassT> class ModuleToPostOrderCGSCCPassAdaptor { 304public: 305 explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) 306 : Pass(std::move(Pass)) {} 307 // We have to explicitly define all the special member functions because MSVC 308 // refuses to generate them. 309 ModuleToPostOrderCGSCCPassAdaptor( 310 const ModuleToPostOrderCGSCCPassAdaptor &Arg) 311 : Pass(Arg.Pass) {} 312 ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg) 313 : Pass(std::move(Arg.Pass)) {} 314 friend void swap(ModuleToPostOrderCGSCCPassAdaptor &LHS, 315 ModuleToPostOrderCGSCCPassAdaptor &RHS) { 316 using std::swap; 317 swap(LHS.Pass, RHS.Pass); 318 } 319 ModuleToPostOrderCGSCCPassAdaptor & 320 operator=(ModuleToPostOrderCGSCCPassAdaptor RHS) { 321 swap(*this, RHS); 322 return *this; 323 } 324 325 /// \brief Runs the CGSCC pass across every SCC in the module. 326 PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { 327 assert(AM && "We need analyses to compute the call graph!"); 328 329 // Setup the CGSCC analysis manager from its proxy. 330 CGSCCAnalysisManager &CGAM = 331 AM->getResult<CGSCCAnalysisManagerModuleProxy>(M).getManager(); 332 333 // Get the call graph for this module. 334 LazyCallGraph &CG = AM->getResult<LazyCallGraphAnalysis>(M); 335 336 PreservedAnalyses PA = PreservedAnalyses::all(); 337 for (LazyCallGraph::SCC &C : CG.postorder_sccs()) { 338 PreservedAnalyses PassPA = Pass.run(&C, &CGAM); 339 340 // We know that the CGSCC pass couldn't have invalidated any other 341 // SCC's analyses (that's the contract of a CGSCC pass), so 342 // directly handle the CGSCC analysis manager's invalidation here. 343 // FIXME: This isn't quite correct. We need to handle the case where the 344 // pass updated the CG, particularly some child of the current SCC, and 345 // invalidate its analyses. 346 CGAM.invalidate(&C, PassPA); 347 348 // Then intersect the preserved set so that invalidation of module 349 // analyses will eventually occur when the module pass completes. 350 PA.intersect(std::move(PassPA)); 351 } 352 353 // By definition we preserve the proxy. This precludes *any* invalidation 354 // of CGSCC analyses by the proxy, but that's OK because we've taken 355 // care to invalidate analyses in the CGSCC analysis manager 356 // incrementally above. 357 PA.preserve<CGSCCAnalysisManagerModuleProxy>(); 358 return PA; 359 } 360 361 static StringRef name() { return "ModuleToPostOrderCGSCCPassAdaptor"; } 362 363private: 364 CGSCCPassT Pass; 365}; 366 367/// \brief A function to deduce a function pass type and wrap it in the 368/// templated adaptor. 369template <typename CGSCCPassT> 370ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT> 371createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) { 372 return std::move( 373 ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass))); 374} 375 376/// \brief A CGSCC analysis which acts as a proxy for a function analysis 377/// manager. 378/// 379/// This primarily proxies invalidation information from the CGSCC analysis 380/// manager and CGSCC pass manager to a function analysis manager. You should 381/// never use a function analysis manager from within (transitively) a CGSCC 382/// pass manager unless your parent CGSCC pass has received a proxy result 383/// object for it. 384class FunctionAnalysisManagerCGSCCProxy { 385public: 386 class Result { 387 public: 388 explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {} 389 // We have to explicitly define all the special member functions because 390 // MSVC refuses to generate them. 391 Result(const Result &Arg) : FAM(Arg.FAM) {} 392 Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {} 393 Result &operator=(Result RHS) { 394 std::swap(FAM, RHS.FAM); 395 return *this; 396 } 397 ~Result(); 398 399 /// \brief Accessor for the \c FunctionAnalysisManager. 400 FunctionAnalysisManager &getManager() { return *FAM; } 401 402 /// \brief Handler for invalidation of the SCC. 403 /// 404 /// If this analysis itself is preserved, then we assume that the set of \c 405 /// Function objects in the \c SCC hasn't changed and thus we don't need 406 /// to invalidate *all* cached data associated with a \c Function* in the \c 407 /// FunctionAnalysisManager. 408 /// 409 /// Regardless of whether this analysis is marked as preserved, all of the 410 /// analyses in the \c FunctionAnalysisManager are potentially invalidated 411 /// based on the set of preserved analyses. 412 bool invalidate(LazyCallGraph::SCC *C, const PreservedAnalyses &PA); 413 414 private: 415 FunctionAnalysisManager *FAM; 416 }; 417 418 static void *ID() { return (void *)&PassID; } 419 420 explicit FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager &FAM) 421 : FAM(&FAM) {} 422 // We have to explicitly define all the special member functions because MSVC 423 // refuses to generate them. 424 FunctionAnalysisManagerCGSCCProxy( 425 const FunctionAnalysisManagerCGSCCProxy &Arg) 426 : FAM(Arg.FAM) {} 427 FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManagerCGSCCProxy &&Arg) 428 : FAM(std::move(Arg.FAM)) {} 429 FunctionAnalysisManagerCGSCCProxy & 430 operator=(FunctionAnalysisManagerCGSCCProxy RHS) { 431 std::swap(FAM, RHS.FAM); 432 return *this; 433 } 434 435 /// \brief Run the analysis pass and create our proxy result object. 436 /// 437 /// This doesn't do any interesting work, it is primarily used to insert our 438 /// proxy result object into the module analysis cache so that we can proxy 439 /// invalidation to the function analysis manager. 440 /// 441 /// In debug builds, it will also assert that the analysis manager is empty 442 /// as no queries should arrive at the function analysis manager prior to 443 /// this analysis being requested. 444 Result run(LazyCallGraph::SCC *C); 445 446private: 447 static char PassID; 448 449 FunctionAnalysisManager *FAM; 450}; 451 452/// \brief A function analysis which acts as a proxy for a CGSCC analysis 453/// manager. 454/// 455/// This primarily provides an accessor to a parent CGSCC analysis manager to 456/// function passes. Only the const interface of the CGSCC analysis manager is 457/// provided to indicate that once inside of a function analysis pass you 458/// cannot request a CGSCC analysis to actually run. Instead, the user must 459/// rely on the \c getCachedResult API. 460/// 461/// This proxy *doesn't* manage the invalidation in any way. That is handled by 462/// the recursive return path of each layer of the pass manager and the 463/// returned PreservedAnalysis set. 464class CGSCCAnalysisManagerFunctionProxy { 465public: 466 /// \brief Result proxy object for \c ModuleAnalysisManagerFunctionProxy. 467 class Result { 468 public: 469 explicit Result(const CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} 470 // We have to explicitly define all the special member functions because 471 // MSVC refuses to generate them. 472 Result(const Result &Arg) : CGAM(Arg.CGAM) {} 473 Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {} 474 Result &operator=(Result RHS) { 475 std::swap(CGAM, RHS.CGAM); 476 return *this; 477 } 478 479 const CGSCCAnalysisManager &getManager() const { return *CGAM; } 480 481 /// \brief Handle invalidation by ignoring it, this pass is immutable. 482 bool invalidate(Function *) { return false; } 483 484 private: 485 const CGSCCAnalysisManager *CGAM; 486 }; 487 488 static void *ID() { return (void *)&PassID; } 489 490 CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager &CGAM) 491 : CGAM(&CGAM) {} 492 // We have to explicitly define all the special member functions because MSVC 493 // refuses to generate them. 494 CGSCCAnalysisManagerFunctionProxy( 495 const CGSCCAnalysisManagerFunctionProxy &Arg) 496 : CGAM(Arg.CGAM) {} 497 CGSCCAnalysisManagerFunctionProxy(CGSCCAnalysisManagerFunctionProxy &&Arg) 498 : CGAM(std::move(Arg.CGAM)) {} 499 CGSCCAnalysisManagerFunctionProxy & 500 operator=(CGSCCAnalysisManagerFunctionProxy RHS) { 501 std::swap(CGAM, RHS.CGAM); 502 return *this; 503 } 504 505 /// \brief Run the analysis pass and create our proxy result object. 506 /// Nothing to see here, it just forwards the \c CGAM reference into the 507 /// result. 508 Result run(Function *) { return Result(*CGAM); } 509 510private: 511 static char PassID; 512 513 const CGSCCAnalysisManager *CGAM; 514}; 515 516/// \brief Adaptor that maps from a SCC to its functions. 517/// 518/// Designed to allow composition of a FunctionPass(Manager) and 519/// a CGSCCPassManager. Note that if this pass is constructed with a pointer 520/// to a \c CGSCCAnalysisManager it will run the 521/// \c FunctionAnalysisManagerCGSCCProxy analysis prior to running the function 522/// pass over the SCC to enable a \c FunctionAnalysisManager to be used 523/// within this run safely. 524template <typename FunctionPassT> class CGSCCToFunctionPassAdaptor { 525public: 526 explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass) 527 : Pass(std::move(Pass)) {} 528 // We have to explicitly define all the special member functions because MSVC 529 // refuses to generate them. 530 CGSCCToFunctionPassAdaptor(const CGSCCToFunctionPassAdaptor &Arg) 531 : Pass(Arg.Pass) {} 532 CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg) 533 : Pass(std::move(Arg.Pass)) {} 534 friend void swap(CGSCCToFunctionPassAdaptor &LHS, CGSCCToFunctionPassAdaptor &RHS) { 535 using std::swap; 536 swap(LHS.Pass, RHS.Pass); 537 } 538 CGSCCToFunctionPassAdaptor &operator=(CGSCCToFunctionPassAdaptor RHS) { 539 swap(*this, RHS); 540 return *this; 541 } 542 543 /// \brief Runs the function pass across every function in the module. 544 PreservedAnalyses run(LazyCallGraph::SCC *C, CGSCCAnalysisManager *AM) { 545 FunctionAnalysisManager *FAM = nullptr; 546 if (AM) 547 // Setup the function analysis manager from its proxy. 548 FAM = &AM->getResult<FunctionAnalysisManagerCGSCCProxy>(C).getManager(); 549 550 PreservedAnalyses PA = PreservedAnalyses::all(); 551 for (LazyCallGraph::Node *N : *C) { 552 PreservedAnalyses PassPA = Pass.run(&N->getFunction(), FAM); 553 554 // We know that the function pass couldn't have invalidated any other 555 // function's analyses (that's the contract of a function pass), so 556 // directly handle the function analysis manager's invalidation here. 557 if (FAM) 558 FAM->invalidate(&N->getFunction(), PassPA); 559 560 // Then intersect the preserved set so that invalidation of module 561 // analyses will eventually occur when the module pass completes. 562 PA.intersect(std::move(PassPA)); 563 } 564 565 // By definition we preserve the proxy. This precludes *any* invalidation 566 // of function analyses by the proxy, but that's OK because we've taken 567 // care to invalidate analyses in the function analysis manager 568 // incrementally above. 569 // FIXME: We need to update the call graph here to account for any deleted 570 // edges! 571 PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 572 return PA; 573 } 574 575 static StringRef name() { return "CGSCCToFunctionPassAdaptor"; } 576 577private: 578 FunctionPassT Pass; 579}; 580 581/// \brief A function to deduce a function pass type and wrap it in the 582/// templated adaptor. 583template <typename FunctionPassT> 584CGSCCToFunctionPassAdaptor<FunctionPassT> 585createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) { 586 return std::move(CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass))); 587} 588 589} 590 591#endif 592