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