Skip to content

Conversation

@rturrado
Copy link
Contributor

@rturrado rturrado commented Aug 16, 2025

Context:

Issue #1684 points to the maintenance problem of having to add a mlir::registerPass(<module>::create<pass name>Pass); at registerAllCatalystPasses function for every new pass.

Description of the Change:

An early look at the <module>/Transforms/Passes.h.inc files, e.g., Catalyst/Transforms/Passes.h.inc, shows that:

  • There is already an auto generated register<module>Passes function that registers each pass in a group of passes, e.g., Gradient or Quantum. This function is enabled by the GEN_PASS_REGISTRATION macro.
  • Function declarations and implementations for creating each pass are also auto generated. They have the name create<pass name>Pass. Declarations are enabled by the GEN_PASS_DECL_<pass name in uppercase>PASS macro. Implementations are enabled by the GEN_PASS_DEF_<pass name in uppercase>PASS macro. And, for a group of passes, all the declarations can be enabled at once with the GEN_PASS_DECL macro.

This PR tries to use all that auto generated code, and so get rid of the manual pass registration and creation code.

Benefits:

  • No need to maintain code when adding a new pass. Note though that if the pass is added to a new group of passes, some scaffolding will be needed. But this can be replicated from other groups of passes.
  • Less boilerplate code.

Possible Drawbacks:

I have a couple of questions that I would like to be considered during the code review:

  1. CompilerDriver calls mlir::mhlo::registerAllMhloPasses (not catalyst::registerMhloPasses). However, it then goes on to add catalyst::createMhloLegalizeControlFlowPass, catalyst::createMhloLegalizeToStandardPass, and catalyst::createMhloLegalizeSortPass as nested passes, without previously registering them. It is a bit strange to me that you don't need to register nested passes.
  2. All Quantum passes are implemented now under catalyst::quantum namespace. I did this to ease the refactoring. It also looks OK to my eyes because, for example, Gradient passes are implemented under catalyst::gradient. But a) there may be a reason I don't know why Quantum passes were just under catalyst namespace, and b) I don't know either if this change can affect the connection with Python code.

Related GitHub Issues:

#1684

(Paul: [sc-89760])

@github-actions github-actions bot added the external PRs where the author is not a part of PennyLane Org (or part of external contributors team) label Aug 16, 2025
@rniczh
Copy link
Contributor

rniczh commented Aug 18, 2025

  1. CompilerDriver calls mlir::mhlo::registerAllMhloPasses (not catalyst::registerMhloPasses). However, it then goes on to add catalyst::createMhloLegalizeControlFlowPass, catalyst::createMhloLegalizeToStandardPass, and catalyst::createMhloLegalizeSortPass as nested passes, without previously registering them. It is a bit strange to me that you don't need to register nested passes.

I'm not sure I fully understand your question. If you're asking why you can add passes created by these factory functions to the pipeline without registering them first, it's because pass registration and adding passes to the pipeline are independent in MLIR. Registering a pass is mainly intended to support the CLI, where passes can be referenced by name in a textual pipeline. So, you can add passes (addPass or addNestedPass) regardless of whether they have been registered.

But, in the current design, the factory functions you mentioned (such as createMhloLegalizeControlFlowPass) have also been registered, as seen here: RegisterAllPasses.cpp, line 65.

@rturrado
Copy link
Contributor Author

I'm not sure I fully understand your question. If you're asking why you can add passes created by these factory functions to the pipeline without registering them first, it's because pass registration and adding passes to the pipeline are independent in MLIR. Registering a pass is mainly intended to support the CLI, where passes can be referenced by name in a textual pipeline. So, you can add passes (addPass or addNestedPass) regardless of whether they have been registered.

Many thanks for the explanation. That was exactly my doubt, yes.

But, in the current design, the factory functions you mentioned (such as createMhloLegalizeControlFlowPass) have also been registered, as seen here: RegisterAllPasses.cpp, line 65.

Good spot. I will add those registrations to the PR then. The new catalyst::registerAllPasses should call the auto generated registerMhloPasses.

…es, and 2) manually implementing a creation function for a new pass (e.g., std::unique_ptr<mlir::Pass> createQuantumBufferizationPass). I have understood that the first of those points was the main goal of issue PennyLaneAI#1684 (Refactor Catalyst pass registering).

Add mlir/include/RegisterAllPasses with a catalyst::registerAllPasses convenience function. This function calls the pass registration functions for every group (e.g., registerQuantumPasses). And those pass registration functions 1) are auto generated, and 2) sit in the <module>/Transforms/Passes.h.inc file (e.g., catalyst/mlir/build/include/Quantum/Transforms/Passes.h.inc).

Remove Catalyst/Transforms/RegisterAllPasses.cpp, and catalyst::registerAllCatalystPasses. This is the function where we were manually registering every pass. And that we needed to update for every new pass.

Passes.h:
- Remove manual pass creation and pass registration function declarations. The implementation of those functions is also removed from every file implementing a pass.
- Define GEN_PASS_DECL and GEN_PASS_REGISTRATION. Include <module>/Transforms/Passes.h.inc. This adds the auto generated pass creation and pass registration function declarations.

Passes.td:
- Remove all constructor variables. These variables point to manual pass creation functions. If you don't use these constructor variables, constructors with the same names will be auto generated in the Passes.h.inc files.

CMakeLists.txt:
- Change mlir_tablegen group name to start with uppercase (e.g., catalyst to Catalyst). That simply translates into, e.g., a name such as registerCatalystPasses being generated instead of registercatalystPasses.
- Change mlir_tablegen group name for mlir-hlo to Mhlo. That avoids registermlir-hloPasses being generated as a function name, which is an invalid name.

Remove include of <module>/Transforms/Passes.h from cpp files where a Passes.h.inc is later included.

Add GEN_PASS_DECL_<pass> to cpp files where GEN_PASS_DEF_<pass> was previously used. This is needed to add the declarations for the pass creation functions.

All Quantum passes are implemented now under catalyst::quantum namespace.

TODO: check if GEN_PASS_DECL_<pass> are really needed.
TODO: CompilerDriver calls mlir::mhlo::registerAllMhloPasses (not catalyst::registerMhloPasses). However, it then goes on to add catalyst::createMhloLegalizeControlFlowPass, catalyst::createMhloLegalizeToStandardPass, and catalyst::createMhloLegalizeSortPass as nested passes, without previously registering them. Is this OK?
TODO: I have moved Quantum passes to catalyst::quantum. Is this OK? May it cause problems from the Python connection?
…h DEF and DECL defines are needed, put the declarations before the definitions.

TODO: CompilerDriver calls mlir::mhlo::registerAllMhloPasses (not catalyst::registerMhloPasses). However, it then goes on to add catalyst::createMhloLegalizeControlFlowPass, catalyst::createMhloLegalizeToStandardPass, and catalyst::createMhloLegalizeSortPass as nested passes, without previously registering them. Is this OK?
TODO: update 'Writing and running your first Catalyst pass' section at doc/dev/transforms.rst.
…dev/transforms.rst.

TODO: CompilerDriver calls mlir::mhlo::registerAllMhloPasses (not catalyst::registerMhloPasses). However, it then goes on to add catalyst::createMhloLegalizeControlFlowPass, catalyst::createMhloLegalizeToStandardPass, and catalyst::createMhloLegalizeSortPass as nested passes, without previously registering them. Is this OK?
- Add registerMhloPasses call to registerAllPasses function in catalyst/mlir/include/RegisterAllPasses.h.

I've also taken the opportunity to do the following changes:
- Move Passes.h, Passes.td, and mhlo_legalize_to_standard_patterns.td from catalyst/mlir/include/mlir-hlo to a Transforms subfolder.
- Move mhlo_legalize_control_flow.cpp, mhlo_legalize_sort.cpp, and mhlo_legalize_to_std.cpp from catalyst/mlir/lib/mlir-hlo to a Transforms subfolder.
- Catalyst mlir-hlo passes are now under catalyst::mhlo.
- Rename mhlo_legalize_to_std.cpp to mhlo_legalize_to_standard.cpp.
- Rename populateMhloToStdPatterns function to populateMhloToStandardPatterns in mhlo_legalize_to_standard.cpp.
- Rename public tablegen targets MLIRHLOCatalystPassIncGen and MLIRMhloLegalizeToStandardIncGen to CatalystMhloPassIncGen and CatalystMhloLegalizeToStandardIncGen respectively.
- Simplify header inclusion in Pipelines.cpp.
@rturrado rturrado force-pushed the issue_1684_refactor_catalyst_pass_registering branch from fc1c52c to 6cafe77 Compare August 18, 2025 11:34
@dime10
Copy link
Contributor

dime10 commented Aug 18, 2025

All Quantum passes are implemented now under catalyst::quantum namespace. I did this to ease the refactoring. It also looks OK to my eyes because, for example, Gradient passes are implemented under catalyst::gradient. But a) there may be a reason I don't know why Quantum passes were just under catalyst namespace, and b) I don't know either if this change can affect the connection with Python code.

Possibly just historic when Quantum was the only dialect. I don't see an issue having these under the quantum namespace.

In any case, nice work 💯

@paul0403
Copy link
Member

paul0403 commented Aug 18, 2025

  1. CompilerDriver calls mlir::mhlo::registerAllMhloPasses (not catalyst::registerMhloPasses). However, it then goes on to add catalyst::createMhloLegalizeControlFlowPass, catalyst::createMhloLegalizeToStandardPass, and catalyst::createMhloLegalizeSortPass as nested passes, without previously registering them. It is a bit strange to me that you don't need to register nested passes.

Thanks for working on this! 🥳

To answer this question: the function call mlir::mhlo::registerAllMhloPasses comes from mlir-hlo, which is one of our dependencies (hence the mlir::mhlo:: instead of catalyst::). However, the three passes you mentioned are somewhat special, in the sense that they are, registry-wise, completely independent from the upstream hlo passes controlled by mlir::mhlo::registerAllMhloPasses, and they are just like other passes in catalyst.

Thus the three passes you mentioned should currently be registered in RegisterAllPasses.cpp.

But do note that we are going through some migration for the hlo dependency. The registration process for these three (somewhat special) passes will change a bit. We can revisit this after #1921 ! For now, we can just work on the other passes!

@rturrado
Copy link
Contributor Author

Thanks for working on this! 🥳

Appreciated!

To answer this question: the function call mlir::mhlo::registerAllMhloPasses comes from mlir-hlo, which is one of our dependencies (hence the mlir::mhlo:: instead of catalyst::). However, the three passes you mentioned are somewhat special, in the sense that they are, registry-wise, completely independent from the upstream hlo passes controlled by mlir::mhlo::registerAllMhloPasses, and they are just like other passes in catalyst.

That's it. We can see this in this PR's code. For example, in mlir/lib/Driver/Pipelines.cpp, createHloLoweringPipeline function:

    pm.addPass(mlir::mhlo::createStablehloLegalizeToHloPass());
    pm.addNestedPass<mlir::func::FuncOp>(catalyst::mhlo::createMhloLegalizeControlFlowPass());
    pm.addNestedPass<mlir::func::FuncOp>(catalyst::mhlo::createMhloLegalizeToStandardPass());
    pm.addNestedPass<mlir::func::FuncOp>(catalyst::mhlo::createMhloLegalizeSortPass());

Thus the three passes you mentioned should currently be registered in RegisterAllPasses.cpp.

They were there indeed, as @rniczh had also commented. And they still are in this PR's code, now in include/RegisterAllPasses.h, catalyst::registerAllPasses function, mhlo::registerMhloPasses(); line.

@codecov
Copy link

codecov bot commented Aug 18, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.42%. Comparing base (480e0a9) to head (8760d56).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1984   +/-   ##
=======================================
  Coverage   97.42%   97.42%           
=======================================
  Files          92       92           
  Lines       10424    10424           
  Branches     1002     1002           
=======================================
  Hits        10156    10156           
  Misses        211      211           
  Partials       57       57           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@paul0403
Copy link
Member

Hi! The stablehlo migration is now done, please update your local and PR with the following:

  1. Pull from latest main
  2. git submodule update --init. This will clone the new submodule mlir/stablehlo
  3. git submodule status to check your versions. You should see
 8c1a596158f6194f10e8ffd56a1660a61c54337e mlir/Enzyme (v0.0.186)
 f8cb7987c64dcffb72414a40560055cb717dbf74 mlir/llvm-project (f8cb7987c64)
 69d6dae46e1c7de36e6e6973654754f05353cba5 mlir/stablehlo (69d6dae4)

You can also find them in .dep-versions
4. rm -rf mlir/mlir-hlo/. We no longer need the mhlo submodule.
5. make all should work out of the box. If you encounter failures, trying cleaning first.
(If you prefer individual steps, the make mhlo step is now replaced with make stablehlo. The built files are in mlir/stablehlo/build)

If you have any questions, you can look at the PR #1921 or ask me directly!

@rturrado
Copy link
Contributor Author

Hi! The stablehlo migration is now done, please update your local and PR ...

Many thanks, I'm on it!

- Move {include,lib}/hlo-extensions files to a Transforms subfolder.
- Move hlo-extensions passes under catalyst::hlo.
- Rename mlir_tablegen stablehlo group name to Stablehlo.
- Rename stablehlo_legalize_to_std.cpp to stablehlo_legalize_to_standard.cpp.
@rturrado
Copy link
Contributor Author

Any idea why docs may be failing? I can build them locally with some warnings:

...
writing output... [100%] releases/changelog-dev
/home/rturrado/Projects/catalyst/frontend/catalyst/passes/__init__.py:docstring of catalyst.passes:7: WARNING: unknown document: 'introduction/compiling_circuits' [ref.doc]
/home/rturrado/Projects/catalyst/frontend/catalyst/api_extensions/quantum_operators.py:docstring of catalyst.api_extensions.quantum_operators.measure:25: WARNING: unknown document: 'introduction/dynamic_quantum_circuits' [ref.doc]
/home/rturrado/Projects/catalyst/frontend/catalyst/passes/pass_api.py:docstring of catalyst.passes.pass_api.apply_pass:1: WARNING: unknown document: 'dev/plugins' [ref.doc]
/home/rturrado/Projects/catalyst/frontend/catalyst/passes/pass_api.py:docstring of catalyst.passes.pass_api.apply_pass_plugin:1: WARNING: unknown document: 'dev/plugins' [ref.doc]
/home/rturrado/Projects/catalyst/frontend/catalyst/passes/builtin_passes.py:docstring of catalyst.passes.builtin_passes.cancel_inverses:25: WARNING: unknown document: 'introduction/compiling_circuits' [ref.doc]
/home/rturrado/Projects/catalyst/frontend/catalyst/passes/builtin_passes.py:docstring of catalyst.passes.builtin_passes.ions_decomposition:11: WARNING: unknown document: 'introduction/compiling_circuits' [ref.doc]
/home/rturrado/Projects/catalyst/frontend/catalyst/passes/builtin_passes.py:docstring of catalyst.passes.builtin_passes.merge_rotations:21: WARNING: unknown document: 'introduction/compiling_circuits' [ref.doc]
/home/rturrado/Projects/catalyst/frontend/catalyst/passes/pass_api.py:docstring of catalyst.passes.pass_api.pipeline:17: WARNING: unknown document: 'code/passes' [ref.doc]
/home/rturrado/Projects/catalyst/doc/dev/dialects.rst:74: WARNING: undefined label: '/dev/dialects.rst#using-the-dialect' [ref.ref]
/home/rturrado/Projects/catalyst/doc/dev/dialects.rst:138: WARNING: Lexing literal_block 'include "mlir/IR/OpBase.td"\n\nclass OpenQASM_Op<string nameInIR> : Op<OpenQASMDialect, nameInIR, []>;\n\ndef RZGate : OpenQASM_Op<"RZ"> {\n    let summary = "A single-qubit rotation around the Z-axis by an angle θ.";\n\n    let arguments = (ins\n        F64:$theta,\n        QubitType:$qubit\n    );\n\n    let results = (outs\n    );\n\n    let assemblyFormat = [{\n        `(` $theta `)` $qubit attr-dict `:` type($qubit)\n    }];\n}' as "tablegen" resulted in an error at token: '`'. Retrying in relaxed mode. [misc.highlighting_failure]                                                                                                                                                                                                                                                                                         
/home/rturrado/Projects/catalyst/doc/dev/quick_start.rst:92: WARNING: unknown document: 'introduction/operations' [ref.doc]
/home/rturrado/Projects/catalyst/doc/dev/quick_start.rst:105: WARNING: unknown document: 'introduction/templates' [ref.doc]
/home/rturrado/Projects/catalyst/doc/dev/quick_start.rst:121: WARNING: unknown document: 'introduction/operations' [ref.doc]
/home/rturrado/Projects/catalyst/doc/dev/quick_start.rst:144: WARNING: unknown document: 'introduction/measurements' [ref.doc]
/home/rturrado/Projects/catalyst/doc/dev/sharp_bits.rst:684: WARNING: unknown document: 'code/qml_transforms' [ref.doc]
/home/rturrado/Projects/catalyst/doc/releases/changelog-0.12.0.md:252: WARNING: unknown document: 'sharp_bits' [ref.doc]
generating indices... genindex py-modindex done
copying linked files... 
copying notebooks ... [100%] demos/qml_optimization.ipynb
highlighting module code... [100%] catalyst.utils.exceptions
writing additional pages... search done
copying images... [100%] _static/pl-catalyst-logo-lightmode.png
dumping search index in English (code: en)... done
dumping object inventory... done
build succeeded, 101 warnings.

The HTML pages are in _build/html.
make[1]: Leaving directory '/home/rturrado/Projects/catalyst/doc'

@paul0403
Copy link
Member

Any idea why docs may be failing? I can build them locally with some warnings:

...
writing output... [100%] releases/changelog-dev
/home/rturrado/Projects/catalyst/frontend/catalyst/passes/__init__.py:docstring of catalyst.passes:7: WARNING: unknown document: 'introduction/compiling_circuits' [ref.doc]
/home/rturrado/Projects/catalyst/frontend/catalyst/api_extensions/quantum_operators.py:docstring of catalyst.api_extensions.quantum_operators.measure:25: WARNING: unknown document: 'introduction/dynamic_quantum_circuits' [ref.doc]
/home/rturrado/Projects/catalyst/frontend/catalyst/passes/pass_api.py:docstring of catalyst.passes.pass_api.apply_pass:1: WARNING: unknown document: 'dev/plugins' [ref.doc]
/home/rturrado/Projects/catalyst/frontend/catalyst/passes/pass_api.py:docstring of catalyst.passes.pass_api.apply_pass_plugin:1: WARNING: unknown document: 'dev/plugins' [ref.doc]
/home/rturrado/Projects/catalyst/frontend/catalyst/passes/builtin_passes.py:docstring of catalyst.passes.builtin_passes.cancel_inverses:25: WARNING: unknown document: 'introduction/compiling_circuits' [ref.doc]
/home/rturrado/Projects/catalyst/frontend/catalyst/passes/builtin_passes.py:docstring of catalyst.passes.builtin_passes.ions_decomposition:11: WARNING: unknown document: 'introduction/compiling_circuits' [ref.doc]
/home/rturrado/Projects/catalyst/frontend/catalyst/passes/builtin_passes.py:docstring of catalyst.passes.builtin_passes.merge_rotations:21: WARNING: unknown document: 'introduction/compiling_circuits' [ref.doc]
/home/rturrado/Projects/catalyst/frontend/catalyst/passes/pass_api.py:docstring of catalyst.passes.pass_api.pipeline:17: WARNING: unknown document: 'code/passes' [ref.doc]
/home/rturrado/Projects/catalyst/doc/dev/dialects.rst:74: WARNING: undefined label: '/dev/dialects.rst#using-the-dialect' [ref.ref]
/home/rturrado/Projects/catalyst/doc/dev/dialects.rst:138: WARNING: Lexing literal_block 'include "mlir/IR/OpBase.td"\n\nclass OpenQASM_Op<string nameInIR> : Op<OpenQASMDialect, nameInIR, []>;\n\ndef RZGate : OpenQASM_Op<"RZ"> {\n    let summary = "A single-qubit rotation around the Z-axis by an angle θ.";\n\n    let arguments = (ins\n        F64:$theta,\n        QubitType:$qubit\n    );\n\n    let results = (outs\n    );\n\n    let assemblyFormat = [{\n        `(` $theta `)` $qubit attr-dict `:` type($qubit)\n    }];\n}' as "tablegen" resulted in an error at token: '`'. Retrying in relaxed mode. [misc.highlighting_failure]                                                                                                                                                                                                                                                                                         
/home/rturrado/Projects/catalyst/doc/dev/quick_start.rst:92: WARNING: unknown document: 'introduction/operations' [ref.doc]
/home/rturrado/Projects/catalyst/doc/dev/quick_start.rst:105: WARNING: unknown document: 'introduction/templates' [ref.doc]
/home/rturrado/Projects/catalyst/doc/dev/quick_start.rst:121: WARNING: unknown document: 'introduction/operations' [ref.doc]
/home/rturrado/Projects/catalyst/doc/dev/quick_start.rst:144: WARNING: unknown document: 'introduction/measurements' [ref.doc]
/home/rturrado/Projects/catalyst/doc/dev/sharp_bits.rst:684: WARNING: unknown document: 'code/qml_transforms' [ref.doc]
/home/rturrado/Projects/catalyst/doc/releases/changelog-0.12.0.md:252: WARNING: unknown document: 'sharp_bits' [ref.doc]
generating indices... genindex py-modindex done
copying linked files... 
copying notebooks ... [100%] demos/qml_optimization.ipynb
highlighting module code... [100%] catalyst.utils.exceptions
writing additional pages... search done
copying images... [100%] _static/pl-catalyst-logo-lightmode.png
dumping search index in English (code: en)... done
dumping object inventory... done
build succeeded, 101 warnings.

The HTML pages are in _build/html.
make[1]: Leaving directory '/home/rturrado/Projects/catalyst/doc'

autoray released a new version a couple hours ago 🫠 we are handling this right now

(Sorry for all the inconvenience, there has been many dependency issues this week...)

@rturrado
Copy link
Contributor Author

autoray released a new version a couple hours ago 🫠 we are handling this right now

Thanks for the explanation!

(Sorry for all the inconvenience, there has been many dependency issues this week...)

Nah, no problem at all.

@PennyLaneAI PennyLaneAI deleted a comment from rturrado Oct 24, 2025
@paul0403
Copy link
Member

paul0403 commented Oct 24, 2025

I deleted all DECL conversations (except the first one) to not flood the PR page.

@PennyLaneAI PennyLaneAI deleted a comment from rturrado Oct 24, 2025
@PennyLaneAI PennyLaneAI deleted a comment from rturrado Oct 24, 2025
@PennyLaneAI PennyLaneAI deleted a comment from rturrado Oct 24, 2025
@PennyLaneAI PennyLaneAI deleted a comment from rturrado Oct 24, 2025
@PennyLaneAI PennyLaneAI deleted a comment from rturrado Oct 24, 2025
@PennyLaneAI PennyLaneAI deleted a comment from rturrado Oct 24, 2025
@PennyLaneAI PennyLaneAI deleted a comment from rturrado Oct 24, 2025
@PennyLaneAI PennyLaneAI deleted a comment from rturrado Oct 24, 2025
@PennyLaneAI PennyLaneAI deleted a comment from rturrado Oct 24, 2025
@rturrado
Copy link
Contributor Author

I deleted all DECL conversations (except the first one) to not flood the PR page.

Cool. Regarding this, as I commented above, we can add them back, for consistency and because they do no harm. It's maybe easier for future coders to just add both DEF and DECL by default.

@paul0403
Copy link
Member

I deleted all DECL conversations (except the first one) to not flood the PR page.

Cool. Regarding this, as I commented above, we can add them back, for consistency and because they do no harm. It's maybe easier for future coders to just add both DEF and DECL by default.

I'm fine with either adding them back or not adding them back, so let's go with whichever is easier for you : )

Just remember to add to the documentation saying DECL is needed when a pass has options!

Copy link
Contributor

@joeycarter joeycarter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fantastic, thanks @rturrado! I only had a few minor things, happy to approve once they're resolved.

(It looks like there were ongoing conversations with @paul0403 while I reviewing, so please ignore any of the resulting cross-talk or things that have already been resolved.)

Follow the following order:
- standard headers (or gmock, gtest)
- llvm
- mlir
- stablehlo
- internal headers (from this Catalyst project)
Also take the opportunity to cut some lines short.
@rturrado
Copy link
Contributor Author

Aha! DECL is needed when the pass has options! I remember now, this was indeed the issue that we ran into!

Thanks for the comment!

In that case I'm good with the removals, since most of our passes don't have options 👍

Cool.

Let's add what DECL does to the documentation then! @rturrado

It says now, also as suggested by @joeycarter (more or less):

Note that the ``GEN_PASS_DECL_...PASS`` macro definitions are used to enable additional declarations,
such as `pass options`, and thus may not always be needed.

But we're still on time to adjust that comment, of course.

Copy link
Member

@paul0403 paul0403 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome 🥳 🤩

Copy link
Contributor

@joeycarter joeycarter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thanks @rturrado! 💯

@rturrado
Copy link
Contributor Author

Thanks to you, guys! 🍕🎈

@joeycarter joeycarter merged commit 1b29c70 into PennyLaneAI:main Oct 27, 2025
35 checks passed
@rturrado rturrado deleted the issue_1684_refactor_catalyst_pass_registering branch October 27, 2025 19:00
lazypanda10117 pushed a commit that referenced this pull request Oct 28, 2025
**Context:**

Issue #1684 points to the maintenance problem of having to add a
`mlir::registerPass(<module>::create<pass name>Pass);` at
`registerAllCatalystPasses` function for every new pass.

**Description of the Change:**

An early look at the `<module>/Transforms/Passes.h.inc` files, e.g.,
`Catalyst/Transforms/Passes.h.inc`, shows that:
- There is already an auto generated `register<module>Passes` function
that registers each pass in a group of passes, e.g., Gradient or
Quantum. This function is enabled by the GEN_PASS_REGISTRATION macro.
- Function declarations and implementations for creating each pass are
also auto generated. They have the name `create<pass name>Pass`.
Declarations are enabled by the `GEN_PASS_DECL_<pass name in
uppercase>PASS` macro. Implementations are enabled by the
`GEN_PASS_DEF_<pass name in uppercase>PASS` macro. And, for a group of
passes, all the declarations can be enabled at once with the
`GEN_PASS_DECL` macro.

This PR tries to use all that auto generated code, and so get rid of the
manual pass registration and creation code.

**Benefits:**

- No need to maintain code when adding a new pass. Note though that if
the pass is added to a new group of passes, some scaffolding will be
needed. But this can be replicated from other groups of passes.
- Less boilerplate code.

**Possible Drawbacks:**

I have a couple of questions that I would like to be considered during
the code review:
1) CompilerDriver calls `mlir::mhlo::registerAllMhloPasses` (not
`catalyst::registerMhloPasses`). However, it then goes on to add
`catalyst::createMhloLegalizeControlFlowPass`,
`catalyst::createMhloLegalizeToStandardPass`, and
`catalyst::createMhloLegalizeSortPass` as nested passes, without
previously registering them. It is a bit strange to me that you don't
need to register nested passes.
2) All Quantum passes are implemented now under `catalyst::quantum`
namespace. I did this to ease the refactoring. It also looks OK to my
eyes because, for example, Gradient passes are implemented under
`catalyst::gradient`. But a) there may be a reason I don't know why
Quantum passes were just under `catalyst` namespace, and b) I don't know
either if this change can affect the connection with Python code.

**Related GitHub Issues:**

(Paul: [sc-89760])

---------

Co-authored-by: ringo-but-quantum <>
Co-authored-by: Joey Carter <joseph.carter@xanadu.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external PRs where the author is not a part of PennyLane Org (or part of external contributors team)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants