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 27 namespace llvm { 28 29 class CGSCCAnalysisManager; 30 31 class CGSCCPassManager { 32 public: 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 52 private: 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. 72 class 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 81 public: 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 107 private: 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. 162 class CGSCCAnalysisManagerModuleProxy { 163 public: 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 224 private: 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. 242 class ModuleAnalysisManagerCGSCCProxy { 243 public: 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 288 private: 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. 303 template <typename CGSCCPassT> class ModuleToPostOrderCGSCCPassAdaptor { 304 public: 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 363 private: 364 CGSCCPassT Pass; 365 }; 366 367 /// \brief A function to deduce a function pass type and wrap it in the 368 /// templated adaptor. 369 template <typename CGSCCPassT> 370 ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT> 371 createModuleToPostOrderCGSCCPassAdaptor(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. 384 class FunctionAnalysisManagerCGSCCProxy { 385 public: 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 446 private: 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. 464 class CGSCCAnalysisManagerFunctionProxy { 465 public: 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 510 private: 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. 524 template <typename FunctionPassT> class CGSCCToFunctionPassAdaptor { 525 public: 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 577 private: 578 FunctionPassT Pass; 579 }; 580 581 /// \brief A function to deduce a function pass type and wrap it in the 582 /// templated adaptor. 583 template <typename FunctionPassT> 584 CGSCCToFunctionPassAdaptor<FunctionPassT> 585 createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) { 586 return std::move(CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass))); 587 } 588 589 } 590 591 #endif 592