LLVM Tips and Tricks

ADDING A PASS TO THE DEFAULT CLANG PIPELINE

LLVM official documentation gives a fairly clear way to run a single pass using opt:


    clang -emit-llvm $(CFLAGS) -o target.bc -c target.c
    opt -passes="mypass" target.bc > target_optimized.bc
    clang target_optimized.bc -o $@
By default, other passes do not run using this method, and if you wanted your pass to run on any project you build, you would have to modify the projects' Makefiles (or other configuration files) in order to run your pass. Instead you can add your pass to the default Clang pipeline.

Option 1: Add a Pass to Default LLVM Pipeline.
Clang builds the default LLVM pipeline as part of its own pass pipeline. The default LLVM pipelines are in /llvm/lib/Passes/PassBuilderPipelines.cpp, and the function you will probably edit is buildPerModuleDefaultPipeline(Level, LTOPreLink). You can directly add your pass somewhere using:

    MPM.addPass(myPass());
If you want your pass to run only on certain optimization levels, you can check Level == OptimizationLevel::O0, changing O0 to the relevant level. You can also place your call to addPass in one of the callee functions like buildModuleSimplificationPipeline if the function seems appropriate.

Option 2: Add a Pass to Default Clang Pipeline.
The relevant file here is /clang/lib/CodeGen/BackendUtil.cpp, and the relevant function is RunOptimizationPipeline. Most passes applied by Clang are added using callbacks. For example, if you'd like your pass to be run with default early simplification passes, then you can use PB.registerPipelineEarlySimplificationEPCallback(...). There are a number of callbacks that you can use which determine at which point during compliation your pass would run. In a nutshell, the RunOptimizationPipeline registers the callbacks, builds the default pipeline (inserting the callback passes as specified earlier) with MPM = PB.buildPerModuleDefaultPipeline(Level), adds some final passes to the pipeline, and then runs the pipeline. So, callbacks should be inserted before the call to PB.buildPerModuleDefaultPipeline. If you're okay with running your pass at the end of the pipeline, then you can use MPM.addPass(myPass()) after that call, but before the statement MPM.run(*TheModule, MAM); at the very end of the function.


With either option, you can just run clang as normal and have your pass run. Yay!

WHICH PASSES ARE IN THE PIPELINE?

Using opt, you can just use the -print-pipeline-passes flag, but Clang doesn't seem to have an option for this right now.

OPT AND CLANG QUIRKS

If you run Clang with -emit-llvm, it does not use LTO and it defaults to -O0. If you intend to run opt after clang -emit-llvm, you may have to include -disable-O0-optnone, which would otherwise refuse to let passes run on the optnone-labeled functions.

When you run opt, it won't run the default LLVM pass pipeline, so when specifying passes, you can specify -passes="myPass,default,myOtherPass", which runs the passes in the order you listed them. There is no way (I think) to use opt to run the default Clang pipeline.