Skip to content

Commit 5b52511

Browse files
committed
🔄 Rename dealloc to sink in QCO dialect for qubit management
1 parent 4fdd34f commit 5b52511

17 files changed

Lines changed: 103 additions & 104 deletions

File tree

mlir/include/mlir/Dialect/QCO/Builder/QCOProgramBuilder.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,24 +1228,24 @@ class QCOProgramBuilder final : public ImplicitLocOpBuilder {
12281228
//===--------------------------------------------------------------------===//
12291229

12301230
/**
1231-
* @brief Explicitly deallocate a qubit
1231+
* @brief Consume a qubit value (end of lifetime)
12321232
*
12331233
* @details
12341234
* Validates and removes the qubit from tracking. Optional; `finalize()`
1235-
* automatically deallocates all remaining qubits.
1235+
* automatically sinks all remaining qubits.
12361236
*
1237-
* @param qubit Qubit to deallocate (must be valid/unconsumed)
1237+
* @param qubit Qubit to sink (must be valid/unconsumed)
12381238
* @return Reference to this builder for method chaining
12391239
*
12401240
* @par Example:
12411241
* ```c++
1242-
* builder.dealloc(q);
1242+
* builder.sink(q);
12431243
* ```
12441244
* ```mlir
1245-
* qco.dealloc %q : !qco.qubit
1245+
* qco.sink %q : !qco.qubit
12461246
* ```
12471247
*/
1248-
QCOProgramBuilder& dealloc(Value qubit);
1248+
QCOProgramBuilder& sink(Value qubit);
12491249

12501250
//===--------------------------------------------------------------------===//
12511251
// SCF operations

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

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,19 +93,20 @@ def AllocOp : QCOOp<"alloc", [MemoryEffects<[MemAlloc]>]> {
9393
let hasVerifier = 1;
9494
}
9595

96-
def DeallocOp : QCOOp<"dealloc", [MemoryEffects<[MemFree]>]> {
97-
let summary = "Deallocate a qubit";
96+
def SinkOp : QCOOp<"sink", [MemoryEffects<[MemFree]>]> {
97+
let summary = "Consume a qubit value (end of lifetime)";
9898
let description = [{
99-
Deallocates a qubit.
99+
Consumes a qubit SSA value and marks the end of its lifetime.
100100

101-
In QCO's value/linear semantics, this operation also serves as the sink
102-
that consumes the qubit SSA value (ensuring every qubit value is used
103-
exactly once). When converting back to QC (reference semantics), deallocs
104-
corresponding to static qubits may be erased.
101+
This operation is the canonical "sink" for QCO's linear/value semantics:
102+
every qubit value must be consumed exactly once on all paths.
103+
104+
When converting back to QC (reference semantics), sinks corresponding to
105+
static qubits may be erased.
105106

106107
Example:
107108
```mlir
108-
qco.dealloc %q : !qco.qubit
109+
qco.sink %q : !qco.qubit
109110
```
110111
}];
111112

mlir/include/mlir/Dialect/QCO/Utils/Drivers.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ template <typename Fn> void walkUnit(Region& region, Fn&& fn) {
107107
.template Case<MeasureOp>([&](MeasureOp op) {
108108
qubits.remap(op.getQubitIn(), op.getQubitOut());
109109
})
110-
.template Case<DeallocOp>(
111-
[&](DeallocOp op) { qubits.remove(op.getQubit()); });
110+
.template Case<SinkOp>(
111+
[&](SinkOp op) { qubits.remove(op.getQubit()); });
112112
}
113113
}
114114
} // namespace mlir::qco

mlir/lib/Conversion/JeffToQCO/JeffToQCO.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ struct ConvertJeffQubitAllocOpToQCO final
406406
};
407407

408408
/**
409-
* @brief Converts jeff.qubit_free to qco.reset + qco.dealloc
409+
* @brief Converts jeff.qubit_free to qco.reset + qco.sink
410410
*
411411
* @par Example:
412412
* ```mlir
@@ -415,7 +415,7 @@ struct ConvertJeffQubitAllocOpToQCO final
415415
* is converted to
416416
* ```mlir
417417
* %q_out = qco.reset %q_in : !qco.qubit
418-
* qco.dealloc %q_out : !qco.qubit
418+
* qco.sink %q_out : !qco.qubit
419419
* ```
420420
*/
421421
struct ConvertJeffQubitFreeOpToQCO final
@@ -427,21 +427,21 @@ struct ConvertJeffQubitFreeOpToQCO final
427427
ConversionPatternRewriter& rewriter) const override {
428428
auto resetOp =
429429
qco::ResetOp::create(rewriter, op.getLoc(), adaptor.getInQubit());
430-
rewriter.replaceOpWithNewOp<qco::DeallocOp>(op, resetOp.getQubitOut());
430+
rewriter.replaceOpWithNewOp<qco::SinkOp>(op, resetOp.getQubitOut());
431431
return success();
432432
}
433433
};
434434

435435
/**
436-
* @brief Converts jeff.qubit_free_zero to qco.dealloc
436+
* @brief Converts jeff.qubit_free_zero to qco.sink
437437
*
438438
* @par Example:
439439
* ```mlir
440440
* jeff.qubit_free_zero %q : !jeff.qubit
441441
* ```
442442
* is converted to
443443
* ```mlir
444-
* qco.dealloc %q : !qco.qubit
444+
* qco.sink %q : !qco.qubit
445445
* ```
446446
*/
447447
struct ConvertJeffQubitFreeZeroOpToQCO final
@@ -451,13 +451,13 @@ struct ConvertJeffQubitFreeZeroOpToQCO final
451451
LogicalResult
452452
matchAndRewrite(jeff::QubitFreeZeroOp op, OpAdaptor adaptor,
453453
ConversionPatternRewriter& rewriter) const override {
454-
rewriter.replaceOpWithNewOp<qco::DeallocOp>(op, adaptor.getInQubit());
454+
rewriter.replaceOpWithNewOp<qco::SinkOp>(op, adaptor.getInQubit());
455455
return success();
456456
}
457457
};
458458

459459
/**
460-
* @brief Converts jeff.qubit_measure to qco.measure + qco.dealloc
460+
* @brief Converts jeff.qubit_measure to qco.measure + qco.sink
461461
*
462462
* @par Example:
463463
* ```mlir
@@ -466,7 +466,7 @@ struct ConvertJeffQubitFreeZeroOpToQCO final
466466
* is converted to
467467
* ```mlir
468468
* %q_out, %result = qco.measure %q_in : !qco.qubit
469-
* qco.dealloc %q_out : !qco.qubit
469+
* qco.sink %q_out : !qco.qubit
470470
* ```
471471
*/
472472
struct ConvertJeffQubitMeasureOpToQCO final
@@ -479,7 +479,7 @@ struct ConvertJeffQubitMeasureOpToQCO final
479479
auto loc = op.getLoc();
480480
auto measureOp =
481481
qco::MeasureOp::create(rewriter, loc, adaptor.getInQubit());
482-
qco::DeallocOp::create(rewriter, loc, measureOp.getQubitOut());
482+
qco::SinkOp::create(rewriter, loc, measureOp.getQubitOut());
483483
rewriter.replaceOp(op, measureOp.getResult());
484484
return success();
485485
}

mlir/lib/Conversion/QCOToJeff/QCOToJeff.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -269,23 +269,22 @@ struct ConvertQCOAllocOpToJeff final
269269
};
270270

271271
/**
272-
* @brief Converts qco.dealloc to jeff.qubit_free_zero
272+
* @brief Converts qco.sink to jeff.qubit_free_zero
273273
*
274274
* @par Example:
275275
* ```mlir
276-
* qco.dealloc %q : !qco.qubit
276+
* qco.sink %q : !qco.qubit
277277
* ```
278278
* is converted to
279279
* ```mlir
280280
* jeff.qubit_free_zero %q : !jeff.qubit
281281
* ```
282282
*/
283-
struct ConvertQCODeallocOpToJeff final
284-
: StatefulOpConversionPattern<qco::DeallocOp> {
283+
struct ConvertQCOSinkOpToJeff final : StatefulOpConversionPattern<qco::SinkOp> {
285284
using StatefulOpConversionPattern::StatefulOpConversionPattern;
286285

287286
LogicalResult
288-
matchAndRewrite(qco::DeallocOp op, OpAdaptor adaptor,
287+
matchAndRewrite(qco::SinkOp op, OpAdaptor adaptor,
289288
ConversionPatternRewriter& rewriter) const override {
290289
rewriter.replaceOpWithNewOp<jeff::QubitFreeZeroOp>(op, adaptor.getQubit());
291290
return success();
@@ -1364,7 +1363,7 @@ struct QCOToJeff final : impl::QCOToJeffBase<QCOToJeff> {
13641363
// Register operation conversion patterns
13651364
jeff::populateNativeToJeffConversionPatterns(patterns);
13661365
patterns.add<
1367-
ConvertQCOAllocOpToJeff, ConvertQCODeallocOpToJeff,
1366+
ConvertQCOAllocOpToJeff, ConvertQCOSinkOpToJeff,
13681367
ConvertQCOMeasureOpToJeff, ConvertQCOResetOpToJeff,
13691368
ConvertQCOGPhaseOpToJeff,
13701369
ConvertQCOOneTargetZeroParameterToJeff<qco::IdOp, jeff::IOp, false>,

mlir/lib/Conversion/QCOToQC/QCOToQC.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ struct ConvertQCOAllocOp final : OpConversionPattern<qco::AllocOp> {
9696
};
9797

9898
/**
99-
* @brief Converts qco.dealloc to qc.dealloc (dynamic) or erases it (static).
99+
* @brief Converts qco.sink to qc.dealloc (dynamic) or erases it (static).
100100
*
101101
* @details
102102
* For dynamic qubits (`!qco.qubit`), converts to `qc.dealloc`.
@@ -105,23 +105,23 @@ struct ConvertQCOAllocOp final : OpConversionPattern<qco::AllocOp> {
105105
*
106106
* Example transformation (dynamic):
107107
* ```mlir
108-
* qco.dealloc %q_qco : !qco.qubit
108+
* qco.sink %q_qco : !qco.qubit
109109
* // becomes:
110110
* qc.dealloc %q_qc : !qc.qubit
111111
* ```
112112
*
113113
* Example transformation (static):
114114
* ```mlir
115-
* qco.dealloc %q_qco : !qco.qubit<static>
115+
* qco.sink %q_qco : !qco.qubit<static>
116116
* // becomes:
117117
* (erased)
118118
* ```
119119
*/
120-
struct ConvertQCODeallocOp final : OpConversionPattern<qco::DeallocOp> {
120+
struct ConvertQCOSinkOp final : OpConversionPattern<qco::SinkOp> {
121121
using OpConversionPattern::OpConversionPattern;
122122

123123
LogicalResult
124-
matchAndRewrite(qco::DeallocOp op, OpAdaptor adaptor,
124+
matchAndRewrite(qco::SinkOp op, OpAdaptor adaptor,
125125
ConversionPatternRewriter& rewriter) const override {
126126
if (op.getQubit().getType().getIsStatic()) {
127127
rewriter.eraseOp(op);
@@ -769,7 +769,7 @@ struct QCOToQC final : impl::QCOToQCBase<QCOToQC> {
769769
// Register operation conversion patterns
770770
// Note: No state tracking needed - OpAdaptors handle type conversion
771771
patterns.add<
772-
ConvertQCOAllocOp, ConvertQCODeallocOp, ConvertQCOStaticOp,
772+
ConvertQCOAllocOp, ConvertQCOSinkOp, ConvertQCOStaticOp,
773773
ConvertQCOMeasureOp, ConvertQCOResetOp,
774774
ConvertQCOZeroTargetOneParameterToQC<qco::GPhaseOp, qc::GPhaseOp>,
775775
ConvertQCOOneTargetZeroParameterToQC<qco::XOp, qc::XOp>,

mlir/lib/Conversion/QCToQCO/QCToQCO.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ namespace {
276276
* QC uses reference semantics and does not enforce linear typing for qubits.
277277
* After conversion, QCO requires that every qubit SSA value is consumed
278278
* exactly once. For allocations (including static qubits), the sink is
279-
* `qco.dealloc`. This pattern inserts `qco.dealloc` operations for all
279+
* `qco.sink`. This pattern inserts `qco.sink` operations for all
280280
* still-live qubits tracked in the lowering state right before the return.
281281
*/
282282
struct ConvertFuncReturnOp final : StatefulOpConversionPattern<func::ReturnOp> {
@@ -319,7 +319,7 @@ struct ConvertFuncReturnOp final : StatefulOpConversionPattern<func::ReturnOp> {
319319
llvm::sort(liveQubitsSorted, SSAOrder{});
320320

321321
for (Value qubit : liveQubitsSorted) {
322-
qco::DeallocOp::create(rewriter, op.getLoc(), qubit);
322+
qco::SinkOp::create(rewriter, op.getLoc(), qubit);
323323
}
324324

325325
state.qubitMap.erase(funcRegion);
@@ -397,18 +397,18 @@ struct ConvertQCAllocOp final : StatefulOpConversionPattern<qc::AllocOp> {
397397
};
398398

399399
/**
400-
* @brief Converts qc.dealloc to qco.dealloc
400+
* @brief Converts qc.dealloc to qco.sink
401401
*
402402
* @details
403403
* Deallocates a qubit by looking up its latest QCO value and creating
404-
* a corresponding qco.dealloc operation. The mapping is removed from
404+
* a corresponding qco.sink operation. The mapping is removed from
405405
* the state as the qubit is no longer in use.
406406
*
407407
* Example transformation:
408408
* ```mlir
409409
* qc.dealloc %q : !qc.qubit
410410
* // becomes (where %q maps to %q_final):
411-
* qco.dealloc %q_final : !qco.qubit
411+
* qco.sink %q_final : !qco.qubit
412412
* ```
413413
*/
414414
struct ConvertQCDeallocOp final : StatefulOpConversionPattern<qc::DeallocOp> {
@@ -424,8 +424,8 @@ struct ConvertQCDeallocOp final : StatefulOpConversionPattern<qc::DeallocOp> {
424424
Value qcQubit = op.getQubit();
425425
Value qcoQubit = lookupMappedQubit(state, operation, qcQubit);
426426

427-
// Create the dealloc operation
428-
rewriter.replaceOpWithNewOp<qco::DeallocOp>(op, qcoQubit);
427+
// Create the sink operation
428+
rewriter.replaceOpWithNewOp<qco::SinkOp>(op, qcoQubit);
429429

430430
// Remove from state as qubit is no longer in use
431431
qubitMap.erase(qcQubit);
@@ -1130,7 +1130,7 @@ struct QCToQCO final : impl::QCToQCOBase<QCToQCO> {
11301130
// Conversion of qc types in func.return
11311131
//
11321132
// Note: `func.return` may already be type-legal even though we still need
1133-
// to insert sink operations (`qco.dealloc`) for remaining live
1133+
// to insert sink operations (`qco.sink`) for remaining live
11341134
// qubits. Therefore, we make it dynamically illegal unless the lowering
11351135
// state has no remaining qubits.
11361136
patterns.add<ConvertFuncReturnOp>(typeConverter, context, &state);

mlir/lib/Dialect/QCO/Builder/QCOProgramBuilder.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -810,13 +810,13 @@ ValueRange QCOProgramBuilder::inv(
810810
// Deallocation
811811
//===----------------------------------------------------------------------===//
812812

813-
QCOProgramBuilder& QCOProgramBuilder::dealloc(Value qubit) {
813+
QCOProgramBuilder& QCOProgramBuilder::sink(Value qubit) {
814814
checkFinalized();
815815

816816
validateQubitValue(qubit);
817817
validQubits.erase(qubit);
818818

819-
DeallocOp::create(*this, qubit);
819+
SinkOp::create(*this, qubit);
820820

821821
return *this;
822822
}
@@ -924,7 +924,7 @@ OwningOpRef<ModuleOp> QCOProgramBuilder::finalize() {
924924
llvm::sort(sortedQubits, SSAOrder{});
925925

926926
for (auto qubit : sortedQubits) {
927-
DeallocOp::create(*this, qubit);
927+
SinkOp::create(*this, qubit);
928928
}
929929

930930
// Automatically deallocate all still-allocated tensors

mlir/lib/Dialect/QCO/IR/QubitManagement/DeallocOp.cpp renamed to mlir/lib/Dialect/QCO/IR/QubitManagement/SinkOp.cpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
#include <llvm/Support/Casting.h>
1414
#include <mlir/IR/MLIRContext.h>
15-
#include <mlir/IR/OperationSupport.h>
1615
#include <mlir/IR/PatternMatch.h>
1716
#include <mlir/Support/LogicalResult.h>
1817

@@ -22,21 +21,19 @@ using namespace mlir::qco;
2221
namespace {
2322

2423
/**
25-
* @brief Remove matching allocation and deallocation pairs without operations
24+
* @brief Remove matching allocation/static and sink pairs without operations
2625
* between them.
2726
*/
28-
struct RemoveAllocDeallocPair final : OpRewritePattern<DeallocOp> {
27+
struct RemoveAllocSinkPair final : OpRewritePattern<SinkOp> {
2928
using OpRewritePattern::OpRewritePattern;
3029

31-
LogicalResult matchAndRewrite(DeallocOp op,
30+
LogicalResult matchAndRewrite(SinkOp op,
3231
PatternRewriter& rewriter) const override {
33-
// Check if the predecessor is an AllocOp or a StaticOp
3432
auto* defOp = op.getQubit().getDefiningOp();
3533
if (!llvm::isa<AllocOp, StaticOp>(defOp)) {
3634
return failure();
3735
}
3836

39-
// Remove the AllocOp/StaticOp and the DeallocOp
4037
rewriter.eraseOp(op);
4138
rewriter.eraseOp(defOp);
4239
return success();
@@ -45,7 +42,7 @@ struct RemoveAllocDeallocPair final : OpRewritePattern<DeallocOp> {
4542

4643
} // namespace
4744

48-
void DeallocOp::getCanonicalizationPatterns(RewritePatternSet& results,
49-
MLIRContext* context) {
50-
results.add<RemoveAllocDeallocPair>(context);
45+
void SinkOp::getCanonicalizationPatterns(RewritePatternSet& results,
46+
MLIRContext* context) {
47+
results.add<RemoveAllocSinkPair>(context);
5148
}

0 commit comments

Comments
 (0)