Skip to content

Commit dbc6534

Browse files
authored
🔥 Remove register information from allocation operations (#1623)
## Description After #1580, it no longer makes sense to store register information in `qc::AllocOp` and `qco::AllocOp`. This PR thus removes this information. ## Checklist - [x] The pull request only contains commits that are focused and relevant to this change. - [x] ~~I have added appropriate tests that cover the new/changed functionality.~~ - [x] ~~I have updated the documentation to reflect these changes.~~ - [x] I have added entries to the changelog for any noteworthy additions, changes, fixes, or removals. - [x] ~~I have added migration instructions to the upgrade guide (if needed).~~ - [x] The changes follow the project's style guidelines and introduce no new warnings. - [x] The changes are fully tested and pass the CI checks. - [x] I have reviewed my own code changes.
1 parent 6f076d2 commit dbc6534

7 files changed

Lines changed: 39 additions & 186 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ This project adheres to [Semantic Versioning], with the exception that minor rel
1515
- ✨ Add conversions between Jeff and QCO ([#1479], [#1548], [#1565]) ([**@denialhaag**])
1616
- ✨ Add a `place-and-route` pass for mapping circuits to architectures with restricted topologies ([#1537], [#1547], [#1568], [#1581], [#1583], [#1588]) ([**@MatthiasReumann**])
1717
- ✨ Add initial infrastructure for new QC and QCO MLIR dialects
18-
([#1264], [#1330], [#1402], [#1428], [#1430], [#1436], [#1443], [#1446], [#1464], [#1465], [#1470], [#1471], [#1472], [#1474], [#1475], [#1506], [#1510], [#1513], [#1521], [#1542], [#1548], [#1550], [#1554], [#1567], [#1569], [#1570], [#1572], [#1573], [#1580], [#1602])
18+
([#1264], [#1330], [#1402], [#1428], [#1430], [#1436], [#1443], [#1446], [#1464], [#1465], [#1470], [#1471], [#1472], [#1474], [#1475], [#1506], [#1510], [#1513], [#1521], [#1542], [#1548], [#1550], [#1554], [#1567], [#1569], [#1570], [#1572], [#1573], [#1580], [#1602], [#1623])
1919
([**@burgholzer**], [**@denialhaag**], [**@taminob**], [**@DRovara**], [**@li-mingbao**], [**@Ectras**], [**@MatthiasReumann**], [**@simon1hofmann**])
2020

2121
### Changed
@@ -335,6 +335,7 @@ _📚 Refer to the [GitHub Release Notes](https://github.com/munich-quantum-tool
335335

336336
<!-- PR links -->
337337

338+
[#1623]: https://github.com/munich-quantum-toolkit/core/pull/1623
338339
[#1602]: https://github.com/munich-quantum-toolkit/core/pull/1602
339340
[#1596]: https://github.com/munich-quantum-toolkit/core/pull/1596
340341
[#1593]: https://github.com/munich-quantum-toolkit/core/pull/1593

mlir/include/mlir/Dialect/QC/IR/QCOps.td

Lines changed: 10 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -33,48 +33,23 @@ class QCOp<string mnemonic, list<Trait> traits = []>
3333
def AllocOp : QCOp<"alloc", [MemoryEffects<[MemAlloc]>]> {
3434
let summary = "Allocate a qubit dynamically";
3535
let description = [{
36-
Allocates a new qubit dynamically and returns a reference to it.
37-
The qubit is initialized to the |0⟩ state.
36+
Allocates a new qubit dynamically and returns a reference to it.
37+
The qubit is initialized to the |0⟩ state.
3838

39-
Optionally, the qubit can be part of a register by specifying:
40-
- `register_name`: The name of the register this qubit belongs to
41-
- `register_size`: The total size of the register
42-
- `register_index`: The index of this qubit within the register
39+
Example:
40+
```mlir
41+
%q = qc.alloc : !qc.qubit
42+
```
43+
}];
4344

44-
Example (single qubit):
45-
```mlir
46-
%q = qc.alloc : !qc.qubit
47-
```
48-
49-
Example (qubits in a register):
50-
```mlir
51-
%q0 = qc.alloc("q", 3, 0) : !qc.qubit
52-
%q1 = qc.alloc("q", 3, 1) : !qc.qubit
53-
%q2 = qc.alloc("q", 3, 2) : !qc.qubit
54-
```
55-
}];
56-
57-
let arguments = (ins OptionalAttr<StrAttr>:$register_name,
58-
OptionalAttr<ConfinedAttr<I64Attr, [IntPositive]>>:$register_size,
59-
OptionalAttr<ConfinedAttr<I64Attr, [IntNonNegative]>>:$register_index);
6045
let results = (outs QubitType:$result);
6146
let assemblyFormat = [{
62-
(`(` $register_name^ `,` $register_size `,` $register_index `)`)?
63-
attr-dict `:` type($result)
64-
}];
47+
attr-dict `:` type($result)
48+
}];
6549

6650
let builders = [OpBuilder<(ins), [{
67-
build($_builder, $_state, QubitType::get($_builder.getContext()), nullptr, nullptr, nullptr);
68-
}]>,
69-
OpBuilder<(ins "::mlir::StringAttr":$register_name,
70-
"::mlir::IntegerAttr":$register_size,
71-
"::mlir::IntegerAttr":$register_index),
72-
[{
73-
build($_builder, $_state, QubitType::get($_builder.getContext()),
74-
register_name, register_size, register_index);
51+
build($_builder, $_state, QubitType::get($_builder.getContext()));
7552
}]>];
76-
77-
let hasVerifier = 1;
7853
}
7954

8055
def DeallocOp : QCOp<"dealloc", [MemoryEffects<[MemFree]>]> {

mlir/include/mlir/Dialect/QCO/IR/QCOOps.td

Lines changed: 10 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -33,48 +33,23 @@ class QCOOp<string mnemonic, list<Trait> traits = []>
3333
def AllocOp : QCOOp<"alloc", [MemoryEffects<[MemAlloc]>]> {
3434
let summary = "Allocate a qubit dynamically";
3535
let description = [{
36-
Allocates a new qubit dynamically and returns an SSA value representing it.
37-
The qubit is initialized to the |0⟩ state.
36+
Allocates a new qubit dynamically and returns an SSA value representing it.
37+
The qubit is initialized to the |0⟩ state.
3838

39-
Optionally, the qubit can be part of a register by specifying:
40-
- `register_name`: The name of the register this qubit belongs to
41-
- `register_size`: The total size of the register
42-
- `register_index`: The index of this qubit within the register
39+
Example:
40+
```mlir
41+
%q = qco.alloc : !qco.qubit
42+
```
43+
}];
4344

44-
Example (single qubit):
45-
```mlir
46-
%q = qco.alloc : !qco.qubit
47-
```
48-
49-
Example (qubits in a register):
50-
```mlir
51-
%q0 = qco.alloc("q", 3, 0) : !qco.qubit
52-
%q1 = qco.alloc("q", 3, 1) : !qco.qubit
53-
%q2 = qco.alloc("q", 3, 2) : !qco.qubit
54-
```
55-
}];
56-
57-
let arguments = (ins OptionalAttr<StrAttr>:$register_name,
58-
OptionalAttr<ConfinedAttr<I64Attr, [IntPositive]>>:$register_size,
59-
OptionalAttr<ConfinedAttr<I64Attr, [IntNonNegative]>>:$register_index);
6045
let results = (outs QubitType:$result);
6146
let assemblyFormat = [{
62-
(`(` $register_name^ `,` $register_size `,` $register_index `)`)?
63-
attr-dict `:` type($result)
64-
}];
47+
attr-dict `:` type($result)
48+
}];
6549

6650
let builders = [OpBuilder<(ins), [{
67-
build($_builder, $_state, QubitType::get($_builder.getContext()), nullptr, nullptr, nullptr);
68-
}]>,
69-
OpBuilder<(ins "::mlir::StringAttr":$register_name,
70-
"::mlir::IntegerAttr":$register_size,
71-
"::mlir::IntegerAttr":$register_index),
72-
[{
73-
build($_builder, $_state, QubitType::get($_builder.getContext()),
74-
register_name, register_size, register_index);
51+
build($_builder, $_state, QubitType::get($_builder.getContext()));
7552
}]>];
76-
77-
let hasVerifier = 1;
7853
}
7954

8055
def SinkOp : QCOOp<"sink", [MemoryEffects<[MemFree]>]> {

mlir/lib/Conversion/QCOToQC/QCOToQC.cpp

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -226,19 +226,13 @@ struct ConvertQTensorDeallocOp final : OpConversionPattern<qtensor::DeallocOp> {
226226
/**
227227
* @brief Converts qco.alloc to qc.alloc
228228
*
229-
* @details
230-
* Allocates a new qubit initialized to the |0⟩ state. Register metadata
231-
* (name, size, index) is preserved during conversion.
232-
*
233-
* The conversion is straightforward: the QCO allocation produces an SSA
234-
* value, while the QC allocation produces a reference. MLIR's type
235-
* conversion system automatically handles the semantic shift.
236-
*
237-
* Example transformation:
229+
* @par Example:
238230
* ```mlir
239-
* %q0 = qco.alloc("q", 3, 0) : !qco.qubit
240-
* // becomes:
241-
* %q = qc.alloc("q", 3, 0) : !qc.qubit
231+
* %q = qco.alloc : !qco.qubit
232+
* ```
233+
* is converted to
234+
* ```mlir
235+
* %q = qc.alloc : !qc.qubit
242236
* ```
243237
*/
244238
struct ConvertQCOAllocOp final : StatefulOpConversionPattern<qco::AllocOp> {
@@ -254,10 +248,8 @@ struct ConvertQCOAllocOp final : StatefulOpConversionPattern<qco::AllocOp> {
254248
assert(qubitMode != QubitAddressingMode::Static &&
255249
"Static qubits cannot be mixed with dynamic qubits");
256250

257-
// Create qc.alloc with preserved register metadata
258-
rewriter.replaceOpWithNewOp<qc::AllocOp>(op, op.getRegisterNameAttr(),
259-
op.getRegisterSizeAttr(),
260-
op.getRegisterIndexAttr());
251+
// Create qc.alloc
252+
rewriter.replaceOpWithNewOp<qc::AllocOp>(op);
261253

262254
return success();
263255
}

mlir/lib/Conversion/QCToQCO/QCToQCO.cpp

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -552,19 +552,13 @@ struct ConvertMemRefDeallocOp final
552552
/**
553553
* @brief Converts qc.alloc to qco.alloc
554554
*
555-
* @details
556-
* Allocates a new qubit and establishes the initial mapping in the state.
557-
* Both dialects initialize qubits to the |0⟩ state.
558-
*
559-
* Register metadata (name, size, index) is preserved during conversion,
560-
* allowing the QCO representation to maintain register information for
561-
* debugging and visualization.
562-
*
563-
* Example transformation:
555+
* @par Example:
564556
* ```mlir
565-
* %q = qc.alloc("q", 3, 0) : !qc.qubit
566-
* // becomes:
567-
* %q0 = qco.alloc("q", 3, 0) : !qco.qubit
557+
* %q = qc.alloc : !qc.qubit
558+
* ```
559+
* is converted to
560+
* ```mlir
561+
* %q = qco.alloc : !qco.qubit
568562
* ```
569563
*/
570564
struct ConvertQCAllocOp final : StatefulOpConversionPattern<qc::AllocOp> {
@@ -574,19 +568,13 @@ struct ConvertQCAllocOp final : StatefulOpConversionPattern<qc::AllocOp> {
574568
matchAndRewrite(qc::AllocOp op, OpAdaptor /*adaptor*/,
575569
ConversionPatternRewriter& rewriter) const override {
576570
auto& state = getState();
577-
auto* operation = op.getOperation();
578571
auto qcQubit = op.getResult();
579572

580-
// Create the qco.alloc operation with preserved register metadata
581-
auto qcoOp = rewriter.replaceOpWithNewOp<qco::AllocOp>(
582-
op, op.getRegisterNameAttr(), op.getRegisterSizeAttr(),
583-
op.getRegisterIndexAttr());
573+
// Create the qco.alloc operation
574+
auto qcoOp = rewriter.replaceOpWithNewOp<qco::AllocOp>(op);
584575

585576
auto qcoQubit = qcoOp.getResult();
586-
587-
// Establish initial mapping: this QC qubit reference now corresponds
588-
// to this QCO SSA value
589-
assignMappedQubit(state, operation, qcQubit, qcoQubit);
577+
assignMappedQubit(state, qcoOp, qcQubit, qcoQubit);
590578

591579
return success();
592580
}

mlir/lib/Dialect/QC/IR/QubitManagement/AllocOp.cpp

Lines changed: 0 additions & 39 deletions
This file was deleted.

mlir/lib/Dialect/QCO/IR/QubitManagement/AllocOp.cpp

Lines changed: 0 additions & 39 deletions
This file was deleted.

0 commit comments

Comments
 (0)