Per http://llvm.org/OpenProjects.html#llvm_loopnest, the goal of this patch is to create facilities that allow implementing loop nest passes that run on top-level loop nests for the New Pass Manager.
Under the design, the loop nest passes will have a run method with the following signature:
PreservedAnalyses run(LoopNest &LN, LoopNestAnalysisManager &AM, LoopStandardAnalysisResults &AR, LNPMUpdater &U);
LNPMUpdater (short for loop nest pass manager updater) supports invalidating loop nests (markLoopNestAsDeleted), re-visiting the current loop nest (revisitCurrentLoopNest) and adding new top-level loop nests to the function (addNewLoopNests).
The loop nest passes can be grouped together by LoopNestPassManager, and then embedded into an FPM via FunctionToLoopNestPassAdaptor. Since both FunctionToLoopNestPassAdaptor and FunctionToLoopPassAdaptor require loop canonicalization passes to be run first, the LoopNestToLoopPassAdaptor is also introduced in the patch.
The intended usage of the adaptor is to group the loop passes together into an LPM first, and then embed the LPM into LoopNestPassManager. With this, the loop canonicalization phase will be run only once for both loop and loop nest passes. One example is as follows:
LoopPassManager LPM; LPM.addPass(SomeLoopPass()); LoopNestPassManager LNPM; LNPM.addPass(SomeLoopNestPass()); LNPM.addPass(createLoopNestToLoopPassAdaptor(std::move(LPM))); FunctionPassManager FPM; FPM.addPass(createFunctionToLoopNestPassAdaptor(std::move(LNPM)));
Note that the loop nest pass should explicitly preserve the LoopNestAnalysis (or just returns PreservedAnalyses::all()) if it does not modify the loop structures. Otherwise, the LoopNest object will be re-built every time a loop nest gets revisited.
Currently, the LoopNestAnalysisManager is nothing but a wrapper around LoopAnalysisManager (the former holds a reference to the latter) that provides the APIs on LoopNest and forwards the requests to the internal LPM. That is, the loop nest analyses should still be implemented as loop analyses, and the run method of the analysis receives the root loop of the corresponding loop nest.
The reason behind the design is that we do not support updating the LoopNest object dynamically yet. That means the LoopNest object will be constantly invalidated by the loop nest passes and loop passes, and invalidating a LoopNest structure means that we have to invalidate all analyses associated with it. This is quite inefficient since the analyses might have the ability to be maintained online.
There is no LoopAnalysisManagerLoopNestProxy since the two analysis managers are essentially the same thing. However, LoopNestAnalysisManager still provides a getter getLoopAnalysisManager() to extract the internal LAM. The invalidate() method of LoopNestAnalysisManager comprises two steps: firstly, the "loop analyses" of loops in the subtree are invalidated (one can preserve all analyses on Loop to avoid this), and secondly, the loop analyses and loop nest analyses of the root loop are invalidated. This is similar to what the inner proxies offer.
Other facilities like parsing the pipeline, the proxies between analysis managers, are also implemented in this patch. The PassBuilderCallbacksTest has also been applied to loop-nest-related infrastructures. The actual functionalities of the components, however, are not tested yet. Still, embedding loop passes into LNPM seems to be working as I've modified some existing loop-pass related tests to verify the results. Also, all the existing unit-tests and regression-tests work, so at least this is not breaking anything now.
Though we definitely need more testing on the functionalities, I would like the submit the diff earlier to see what you think about the patch and the design. Fine-grained tests will be added later.
Please kindly provide feedback and comments on the patch. Thank you very much!
clang-format: please reformat the code