diff --git a/CHANGELOG.md b/CHANGELOG.md index ca4b9033a2..3683596181 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ This project adheres to [Semantic Versioning], with the exception that minor rel ### Added -- ✨ Add initial infrastructure for new QC and QCO MLIR dialects ([#1264], [#1402], [#1428], [#1430], [#1436], [#1443], [#1446], [#1464], [#1465], [#1470], [#1471], [#1472], [#1475]) ([**@burgholzer**], [**@denialhaag**], [**@taminob**], [**@DRovara**], [**@li-mingbao**]) +- ✨ Add initial infrastructure for new QC and QCO MLIR dialects ([#1264], [#1402], [#1428], [#1430], [#1436], [#1443], [#1446], [#1464], [#1465], [#1470], [#1471], [#1472], [#1474], [#1475]) ([**@burgholzer**], [**@denialhaag**], [**@taminob**], [**@DRovara**], [**@li-mingbao**]) ### Changed @@ -327,6 +327,7 @@ _📚 Refer to the [GitHub Release Notes](https://github.com/munich-quantum-tool [#1481]: https://github.com/munich-quantum-toolkit/core/pull/1481 [#1475]: https://github.com/munich-quantum-toolkit/core/pull/1475 +[#1474]: https://github.com/munich-quantum-toolkit/core/pull/1474 [#1472]: https://github.com/munich-quantum-toolkit/core/pull/1472 [#1471]: https://github.com/munich-quantum-toolkit/core/pull/1471 [#1470]: https://github.com/munich-quantum-toolkit/core/pull/1470 diff --git a/mlir/include/mlir/Dialect/QCO/IR/QCODialect.h b/mlir/include/mlir/Dialect/QCO/IR/QCODialect.h index 67fd0c12a2..a713c669b7 100644 --- a/mlir/include/mlir/Dialect/QCO/IR/QCODialect.h +++ b/mlir/include/mlir/Dialect/QCO/IR/QCODialect.h @@ -80,6 +80,9 @@ template class TargetAndParameterArityTrait { } return this->getOperation()->getOperand(i); } + OperandRange getInputQubits() { + return this->getOperation()->getOperands().slice(0, T); + } Value getOutputQubit(size_t i) { if constexpr (T == 0) { llvm::reportFatalUsageError("Operation does not have qubits"); @@ -89,6 +92,7 @@ template class TargetAndParameterArityTrait { } return this->getOperation()->getResult(i); } + ResultRange getOutputQubits() { return this->getOperation()->getResults(); } Value getInputTarget(const size_t i) { return getInputQubit(i); } Value getOutputTarget(const size_t i) { return getOutputQubit(i); } diff --git a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td index b7e08461fb..8bf0025f96 100644 --- a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td +++ b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td @@ -102,10 +102,20 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { "Returns the i-th input qubit (targets + controls combined).", "Value", "getInputQubit", (ins "size_t":$i) >, + InterfaceMethod< + "Returns a range of all input qubits (targets + controls combined).", + "OperandRange", + "getInputQubits", (ins) + >, InterfaceMethod< "Returns the i-th output qubit (targets + controls combined).", "Value", "getOutputQubit", (ins "size_t":$i) >, + InterfaceMethod< + "Returns a range of all output qubits (targets + controls combined).", + "ResultRange", + "getOutputQubits", (ins) + >, InterfaceMethod< "Returns the i-th target input qubit.", "Value", "getInputTarget", (ins "size_t":$i) @@ -163,6 +173,8 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { "Returns the base symbol/mnemonic of the operation.", "StringRef", "getBaseSymbol", (ins) >, + + // Unitary matrix helpers InterfaceMethod< "Populates the given 1x1 unitary matrix if possible.", "bool", "getUnitaryMatrix1x1", diff --git a/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td b/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td index 1ccf16320c..f5241f3800 100644 --- a/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td +++ b/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td @@ -1023,7 +1023,9 @@ def BarrierOp : QCOOp<"barrier", traits = [UnitaryOpInterface]> { size_t getNumTargets(); static size_t getNumControls(); Value getInputQubit(size_t i); + OperandRange getInputQubits(); Value getOutputQubit(size_t i); + ResultRange getOutputQubits(); Value getInputTarget(size_t i); Value getOutputTarget(size_t i); static Value getInputControl(size_t i); @@ -1113,7 +1115,9 @@ def CtrlOp : QCOOp<"ctrl", traits = size_t getNumTargets(); size_t getNumControls(); Value getInputQubit(size_t i); + OperandRange getInputQubits(); Value getOutputQubit(size_t i); + ResultRange getOutputQubits(); Value getInputTarget(size_t i); Value getOutputTarget(size_t i); Value getInputControl(size_t i); diff --git a/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp b/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp index caa07a6e7c..4028fc9efe 100644 --- a/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp @@ -160,22 +160,26 @@ Value CtrlOp::getInputQubit(const size_t i) { return getControlsIn()[i]; } if (numControls <= i && i < getNumQubits()) { - return getBodyUnitary().getInputQubit(i - numControls); + return getTargetsIn()[i - numControls]; } llvm::reportFatalUsageError("Invalid qubit index"); } +OperandRange CtrlOp::getInputQubits() { return this->getOperands(); } + Value CtrlOp::getOutputQubit(const size_t i) { const auto numControls = getNumControls(); if (i < numControls) { return getControlsOut()[i]; } if (numControls <= i && i < getNumQubits()) { - return getBodyUnitary().getOutputQubit(i - numControls); + return getTargetsOut()[i - numControls]; } llvm::reportFatalUsageError("Invalid qubit index"); } +ResultRange CtrlOp::getOutputQubits() { return this->getResults(); } + Value CtrlOp::getInputTarget(const size_t i) { if (i >= getNumTargets()) { llvm::reportFatalUsageError("Target index out of bounds"); diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp index 16da64cbe1..0d0f90e078 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp @@ -84,8 +84,12 @@ size_t BarrierOp::getNumControls() { return 0; } Value BarrierOp::getInputQubit(const size_t i) { return getInputTarget(i); } +OperandRange BarrierOp::getInputQubits() { return getQubitsIn(); } + Value BarrierOp::getOutputQubit(const size_t i) { return getOutputTarget(i); } +ResultRange BarrierOp::getOutputQubits() { return getQubitsOut(); } + Value BarrierOp::getInputTarget(const size_t i) { if (i < getNumTargets()) { return getQubitsIn()[i];