Nested Pass Manager Usage

I have a pass pipeline that operates on a module that will start with this structure

module {
   ....
}

After a few passes are run the module looks like

module {
   ...
   module {gpu.container_module} {
     ...
   }
}

And after even more passes are run looks like.

module {
   ....
   module {gpu.container_module} {
   ....
      spv.module {
      ....
      }
   ....
   }
   ...
}

I set up the pipeline as follows

PassManager pm(ctx);
/// Add passes to operate on the outermost module to create module {gpu.container_module}

OpPassManager &nestedModulePM = pm.nest<ModuleOp>();
/// Add passes to operate on module {gpu.container_module} to create spv.module

OpPassManager &spirvModulePM = nestedModulePM.nest<spirv::ModuleOp>();
/// Add passes to operate on spv.module

This follows what is described here
This doesnt seem to be invoking the passes on the spirv::ModuleOp. Wondering if I am missing something here, and if I am using the pass manager as intended.

That looks right, what pass are you trying to run?

This pass : llvm-project/LowerABIAttributesPass.cpp at 20f005d25f488fa1dc69d6792700e014c6a5d165 · llvm/llvm-project · GitHub

Got some help from River on triaging this. My reading of the module structure was wrong. It is actually

module {gpu.container_module} {
   ...
   spv.module {
      ...
   }
}

So the top level module is the one with the gpu.container_module attribute (I mistakenly thought there is an implicit top-level module). Changing the pipeline as follows works

PassManager pm(ctx);
/// Add passes to operate on the outermost module to create module {gpu.container_module}

OpPassManager &spirvModulePM = pm.nest<spirv::ModuleOp>();
/// Add passes to operate on spv.module