Adding the pass to the LLVM source tree – Optimizing IR

Implementing a new pass as a plugin is useful if you plan to use it with a precompiled clang, for example. On the other hand, if you write your own compiler, then there can be good reasons to add your new passes directly to the LLVM source tree. There are two different ways you can do this – as a plugin and as a fully integrated pass. The plugin approach requires fewer changes.

Utilizing the plugin mechanisms inside the LLVM source tree

The source of passes that perform transformations on LLVM IR is located in the llvm-project/llvm/lib/Transforms directory. Inside this directory, create a new directory called PPProfiler and copy the source file, PPProfiler.cpp, into it. You do not need to make any source changes!

To integrate the new plugin into the build system, create a file called CMakeLists.txt with the following content:
add_llvm_pass_plugin(PPProfiler PPProfiler.cpp)

Finally, in the CmakeLists.txt file in the parent directory, you need to include the new source directory by adding the following line:
add_subdirectory(PPProfiler)

You are now ready to build LLVM with PPProfiler added. Change into the build directory of LLVM and manually run Ninja:
$ ninja install

CMake will detect a change in the build description and rerun the configuration step. You will see an additional line:
— Registering PPProfiler as a pass plugin (static build: OFF)

This tells you that the plugin was detected and has been built as a shared library. After the installation step, you will find that shared library, PPProfiler.so, in the <install directory>/lib directory.

So far, the only difference to the pass plugin from the previous section is that the shared library is installed as part of LLVM. But you can also statically link the new plugin to the LLVM tools. To do this, you need to rerun the CMake configuration and add the -DLLVM_PPPROFILER_LINK_INTO_TOOLS=ON option on the command line. Look for this information from CMake to confirm the changed build option:
— Registering PPProfiler as a pass plugin (static build: ON)

After compiling and installing LLVM again, the following has changed:

  • The plugin is compiled into the static library, libPPProfiler.a, and that library is installed in the <install directory>/lib directory.
  • The LLVM tools, such as opt, are linked against that library.
  • The plugin is registered as an extension. You can check that the <install directory>/include/llvm/Support/Extension.def file now contains the following line:

HANDLE_EXTENSION(PPProfiler)

In addition, all tools that support this extension mechanism pick up the new pass. In the Creating an optimization pipeline section, you will learn how to do this in your compiler.

This approach works well because the new source files reside in a separate directory, and only one existing file was changed. This minimizes the probability of merge conflicts if you try to keep your modified LLVM source tree in sync with the main repository.

There are also situations where adding the new pass as a plugin is not the best way. The passes that LLVM provides use a different way for registration. If you develop a new pass and propose to add it to LLVM, and the LLVM community accepts your contribution, then you will want to use the same registration mechanism.