These steps add a pass to LLVM 3.8. This guide was co-authored with @anh-q
Pick a pass class based on its purpose.
| Class | Purpose |
|---|---|
| ModulePass | Execute on entire module. Suitable for whole-program analysis and transformation. |
| FunctionPass | Execute on each function. Does not provide inter-procedural view. |
| ImmutablePass | Used to maintain information about current compilation state. |
| MachineFunctionPass | Execute machine code generated for a specific target. Cannot modify anything related to IR. |
Classify your pass based on its functionality. Below are some popular categories of an LLVM pass. The category will decide where your pass belong to in the source code hierarchy.
| Category | Functionality | Declaration Location | Implementation Location |
|---|---|---|---|
| Analysis | Compute information that other passes can used. | include/llvm/Analysis | lib/Analysis |
| CodeGen | Generate machine code from IR. | include/llvm/CodeGen | lib/CodeGen |
| Transform | Modify program's IR. Within the Transform category, IPO means inter-procedural. | include/llvm/Transforms | lib/Transforms |
| Utility | Passes that do not fit any of the above categories. |
- Write the declarations in the pass’ header file. Place header file in an appropriate location. See
MyPass.h. - Write the pass’ implementation in the pass’ source file. Place in the appropriate location. Override
runOnModule()for module passes,runOnFunction()for functions, etc. SeeMyPass.c
- Use the
STATISTICmacro if necessary for keeping pass performance statistics (e.g. number of optimizations performed, pass execution time, etc.). Logging the statistics requires passing the-statsoption at the command line invocation. - Use the
INITIALIZE_PASSmacro to prepare the pass for registration. If MyPass uses analysis from other pass such as CallGraph, useINITIALIZE_PASS_BEGINinstead ofINITIALIZE_PASSso that pass manager can runMyPassafter the required analysis pass. SeeINITIALIZE_PASS_BEGINin LLVM documentation for specific example. Also, remember to implementgetAnalysisUsage()`. - Override
doInitialization()ordoFinalization()if needed. This does not apply toImmutablePass. - Avoid the following:
- Using
std::endlor include<iostream>, because of unnecessary code to initialize iostream object at startup. - Declaring
using namespace std, because of namespace conflicts with the LLVM namespace.
- Using
- Register your pass source files with CMake:
- Add a
add_llvm_loadable_moduleentry to the source’s directory’s CMakeLists.txt. This provides a rule to CMake to make your pass’ dynamically loaded library. - Add a
add_subdirectoryto the source’s parent directory’s CMakeLists.txt. This provides a rule to CMake to add your pass’ directory to the build. - Register your pass with the LLVM pass manager:
- Declare
ModulePass *createMyPassPass();in:- include/llvm/Analysis/Passes.h (Analysis pass)
- include/llvm/CodeGen/Passes.h (CodeGen pass)
- include/llvm/Transforms/IPO.h (IPO pass)
- include/llvm/Transforms/MyPass/MyPass.h (Transform passes)
- Call
initializeMyPassPass(registry);in:- lib/Analysis/Analysis.cpp (Analysis pass)
- lib/CodeGen/CodeGen.cpp (CodeGen pass)
- lib/Transforms/IPO/IPO.cpp (IPO and Transform passes)
- Add a signature for
(void) llvm::createMyPassPass();in include/llvm/LinkAllPasses.h - Add a signature for
void initializeMyPassPass(PassRegistry&);to include/llvm/InitializePasses.h
- Declare
- Place pass in LLVM pipeline:
- Optimization passes (passes which operate in IR): lib/Transforms/PassManagerBuilder.cpp
- CodeGen passes: lib/CodeGen/LLVMTargetMachine.cpp.
- Create a front-end invocation flag. See +Add a LLVM Front-end Invocation Option