Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c602a54
Use the transform dialect from our repository instead of the xDSL one
erick-xanadu Jul 24, 2025
eb94a67
Redefine Transform
erick-xanadu Jul 24, 2025
ebade75
copies over ApplyRegisteredPassOp
erick-xanadu Jul 24, 2025
966a678
Use DictionaryAttr instead of StringAttr
erick-xanadu Jul 24, 2025
c3905c6
Redefine ApplyRegisteredPassOp
erick-xanadu Jul 24, 2025
2e21cb8
initial test
erick-xanadu Jul 24, 2025
0d1f4fa
Apply suggestions from code review
erick-xanadu Jul 24, 2025
9ecadb7
Apply suggestions from code review
erick-xanadu Jul 24, 2025
8c62649
Fix imports
mehrdad2m Jul 31, 2025
6b83c17
move test to separate file
mehrdad2m Jul 31, 2025
25dd616
fix type hints
mehrdad2m Aug 1, 2025
3397df1
Merge branch 'master' into eochoa/2025-07-24/transform-dialect-update
mehrdad2m Aug 1, 2025
701f80b
isort after rebase
mehrdad2m Aug 1, 2025
c0fda72
fix type hint
mehrdad2m Aug 1, 2025
6f3e1ad
Merge branch 'master' into eochoa/2025-07-24/transform-dialect-update
mehrdad2m Aug 1, 2025
0b7b631
import original transform separately
mehrdad2m Aug 1, 2025
58a4a0f
remove redundant code
mehrdad2m Aug 1, 2025
9f51c7b
check full option dict
mehrdad2m Aug 1, 2025
b0a3120
Update transform_interpreter to utilize full options data for PassPip…
mehrdad2m Aug 5, 2025
262b32b
Add more unit tests for ApplyRegisteredPassOp with various options
mehrdad2m Aug 5, 2025
28c98e8
Merge branch 'master' into eochoa/2025-07-24/transform-dialect-update
mehrdad2m Aug 7, 2025
8558383
Merge branch 'master' into eochoa/2025-07-24/transform-dialect-update
mehrdad2m Aug 14, 2025
6e94592
remove wildcard import
mehrdad2m Aug 14, 2025
d3b9139
fix a mistake
mehrdad2m Aug 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 136 additions & 0 deletions pennylane/compiler/python_compiler/dialects/transform.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# Copyright 2025 Xanadu Quantum Technologies Inc.

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
This file contains an updated version of the transform dialect.
As of the time of writing, xDSL uses the MLIR released with LLVM's
version 20.1.7. However, https://github.com/PennyLaneAI/catalyst/pull/1916
will be updating MLIR where the transform dialect has the
`apply_registered_pass` operation re-defined.

See the following changelog on the above PR

Things related to transform.apply_registered_pass op:

It now takes in a dynamic_options

[MLIR][Transform] Allow ApplyRegisteredPassOp to take options as
a param llvm/llvm-project#142683. We don't need to use this as all our pass options are static.
https://github.com/llvm/llvm-project/pull/142683

The options it takes in are now dictionaries instead of strings
[MLIR][Transform] apply_registered_pass op's options as a dict llvm/llvm-project#143159
https://github.com/llvm/llvm-project/pull/143159

This file will re-define the apply_registered_pass operation in xDSL
and the transform dialect.

Once xDSL moves to a newer version of MLIR, these changes should
be contributed upstream.
"""

from xdsl.dialects.builtin import DictionaryAttr

# pylint: disable=unused-wildcard-import,wildcard-import
from xdsl.dialects.transform import *


@irdl_op_definition

Check notice on line 48 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L48

Undefined variable 'irdl_op_definition' (undefined-variable)
# pylint: disable=function-redefined
class ApplyRegisteredPassOp(IRDLOperation):

Check notice on line 50 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L50

Too few public methods (0/2) (too-few-public-methods)

Check notice on line 50 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L50

Undefined variable 'IRDLOperation' (undefined-variable)
"""
See external [documentation](https://mlir.llvm.org/docs/Dialects/Transform/#transformapply_registered_pass-transformapplyregisteredpassop).
"""

name = "transform.apply_registered_pass"

options = prop_def(DictionaryAttr, default_value=DictionaryAttr({}))

Check notice on line 57 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L57

Undefined variable 'prop_def' (undefined-variable)
pass_name = prop_def(StringAttr)

Check notice on line 58 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L58

Undefined variable 'StringAttr' (undefined-variable)

Check notice on line 58 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L58

Undefined variable 'prop_def' (undefined-variable)
target = operand_def(TransformHandleType)

Check notice on line 59 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L59

Undefined variable 'operand_def' (undefined-variable)

Check notice on line 59 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L59

Undefined variable 'TransformHandleType' (undefined-variable)
result = result_def(TransformHandleType)

Check notice on line 60 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L60

Undefined variable 'result_def' (undefined-variable)

Check notice on line 60 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L60

Undefined variable 'TransformHandleType' (undefined-variable)
# While this assembly format doesn't match
# the one in upstream MLIR,
# this is because xDSL currently lacks CustomDirectives
# https://mlir.llvm.org/docs/DefiningDialects/Operations/#custom-directives
# https://github.com/xdslproject/xdsl/pull/4829
# However, storing the property in the attribute should still work
# specially when parsing and printing in generic format.
# Which is how Catalyst and XDSL currently communicate at the moment.
# TODO: Add test.
assembly_format = "$pass_name `to` $target attr-dict `:` functional-type(operands, results)"
irdl_options = [ParsePropInAttrDict()]

Check notice on line 71 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L71

Undefined variable 'ParsePropInAttrDict' (undefined-variable)

def __init__(
self,
pass_name: str | StringAttr,

Check notice on line 75 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L75

Undefined variable 'StringAttr' (undefined-variable)
target: SSAValue,

Check notice on line 76 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L76

Undefined variable 'SSAValue' (undefined-variable)
options: dict | DictionaryAttr | None = None,
):
if isinstance(pass_name, str):
pass_name = StringAttr(pass_name)

Check notice on line 80 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L80

Undefined variable 'StringAttr' (undefined-variable)

if isinstance(options, dict):
options = DictionaryAttr(options)

super().__init__(
properties={
"pass_name": pass_name,
"options": options,
},
operands=[target],
result_types=[target.type],
)


# Copied over from xDSL's sources
# the main difference will be the use
# of a different ApplyRegisteredPassOp
Transform = Dialect(

Check notice on line 98 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L98

Undefined variable 'Dialect' (undefined-variable)
"transform",
[
ApplyRegisteredPassOp,
GetConsumersOfResultOp,

Check notice on line 102 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L102

Undefined variable 'GetConsumersOfResultOp' (undefined-variable)
GetDefiningOp,

Check notice on line 103 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L103

Undefined variable 'GetDefiningOp' (undefined-variable)
GetParentOp,

Check notice on line 104 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L104

Undefined variable 'GetParentOp' (undefined-variable)
GetProducerOfOperandOp,

Check notice on line 105 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L105

Undefined variable 'GetProducerOfOperandOp' (undefined-variable)
GetResultOp,

Check notice on line 106 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L106

Undefined variable 'GetResultOp' (undefined-variable)
GetTypeOp,

Check notice on line 107 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L107

Undefined variable 'GetTypeOp' (undefined-variable)
IncludeOp,

Check notice on line 108 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L108

Undefined variable 'IncludeOp' (undefined-variable)
MatchOperationEmptyOp,

Check notice on line 109 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L109

Undefined variable 'MatchOperationEmptyOp' (undefined-variable)
MatchOperationNameOp,

Check notice on line 110 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L110

Undefined variable 'MatchOperationNameOp' (undefined-variable)
MatchParamCmpIOp,

Check notice on line 111 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L111

Undefined variable 'MatchParamCmpIOp' (undefined-variable)
MergeHandlesOp,

Check notice on line 112 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L112

Undefined variable 'MergeHandlesOp' (undefined-variable)
ParamConstantOp,

Check notice on line 113 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L113

Undefined variable 'ParamConstantOp' (undefined-variable)
SplitHandleOp,

Check notice on line 114 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L114

Undefined variable 'SplitHandleOp' (undefined-variable)
SequenceOp,

Check notice on line 115 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L115

Undefined variable 'SequenceOp' (undefined-variable)
YieldOp,

Check notice on line 116 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L116

Undefined variable 'YieldOp' (undefined-variable)
TileOp,

Check notice on line 117 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L117

Undefined variable 'TileOp' (undefined-variable)
TileToForallOp,

Check notice on line 118 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L118

Undefined variable 'TileToForallOp' (undefined-variable)
SelectOp,

Check notice on line 119 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L119

Undefined variable 'SelectOp' (undefined-variable)
NamedSequenceOp,

Check notice on line 120 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L120

Undefined variable 'NamedSequenceOp' (undefined-variable)
CastOp,

Check notice on line 121 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L121

Undefined variable 'CastOp' (undefined-variable)
MatchOp,

Check notice on line 122 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L122

Undefined variable 'MatchOp' (undefined-variable)
],
[
# Types
AffineMapType,

Check notice on line 126 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L126

Undefined variable 'AffineMapType' (undefined-variable)
AnyOpType,

Check notice on line 127 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L127

Undefined variable 'AnyOpType' (undefined-variable)
AnyValueType,

Check notice on line 128 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L128

Undefined variable 'AnyValueType' (undefined-variable)
AnyParamType,

Check notice on line 129 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L129

Undefined variable 'AnyParamType' (undefined-variable)
OperationType,

Check notice on line 130 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L130

Undefined variable 'OperationType' (undefined-variable)
ParamType,

Check notice on line 131 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L131

Undefined variable 'ParamType' (undefined-variable)
TypeParamType,

Check notice on line 132 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L132

Undefined variable 'TypeParamType' (undefined-variable)
# Attributes
FailurePropagationModeAttr,

Check notice on line 134 in pennylane/compiler/python_compiler/dialects/transform.py

View check run for this annotation

codefactor.io / CodeFactor

pennylane/compiler/python_compiler/dialects/transform.py#L134

Undefined variable 'FailurePropagationModeAttr' (undefined-variable)
],
)
2 changes: 1 addition & 1 deletion pennylane/compiler/python_compiler/jax_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@
from xdsl.dialects import scf as xscf
from xdsl.dialects import stablehlo as xstablehlo
from xdsl.dialects import tensor as xtensor
from xdsl.dialects import transform as xtransform
from xdsl.ir import Dialect as xDialect
from xdsl.parser import Parser as xParser
from xdsl.traits import SymbolTable as xSymbolTable

from .dialects import MBQC, Quantum
from .dialects import transform as xtransform

JaxJittedFunction: TypeAlias = _jax.PjitFunction # pylint: disable=c-extension-no-member

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

from catalyst.compiler import _quantum_opt # pylint: disable=protected-access
from xdsl.context import Context
from xdsl.dialects import builtin, transform
from xdsl.dialects import builtin
from xdsl.interpreter import Interpreter, PythonValues, impl, register_impls
from xdsl.interpreters.transform import TransformFunctions
from xdsl.parser import Parser
Expand All @@ -32,6 +32,8 @@
from xdsl.rewriter import Rewriter
from xdsl.utils.exceptions import PassFailedException

from pennylane.compiler.python_compiler.dialects import transform


# pylint: disable=too-few-public-methods
@register_impls
Expand Down
21 changes: 20 additions & 1 deletion tests/python_compiler/test_python_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@
jax = pytest.importorskip("jax")
jaxlib = pytest.importorskip("jaxlib")
xdsl = pytest.importorskip("xdsl")
filecheck = pytest.importorskip("filecheck")

from catalyst import CompileError
from xdsl import passes
from xdsl.context import Context
from xdsl.dialects import builtin, transform
from xdsl.dialects import builtin
from xdsl.interpreters import Interpreter

from pennylane.compiler.python_compiler import Compiler
from pennylane.compiler.python_compiler.dialects import transform
from pennylane.compiler.python_compiler.jax_utils import (
jax_from_docstring,
module,
Expand Down Expand Up @@ -205,5 +207,22 @@ def program():
assert captured.out.strip() == "hello world"


def test_transform_dialect_update(run_filecheck):

program = """
"builtin.module"() ({
"transform.named_sequence"() <{function_type = (!transform.any_op) -> (), sym_name = "__transform_main"}> ({
^bb0(%arg0: !transform.any_op):
%0 = "transform.structured.match"(%arg0) <{ops = ["func.func"]}> : (!transform.any_op) -> !transform.any_op
// CHECK: "invalid-option"
%1 = "transform.apply_registered_pass"(%0) <{options = {"invalid-option" = 1 : i64}, pass_name = "canonicalize"}> : (!transform.any_op) -> !transform.any_op
"transform.yield"() : () -> ()
}) : () -> ()
}) {transform.with_named_sequence} : () -> ()
"""

run_filecheck(program, ())


if __name__ == "__main__":
pytest.main(["-x", __file__])