registering passes at the beginning/end of opt passes (new pass manager)

Hello all,

Can I register passes at the beginning/end of opt passes (new pass manager)?

I found that registerPipelineStartEPCallback/registerOptimizerLastEPCallback work successfully for clang, but they don’t fire when opt -passes=“” is used.


I’m not sure what’s your context. I think -passes is only used for specify the entire pipeline instead of inserting callbacks into an existing pipeline.

You can either directly modify PassBuilder’s code to run Passes before/after a Pass.

Or writing a new PassManager PassPlugin and use the PassBuilder instance in there (see the comments in include/llvm/Passes/PassPlugin.h [1]) to call registerPipelineStartEPCallback. Then load that plugin using opt.



There are various opt options 1 that let you specify passes to add at specific points in the pipeline. Also, specifying a target may cause the corresponding TargetMachine to register pass callbacks.
Something like “-passes=default” that creates a full pipeline will add those passes to the pipeline. Otherwise they aren’t invoked.

Hello Min-Yih, Arthur.

Thank you for the infos.
The context was that I wanted to run a special pass at the beginning/end of passes whenever a user is running opt with one’s custom arguments.
I was curious whether there is a way to do this without using a wrapper script that introduces the special pass’s name to -passes=“…” options somehow.

It seems the register callback functions are invoked only when a default pipeline like default is used, not when a pass like -passes=‘simplify-cfg’ is given, as Arthur described.
Since the special pass should run regardless of whether the pass is default or not, I’ll turn to manually giving the pass name and find out.


Okay, I tried something like this:

Given opt -passes=‘…’, my bash script strips the quotes, puts module(mypass) at the begin/end, put quotes again, and runs it. mypass is a module-level pass.

ex) Given opt -passes=‘sroa’ , it emits opt -passes=‘module(mypass),sroa,module(mypass)’

The emitted command seems working in this case, but I found that it breaks when loop-level passes are there:

ex) Running opt -passes=‘module(mypass),loop(unswitch),module(mypass)’ shows:
build/bin/opt: invalid use of ‘loop’ pass as module pipeline

Is there a way to correctly add ‘mypass’ to the begin/end of the passes regardless of the level of the pipeline?


You could always specify the full adaptor stack for loop passes, e.g. “module(function(loop(unswitch)))”.

Another option is to register your passes via the flags mentioned above and run default, which should invoke all the registered callbacks.

Is there a rewriter tool that converts input passes into a string with full adaptor stacks?

It seems manually updating existing tests’ passes to have full adaptor stack is a tricky job; it would be great if there is an automatic way of doing that.


Currently there isn’t such a rewriter. Although I may want to create one so we can mass migrate tests to use the -passes= form after the NPM switch.

Wow, I should use the rewriter when the migration happens.
Thanks for the info!