========================== 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 a 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`` and ``FunctionPass2`` on the first function in a module, then run both passes on 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()``. Clang's ``BackendUtil.cpp`` shows examples of a frontend adding (mostly sanitizer) passes to various parts of the pipeline. ``AMDGPUTargetMachine::registerPassBuilderCallbacks()`` is an example of a backend adding passes to various parts of the pipeline. 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.