xref: /llvm-project/llvm/docs/WritingAnLLVMNewPMPass.rst (revision 1b5fae9118ab3450f22fb45f686a2cd0d979cbb4)
1====================
2Writing an LLVM Pass
3====================
4
5.. program:: opt
6
7.. contents::
8    :local:
9
10Introduction --- What is a pass?
11================================
12
13.. warning::
14  This document deals with the new pass manager. LLVM uses the legacy pass
15  manager for the codegen pipeline. For more details, see
16  :doc:`WritingAnLLVMPass` and :doc:`NewPassManager`.
17
18The LLVM pass framework is an important part of the LLVM system, because LLVM
19passes are where most of the interesting parts of the compiler exist. Passes
20perform the transformations and optimizations that make up the compiler, they
21build the analysis results that are used by these transformations, and they
22are, above all, a structuring technique for compiler code.
23
24Unlike passes under the legacy pass manager where the pass interface is
25defined via inheritance, passes under the new pass manager rely on
26concept-based polymorphism, meaning there is no explicit interface (see
27comments in ``PassManager.h`` for more details). All LLVM passes inherit from
28the CRTP mix-in ``PassInfoMixin<PassT>``. The pass should have a ``run()``
29method which returns a ``PreservedAnalyses`` and takes in some unit of IR
30along with an analysis manager. For example, a function pass would have a
31``PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);`` method.
32
33We start by showing you how to construct a pass, from setting up the build,
34creating the pass, to executing and testing it. Looking at existing passes is
35always a great way to learn details.
36
37Quick Start --- Writing hello world
38===================================
39
40Here we describe how to write the "hello world" of passes. The "HelloWorld"
41pass is designed to simply print out the name of non-external functions that
42exist in the program being compiled. It does not modify the program at all,
43it just inspects it.
44
45The code below already exists; feel free to create a pass with a different
46name alongside the HelloWorld source files.
47
48.. _writing-an-llvm-npm-pass-build:
49
50Setting up the build
51--------------------
52
53First, configure and build LLVM as described in :doc:`GettingStarted`.
54
55Next, we will reuse an existing directory (creating a new directory involves
56messing around with more CMake files than we want). For this example, we'll use
57``llvm/lib/Transforms/Utils/HelloWorld.cpp``, which has already been created.
58If you'd like to create your own pass, add a new source file into
59``llvm/lib/Transforms/Utils/CMakeLists.txt`` (assuming you want your pass in
60the ``Transforms/Utils`` directory.
61
62Now that we have the build set up for a new pass, we need to write the code
63for the pass itself.
64
65.. _writing-an-llvm-npm-pass-basiccode:
66
67Basic code required
68-------------------
69
70Now that the build is setup for a new pass, we just have to write it.
71
72First we need to define the pass in a header file. We'll create
73``llvm/include/llvm/Transforms/Utils/HelloWorld.h``. The file should
74contain the following boilerplate:
75
76.. code-block:: c++
77
78  #ifndef LLVM_TRANSFORMS_HELLONEW_HELLOWORLD_H
79  #define LLVM_TRANSFORMS_HELLONEW_HELLOWORLD_H
80
81  #include "llvm/IR/PassManager.h"
82
83  namespace llvm {
84
85  class HelloWorldPass : public PassInfoMixin<HelloWorldPass> {
86  public:
87    PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
88  };
89
90  } // namespace llvm
91
92  #endif // LLVM_TRANSFORMS_HELLONEW_HELLOWORLD_H
93
94This creates the class for the pass with a declaration of the ``run()``
95method which actually runs the pass. Inheriting from ``PassInfoMixin<PassT>``
96sets up some more boilerplate so that we don't have to write it ourselves.
97
98Our class is in the ``llvm`` namespace so that we don't pollute the global
99namespace.
100
101Next we'll create ``llvm/lib/Transforms/Utils/HelloWorld.cpp``, starting
102with
103
104.. code-block:: c++
105
106  #include "llvm/Transforms/Utils/HelloWorld.h"
107
108... to include the header file we just created.
109
110.. code-block:: c++
111
112  using namespace llvm;
113
114... is required because the functions from the include files live in the llvm
115namespace. This should only be done in non-header files.
116
117Next we have the pass's ``run()`` definition:
118
119.. code-block:: c++
120
121  PreservedAnalyses HelloWorldPass::run(Function &F,
122                                        FunctionAnalysisManager &AM) {
123    errs() << F.getName() << "\n";
124    return PreservedAnalyses::all();
125  }
126
127... which simply prints out the name of the function to stderr. The pass
128manager will ensure that the pass will be run on every function in a module.
129The ``PreservedAnalyses`` return value says that all analyses (e.g. dominator
130tree) are still valid after this pass since we didn't modify any functions.
131
132That's it for the pass itself. Now in order to "register" the pass, we need
133to add it to a couple places. Add the following to
134``llvm/lib/Passes/PassRegistry.def`` in the ``FUNCTION_PASS`` section
135
136.. code-block:: c++
137
138  FUNCTION_PASS("helloworld", HelloWorldPass())
139
140... which adds the pass under the name "helloworld".
141
142``llvm/lib/Passes/PassRegistry.def`` is #include'd into
143``llvm/lib/Passes/PassBuilder.cpp`` multiple times for various reasons. Since
144it constructs our pass, we need to also add the proper #include in
145``llvm/lib/Passes/PassBuilder.cpp``:
146
147.. code-block:: c++
148
149  #include "llvm/Transforms/Utils/HelloWorld.h"
150
151This should be all the code necessary for our pass, now it's time to compile
152and run it.
153
154Running a pass with ``opt``
155---------------------------
156
157Now that you have a brand new shiny pass, we can build :program:`opt` and use
158it to run some LLVM IR through the pass.
159
160.. code-block:: console
161
162  $ ninja -C build/ opt
163  # or whatever build system/build directory you are using
164
165  $ cat /tmp/a.ll
166  define i32 @foo() {
167    %a = add i32 2, 3
168    ret i32 %a
169  }
170
171  define void @bar() {
172    ret void
173  }
174
175  $ build/bin/opt -disable-output /tmp/a.ll -passes=helloworld
176  foo
177  bar
178
179Our pass ran and printed the names of functions as expected!
180
181Testing a pass
182--------------
183
184Testing our pass is important to prevent future regressions. We'll add a lit
185test at ``llvm/test/Transforms/Utils/helloworld.ll``. See
186:doc:`TestingGuide` for more information on testing.
187
188.. code-block:: llvm
189
190  $ cat llvm/test/Transforms/Utils/helloworld.ll
191  ; RUN: opt -disable-output -passes=helloworld %s 2>&1 | FileCheck %s
192
193  ; CHECK: {{^}}foo{{$}}
194  define i32 @foo() {
195    %a = add i32 2, 3
196    ret i32 %a
197  }
198
199  ; CHECK-NEXT: {{^}}bar{{$}}
200  define void @bar() {
201    ret void
202  }
203
204  $ ninja -C build check-llvm
205  # runs our new test alongside all other llvm lit tests
206
207FAQs
208====
209
210Required passes
211---------------
212
213A pass that defines a static ``isRequired()`` method that returns true is a required pass. For example:
214
215.. code-block:: c++
216
217  class HelloWorldPass : public PassInfoMixin<HelloWorldPass> {
218  public:
219    PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
220
221    static bool isRequired() { return true; }
222  };
223
224A required pass is a pass that may not be skipped. An example of a required
225pass is ``AlwaysInlinerPass``, which must always be run to preserve
226``alwaysinline`` semantics. Pass managers are required since they may contain
227other required passes.
228
229An example of how a pass can be skipped is the ``optnone`` function
230attribute, which specifies that optimizations should not be run on the
231function. Required passes will still be run on ``optnone`` functions.
232
233For more implementation details, see
234``PassInstrumentation::runBeforePass()``.
235
236Registering passes as plugins
237-----------------------------
238
239LLVM provides a mechanism to register pass plugins within various tools like
240``clang`` or ``opt``. A pass plugin can add passes to default optimization
241pipelines or to be manually run via tools like ``opt``.  For more information,
242see :doc:`NewPassManager`.
243
244Create a CMake project at the root of the repo alongside
245other projects.  This project must contain the following minimal
246``CMakeLists.txt``:
247
248.. code-block:: cmake
249
250    add_llvm_pass_plugin(MyPassName source.cpp)
251
252See the definition of ``add_llvm_pass_plugin`` for more CMake details.
253
254The pass must provide at least one of two entry points for the new pass manager,
255one for static registration and one for dynamically loaded plugins:
256
257- ``llvm::PassPluginLibraryInfo get##Name##PluginInfo();``
258- ``extern "C" ::llvm::PassPluginLibraryInfo llvmGetPassPluginInfo() LLVM_ATTRIBUTE_WEAK;``
259
260Pass plugins are compiled and linked dynamically by default. Setting
261``LLVM_${NAME}_LINK_INTO_TOOLS`` to ``ON`` turns the project into a statically
262linked extension.
263
264For an in-tree example, see ``llvm/examples/Bye/``.
265
266To make ``PassBuilder`` aware of statically linked pass plugins:
267
268.. code-block:: c++
269
270    // Declare plugin extension function declarations.
271    #define HANDLE_EXTENSION(Ext) llvm::PassPluginLibraryInfo get##Ext##PluginInfo();
272    #include "llvm/Support/Extension.def"
273
274    ...
275
276    // Register plugin extensions in PassBuilder.
277    #define HANDLE_EXTENSION(Ext) get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);
278    #include "llvm/Support/Extension.def"
279
280To make ``PassBuilder`` aware of dynamically linked pass plugins:
281
282.. code-block:: c++
283
284    // Load plugin dynamically.
285    auto Plugin = PassPlugin::Load(PathToPlugin);
286    if (!Plugin)
287      report_error();
288    // Register plugin extensions in PassBuilder.
289    Plugin.registerPassBuilderCallbacks(PB);
290