diff --git a/llvm/docs/NewPassManager.rst b/llvm/docs/NewPassManager.rst new file mode 100644 --- /dev/null +++ b/llvm/docs/NewPassManager.rst @@ -0,0 +1,163 @@ +========================== +Using the New Pass Manager +========================== + +.. contents:: + :local: + +Adding Passes to a Pass Manager +=============================== + +For how to write a new PM pass, see :doc:`this page `. + +To add a pass to a new PM pass manager, the important thing is to match the +pass type and the pass manager type. For example, a ``FunctionPassManager`` +can only contain function passes: + +.. code-block:: c++ + + FunctionPassManager FPM; + // InstSimplifyPass is a function pass + FPM.addPass(InstSimplifyPass()); + +If you want add a loop pass that runs on all loops in a function to a +``FunctionPassManager``, the loop pass must be wrapped in an function pass +adaptor that goes through all the loops in the function and runs the loop +pass on each one. + +.. code-block:: c++ + + FunctionPassManager FPM; + // LoopRotatePass is a loop pass + FPM.addPass(createFunctionToLoopPassAdaptor(LoopRotatePass())); + +The IR hierarchy in terms of the new PM is Module -> (CGSCC ->) Function -> +Loop, where going through a CGSCC is optional. + +.. code-block:: c++ + + FunctionPassManager FPM; + // loop -> function + FPM.addPass(createFunctionToLoopPassAdaptor(LoopFooPass())); + + CGSCCPassManager CGPM; + // loop -> function -> cgscc + CGPM.addPass(createCGSCCToFunctionPassAdaptor(createFunctionToLoopPassAdaptor(LoopFooPass()))); + // function -> cgscc + CGPM.addPass(createCGSCCToFunctionPassAdaptor(FunctionFooPass())); + + ModulePassManager MPM; + // loop -> function -> module + MPM.addPass(createModuleToFunctionPassAdaptor(createFunctionToLoopPassAdaptor(LoopFooPass()))); + // function -> module + MPM.addPass(createModuleToFunctionPassAdaptor(FunctionFooPass())); + + // loop -> function -> cgscc -> module + MPM.addPass(createModuleToCGSCCPassAdaptor(createCGSCCToFunctionPassAdaptor(createFunctionToLoopPassAdaptor(LoopFooPass())))); + // function -> cgscc -> module + MPM.addPass(createModuleToCGSCCPassAdaptor(createCGSCCToFunctionPassAdaptor(FunctionFooPass()))); + + +A pass manager of a specific IR unit is also a pass of that kind. For +example, a ``FunctionPassManager`` is a function pass, meaning it can be +added to a ``ModulePassManager``: + +.. code-block:: c++ + + ModulePassManager MPM; + + FunctionPassManager FPM; + // InstSimplifyPass is a function pass + FPM.addPass(InstSimplifyPass()); + + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + +Generally you want to group CGSCC/function/loop passes together in a pass +manager, as opposed to adding adaptors for each pass to the containing upper +level pass manager. For example, + +.. code-block:: c++ + + ModulePassManager MPM; + MPM.addPass(createModuleToFunctionPassAdaptor(FunctionPass1())); + MPM.addPass(createModuleToFunctionPassAdaptor(FunctionPass2())); + MPM.run(); + +will run ``FunctionPass1`` on each function in a module, then run +``FunctionPass2`` on each function in the module. In contrast, + +.. code-block:: c++ + + ModulePassManager MPM; + + FunctionPassManager FPM; + FPM.addPass(FunctionPass1()); + FPM.addPass(FunctionPass2()); + + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + +will, run ``FunctionPass1`` on the first function in a module, then run +``FunctionPass2`` on it. Then do the same for the second function in the +module, and so on. This is better for cache locality around LLVM data +structures. This similarly applies for the other IR types, and in some cases +can even affect the quality of optimization. For example, running all loop +passes on a loop may cause a later loop to be able to be optimized more than +if each loop pass were run separately. + +Inserting Passes into Default Pipelines +======================================= + +Rather than manually adding passes to a pass manager, the typical way of +creating a pass manager is to use a ``PassBuilder`` and call something like +``PassBuilder::buildPerModuleDefaultPipeline()`` which creates a typical +pipeline for a given optimization level. + +Sometimes either frontends or backends will want to inject passes into the +pipeline. For example, frontends may want to add instrumentation, and target +backends may want to add passes that lower custom intrinsics. For these +cases, ``PassBuilder`` exposes callbacks that allow injecting passes into +certain parts of the pipeline. For example, + +.. code-block:: c++ + + PassBuilder PB; + PB.registerPipelineStartEPCallback([&](ModulePassManager &MPM, + PassBuilder::OptimizationLevel Level) { + MPM.addPass(FooPass()); + }; + +will add ``FooPass`` near the very beginning of the pipeline for pass +managers created by that ``PassBuilder``. See the documentation for +``PassBuilder`` for the various places that passes can be added. + +If a ``PassBuilder`` has a corresponding ``TargetMachine`` for a backend, it +will call ``TargetMachine::registerPassBuilderCallbacks()`` to allow the +backend to inject passes into the pipeline. This is equivalent to the legacy +PM's ``TargetMachine::adjustPassManager()``. + +Status of the New and Legacy Pass Managers +========================================== + +LLVM currently contains two pass managers, the legacy PM and the new PM. The +optimization pipeline (aka the middle-end) works with both the legacy PM and +the new PM, whereas the backend target-dependent code generation only works +with the legacy PM. + +For the optimization pipeline, the new PM is the default PM. The legacy PM is +available for the optimization pipeline either by setting the CMake flag +``-DENABLE_EXPERIMENTAL_NEW_PASS_MANAGER=OFF`` when building LLVM, or by +various compiler/linker flags, e.g. ``-flegacy-pass-manager`` for ``clang``. + +There will be efforts to deprecate and remove the legacy PM for the +optimization pipeline in the future. + +Some IR passes are considered part of the backend codegen pipeline even if +they are LLVM IR passes (whereas all MIR passes are codegen passes). This +includes anything added via ``TargetPassConfig`` hooks, e.g. +``TargetPassConfig::addCodeGenPrepare()``. As mentioned before, passes added +in ``TargetMachine::adjustPassManager()`` are part of the optimization +pipeline, and should have a corresponding line in +``TargetMachine::registerPassBuilderCallbacks()``. + +Currently there are efforts to make the codegen pipeline work with the new +PM. diff --git a/llvm/docs/UserGuides.rst b/llvm/docs/UserGuides.rst --- a/llvm/docs/UserGuides.rst +++ b/llvm/docs/UserGuides.rst @@ -44,6 +44,7 @@ MCJITDesignAndImplementation ORCv2 JITLink + NewPassManager NVPTXUsage Phabricator Passes