aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp
AgeCommit message (Collapse)AuthorFilesLines
2025-04-18unittests: Avoid using getNumUses (#136352)Matt Arsenault1-1/+1
2025-01-24[NFC][DebugInfo] Use iterator moveBefore at many call-sites (#123583)Jeremy Morse1-1/+1
As part of the "RemoveDIs" project, BasicBlock::iterator now carries a debug-info bit that's needed when getFirstNonPHI and similar feed into instruction insertion positions. Call-sites where that's necessary were updated a year ago; but to ensure some type safety however, we'd like to have all calls to moveBefore use iterators. This patch adds a (guaranteed dereferenceable) iterator-taking moveBefore, and changes a bunch of call-sites where it's obviously safe to change to use it by just calling getIterator() on an instruction pointer. A follow-up patch will contain less-obviously-safe changes. We'll eventually deprecate and remove the instruction-pointer insertBefore, but not before adding concise documentation of what considerations are needed (very few).
2024-08-08[DebugInfo][RemoveDIs] Use iterator-insertion in unittests and fuzzer (#102015)Jeremy Morse1-18/+19
These are the final few places in LLVM that use instruction pointers to insert instructions -- use iterators instead, which is needed for debug-info correctness in the future. Most of this is a gentle scattering of getIterator calls or not deref-then-addrofing iterators. libfuzzer does require a storage change to keep built instruction positions in a container though. The unit-test changes are very straightforwards. This leaves us in a position where libfuzzer can't fuzz on either of debug-info records, however I don't believe that fuzzing of debug-info is in scope for the library.
2024-07-10[CGSCC] Remove CGSCCUpdateResult::InvalidatedRefSCCs (#98213)Arthur Eubanks1-0/+55
The RefSCC that a function marked dead is in may still contain valid SCCs that we want to visit. We rely on InvalidatedSCCs to skip SCCs containing dead functions. The addition of RefSCCs in CallGraphUpdater to InvalidatedRefSCCs was causing asserts as reported in #94815. Fix some more CallGraphUpdater function deletion methods as well.
2024-06-21[IR] Don't include PassInstrumentation.h in PassManager.h (NFC) (#96219)Nikita Popov1-0/+1
Move PassInstrumentationAnalysis into PassInstrumentation.h and stop including it in PassManager.h (effectively inverting the direction of the dependency). Most places using PassManager are not interested in PassInstrumentation, and we no longer have any uses of it in PassManager.h itself (only in PassManagerImpl.h).
2024-06-11[CGSCC] Fix compile time blowup with large RefSCCs (#94815)Arthur Eubanks1-7/+5
In some modules, e.g. Kotlin-generated IR, we end up with a huge RefSCC and the call graph updates done as a result of the inliner take a long time. This is due to RefSCC::removeInternalRefEdges() getting called many times, each time removing one function from the RefSCC, but each call to removeInternalRefEdges() is proportional to the size of the RefSCC. There are two places that call removeInternalRefEdges(), in updateCGAndAnalysisManagerForPass() and LazyCallGraph::removeDeadFunction(). 1) Since LazyCallGraph can deal with spurious (edges that exist in the graph but not in the IR) ref edges, we can simply not call removeInternalRefEdges() in updateCGAndAnalysisManagerForPass(). 2) LazyCallGraph::removeDeadFunction() still ends up taking the brunt of compile time with the above change for the original reason. So instead we batch all the dead function removals so we can call removeInternalRefEdges() just once. This requires some changes to callers of removeDeadFunction() to not actually erase the function from the module, but defer it to when we batch delete dead functions at the end of the CGSCC run, leaving the function body as "unreachable" in the meantime. We still need to ensure that call edges are accurate. I had also tried deleting dead functions after visiting a RefSCC, but deleting them all at once at the end was simpler. Many test changes are due to not performing unnecessary revisits of an SCC (the CGSCC infrastructure deems ref edge refinements as unimportant when it comes to revisiting SCCs, although that seems to not be consistently true given these changes) because we don't remove some ref edges. Specifically for devirt-invalidated.ll this seems to expose an inlining order issue with the inliner. Probably unimportant for this type of intentionally weird call graph. Compile time: https://llvm-compile-time-tracker.com/compare.php?from=6f2c61071c274a1b5e212e6ad4114641ec7c7fc3&to=b08c90d05e290dd065755ea776ceaf1420680224&stat=instructions:u
2023-11-16[CGSCCPassManagerTest] Replace no-op bitcast to create constant using the ↵Youngsuk Kim1-3/+2
old function (#72460) With opaque pointers enabled, the existing ptr-to-ptr bitcast is a no-op and no longer creates a constant that references the old function. Replace the no-op bitcast with code that creates a constant that references the old function. The test now fails if the 1 new line of code added to `CallGraphUpdater::replaceFunctionWith()` in cb0ecc5c33bd56a3eed0fa30ac787accec45d637 is removed (test passes if kept intact). --------- Co-authored-by: Nikita Popov <github@npopov.com>
2023-11-07[NFC] Remove Type::getInt8PtrTy (#71029)Paulo Matos1-12/+15
Replace this with PointerType::getUnqual(). Followup to the opaque pointer transition. Fixes an in-code TODO item.
2022-02-23[NFC] Add #include for constantsBill Wendling1-0/+1
2021-05-21Revert "[NPM] Do not run function simplification pipeline unnecessarily"Arthur Eubanks1-1/+0
This reverts commit 97ab068034161fb35e5c9a7b293bf1e569cf077b. Depends on D100917, which is to be reverted.
2021-05-07[NewPM] Hide pass manager debug logging behind -debug-pass-manager-verboseArthur Eubanks1-84/+84
Printing pass manager invocations is fairly verbose and not super useful. This allows us to remove DebugLogging from pass managers and PassBuilder since all logging (aside from analysis managers) goes through instrumentation now. This has the downside of never being able to print the top level pass manager via instrumentation, but that seems like a minor downside. Reviewed By: ychen Differential Revision: https://reviews.llvm.org/D101797
2021-05-07[NewPM] Move analysis invalidation/clearing logging to instrumentationArthur Eubanks1-2/+1
We're trying to move DebugLogging into instrumentation, rather than being part of PassManagers/AnalysisManagers. Reviewed By: ychen Differential Revision: https://reviews.llvm.org/D102093
2021-05-06[NPM] Do not run function simplification pipeline unnecessarilyMircea Trofin1-0/+1
The CGSCC pass manager interplay with the FunctionAnalysisManagerCGSCCProxy is 'special' in the sense that the former will rerun the latter if there are changes to a SCC structure; that being said, some of the functions in the SCC may be unchanged. In that case, the function simplification pipeline will be re-run, which impacts compile time[1]. This patch allows the function simplification pipeline be skipped if it was already run and the function was not modified since. The behavior is currently disabled by default. This is because, currently, the rerunning of the function simplification pipeline on an unchanged function may still result in changes. The patch simplifies investigating and fixing those cases where repeated function pass runs do actually positively impact code quality, while offering an easy workaround for those impacted negatively by compile time regressions, and not impacting mainline scenarios. [1] A [[ http://llvm-compile-time-tracker.com/compare.php?from=eb37d3546cd0c6e67798496634c45e501f7806f1&to=ac722d1190dc7bbdd17e977ef7ec95e69eefc91e&stat=instructions | compile time tracker ]] run with the option enabled. Differential Revision: https://reviews.llvm.org/D98103
2021-03-18Reapply "[NPM][CGSCC] FunctionAnalysisManagerCGSCCProxy: do not clear ↵Mircea Trofin1-0/+25
immutable function passes" This reverts commit 11b70b9e3a7458b5b78c30020b56e8ca563a4801. The bot failure was due to ArgumentPromotion deleting functions without deleting their analyses. This was separately fixed in 4b1c807.
2021-03-11Revert "[NPM][CGSCC] FunctionAnalysisManagerCGSCCProxy: do not clear ↵Mircea Trofin1-25/+0
immutable function passes" This reverts commit 5eaeb0fa67e57391f5584a3f67fdb131e93afda6. It appears there are analyses that assume clearing - example: https://lab.llvm.org/buildbot#builders/36/builds/5964
2021-03-11[NPM][CGSCC] FunctionAnalysisManagerCGSCCProxy: do not clear immutable ↵Mircea Trofin1-0/+25
function passes Check with the analysis result by calling invalidate instead of clear on the analysis manager. Differential Revision: https://reviews.llvm.org/D98440
2021-01-06[CGSCC][Coroutine][NewPM] Properly support function splitting/outliningArthur Eubanks1-13/+20
Previously when trying to support CoroSplit's function splitting, we added in a hack that simply added the new function's node into the original function's SCC (https://reviews.llvm.org/D87798). This is incorrect since it might be in its own SCC. Now, more similar to the previous design, we have callers explicitly notify the LazyCallGraph that a function has been split out from another one. In order to properly support CoroSplit, there are two ways functions can be split out. One is the normal expected "outlining" of one function into a new one. The new function may only contain references to other functions that the original did. The original function must reference the new function. The new function may reference the original function, which can result in the new function being in the same SCC as the original function. The weird case is when the original function indirectly references the new function, but the new function directly calls the original function, resulting in the new SCC being a parent of the original function's SCC. This form of function splitting works with CoroSplit's Switch ABI. The second way of splitting is more specific to CoroSplit. CoroSplit's Retcon and Async ABIs split the original function into multiple functions that all reference each other and are referenced by the original function. In order to keep the LazyCallGraph in a valid state, all new functions must be processed together, else some nodes won't be populated. To keep things simple, this only supports the case where all new edges are ref edges, and every new function references every other new function. There can be a reference back from any new function to the original function, putting all functions in the same RefSCC. This also adds asserts that all nodes in a (Ref)SCC can reach all other nodes to prevent future incorrect hacks. The original hacks in https://reviews.llvm.org/D87798 are no longer necessary since all new functions should have been registered before calling updateCGAndAnalysisManagerForPass. This fixes all coroutine tests when opt's -enable-new-pm is true by default. This also fixes PR48190, which was likely due to the previous hack breaking SCC invariants. Reviewed By: rnk Differential Revision: https://reviews.llvm.org/D93828
2020-12-17[test] Factor out creation of copy of SCC Nodes into functionArthur Eubanks1-18/+13
Reviewed By: rnk Differential Revision: https://reviews.llvm.org/D93434
2020-12-16[test] Cleanup some CGSCCPassManager testsArthur Eubanks1-22/+59
Don't iterate over SCC as we potentially modify it. Verify module (and fix some broken ones). Only run pass once and make sure that it's actually run. Rename tests to just end in a number since I'm planning on adding a bunch more which won't have good individual names. Instead, add comments on the transformations that each test does. Reviewed By: rnk Differential Revision: https://reviews.llvm.org/D93427
2020-11-11[CGSCC][Inliner] Handle new non-trivial edges in ↵Arthur Eubanks1-0/+65
updateCGAndAnalysisManagerForPass Previously the inliner did a bit of a hack by adding ref edges for all new edges introduced by performing an inline before calling updateCGAndAnalysisManagerForPass(). This was because updateCGAndAnalysisManagerForPass() didn't handle new non-trivial call edges. This adds handling of non-trivial call edges to updateCGAndAnalysisManagerForPass(). The inliner called updateCGAndAnalysisManagerForFunctionPass() since it was handling adding newly introduced edges (so updateCGAndAnalysisManagerForPass() would only have to handle promotion), but now it needs to call updateCGAndAnalysisManagerForCGSCCPass() since updateCGAndAnalysisManagerForPass() is now handling the new call edges and function passes cannot add new edges. We follow the previous path of adding trivial ref edges then letting promotion handle changing the ref edges to call edges and the CGSCC updates. So this still does not allow adding call edges that result in an addition of a non-trivial ref edge. This is in preparation for better detecting devirtualization. Previously since the inliner itself would add ref edges, updateCGAndAnalysisManagerForPass() would think that promotion and thus devirtualization had happened after any sort of inlining. Reviewed By: asbirlea Differential Revision: https://reviews.llvm.org/D91046
2020-11-02[LazyCallGraph] Build SCCs of the reference graph in orderFangrui Song1-11/+11
``` // The legacy PM CGPassManager discovers SCCs this way: for function in the source order tarjanSCC(function) // While the new PM CGSCCPassManager does: for function in the reversed source order [1] discover a reference graph SCC build call graph SCCs inside the reference graph SCC ``` In the common cases, reference graph ~= call graph, the new PM order is undesired because for `a | b | c` (3 independent functions), the new PM will process them in the reversed order: c, b, a. If `a <-> b <-> c`, we can see that `-print-after-all` will report the sole SCC as `scc: (c, b, a)`. This patch corrects the iteration order. The discovered SCC order will match the legacy PM in the common cases. For some tests (`Transforms/Inline/cgscc-*.ll` and `unittests/Analysis/CGSCCPassManagerTest.cpp`), the behaviors are dependent on the SCC discovery order and there are too many check lines for the particular order. This patch simply reverses the function order to avoid changing too many check lines. Differential Revision: https://reviews.llvm.org/D90566
2020-09-23[NewPM][CGSCC] Handle newly added functions in updateCGAndAnalysisManagerForPassArthur Eubanks1-8/+25
This seems to fit the CGSCC updates model better than calling addNewFunctionInto{Ref,}SCC() on newly created/outlined functions. Now addNewFunctionInto{Ref,}SCC() are no longer necessary. However, this doesn't work on newly outlined functions that aren't referenced by the original function. e.g. if a() was outlined into b() and c(), but c() is only referenced by b() and not by a(), this will trigger an assert. This also fixes an issue I was seeing with newly created functions not having passes run on them. Ran check-llvm with expensive checks. Reviewed By: asbirlea Differential Revision: https://reviews.llvm.org/D87798
2020-09-15[CGSCC][NewPM] Fix adding mutually recursive new functionsArthur Eubanks1-0/+55
When adding a new function via addNewFunctionIntoRefSCC(), it creates a new node and immediately populates the edges. Since populateSlow() calls G->get() on all referenced functions, it will create a node (but not populate it) for functions that haven't yet been added. If we add two mutually recursive functions, the assert that the node should never have been created will fire when the second function is added. So here we remove that assert since the node may have already been created (but not yet populated). createNode() is only called from addNewFunctionInto{,Ref}SCC(). https://bugs.llvm.org/show_bug.cgi?id=47502 Reviewed By: jdoerfert Differential Revision: https://reviews.llvm.org/D87623
2020-06-14[NewPM] Avoid redundant CGSCC run for updated SCCWenlei He1-5/+5
Summary: When an SCC got split due to inlining, we have two mechanisms for reprocessing the updated SCC, first is UR.UpdatedC that repeatedly rerun the new, current SCC; second is a worklist for all newly split SCCs. We can avoid rerun of the same SCC when the SCC is set to be processed by both mechanisms *back to back*. In pathological cases, such redundant rerun could cause exponential size growth due to inlining along cycles, even when there's no SCC mutation and hence convergence is not a problem. Note that it's ok to have SCC updated and rerun immediately, and also in the work list if we have actually moved an SCC to be topologically "below" the current one due to merging. In that case, we will need to revisit the current SCC after those moved SCCs. For that reason, the redundant avoidance here only targets back to back rerun of the same SCC - the case described by the now removed FIXME comment. Reviewers: chandlerc, wmi Subscribers: llvm-commits, hoy Tags: #llvm Differential Revision: https://reviews.llvm.org/D80589
2020-05-13[NewPassManager] Add assertions when getting statefull cached analysis.Alina Sbirlea1-93/+119
Summary: Analyses that are statefull should not be retrieved through a proxy from an outer IR unit, as these analyses are only invalidated at the end of the inner IR unit manager. This patch disallows getting the outer manager and provides an API to get a cached analysis through the proxy. If the analysis is not stateless, the call to getCachedResult will assert. Reviewers: chandlerc Subscribers: mehdi_amini, eraman, hiraditya, zzheng, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D72893
2020-04-15[CallSite removal][TargetLibraryInfo] Replace ImmutableCallSite with ↵Craig Topper1-0/+1
CallBase in one of the getLibFunc signatures. NFC Differential Revision: https://reviews.llvm.org/D78083
2020-04-08[CallGraphUpdater] Remove dead constants before replacing a functionJohannes Doerfert1-0/+4
Dead constants might be left when a function is replaced, we can gracefully handle this case and avoid complexity for the users who would see an assertion otherwise.
2020-02-18[LazyCallGraph] Fix ambiguous index valueBrian Gesiak1-0/+50
After having committed https://reviews.llvm.org/D72226, 2 buildbots running GCC 5.4.0 began failing. The cause was the order in which those compilers evaluated the left- and right-hand sides of the expression `RC.SCCIndices[C] = RC.SCCIndices.size();`. This commit splits the expression into multiple statements to avoid ambiguity, and adds a test case that exercises the code that caused the test failures on those older compilers (which was originally included in the reviewed patch, https://reviews.llvm.org/D72226).
2020-02-17Revert "Add LazyCallGraph API to add function to RefSCC"Brian Gesiak1-49/+0
This reverts commit https://reviews.llvm.org/rG449a13509190b1c57e5fcf5cd7e8f0f647f564b4, due to buildbot failures such as http://lab.llvm.org:8011/builders/clang-cmake-x86_64-avx2-linux/builds/13251.
2020-02-17Add LazyCallGraph API to add function to RefSCCBrian Gesiak1-0/+49
Summary: Depends on https://reviews.llvm.org/D70927. `LazyCallGraph::addNewFunctionIntoSCC` allows users to insert a new function node into a call graph, into a specific, existing SCC. Extend this interface such that functions can be added even when they do not belong in any existing SCC, but instead in a new SCC within an existing RefSCC. The ability to insert new functions as part of a RefSCC is necessary for outlined functions that do not form a strongly connected cycle with the function they are outlined from. An example of such a function would be the coroutine funclets 'f.resume', etc., which are outlined from a coroutine 'f'. Coroutine 'f' only references the funclets' addresses, it does not call them directly. Reviewers: jdoerfert, chandlerc, wenlei, hfinkel Reviewed By: jdoerfert Subscribers: hfinkel, JonChesterfield, mehdi_amini, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D72226
2020-02-08Introduce a CallGraph updater helper classJohannes Doerfert1-1/+237
The CallGraphUpdater is a helper that simplifies the process of updating the call graph, both old and new style, while running an CGSCC pass. The uses are contained in different commits, e.g. D70767. More functionality is added as we need it. Reviewed By: modocache, hfinkel Differential Revision: https://reviews.llvm.org/D70927
2020-02-02[PM][CGSCC] Add a helper to update the call graph from SCC passesJohannes Doerfert1-0/+147
With this patch new trivial edges can be added to an SCC in a CGSCC pass via the updateCGAndAnalysisManagerForCGSCCPass method. It shares almost all the code with the existing updateCGAndAnalysisManagerForFunctionPass method but it implements the first step towards the TODOs. This was initially part of D70927. Reviewed By: JonChesterfield Differential Revision: https://reviews.llvm.org/D72025
2020-01-17[UnitTests] Add invalidate methods.Alina Sbirlea1-0/+22
2019-09-07Change TargetLibraryInfo analysis passes to always require FunctionTeresa Johnson1-1/+1
Summary: This is the first change to enable the TLI to be built per-function so that -fno-builtin* handling can be migrated to use function attributes. See discussion on D61634 for background. This is an enabler for fixing handling of these options for LTO, for example. This change should not affect behavior, as the provided function is not yet used to build a specifically per-function TLI, but rather enables that migration. Most of the changes were very mechanical, e.g. passing a Function to the legacy analysis pass's getTLI interface, or in Module level cases, adding a callback. This is similar to the way the per-function TTI analysis works. There was one place where we were looking for builtins but not in the context of a specific function. See FindCXAAtExit in lib/Transforms/IPO/GlobalOpt.cpp. I'm somewhat concerned my workaround could provide the wrong behavior in some corner cases. Suggestions welcome. Reviewers: chandlerc, hfinkel Subscribers: arsenm, dschuff, jvesely, nhaehnle, mehdi_amini, javed.absar, sbc100, jgravelle-google, eraman, aheejin, steven_wu, george.burgess.iv, dexonsmith, jfb, asbirlea, gchatelet, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D66428 llvm-svn: 371284
2019-03-28[NewPM] Fix a nasty bug with analysis invalidation in the new PM.Chandler Carruth1-10/+14
The issue here is that we actually allow CGSCC passes to mutate IR (and therefore invalidate analyses) outside of the current SCC. At a minimum, we need to support mutating parent and ancestor SCCs to support the ArgumentPromotion pass which rewrites all calls to a function. However, the analysis invalidation infrastructure is heavily based around not needing to invalidate the same IR-unit at multiple levels. With Loop passes for example, they don't invalidate other Loops. So we need to customize how we handle CGSCC invalidation. Doing this without gratuitously re-running analyses is even harder. I've avoided most of these by using an out-of-band preserved set to accumulate the cross-SCC invalidation, but it still isn't perfect in the case of re-visiting the same SCC repeatedly *but* it coming off the worklist. Unclear how important this use case really is, but I wanted to call it out. Another wrinkle is that in order for this to successfully propagate to function analyses, we have to make sure we have a proxy from the SCC to the Function level. That requires pre-creating the necessary proxy. The motivating test case now works cleanly and is added for ArgumentPromotion. Thanks for the review from Philip and Wei! Differential Revision: https://reviews.llvm.org/D59869 llvm-svn: 357137
2019-01-19Update the file headers across all of the LLVM projects in the monorepoChandler Carruth1-4/+3
to reflect the new license. We understand that people may be surprised that we're moving the header entirely to discuss the new license. We checked this carefully with the Foundation's lawyer and we believe this is the correct approach. Essentially, all code in the project is now made available by the LLVM project under our new license, so you will see that the license headers include that license only. Some of our contributors have contributed code under our old license, and accordingly, we have retained a copy of our old license notice in the top-level files in each project and repository. llvm-svn: 351636
2018-09-20[New PM] Introducing PassInstrumentation frameworkFedor Sergeev1-0/+7
Pass Execution Instrumentation interface enables customizable instrumentation of pass execution, as per "RFC: Pass Execution Instrumentation interface" posted 06/07/2018 on llvm-dev@ The intent is to provide a common machinery to implement all the pass-execution-debugging features like print-before/after, opt-bisect, time-passes etc. Here we get a basic implementation consisting of: * PassInstrumentationCallbacks class that handles registration of callbacks and access to them. * PassInstrumentation class that handles instrumentation-point interfaces that call into PassInstrumentationCallbacks. * Callbacks accept StringRef which is just a name of the Pass right now. There were some ideas to pass an opaque wrapper for the pointer to pass instance, however it appears that pointer does not actually identify the instance (adaptors and managers might have the same address with the pass they govern). Hence it was decided to go simple for now and then later decide on what the proper mental model of identifying a "pass in a phase of pipeline" is. * Callbacks accept llvm::Any serving as a wrapper for const IRUnit*, to remove direct dependencies on different IRUnits (e.g. Analyses). * PassInstrumentationAnalysis analysis is explicitly requested from PassManager through usual AnalysisManager::getResult. All pass managers were updated to run that to get PassInstrumentation object for instrumentation calls. * Using tuples/index_sequence getAnalysisResult helper to extract generic AnalysisManager's extra args out of a generic PassManager's extra args. This is the only way I was able to explicitly run getResult for PassInstrumentationAnalysis out of a generic code like PassManager::run or RepeatedPass::run. TODO: Upon lengthy discussions we agreed to accept this as an initial implementation and then get rid of getAnalysisResult by improving RepeatedPass implementation. * PassBuilder takes PassInstrumentationCallbacks object to pass it further into PassInstrumentationAnalysis. Callbacks registration should be performed directly through PassInstrumentationCallbacks. * new-pm tests updated to account for PassInstrumentationAnalysis being run * Added PassInstrumentation tests to PassBuilderCallbacks unit tests. Other unit tests updated with registration of the now-required PassInstrumentationAnalysis. Made getName helper to return std::string (instead of StringRef initially) to fix asan builtbot failures on CGSCC tests. Reviewers: chandlerc, philip.pfaffe Differential Revision: https://reviews.llvm.org/D47858 llvm-svn: 342664
2018-09-20Temporarily Revert "[New PM] Introducing PassInstrumentation framework"Eric Christopher1-7/+0
as it was causing failures in the asan buildbot. This reverts commit r342597. llvm-svn: 342616
2018-09-19[New PM] Introducing PassInstrumentation frameworkFedor Sergeev1-0/+7
Pass Execution Instrumentation interface enables customizable instrumentation of pass execution, as per "RFC: Pass Execution Instrumentation interface" posted 06/07/2018 on llvm-dev@ The intent is to provide a common machinery to implement all the pass-execution-debugging features like print-before/after, opt-bisect, time-passes etc. Here we get a basic implementation consisting of: * PassInstrumentationCallbacks class that handles registration of callbacks and access to them. * PassInstrumentation class that handles instrumentation-point interfaces that call into PassInstrumentationCallbacks. * Callbacks accept StringRef which is just a name of the Pass right now. There were some ideas to pass an opaque wrapper for the pointer to pass instance, however it appears that pointer does not actually identify the instance (adaptors and managers might have the same address with the pass they govern). Hence it was decided to go simple for now and then later decide on what the proper mental model of identifying a "pass in a phase of pipeline" is. * Callbacks accept llvm::Any serving as a wrapper for const IRUnit*, to remove direct dependencies on different IRUnits (e.g. Analyses). * PassInstrumentationAnalysis analysis is explicitly requested from PassManager through usual AnalysisManager::getResult. All pass managers were updated to run that to get PassInstrumentation object for instrumentation calls. * Using tuples/index_sequence getAnalysisResult helper to extract generic AnalysisManager's extra args out of a generic PassManager's extra args. This is the only way I was able to explicitly run getResult for PassInstrumentationAnalysis out of a generic code like PassManager::run or RepeatedPass::run. TODO: Upon lengthy discussions we agreed to accept this as an initial implementation and then get rid of getAnalysisResult by improving RepeatedPass implementation. * PassBuilder takes PassInstrumentationCallbacks object to pass it further into PassInstrumentationAnalysis. Callbacks registration should be performed directly through PassInstrumentationCallbacks. * new-pm tests updated to account for PassInstrumentationAnalysis being run * Added PassInstrumentation tests to PassBuilderCallbacks unit tests. Other unit tests updated with registration of the now-required PassInstrumentationAnalysis. Reviewers: chandlerc, philip.pfaffe Differential Revision: https://reviews.llvm.org/D47858 llvm-svn: 342597
2018-09-19Revert rL342544: [New PM] Introducing PassInstrumentation frameworkFedor Sergeev1-7/+0
A bunch of bots fail to compile unittests. Reverting. llvm-svn: 342552
2018-09-19[New PM] Introducing PassInstrumentation frameworkFedor Sergeev1-0/+7
Summary: Pass Execution Instrumentation interface enables customizable instrumentation of pass execution, as per "RFC: Pass Execution Instrumentation interface" posted 06/07/2018 on llvm-dev@ The intent is to provide a common machinery to implement all the pass-execution-debugging features like print-before/after, opt-bisect, time-passes etc. Here we get a basic implementation consisting of: * PassInstrumentationCallbacks class that handles registration of callbacks and access to them. * PassInstrumentation class that handles instrumentation-point interfaces that call into PassInstrumentationCallbacks. * Callbacks accept StringRef which is just a name of the Pass right now. There were some ideas to pass an opaque wrapper for the pointer to pass instance, however it appears that pointer does not actually identify the instance (adaptors and managers might have the same address with the pass they govern). Hence it was decided to go simple for now and then later decide on what the proper mental model of identifying a "pass in a phase of pipeline" is. * Callbacks accept llvm::Any serving as a wrapper for const IRUnit*, to remove direct dependencies on different IRUnits (e.g. Analyses). * PassInstrumentationAnalysis analysis is explicitly requested from PassManager through usual AnalysisManager::getResult. All pass managers were updated to run that to get PassInstrumentation object for instrumentation calls. * Using tuples/index_sequence getAnalysisResult helper to extract generic AnalysisManager's extra args out of a generic PassManager's extra args. This is the only way I was able to explicitly run getResult for PassInstrumentationAnalysis out of a generic code like PassManager::run or RepeatedPass::run. TODO: Upon lengthy discussions we agreed to accept this as an initial implementation and then get rid of getAnalysisResult by improving RepeatedPass implementation. * PassBuilder takes PassInstrumentationCallbacks object to pass it further into PassInstrumentationAnalysis. Callbacks registration should be performed directly through PassInstrumentationCallbacks. * new-pm tests updated to account for PassInstrumentationAnalysis being run * Added PassInstrumentation tests to PassBuilderCallbacks unit tests. Other unit tests updated with registration of the now-required PassInstrumentationAnalysis. Reviewers: chandlerc, philip.pfaffe Differential Revision: https://reviews.llvm.org/D47858 llvm-svn: 342544
2017-08-11[PM] Switch the CGSCC debug messages to use the standard LLVM debugChandler Carruth1-4/+4
printing techniques with a DEBUG_TYPE controlling them. It was a mistake to start re-purposing the pass manager `DebugLogging` variable for generic debug printing -- those logs are intended to be very minimal and primarily used for testing. More detailed and comprehensive logging doesn't make sense there (it would only make for brittle tests). Moreover, we kept forgetting to propagate the `DebugLogging` variable to various places making it also ineffective and/or unavailable. Switching to `DEBUG_TYPE` makes this a non-issue. llvm-svn: 310695
2017-07-15[PM/LCG] Teach the LazyCallGraph to maintain reference edges from everyChandler Carruth1-0/+2
function to every defined function known to LLVM as a library function. LLVM can introduce calls to these functions either by replacing other library calls or by recognizing patterns (such as memset_pattern or vector math patterns) and replacing those with calls. When these library functions are actually defined in the module, we need to have reference edges to them initially so that we visit them during the CGSCC walk in the right order and can effectively rebuild the call graph afterward. This was discovered when building code with Fortify enabled as that is a common case of both inline definitions of library calls and simplifications of code into calling them. This can in extreme cases of LTO-ing with libc introduce *many* more reference edges. I discussed a bunch of different options with folks but all of them are unsatisfying. They either make the graph operations substantially more complex even when there are *no* defined libfuncs, or they introduce some other complexity into the callgraph. So this patch goes with the simplest possible solution of actual synthetic reference edges. If this proves to be a memory problem, I'm happy to implement one of the clever techniques to save memory here. llvm-svn: 308088
2017-07-12[PM] Fix a silly bug in my recent update to the CG update logic.Chandler Carruth1-6/+6
I used the wrong variable to update. This was even covered by a unittest I wrote, and the comments for the unittest were correct (if confusing) but the test itself just matched the buggy behavior. =[ llvm-svn: 307764
2017-07-09CGSCCPassManagerTest.cpp: Fix warnings. [-Wunused-variable]NAKAMURA Takumi1-0/+2
llvm-svn: 307511
2017-07-09[PM] Add unittesting of the call graph update logic with complexChandler Carruth1-0/+166
dependencies between analyses. This uncovers even more issues with the proxies and the splitting apart of SCCs which are fixed in this patch. I discovered this while trying to add more rigorous testing for a change I'm making to the call graph update invalidation logic. llvm-svn: 307497
2017-07-09[PM] Finish implementing and fix a chain of bugs uncovered by testingChandler Carruth1-6/+24
the invalidation propagation logic from an SCC to a Function. I wrote the infrastructure to test this but didn't actually use it in the unit test where it was designed to be used. =[ My bad. Once I actually added it to the test case I discovered that it also hadn't been properly implemented, so I've implemented it. The logic in the FAM proxy for an SCC pass to propagate invalidation follows the same ideas as the FAM proxy for a Module pass, but the implementation is a bit different to reflect the fact that it is forwarding just for an SCC. However, implementing this correctly uncovered a surprising "bug" (it was conservatively correct but relatively very expensive) in how we handle invalidation when splitting one SCC into multiple SCCs. We did an eager invalidation when in reality we should be deferring invaliadtion for the *current* SCC to the CGSCC pass manager and just invaliating the newly constructed SCCs. Otherwise we end up invalidating too much too soon. This was exposed by the inliner test case that I've updated. Now, we invalidate *just* the split off '(test1_f)' SCC when doing the CG update, and then the inliner finishes and invalidates the '(test1_g, test1_h)' SCC's analyses. The first few attempts at fixing this hit still more bugs, but all of those are covered by existing tests. For example, the inliner should also preserve the FAM proxy to avoid unnecesasry invalidation, and this is safe because the CG update routines it uses handle any necessary adjustments to the FAM proxy. Finally, the unittests for the CGSCC pass manager needed a bunch of updates where we weren't correctly preserving the FAM proxy because it hadn't been fully implemented and failing to preserve it didn't matter. Note that this doesn't yet fix the current crasher due to MemSSA finding a stale dominator tree, but without this the fix to that crasher doesn't really make any sense when testing because it relies on the proxy behavior. llvm-svn: 307487
2016-12-27[PM] Introduce the facilities for registering cross-IR-unit dependenciesChandler Carruth1-0/+263
that require deferred invalidation. This handles the other real-world invalidation scenario that we have cases of: a function analysis which caches references to a module analysis. We currently do this in the AA aggregation layer and might well do this in other places as well. Since this is relative rare, the technique is somewhat more cumbersome. Analyses need to register themselves when accessing the outer analysis manager's proxy. This proxy is already necessarily present to allow access to the outer IR unit's analyses. By registering here we can track and trigger invalidation when that outer analysis goes away. To make this work we need to enhance the PreservedAnalyses infrastructure to support a (slightly) more explicit model for "sets" of analyses, and allow abandoning a single specific analyses even when a set covering that analysis is preserved. That allows us to describe the scenario of preserving all Function analyses *except* for the one where deferred invalidation has triggered. We also need to teach the invalidator API to support direct ID calls instead of always going through a template to dispatch so that we can just record the ID mapping. I've introduced testing of all of this both for simple module<->function cases as well as for more complex cases involving a CGSCC layer. Much like the previous patch I've not tried to fully update the loop pass management layer because that layer is due to be heavily reworked to use similar techniques to the CGSCC to handle updates. As that happens, we'll have a better testing basis for adding support like this. Many thanks to both Justin and Sean for the extensive reviews on this to help bring the API design and documentation into a better state. Differential Revision: https://reviews.llvm.org/D27198 llvm-svn: 290594
2016-12-10[PM] Support invalidation of inner analysis managers from a pass over the ↵Chandler Carruth1-23/+370
outer IR unit. Summary: This never really got implemented, and was very hard to test before a lot of the refactoring changes to make things more robust. But now we can test it thoroughly and cleanly, especially at the CGSCC level. The core idea is that when an inner analysis manager proxy receives the invalidation event for the outer IR unit, it needs to walk the inner IR units and propagate it to the inner analysis manager for each of those units. For example, each function in the SCC needs to get an invalidation event when the SCC gets one. The function / module interaction is somewhat boring here. This really becomes interesting in the face of analysis-backed IR units. This patch effectively handles all of the CGSCC layer's needs -- both invalidating SCC analysis and invalidating function analysis when an SCC gets invalidated. However, this second aspect doesn't really handle the LoopAnalysisManager well at this point. That one will need some change of design in order to fully integrate, because unlike the call graph, the entire function behind a LoopAnalysis's results can vanish out from under us, and we won't even have a cached API to access. I'd like to try to separate solving the loop problems into a subsequent patch though in order to keep this more focused so I've adapted them to the API and updated the tests that immediately fail, but I've not added the level of testing and validation at that layer that I have at the CGSCC layer. An important aspect of this change is that the proxy for the FunctionAnalysisManager at the SCC pass layer doesn't work like the other proxies for an inner IR unit as it doesn't directly manage the FunctionAnalysisManager and invalidation or clearing of it. This would create an ever worsening problem of dual ownership of this responsibility, split between the module-level FAM proxy and this SCC-level FAM proxy. Instead, this patch changes the SCC-level FAM proxy to work in terms of the module-level proxy and defer to it to handle much of the updates. It only does SCC-specific invalidation. This will become more important in subsequent patches that support more complex invalidaiton scenarios. Reviewers: jlebar Subscribers: mehdi_amini, mcrosier, mzolotukhin, llvm-commits Differential Revision: https://reviews.llvm.org/D27197 llvm-svn: 289317
2016-11-28[PM] Extend the explicit 'invalidate' method API on analysis results toChandler Carruth1-1/+4
accept an Invalidator that allows them to invalidate themselves if their dependencies are in turn invalidated. Rather than recording the dependency graph ahead of time when analysis get results from other analyses, this simply lets each result trigger the immediate invalidation of any analyses they actually depend on. They do this in a way that has three nice properties: 1) They don't have to handle transitive dependencies because the infrastructure will recurse for them. 2) The invalidate methods are still called only once. We just dynamically discover the necessary topological ordering, everything is memoized nicely. 3) The infrastructure still provides a default implementation and can access it so that only analyses which have dependencies need to do anything custom. To make this work at all, the invalidation logic also has to defer the deletion of the result objects themselves so that they can remain alive until we have collected the complete set of results to invalidate. A unittest is added here that has exactly the dependency pattern we are concerned with. It hit the use-after-free described by Sean in much detail in the long thread about analysis invalidation before this change, and even in an intermediate form of this change where we failed to defer the deletion of the result objects. There is an important problem with doing dependency invalidation that *isn't* solved here: we don't *enforce* that results correctly invalidate all the analyses whose results they depend on. I actually looked at what it would take to do that, and it isn't as hard as I had thought but the complexity it introduces seems very likely to outweigh the benefit. The technique would be to provide a base class for an analysis result that would be populated with other results, and automatically provide the invalidate method which immediately does the correct thing. This approach has some nice pros IMO: - Handles the case we care about and nothing else: only *results* that depend on other analyses trigger extra invalidation. - Localized to the result rather than centralized in the analysis manager. - Ties the storage of the reference to another result to the triggering of the invalidation of that analysis. - Still supports extending invalidation in customized ways. But the down sides here are: - Very heavy-weight meta-programming is needed to provide this base class. - Requires a pretty awful API for accessing the dependencies. Ultimately, I fear it will not pull its weight. But we can re-evaluate this at any point if we start discovering consistent problems where the invalidation and dependencies get out of sync. It will fit as a clean layer on top of the facilities in this patch that we can add if and when we need it. Note that I'm not really thrilled with the names for these APIs... The name "Invalidator" seems ok but not great. The method name "invalidate" also. In review some improvements were suggested, but they really need *other* uses of these terms to be updated as well so I'm going to do that in a follow-up commit. I'm working on the actual fixes to various analyses that need to use these, but I want to try to get tests for each of them so we don't regress. And those changes are seperable and obvious so once this goes in I should be able to roll them out throughout LLVM. Many thanks to Sean, Justin, and others for help reviewing here. Differential Revision: https://reviews.llvm.org/D23738 llvm-svn: 288077