Skip to content

Commit f3c06e2

Browse files
dime10paul0403
andauthored
[GOID] Use unified printing for parameter types (#3191)
Small follow-up on #3188 to remove the manual Python -> MLIR type conversion and manual string serialization of MLIR types for the GraphOpID format. Instead the Python binding utilities are used and the MLIR attribute printer handles the string serialization. As a side-effect, more types are supported now that weren't present in the table (e.g. uint). Co-authored-by: paul0403 <paulhaochen.wang@gmail.com>
1 parent 1be4954 commit f3c06e2

4 files changed

Lines changed: 38 additions & 54 deletions

File tree

frontend/catalyst/decomposition/graph_op_id.py

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
"""Python implementation of Graph Operator ID."""
1616

17-
import contextlib
1817
from collections.abc import Mapping, Sequence
1918
from typing import Any
2019

@@ -29,25 +28,14 @@
2928
replace_wires_with_placeholder_wires,
3029
)
3130
from catalyst.from_plxpr.uid import generate_uid
32-
from catalyst.jax_extras.lowering import get_mlir_attribute_from_pyval
31+
from catalyst.jax_extras.lowering import get_mlir_attribute_from_pyval, mlir_build_context
3332

3433
_SPECIAL_LOWERINGS = {}
3534

3635

37-
@contextlib.contextmanager
38-
def _attribute_context():
39-
"""Provide an MLIR context and location for attribute construction."""
40-
if current := ir.Context.current:
41-
with ir.Location.unknown(context=current):
42-
yield current
43-
else:
44-
with ir.Context() as context, ir.Location.unknown(context=context):
45-
yield context
46-
47-
4836
def format_static_data_dict_for_id(static_data):
4937
"""Format the static-data group of a GraphOpID with MLIR's attribute printer."""
50-
with _attribute_context():
38+
with mlir_build_context():
5139
return str(get_mlir_attribute_from_pyval(static_data))
5240

5341

frontend/catalyst/decomposition/type_utils.py

Lines changed: 15 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@
2121
import jax.numpy as jnp
2222
import numpy as np
2323
import pennylane as qp
24+
from jax._src.interpreters.mlir import dtype_to_ir_type
2425
from jax._src.lib.mlir import ir
2526
from jax.core import ShapedArray
2627
from pennylane.pytrees import flatten, unflatten
2728

29+
from catalyst.jax_extras.lowering import mlir_build_context
30+
2831
_MLIR_DTYPES_TO_PY_DTYPES = {
2932
"i1": jnp.bool_,
3033
"i8": jnp.int8,
@@ -38,45 +41,23 @@
3841
"complex<f64>": jnp.complex128,
3942
}
4043

41-
_PY_DTYPES_TO_MLIR_DTYPES = {v: k for k, v in _MLIR_DTYPES_TO_PY_DTYPES.items()} | {
42-
float: "f64",
43-
int: "i64",
44-
complex: "complex<f64>",
45-
ir.F16Type: "f16",
46-
ir.F32Type: "f32",
47-
ir.F64Type: "f64",
48-
(ir.ComplexType, ir.F32Type): "complex<f32>",
49-
(ir.ComplexType, ir.F64Type): "complex<f64>",
50-
np.dtype("bool_"): "i1",
51-
np.dtype("int8"): "i8",
52-
np.dtype("int16"): "i16",
53-
np.dtype("int32"): "i32",
54-
np.dtype("int64"): "i64",
55-
np.dtype("float16"): "f16",
56-
np.dtype("float32"): "f32",
57-
np.dtype("float64"): "f64",
58-
np.dtype("complex64"): "complex<f32>",
59-
np.dtype("complex128"): "complex<f64>",
60-
}
61-
6244

6345
def convert_item_to_mlir_type(item, is_special_lowering=False):
64-
"""Convert a string or PennyLane AbstractArray to an mlir type annotation."""
46+
"""Convert a string or PennyLane AbstractArray to an mlir type annotation.
47+
48+
The type is spelled by MLIR's own printer, applied to the type the value lowers to, which is
49+
what ``printDynamicShape`` in mlir/lib/Quantum/IR/QuantumInterfaces.cpp does as well. One
50+
printer spelling both sides is what keeps a rule compiled here findable by the
51+
``graph-decomposition`` pass.
52+
"""
6553
if isinstance(item, str):
6654
return item
6755

68-
if item.shape == ():
69-
if is_special_lowering:
70-
return _PY_DTYPES_TO_MLIR_DTYPES[item.dtype]
71-
return "tensor<" + _PY_DTYPES_TO_MLIR_DTYPES[item.dtype] + ">"
72-
73-
return (
74-
"tensor<"
75-
+ "x".join(str(dim_size) for dim_size in item.shape)
76-
+ "x"
77-
+ _PY_DTYPES_TO_MLIR_DTYPES[item.dtype]
78-
+ ">"
79-
)
56+
with mlir_build_context():
57+
element_type = dtype_to_ir_type(np.dtype(item.dtype))
58+
if is_special_lowering and item.shape == ():
59+
return str(element_type)
60+
return str(ir.RankedTensorType.get(item.shape, element_type))
8061

8162

8263
def get_dummy_values_for_arg(arg):

frontend/catalyst/from_plxpr/qref_operator2_primitives.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"""
1818

1919
# pylint: disable=unused-argument
20+
import numpy as np
2021
import pennylane as qp
2122
from jax._src.lib.mlir import ir
2223
from jax.core import ShapedArray
@@ -39,7 +40,10 @@
3940
inject_new_rules_into_module,
4041
)
4142
from catalyst.decomposition.graph_op_id import _SPECIAL_LOWERINGS, build_graph_op_id
42-
from catalyst.decomposition.type_utils import get_dummy_values_for_arg
43+
from catalyst.decomposition.type_utils import (
44+
convert_item_to_mlir_type,
45+
get_dummy_values_for_arg,
46+
)
4347
from catalyst.jax_extras.lowering import get_mlir_attribute_from_pyval
4448
from catalyst.jax_extras.patches import mock_attributes
4549
from catalyst.jax_primitives import (
@@ -318,11 +322,10 @@ def compile_decomp_rules(
318322
elif op_cls is qp.QubitUnitary:
319323
num_wires = wire_lens[0]
320324
matrix_size = 2**num_wires
321-
dynamic_shape = {
322-
qp.QubitUnitary.dynamic_argnames[0]: [
323-
f"tensor<{matrix_size}x{matrix_size}xcomplex<f64>>"
324-
]
325-
}
325+
matrix_type = convert_item_to_mlir_type(
326+
ShapedArray((matrix_size, matrix_size), np.complex128)
327+
)
328+
dynamic_shape = {qp.QubitUnitary.dynamic_argnames[0]: [matrix_type]}
326329
wire_argname = qp.QubitUnitary.wire_argnames[0]
327330
op_id = build_graph_op_id("QubitUnitary", dynamic_shape, {wire_argname: wire_lens[0]}, {})
328331

frontend/catalyst/jax_extras/lowering.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
from __future__ import annotations
1717

18+
import contextlib
1819
import dataclasses
1920
import logging
2021
import textwrap
@@ -192,6 +193,17 @@ def custom_lower_jaxpr_to_module(
192193
return ctx.module, ctx.context
193194

194195

196+
@contextlib.contextmanager
197+
def mlir_build_context():
198+
"""Provide an MLIR context and location for attribute and type construction."""
199+
if current := ir.Context.current:
200+
with ir.Location.unknown(context=current):
201+
yield current
202+
else:
203+
with ir.Context() as context, ir.Location.unknown(context=context):
204+
yield context
205+
206+
195207
def get_mlir_attribute_from_pyval(value):
196208
"""
197209
Given a value of any type, construct an mlir attribute of corresponding type.

0 commit comments

Comments
 (0)