Pass nesting in new pass manager

For an optimization pipeline built from the following code, what’s the correct that passes get unnested and scheduled?

ModulePassManager MPM;
CGSCCPassManager CGPM;
FunctionPassManager FPM;
LoopPassManager LPM;





Does each adapted PM (consisting a list of passes for a smaller data structure) get scheduled as a PM after adaption? To elaborate, is this the correct order for the above pipeline? Thanks!

foo-module-pass over the entire module

for each cgscc in the module
   run foo-cgscc-pass over cgscc
   for each func in cgscc
     run foo-func-pass over func
     for each loop in func
        run foo-loop-pass over loop
        run bar-loop-pass over loop
     run bar-func-pass over func

  run bar-cgscc-pass over cgscc

bar-module-pass over the entire module

@aeubanks I’m reading The New Pass Manager - The LLVM Project Blog and loop you in to confirm if this is the correct understanding. Thanks!

I don’t think it’s helpful to think of explicit “scheduling”, the pass managers simply run all of the passes contained in them in order. Something like FunctionToLoopPassAdaptor is just another function pass that gets run, and when it runs it will find all the loops in the function and run its contained pass on each loop. There’s no global scheduler that looks into the pass pipeline, there’s no “unnesting” that happens.

But yes, at a high level the ordering is correct.

The for each cgscc/loop is a bit more complicated though, you have to choose some order, and cgscc/loop passes can change the visit order due to removing/adding those IR constructs. That logic happens mostly in the pass adaptors’ run methods (e.g. ModuleToPostOrderCGSCCPassAdaptor::run).

1 Like