diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d5066991b..fe599b3561 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,10 +11,10 @@ This project adheres to [Semantic Versioning], with the exception that minor rel ### Added -- ✨ Add conversions between Jeff and QCO ([#1479]) ([**@denialhaag**]) +- ✨ Add conversions between Jeff and QCO ([#1479], [#1548]) ([**@denialhaag**]) - ✨ Add a `place-and-route` pass for mapping circuits to architectures with restricted topologies ([#1537], [#1547]) ([**@MatthiasReumann**]) - ✨ Add initial infrastructure for new QC and QCO MLIR dialects - ([#1264], [#1330], [#1402], [#1428], [#1430], [#1436], [#1443], [#1446], [#1464], [#1465], [#1470], [#1471], [#1472], [#1474], [#1475], [#1506], [#1510], [#1513], [#1521]) + ([#1264], [#1330], [#1402], [#1428], [#1430], [#1436], [#1443], [#1446], [#1464], [#1465], [#1470], [#1471], [#1472], [#1474], [#1475], [#1506], [#1510], [#1513], [#1521], [#1548]) ([**@burgholzer**], [**@denialhaag**], [**@taminob**], [**@DRovara**], [**@li-mingbao**], [**@Ectras**], [**@MatthiasReumann**]) ### Changed @@ -329,6 +329,7 @@ _📚 Refer to the [GitHub Release Notes](https://github.com/munich-quantum-tool +[#1548]: https://github.com/munich-quantum-toolkit/core/pull/1548 [#1547]: https://github.com/munich-quantum-toolkit/core/pull/1547 [#1537]: https://github.com/munich-quantum-toolkit/core/pull/1537 [#1521]: https://github.com/munich-quantum-toolkit/core/pull/1521 diff --git a/docs/mlir/Conversions.md b/docs/mlir/Conversions.md index 9da1119faf..654e78d8cd 100644 --- a/docs/mlir/Conversions.md +++ b/docs/mlir/Conversions.md @@ -10,6 +10,16 @@ ``` +## Jeff Conversions + +```{include} Conversions/MLIRQCOToJeff.md + +``` + +```{include} Conversions/MLIRJeffToQCO.md + +``` + ## QIR Conversions ```{include} Conversions/MLIRQCToQIR.md diff --git a/docs/mlir/QCO.md b/docs/mlir/QCO.md index 5411108bd6..5492aae0eb 100644 --- a/docs/mlir/QCO.md +++ b/docs/mlir/QCO.md @@ -9,3 +9,9 @@ tocdepth: 3 ```{include} Dialects/MLIRQCOInterfaces.md :heading-offset: 1 ``` + +## Passes + +```{include} Passes/MLIRQCOTransforms.md + +``` diff --git a/mlir/lib/Compiler/CMakeLists.txt b/mlir/lib/Compiler/CMakeLists.txt index a53a004456..990ac0cb7e 100644 --- a/mlir/lib/Compiler/CMakeLists.txt +++ b/mlir/lib/Compiler/CMakeLists.txt @@ -17,9 +17,9 @@ add_mlir_library( MLIRPass MLIRTransforms MLIRTransformUtils - QCToQCO - QCOToQC - QCToQIR + MLIRQCToQCO + MLIRQCOToQC + MLIRQCToQIR MQT::MLIRSupport DISABLE_INSTALL) diff --git a/mlir/lib/Conversion/JeffToQCO/CMakeLists.txt b/mlir/lib/Conversion/JeffToQCO/CMakeLists.txt index cc195ae69a..0f0b0380aa 100644 --- a/mlir/lib/Conversion/JeffToQCO/CMakeLists.txt +++ b/mlir/lib/Conversion/JeffToQCO/CMakeLists.txt @@ -8,8 +8,8 @@ file(GLOB CONVERSION_SOURCES *.cpp) -add_mlir_library( - JeffToQCO +add_mlir_conversion_library( + MLIRJeffToQCO ${CONVERSION_SOURCES} DEPENDS JeffToQCOIncGen @@ -19,5 +19,5 @@ add_mlir_library( MLIRTransforms DISABLE_INSTALL) -target_include_directories(JeffToQCO PRIVATE ${jeff-mlir_SOURCE_DIR}/include - ${jeff-mlir_BINARY_DIR}/include) +target_include_directories(MLIRJeffToQCO PRIVATE ${jeff-mlir_SOURCE_DIR}/include + ${jeff-mlir_BINARY_DIR}/include) diff --git a/mlir/lib/Conversion/JeffToQCO/JeffToQCO.cpp b/mlir/lib/Conversion/JeffToQCO/JeffToQCO.cpp index 6e26654a7a..80c7f6ac2f 100644 --- a/mlir/lib/Conversion/JeffToQCO/JeffToQCO.cpp +++ b/mlir/lib/Conversion/JeffToQCO/JeffToQCO.cpp @@ -299,59 +299,6 @@ createTwoTargetTwoParameter(JeffOpType& op, ConversionPatternRewriter& rewriter, } } -/** - * @brief Converts a one-target, zero-parameter Jeff operation to QCO - * - * @tparam QCOOpType The operation type of the QCO operation - * @tparam JeffOpType The operation type of the Jeff operation - * @tparam JeffOpAdaptorType The OpAdaptor type of the Jeff operation - * @param op The Jeff operation instance to convert - * @param adaptor The OpAdaptor of the Jeff operation - * @param rewriter The pattern rewriter - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertOneTargetZeroParameter(JeffOpType& op, JeffOpAdaptorType& adaptor, - ConversionPatternRewriter& rewriter) { - if (op.getPower() != 1) { - return rewriter.notifyMatchFailure( - op, "Operations with power != 1 are not yet supported"); - } - - createOneTargetZeroParameter( - op, rewriter, adaptor.getInCtrlQubits(), adaptor.getInQubit()); - - return success(); -} - -/** - * @brief Converts a one-target, one-parameter Jeff operation to QCO - * - * @tparam QCOOpType The operation type of the QCO operation - * @tparam JeffOpType The operation type of the Jeff operation - * @tparam JeffOpAdaptorType The OpAdaptor type of the Jeff operation - * @param op The Jeff operation instance to convert - * @param adaptor The OpAdaptor of the Jeff operation - * @param rewriter The pattern rewriter - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertOneTargetOneParameter(JeffOpType& op, JeffOpAdaptorType& adaptor, - ConversionPatternRewriter& rewriter) { - if (op.getPower() != 1) { - return rewriter.notifyMatchFailure( - op, "Operations with power != 1 are not yet supported"); - } - - createOneTargetOneParameter(op, rewriter, op.getRotation(), - adaptor.getInCtrlQubits(), - adaptor.getInQubit()); - - return success(); -} - /** * @brief Creates a qco.barrier operation from a jeff.custom operation * @@ -618,52 +565,78 @@ struct ConvertJeffGPhaseOpToQCO final : OpConversionPattern { } }; -// OneTargetZeroParameter - -#define DEFINE_ONE_TARGET_ZERO_PARAMETER(OP_CLASS_JEFF, OP_CLASS_QCO) \ - struct ConvertJeff##OP_CLASS_JEFF##ToQCO final \ - : OpConversionPattern { \ - using OpConversionPattern::OpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(jeff::OP_CLASS_JEFF op, OpAdaptor adaptor, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertOneTargetZeroParameter(op, adaptor, \ - rewriter); \ - } \ - }; - -DEFINE_ONE_TARGET_ZERO_PARAMETER(IOp, IdOp) -DEFINE_ONE_TARGET_ZERO_PARAMETER(XOp, XOp) -DEFINE_ONE_TARGET_ZERO_PARAMETER(YOp, YOp) -DEFINE_ONE_TARGET_ZERO_PARAMETER(ZOp, ZOp) -DEFINE_ONE_TARGET_ZERO_PARAMETER(HOp, HOp) -DEFINE_ONE_TARGET_ZERO_PARAMETER(SOp, SOp) -DEFINE_ONE_TARGET_ZERO_PARAMETER(TOp, TOp) - -#undef DEFINE_ONE_TARGET_ZERO_PARAMETER - -// OneTargetOneParameter - -#define DEFINE_ONE_TARGET_ONE_PARAMETER(OP_CLASS_JEFF, OP_CLASS_QCO) \ - struct ConvertJeff##OP_CLASS_JEFF##ToQCO final \ - : OpConversionPattern { \ - using OpConversionPattern::OpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(jeff::OP_CLASS_JEFF op, OpAdaptor adaptor, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertOneTargetOneParameter(op, adaptor, \ - rewriter); \ - } \ - }; - -DEFINE_ONE_TARGET_ONE_PARAMETER(RxOp, RXOp) -DEFINE_ONE_TARGET_ONE_PARAMETER(RyOp, RYOp) -DEFINE_ONE_TARGET_ONE_PARAMETER(RzOp, RZOp) -DEFINE_ONE_TARGET_ONE_PARAMETER(R1Op, POp) - -#undef DEFINE_ONE_TARGET_ONE_PARAMETER +/** + * @brief Converts one-target, zero-parameter Jeff gate to QCO + * + * @tparam QCOOpType The operation type of the QCO operation + * @tparam JeffOpType The operation type of the Jeff operation + * + * @par Example: + * ```mlir + * %q_out = jeff.x {is_adjoint = false, num_ctrls = 0 : i8, power = 1 : i8} + * %q_in : !jeff.qubit + * ``` + * is converted to + * ```mlir + * %q_out = qco.x %q_in : !qco.qubit + * ``` + */ +template +struct ConvertJeffOneTargetZeroParameterToQCO final + : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(JeffOpType op, typename JeffOpType::Adaptor adaptor, + ConversionPatternRewriter& rewriter) const override { + if (op.getPower() != 1) { + return rewriter.notifyMatchFailure( + op, "Operations with power != 1 are not yet supported"); + } + + createOneTargetZeroParameter( + op, rewriter, adaptor.getInCtrlQubits(), adaptor.getInQubit()); + + return success(); + } +}; + +/** + * @brief Converts one-target, one-parameter Jeff gate to QCO + * + * @tparam QCOOpType The operation type of the QCO operation + * @tparam JeffOpType The operation type of the Jeff operation + * + * @par Example: + * ```mlir + * %q_out = jeff.rx(%theta) {is_adjoint = false, num_ctrls = 0 : i8, power = 1 : + * i8} %q_in : !jeff.qubit + * ``` + * is converted to + * ```mlir + * %q_out = qco.rx(%theta) %q_in : !qco.qubit + * ``` + */ +template +struct ConvertJeffOneTargetOneParameterToQCO final + : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(JeffOpType op, typename JeffOpType::Adaptor adaptor, + ConversionPatternRewriter& rewriter) const override { + if (op.getPower() != 1) { + return rewriter.notifyMatchFailure( + op, "Operations with power != 1 are not yet supported"); + } + + createOneTargetOneParameter(op, rewriter, op.getRotation(), + adaptor.getInCtrlQubits(), + adaptor.getInQubit()); + + return success(); + } +}; /** * @brief Converts jeff.u to qco.u @@ -1030,10 +1003,18 @@ struct JeffToQCO final : impl::JeffToQCOBase { .add, + ConvertJeffOneTargetZeroParameterToQCO, + ConvertJeffOneTargetZeroParameterToQCO, + ConvertJeffOneTargetZeroParameterToQCO, + ConvertJeffOneTargetZeroParameterToQCO, + ConvertJeffOneTargetZeroParameterToQCO, + ConvertJeffOneTargetZeroParameterToQCO, + ConvertJeffOneTargetOneParameterToQCO, + ConvertJeffOneTargetOneParameterToQCO, + ConvertJeffOneTargetOneParameterToQCO, + ConvertJeffOneTargetOneParameterToQCO, ConvertJeffUOpToQCO, ConvertJeffSwapOpToQCO, ConvertJeffCustomOpToQCO, ConvertJeffPPROpToQCO, ConvertJeffMainToQCO, ConvertJeffIntConst1OpToArith, diff --git a/mlir/lib/Conversion/QCOToJeff/CMakeLists.txt b/mlir/lib/Conversion/QCOToJeff/CMakeLists.txt index ebc0c17b49..03c1b041d4 100644 --- a/mlir/lib/Conversion/QCOToJeff/CMakeLists.txt +++ b/mlir/lib/Conversion/QCOToJeff/CMakeLists.txt @@ -8,8 +8,8 @@ file(GLOB CONVERSION_SOURCES *.cpp) -add_mlir_library( - QCOToJeff +add_mlir_conversion_library( + MLIRQCOToJeff ${CONVERSION_SOURCES} DEPENDS QCOToJeffIncGen @@ -20,13 +20,13 @@ add_mlir_library( MLIRTransforms DISABLE_INSTALL) -target_include_directories(QCOToJeff PRIVATE ${jeff-mlir_SOURCE_DIR}/include - ${jeff-mlir_BINARY_DIR}/include) +target_include_directories(MLIRQCOToJeff PRIVATE ${jeff-mlir_SOURCE_DIR}/include + ${jeff-mlir_BINARY_DIR}/include) -if(TARGET QCOToJeff) - target_compile_definitions(QCOToJeff PRIVATE MQT_CORE_VERSION="${MQT_CORE_VERSION}") +if(TARGET MLIRQCOToJeff) + target_compile_definitions(MLIRQCOToJeff PRIVATE MQT_CORE_VERSION="${MQT_CORE_VERSION}") endif() -if(TARGET obj.QCOToJeff) - target_compile_definitions(obj.QCOToJeff PRIVATE MQT_CORE_VERSION="${MQT_CORE_VERSION}") +if(TARGET obj.MLIRQCOToJeff) + target_compile_definitions(obj.MLIRQCOToJeff PRIVATE MQT_CORE_VERSION="${MQT_CORE_VERSION}") endif() diff --git a/mlir/lib/Conversion/QCOToJeff/QCOToJeff.cpp b/mlir/lib/Conversion/QCOToJeff/QCOToJeff.cpp index b37dc6cc8a..3541be7571 100644 --- a/mlir/lib/Conversion/QCOToJeff/QCOToJeff.cpp +++ b/mlir/lib/Conversion/QCOToJeff/QCOToJeff.cpp @@ -94,182 +94,29 @@ class StatefulOpConversionPattern : public OpConversionPattern { } // namespace /** - * @brief Converts a one-target, zero-parameter QCO operation to Jeff + * @brief Handles the results of a gate conversion * - * @tparam JeffOpType The operation type of the Jeff operation - * @tparam QCOOpType The operation type of the QCO operation - * @tparam QCOOpAdaptorType The OpAdaptor type of the QCO operation - * @param op The QCO operation instance to convert - * @param adaptor The OpAdaptor instance for the QCO operation - * @param rewriter The pattern rewriter - * @param state The lowering state - * @param isAdjoint Whether the operation is an adjoint operation - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertOneTargetZeroParameter(QCOOpType& op, QCOOpAdaptorType& adaptor, - ConversionPatternRewriter& rewriter, - LoweringState& state, const bool isAdjoint) { - Value target; - if (!state.inModifier()) { - target = adaptor.getQubitIn(); - } else { - target = state.targetsIn[0]; - } - - auto jeffOp = JeffOpType::create(rewriter, op.getLoc(), target, - /*in_ctrl_qubits=*/state.controlsIn, - /*num_ctrls=*/state.controlsIn.size(), - /*is_adjoint=*/state.inInvOp ^ isAdjoint, - /*power=*/1); - - if (!state.inModifier()) { - rewriter.replaceOp(op, jeffOp.getOutQubit()); - } else { - rewriter.eraseOp(op); - state.targetsOut = {jeffOp.getOutQubit()}; - } - if (state.inCtrlOp) { - state.controlsOut = jeffOp.getOutCtrlQubits(); - } - - return success(); -} - -/** - * @brief Converts a one-target, one-parameter QCO operation to Jeff - * - * @tparam JeffOpType The operation type of the Jeff operation - * @tparam QCOOpType The operation type of the QCO operation - * @tparam QCOOpAdaptorType The OpAdaptor type of the QCO operation - * @param op The QCO operation instance to convert - * @param adaptor The OpAdaptor instance for the QCO operation - * @param rewriter The pattern rewriter - * @param state The lowering state - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertOneTargetOneParameter(QCOOpType& op, QCOOpAdaptorType& adaptor, - ConversionPatternRewriter& rewriter, - LoweringState& state) { - Value target; - if (!state.inModifier()) { - target = adaptor.getQubitIn(); - } else { - target = state.targetsIn[0]; - } - - auto jeffOp = - JeffOpType::create(rewriter, op.getLoc(), target, op.getParameter(0), - /*in_ctrl_qubits=*/state.controlsIn, - /*num_ctrls=*/state.controlsIn.size(), - /*is_adjoint=*/state.inInvOp, - /*power=*/1); - - if (!state.inModifier()) { - rewriter.replaceOp(op, jeffOp.getOutQubit()); - } else { - rewriter.eraseOp(op); - state.targetsOut = {jeffOp.getOutQubit()}; - } - if (state.inCtrlOp) { - state.controlsOut = jeffOp.getOutCtrlQubits(); - } - - return success(); -} - -/** - * @brief Converts a one-target, three-parameter QCO operation to Jeff - * - * @tparam JeffOpType The operation type of the Jeff operation - * @tparam QCOOpType The operation type of the QCO operation - * @tparam QCOOpAdaptorType The OpAdaptor type of the QCO operation - * @param op The QCO operation instance to convert - * @param adaptor The OpAdaptor instance for the QCO operation - * @param rewriter The pattern rewriter - * @param state The lowering state - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertOneTargetThreeParameter(QCOOpType& op, QCOOpAdaptorType& adaptor, - ConversionPatternRewriter& rewriter, - LoweringState& state) { - Value target; - if (!state.inModifier()) { - target = adaptor.getQubitIn(); - } else { - target = state.targetsIn[0]; - } - - auto jeffOp = - JeffOpType::create(rewriter, op.getLoc(), target, op.getParameter(0), - op.getParameter(1), op.getParameter(2), - /*in_ctrl_qubits=*/state.controlsIn, - /*num_ctrls=*/state.controlsIn.size(), - /*is_adjoint=*/state.inInvOp, - /*power=*/1); - - if (!state.inModifier()) { - rewriter.replaceOp(op, jeffOp.getOutQubit()); - } else { - rewriter.eraseOp(op); - state.targetsOut = {jeffOp.getOutQubit()}; - } - if (state.inCtrlOp) { - state.controlsOut = jeffOp.getOutCtrlQubits(); - } - - return success(); -} - -/** - * @brief Converts a two-target, zero-parameter QCO operation to Jeff + * @details + * The original QCO operation is replaced or erased, and the state is updated. * - * @tparam JeffOpType The operation type of the Jeff operation - * @tparam QCOOpType The operation type of the QCO operation - * @tparam QCOOpAdaptorType The OpAdaptor type of the QCO operation - * @param op The QCO operation instance to convert - * @param adaptor The OpAdaptor instance for the QCO operation + * @param op The original QCO operation * @param rewriter The pattern rewriter * @param state The lowering state - * @return LogicalResult Success or failure of the conversion + * @param targetsOut The target qubits produced by the new operation + * @param controlsOut The control qubits produced by the new operation */ -template -static LogicalResult -convertTwoTargetZeroParameter(QCOOpType& op, QCOOpAdaptorType& adaptor, - ConversionPatternRewriter& rewriter, - LoweringState& state) { - Value target0; - Value target1; +static void handleResult(Operation* op, ConversionPatternRewriter& rewriter, + LoweringState& state, ValueRange targetsOut, + ValueRange controlsOut) { if (!state.inModifier()) { - target0 = adaptor.getQubit0In(); - target1 = adaptor.getQubit1In(); - } else { - target0 = state.targetsIn[0]; - target1 = state.targetsIn[1]; - } - - auto jeffOp = JeffOpType::create(rewriter, op.getLoc(), target0, target1, - /*in_ctrl_qubits=*/state.controlsIn, - /*num_ctrls=*/state.controlsIn.size(), - /*is_adjoint=*/state.inInvOp, - /*power=*/1); - - if (!state.inModifier()) { - rewriter.replaceOp(op, {jeffOp.getOutQubitOne(), jeffOp.getOutQubitTwo()}); + rewriter.replaceOp(op, targetsOut); } else { rewriter.eraseOp(op); - state.targetsOut = {jeffOp.getOutQubitOne(), jeffOp.getOutQubitTwo()}; + state.targetsOut = llvm::to_vector(targetsOut); } if (state.inCtrlOp) { - state.controlsOut = jeffOp.getOutCtrlQubits(); + state.controlsOut = llvm::to_vector(controlsOut); } - - return success(); } /** @@ -303,15 +150,8 @@ static void createCustomOp(QCOOpType& op, ConversionPatternRewriter& rewriter, /*power=*/1, /*name=*/name, /*num_targets=*/targets.size(), /*num_params=*/params.size()); - if (!state.inModifier()) { - rewriter.replaceOp(op, jeffOp.getOutTargetQubits()); - } else { - rewriter.eraseOp(op); - state.targetsOut = jeffOp.getOutTargetQubits(); - } - if (state.inCtrlOp) { - state.controlsOut = jeffOp.getOutCtrlQubits(); - } + handleResult(op, rewriter, state, jeffOp.getOutTargetQubits(), + jeffOp.getOutCtrlQubits()); } /** @@ -340,15 +180,8 @@ static void createPPROp(QCOOpType& op, ConversionPatternRewriter& rewriter, /*is_adjoint=*/state.inInvOp, /*power=*/1, /*pauli_gates=*/pauliGatesAttr); - if (!state.inModifier()) { - rewriter.replaceOp(op, jeffOp.getOutQubits()); - } else { - rewriter.eraseOp(op); - state.targetsOut = jeffOp.getOutQubits(); - } - if (state.inCtrlOp) { - state.controlsOut = jeffOp.getOutCtrlQubits(); - } + handleResult(op, rewriter, state, jeffOp.getOutQubits(), + jeffOp.getOutCtrlQubits()); } /** @@ -542,31 +375,52 @@ struct ConvertQCOGPhaseOpToJeff final // OneTargetZeroParameter -#define DEFINE_ONE_TARGET_ZERO_PARAMETER(OP_CLASS_QCO, OP_CLASS_JEFF, \ - IS_ADJOINT) \ - struct ConvertQCO##OP_CLASS_QCO##ToJeff final \ - : StatefulOpConversionPattern { \ - using StatefulOpConversionPattern::StatefulOpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qco::OP_CLASS_QCO op, OpAdaptor adaptor, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertOneTargetZeroParameter( \ - op, adaptor, rewriter, getState(), IS_ADJOINT); \ - } \ - }; - -DEFINE_ONE_TARGET_ZERO_PARAMETER(IdOp, IOp, false) -DEFINE_ONE_TARGET_ZERO_PARAMETER(XOp, XOp, false) -DEFINE_ONE_TARGET_ZERO_PARAMETER(YOp, YOp, false) -DEFINE_ONE_TARGET_ZERO_PARAMETER(ZOp, ZOp, false) -DEFINE_ONE_TARGET_ZERO_PARAMETER(HOp, HOp, false) -DEFINE_ONE_TARGET_ZERO_PARAMETER(SOp, SOp, false) -DEFINE_ONE_TARGET_ZERO_PARAMETER(SdgOp, SOp, true) -DEFINE_ONE_TARGET_ZERO_PARAMETER(TOp, TOp, false) -DEFINE_ONE_TARGET_ZERO_PARAMETER(TdgOp, TOp, true) - -#undef DEFINE_ONE_TARGET_ZERO_PARAMETER +/** + * @brief Converts a one-target, zero-parameter QCO gate to Jeff + * + * @tparam QCOOpType The operation type of the QCO gate + * @tparam JeffOpType The operation type of the Jeff gate + * @tparam isAdjoint Whether the operation is an adjoint operation + * + * @par Example: + * ```mlir + * %q_out = qco.x %q_in : !qco.qubit -> !qco.qubit + * ``` + * is converted to + * ```mlir + * %q_out = jeff.x {is_adjoint = false, num_ctrls = 0 : i8, power = 1 : i8} + * %q_in : !jeff.qubit + * ``` + */ +template +struct ConvertQCOOneTargetZeroParameterToJeff final + : StatefulOpConversionPattern { + using StatefulOpConversionPattern::StatefulOpConversionPattern; + + LogicalResult + matchAndRewrite(QCOOpType op, typename QCOOpType::Adaptor adaptor, + ConversionPatternRewriter& rewriter) const override { + auto& state = this->getState(); + + Value target; + if (!state.inModifier()) { + target = adaptor.getQubitIn(); + } else { + target = state.targetsIn[0]; + } + + auto jeffOp = JeffOpType::create(rewriter, op.getLoc(), target, + /*in_ctrl_qubits=*/state.controlsIn, + /*num_ctrls=*/state.controlsIn.size(), + /*is_adjoint=*/state.inInvOp ^ isAdjoint, + /*power=*/1); + + handleResult(op, rewriter, state, jeffOp.getOutQubit(), + jeffOp.getOutCtrlQubits()); + + return success(); + } +}; /** * @brief Converts qco.sx to jeff.custom @@ -638,25 +492,52 @@ struct ConvertQCOSXdgOpToJeff final : StatefulOpConversionPattern { // OneTargetOneParameter -#define DEFINE_ONE_TARGET_ONE_PARAMETER(OP_CLASS_QCO, OP_CLASS_JEFF) \ - struct ConvertQCO##OP_CLASS_QCO##ToJeff final \ - : StatefulOpConversionPattern { \ - using StatefulOpConversionPattern::StatefulOpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qco::OP_CLASS_QCO op, OpAdaptor adaptor, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertOneTargetOneParameter( \ - op, adaptor, rewriter, getState()); \ - } \ - }; - -DEFINE_ONE_TARGET_ONE_PARAMETER(RXOp, RxOp) -DEFINE_ONE_TARGET_ONE_PARAMETER(RYOp, RyOp) -DEFINE_ONE_TARGET_ONE_PARAMETER(RZOp, RzOp) -DEFINE_ONE_TARGET_ONE_PARAMETER(POp, R1Op) - -#undef DEFINE_ONE_TARGET_ONE_PARAMETER +/** + * @brief Converts a one-target, one-parameter QCO gate to Jeff + * + * @tparam QCOOpType The operation type of the QCO gate + * @tparam JeffOpType The operation type of the Jeff gate + * + * @par Example: + * ```mlir + * %q_out = qco.rx(%theta) %q_in : !qco.qubit -> !qco.qubit + * ``` + * is converted to + * ```mlir + * %q_out = jeff.rx(%theta) {is_adjoint = false, num_ctrls = 0 : i8, power = 1 : + * i8} %q_in : !jeff.qubit + * ``` + */ +template +struct ConvertQCOOneTargetOneParameterToJeff final + : StatefulOpConversionPattern { + using StatefulOpConversionPattern::StatefulOpConversionPattern; + + LogicalResult + matchAndRewrite(QCOOpType op, typename QCOOpType::Adaptor adaptor, + ConversionPatternRewriter& rewriter) const override { + auto& state = this->getState(); + + Value target; + if (!state.inModifier()) { + target = adaptor.getQubitIn(); + } else { + target = state.targetsIn[0]; + } + + auto jeffOp = + JeffOpType::create(rewriter, op.getLoc(), target, op.getParameter(0), + /*in_ctrl_qubits=*/state.controlsIn, + /*num_ctrls=*/state.controlsIn.size(), + /*is_adjoint=*/state.inInvOp, + /*power=*/1); + + handleResult(op, rewriter, state, jeffOp.getOutQubit(), + jeffOp.getOutCtrlQubits()); + + return success(); + } +}; // OneTargetTwoParameter @@ -698,15 +579,8 @@ struct ConvertQCOU2OpToJeff final : StatefulOpConversionPattern { /*num_ctrls=*/state.controlsIn.size(), /*is_adjoint=*/state.inInvOp, /*power=*/1); - if (!state.inModifier()) { - rewriter.replaceOp(op, jeffOp.getOutQubit()); - } else { - rewriter.eraseOp(op); - state.targetsOut = {jeffOp.getOutQubit()}; - } - if (state.inCtrlOp) { - state.controlsOut = jeffOp.getOutCtrlQubits(); - } + handleResult(op, rewriter, state, jeffOp.getOutQubit(), + jeffOp.getOutCtrlQubits()); return success(); } @@ -749,41 +623,106 @@ struct ConvertQCOROpToJeff final : StatefulOpConversionPattern { // OneTargetThreeParameter -#define DEFINE_ONE_TARGET_THREE_PARAMETER(OP_CLASS_QCO, OP_CLASS_JEFF) \ - struct ConvertQCO##OP_CLASS_QCO##ToJeff final \ - : StatefulOpConversionPattern { \ - using StatefulOpConversionPattern::StatefulOpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qco::OP_CLASS_QCO op, OpAdaptor adaptor, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertOneTargetThreeParameter( \ - op, adaptor, rewriter, getState()); \ - } \ - }; +/** + * @brief Converts a one-target, three-parameter QCO gate to Jeff + * + * @tparam QCOOpType The operation type of the QCO gate + * @tparam JeffOpType The operation type of the Jeff gate + * + * @par Example: + * ```mlir + * %q_out = qco.u(%theta, %phi, %lambda) %q_in : !qco.qubit -> !qco.qubit + * ``` + * is converted to + * ```mlir + * %q_out = jeff.u(%theta, %phi, %lambda) {is_adjoint = false, num_ctrls = 0 : + * i8, power = 1 : i8} %q_in : !jeff.qubit + * ``` + */ +template +struct ConvertQCOOneTargetThreeParameterToJeff final + : StatefulOpConversionPattern { + using StatefulOpConversionPattern::StatefulOpConversionPattern; -DEFINE_ONE_TARGET_THREE_PARAMETER(UOp, UOp) + LogicalResult + matchAndRewrite(QCOOpType op, typename QCOOpType::Adaptor adaptor, + ConversionPatternRewriter& rewriter) const override { + auto& state = this->getState(); + + Value target; + if (!state.inModifier()) { + target = adaptor.getQubitIn(); + } else { + target = state.targetsIn[0]; + } + + auto jeffOp = + JeffOpType::create(rewriter, op.getLoc(), target, op.getParameter(0), + op.getParameter(1), op.getParameter(2), + /*in_ctrl_qubits=*/state.controlsIn, + /*num_ctrls=*/state.controlsIn.size(), + /*is_adjoint=*/state.inInvOp, + /*power=*/1); -#undef DEFINE_ONE_TARGET_THREE_PARAMETER + handleResult(op, rewriter, state, jeffOp.getOutQubit(), + jeffOp.getOutCtrlQubits()); + + return success(); + } +}; // TwoTargetZeroParameter -#define DEFINE_TWO_TARGET_ZERO_PARAMETER(OP_CLASS_QCO, OP_CLASS_JEFF) \ - struct ConvertQCO##OP_CLASS_QCO##ToJeff final \ - : StatefulOpConversionPattern { \ - using StatefulOpConversionPattern::StatefulOpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qco::OP_CLASS_QCO op, OpAdaptor adaptor, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertTwoTargetZeroParameter( \ - op, adaptor, rewriter, getState()); \ - } \ - }; +/** + * @brief Converts a two-target, zero-parameter QCO gate to Jeff + * + * @tparam QCOOpType The operation type of the QCO gate + * @tparam JeffOpType The operation type of the Jeff gate + * + * @par Example: + * ```mlir + * %q0_out, %q1_out = qco.swap %q0_in, %q1_in : !qco.qubit, !qco.qubit -> + * !qco.qubit, !qco.qubit + * ``` + * is converted to + * ```mlir + * %q0_out, %q1_out = jeff.swap {is_adjoint = false, num_ctrls = 0 : i8, power = + * 1 : i8} %q0_in, %q1_in : !jeff.qubit, !jeff.qubit + * ``` + */ +template +struct ConvertQCOTwoTargetZeroParameterToJeff final + : StatefulOpConversionPattern { + using StatefulOpConversionPattern::StatefulOpConversionPattern; + + LogicalResult + matchAndRewrite(QCOOpType op, typename QCOOpType::Adaptor adaptor, + ConversionPatternRewriter& rewriter) const override { + auto& state = this->getState(); + + Value target0; + Value target1; + if (!state.inModifier()) { + target0 = adaptor.getQubit0In(); + target1 = adaptor.getQubit1In(); + } else { + target0 = state.targetsIn[0]; + target1 = state.targetsIn[1]; + } + + auto jeffOp = JeffOpType::create(rewriter, op.getLoc(), target0, target1, + /*in_ctrl_qubits=*/state.controlsIn, + /*num_ctrls=*/state.controlsIn.size(), + /*is_adjoint=*/state.inInvOp, + /*power=*/1); -DEFINE_TWO_TARGET_ZERO_PARAMETER(SWAPOp, SwapOp) + handleResult(op, rewriter, state, + {jeffOp.getOutQubitOne(), jeffOp.getOutQubitTwo()}, + jeffOp.getOutCtrlQubits()); -#undef DEFINE_TWO_TARGET_ZERO_PARAMETER + return success(); + } +}; /** * @brief Converts qco.iswap to jeff.custom @@ -1477,19 +1416,31 @@ struct QCOToJeff final : impl::QCOToJeffBase { patterns.add< ConvertQCOAllocOpToJeff, ConvertQCODeallocOpToJeff, ConvertQCOMeasureOpToJeff, ConvertQCOResetOpToJeff, - ConvertQCOGPhaseOpToJeff, ConvertQCOIdOpToJeff, ConvertQCOXOpToJeff, - ConvertQCOYOpToJeff, ConvertQCOZOpToJeff, ConvertQCOHOpToJeff, - ConvertQCOSOpToJeff, ConvertQCOSdgOpToJeff, ConvertQCOTOpToJeff, - ConvertQCOTdgOpToJeff, ConvertQCOSXOpToJeff, ConvertQCOSXdgOpToJeff, - ConvertQCORXOpToJeff, ConvertQCORYOpToJeff, ConvertQCORZOpToJeff, - ConvertQCOPOpToJeff, ConvertQCOROpToJeff, ConvertQCOU2OpToJeff, - ConvertQCOUOpToJeff, ConvertQCOSWAPOpToJeff, ConvertQCOiSWAPOpToJeff, - ConvertQCOECROpToJeff, ConvertQCODCXOpToJeff, ConvertQCORXXOpToJeff, - ConvertQCORYYOpToJeff, ConvertQCORZXOpToJeff, ConvertQCORZZOpToJeff, - ConvertQCOXXMinusYYOpToJeff, ConvertQCOXXPlusYYOpToJeff, - ConvertQCOBarrierOpToJeff, ConvertQCOCtrlOpToJeff, - ConvertQCOInvOpToJeff, ConvertQCOYieldOpToJeff, ConvertQCOMainToJeff, - ConvertArithConstOpToJeff>(typeConverter, context, &state); + ConvertQCOGPhaseOpToJeff, + ConvertQCOOneTargetZeroParameterToJeff, + ConvertQCOOneTargetZeroParameterToJeff, + ConvertQCOOneTargetZeroParameterToJeff, + ConvertQCOOneTargetZeroParameterToJeff, + ConvertQCOOneTargetZeroParameterToJeff, + ConvertQCOOneTargetZeroParameterToJeff, + ConvertQCOOneTargetZeroParameterToJeff, + ConvertQCOOneTargetZeroParameterToJeff, + ConvertQCOOneTargetZeroParameterToJeff, + ConvertQCOSXOpToJeff, ConvertQCOSXdgOpToJeff, + ConvertQCOOneTargetOneParameterToJeff, + ConvertQCOOneTargetOneParameterToJeff, + ConvertQCOOneTargetOneParameterToJeff, + ConvertQCOOneTargetOneParameterToJeff, + ConvertQCOROpToJeff, ConvertQCOU2OpToJeff, + ConvertQCOOneTargetThreeParameterToJeff, + ConvertQCOTwoTargetZeroParameterToJeff, + ConvertQCOiSWAPOpToJeff, ConvertQCOECROpToJeff, ConvertQCODCXOpToJeff, + ConvertQCORXXOpToJeff, ConvertQCORYYOpToJeff, ConvertQCORZXOpToJeff, + ConvertQCORZZOpToJeff, ConvertQCOXXMinusYYOpToJeff, + ConvertQCOXXPlusYYOpToJeff, ConvertQCOBarrierOpToJeff, + ConvertQCOCtrlOpToJeff, ConvertQCOInvOpToJeff, ConvertQCOYieldOpToJeff, + ConvertQCOMainToJeff, ConvertArithConstOpToJeff>(typeConverter, context, + &state); // Apply the conversion if (applyPartialConversion(module, target, std::move(patterns)).failed()) { diff --git a/mlir/lib/Conversion/QCOToQC/CMakeLists.txt b/mlir/lib/Conversion/QCOToQC/CMakeLists.txt index c50ca147fe..9c403f8951 100644 --- a/mlir/lib/Conversion/QCOToQC/CMakeLists.txt +++ b/mlir/lib/Conversion/QCOToQC/CMakeLists.txt @@ -8,8 +8,8 @@ file(GLOB CONVERSION_SOURCES *.cpp) -add_mlir_library( - QCOToQC +add_mlir_conversion_library( + MLIRQCOToQC ${CONVERSION_SOURCES} DEPENDS QCOToQCIncGen @@ -22,4 +22,4 @@ add_mlir_library( MLIRFuncTransforms DISABLE_INSTALL) -mqt_mlir_target_use_project_options(QCOToQC) +mqt_mlir_target_use_project_options(MLIRQCOToQC) diff --git a/mlir/lib/Conversion/QCOToQC/QCOToQC.cpp b/mlir/lib/Conversion/QCOToQC/QCOToQC.cpp index 9af0f7f4e6..8d8a604ab4 100644 --- a/mlir/lib/Conversion/QCOToQC/QCOToQC.cpp +++ b/mlir/lib/Conversion/QCOToQC/QCOToQC.cpp @@ -35,220 +35,6 @@ using namespace qc; #define GEN_PASS_DEF_QCOTOQC #include "mlir/Conversion/QCOToQC/QCOToQC.h.inc" -/** - * @brief Converts a zero-target, one-parameter QCO operation to QC - * - * @tparam QCOpType The operation type of the QC operation - * @tparam QCOOpType The operation type of the QCO operation - * @param op The QCO operation instance to convert - * @param rewriter The pattern rewriter - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertZeroTargetOneParameter(QCOOpType& op, - ConversionPatternRewriter& rewriter) { - rewriter.create(op.getLoc(), op.getParameter(0)); - rewriter.eraseOp(op); - return success(); -} - -/** - * @brief Converts a one-target, zero-parameter QCO operation to QC - * - * @tparam QCOpType The operation type of the QC operation - * @tparam QCOOpType The operation type of the QCO operation - * @tparam QCOOpAdaptorType The OpAdaptor type of the QCO operation - * @param op The QCO operation instance to convert - * @param adaptor The OpAdaptor of the QCO operation - * @param rewriter The pattern rewriter - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertOneTargetZeroParameter(QCOOpType& op, QCOOpAdaptorType& adaptor, - ConversionPatternRewriter& rewriter) { - // OpAdaptor provides the already type-converted input qubit - auto qcQubit = adaptor.getQubitIn(); - - // Create the QC operation (in-place, no result) - rewriter.create(op.getLoc(), qcQubit); - - // Replace the output qubit with the same QC reference - rewriter.replaceOp(op, qcQubit); - - return success(); -} - -/** - * @brief Converts a one-target, one-parameter QCO operation to QC - * - * @tparam QCOpType The operation type of the QC operation - * @tparam QCOOpType The operation type of the QCO operation - * @tparam QCOOpAdaptorType The OpAdaptor type of the QCO operation - * @param op The QCO operation instance to convert - * @param adaptor The OpAdaptor of the QCO operation - * @param rewriter The pattern rewriter - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertOneTargetOneParameter(QCOOpType& op, QCOOpAdaptorType& adaptor, - ConversionPatternRewriter& rewriter) { - // OpAdaptor provides the already type-converted input qubit - auto qcQubit = adaptor.getQubitIn(); - - // Create the QC operation (in-place, no result) - rewriter.create(op.getLoc(), qcQubit, op.getParameter(0)); - - // Replace the output qubit with the same QC reference - rewriter.replaceOp(op, qcQubit); - - return success(); -} - -/** - * @brief Converts a one-target, two-parameter QCO operation to QC - * - * @tparam QCOpType The operation type of the QC operation - * @tparam QCOOpType The operation type of the QCO operation - * @tparam QCOOpAdaptorType The OpAdaptor type of the QCO operation - * @param op The QCO operation instance to convert - * @param adaptor The OpAdaptor of the QCO operation - * @param rewriter The pattern rewriter - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertOneTargetTwoParameter(QCOOpType& op, QCOOpAdaptorType& adaptor, - ConversionPatternRewriter& rewriter) { - // OpAdaptor provides the already type-converted input qubit - auto qcQubit = adaptor.getQubitIn(); - - // Create the QC operation (in-place, no result) - rewriter.create(op.getLoc(), qcQubit, op.getParameter(0), - op.getParameter(1)); - - // Replace the output qubit with the same QC reference - rewriter.replaceOp(op, qcQubit); - - return success(); -} - -/** - * @brief Converts a one-target, three-parameter QCO operation to QC - * - * @tparam QCOpType The operation type of the QC operation - * @tparam QCOOpType The operation type of the QCO operation - * @tparam QCOOpAdaptorType The OpAdaptor type of the QCO operation - * @param op The QCO operation instance to convert - * @param adaptor The OpAdaptor of the QCO operation - * @param rewriter The pattern rewriter - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertOneTargetThreeParameter(QCOOpType& op, QCOOpAdaptorType& adaptor, - ConversionPatternRewriter& rewriter) { - // OpAdaptor provides the already type-converted input qubit - auto qcQubit = adaptor.getQubitIn(); - - // Create the QC operation (in-place, no result) - rewriter.create(op.getLoc(), qcQubit, op.getParameter(0), - op.getParameter(1), op.getParameter(2)); - - // Replace the output qubit with the same QC reference - rewriter.replaceOp(op, qcQubit); - - return success(); -} - -/** - * @brief Converts a two-target, zero-parameter QCO operation to QC - * - * @tparam QCOpType The operation type of the QC operation - * @tparam QCOOpType The operation type of the QCO operation - * @tparam QCOOpAdaptorType The OpAdaptor type of the QCO operation - * @param op The QCO operation instance to convert - * @param adaptor The OpAdaptor of the QCO operation - * @param rewriter The pattern rewriter - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertTwoTargetZeroParameter(QCOOpType& op, QCOOpAdaptorType& adaptor, - ConversionPatternRewriter& rewriter) { - // OpAdaptor provides the already type-converted input qubits - auto qcQubit0 = adaptor.getQubit0In(); - auto qcQubit1 = adaptor.getQubit1In(); - - // Create the QC operation (in-place, no result) - rewriter.create(op.getLoc(), qcQubit0, qcQubit1); - - // Replace the output qubits with the same QC references - rewriter.replaceOp(op, {qcQubit0, qcQubit1}); - - return success(); -} - -/** - * @brief Converts a two-target, one-parameter QCO operation to QC - * - * @tparam QCOpType The operation type of the QC operation - * @tparam QCOOpType The operation type of the QCO operation - * @tparam QCOOpAdaptorType The OpAdaptor type of the QCO operation - * @param op The QCO operation instance to convert - * @param adaptor The OpAdaptor of the QCO operation - * @param rewriter The pattern rewriter - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertTwoTargetOneParameter(QCOOpType& op, QCOOpAdaptorType& adaptor, - ConversionPatternRewriter& rewriter) { - // OpAdaptor provides the already type-converted input qubits - auto qcQubit0 = adaptor.getQubit0In(); - auto qcQubit1 = adaptor.getQubit1In(); - - // Create the QC operation (in-place, no result) - rewriter.create(op.getLoc(), qcQubit0, qcQubit1, - op.getParameter(0)); - - // Replace the output qubits with the same QC references - rewriter.replaceOp(op, {qcQubit0, qcQubit1}); - - return success(); -} - -/** - * @brief Converts a two-target, two-parameter QCO operation to QC - * - * @tparam QCOpType The operation type of the QC operation - * @tparam QCOOpType The operation type of the QCO operation - * @tparam QCOOpAdaptorType The OpAdaptor type of the QCO operation - * @param op The QCO operation instance to convert - * @param adaptor The OpAdaptor of the QCO operation - * @param rewriter The pattern rewriter - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertTwoTargetTwoParameter(QCOOpType& op, QCOOpAdaptorType& adaptor, - ConversionPatternRewriter& rewriter) { - // OpAdaptor provides the already type-converted input qubits - auto qcQubit0 = adaptor.getQubit0In(); - auto qcQubit1 = adaptor.getQubit1In(); - - // Create the QC operation (in-place, no result) - rewriter.create(op.getLoc(), qcQubit0, qcQubit1, op.getParameter(0), - op.getParameter(1)); - - // Replace the output qubits with the same QC references - rewriter.replaceOp(op, {qcQubit0, qcQubit1}); - - return success(); -} - /** * @brief Type converter for QCO-to-QC conversion * @@ -397,8 +183,8 @@ struct ConvertQCOMeasureOp final : OpConversionPattern { // Create qc.measure (in-place operation, returns only bit) // Preserve register metadata for output recording - auto qcOp = rewriter.create( - op.getLoc(), qcQubit, op.getRegisterNameAttr(), + auto qcOp = qc::MeasureOp::create( + rewriter, op.getLoc(), qcQubit, op.getRegisterNameAttr(), op.getRegisterSizeAttr(), op.getRegisterIndexAttr()); auto measureBit = qcOp.getResult(); @@ -441,7 +227,7 @@ struct ConvertQCOResetOp final : OpConversionPattern { auto qcQubit = adaptor.getQubitIn(); // Create qc.reset (in-place operation, no result) - rewriter.create(op.getLoc(), qcQubit); + qc::ResetOp::create(rewriter, op.getLoc(), qcQubit); // Replace the output qubit with the same qc reference rewriter.replaceOp(op, qcQubit); @@ -450,273 +236,296 @@ struct ConvertQCOResetOp final : OpConversionPattern { } }; -// ZeroTargetOneParameter - -#define DEFINE_ZERO_TARGET_ONE_PARAMETER(OP_CLASS, OP_NAME, PARAM) \ - /** \ - * @brief Converts qco.OP_NAME to qc.OP_NAME \ - * \ - * @par Example: \ - * ```mlir \ - * qco.OP_NAME(%PARAM) \ - * ``` \ - * is converted to \ - * ```mlir \ - * qc.OP_NAME(%PARAM) \ - * ``` \ - */ \ - struct ConvertQCO##OP_CLASS final : OpConversionPattern { \ - using OpConversionPattern::OpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qco::OP_CLASS op, OpAdaptor /*adaptor*/, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertZeroTargetOneParameter(op, rewriter); \ - } \ - }; - -DEFINE_ZERO_TARGET_ONE_PARAMETER(GPhaseOp, gphase, theta) - -#undef DEFINE_ZERO_TARGET_ONE_PARAMETER - -// OneTargetZeroParameter - -#define DEFINE_ONE_TARGET_ZERO_PARAMETER(OP_CLASS, OP_NAME) \ - /** \ - * @brief Converts qco.OP_NAME to qc.OP_NAME \ - * \ - * @par Example: \ - * ```mlir \ - * %q_out = qco.OP_NAME %q_in : !qco.qubit -> !qco.qubit \ - * ``` \ - * is converted to \ - * ```mlir \ - * qc.OP_NAME %q : !qc.qubit \ - * ``` \ - */ \ - struct ConvertQCO##OP_CLASS final : OpConversionPattern { \ - using OpConversionPattern::OpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qco::OP_CLASS op, OpAdaptor adaptor, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertOneTargetZeroParameter(op, adaptor, \ - rewriter); \ - } \ - }; - -DEFINE_ONE_TARGET_ZERO_PARAMETER(IdOp, id) -DEFINE_ONE_TARGET_ZERO_PARAMETER(XOp, x) -DEFINE_ONE_TARGET_ZERO_PARAMETER(YOp, y) -DEFINE_ONE_TARGET_ZERO_PARAMETER(ZOp, z) -DEFINE_ONE_TARGET_ZERO_PARAMETER(HOp, h) -DEFINE_ONE_TARGET_ZERO_PARAMETER(SOp, s) -DEFINE_ONE_TARGET_ZERO_PARAMETER(SdgOp, sdg) -DEFINE_ONE_TARGET_ZERO_PARAMETER(TOp, t) -DEFINE_ONE_TARGET_ZERO_PARAMETER(TdgOp, tdg) -DEFINE_ONE_TARGET_ZERO_PARAMETER(SXOp, sx) -DEFINE_ONE_TARGET_ZERO_PARAMETER(SXdgOp, sxdg) - -#undef DEFINE_ONE_TARGET_ZERO_PARAMETER - -// OneTargetOneParameter - -#define DEFINE_ONE_TARGET_ONE_PARAMETER(OP_CLASS, OP_NAME, PARAM) \ - /** \ - * @brief Converts qco.OP_NAME to qc.OP_NAME \ - * \ - * @par Example: \ - * ```mlir \ - * %q_out = qco.OP_NAME(%PARAM) %q_in : !qco.qubit -> !qco.qubit \ - * ``` \ - * is converted to \ - * ```mlir \ - * qc.OP_NAME(%PARAM) %q : !qc.qubit \ - * ``` \ - */ \ - struct ConvertQCO##OP_CLASS final : OpConversionPattern { \ - using OpConversionPattern::OpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qco::OP_CLASS op, OpAdaptor adaptor, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertOneTargetOneParameter(op, adaptor, \ - rewriter); \ - } \ - }; - -DEFINE_ONE_TARGET_ONE_PARAMETER(RXOp, rx, theta) -DEFINE_ONE_TARGET_ONE_PARAMETER(RYOp, ry, theta) -DEFINE_ONE_TARGET_ONE_PARAMETER(RZOp, rz, theta) -DEFINE_ONE_TARGET_ONE_PARAMETER(POp, p, theta) - -#undef DEFINE_ONE_TARGET_ONE_PARAMETER - -// OneTargetTwoParameter - -#define DEFINE_ONE_TARGET_TWO_PARAMETER(OP_CLASS, OP_NAME, PARAM1, PARAM2) \ - /** \ - * @brief Converts qco.OP_NAME to qc.OP_NAME \ - * \ - * @par Example: \ - * ```mlir \ - * %q_out = qco.OP_NAME(%PARAM1, %PARAM2) %q_in : !qco.qubit -> \ - * !qco.qubit \ - * ``` \ - * is converted to \ - * ```mlir \ - * qc.OP_NAME(%PARAM1, %PARAM2) %q : !qc.qubit \ - * ``` \ - */ \ - struct ConvertQCO##OP_CLASS final : OpConversionPattern { \ - using OpConversionPattern::OpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qco::OP_CLASS op, OpAdaptor adaptor, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertOneTargetTwoParameter(op, adaptor, \ - rewriter); \ - } \ - }; - -DEFINE_ONE_TARGET_TWO_PARAMETER(ROp, r, theta, phi) -DEFINE_ONE_TARGET_TWO_PARAMETER(U2Op, u2, phi, lambda) - -#undef DEFINE_ONE_TARGET_TWO_PARAMETER - -// OneTargetThreeParameter - -#define DEFINE_ONE_TARGET_THREE_PARAMETER(OP_CLASS, OP_NAME, PARAM1, PARAM2, \ - PARAM3) \ - /** \ - * @brief Converts qco.OP_NAME to qc.OP_NAME \ - * \ - * @par Example: \ - * ```mlir \ - * %q_out = qco.OP_NAME(%PARAM1, %PARAM2, %PARAM3) %q_in : !qco.qubit \ - * -> !qco.qubit \ - * ``` \ - * is converted to \ - * ```mlir \ - * qc.OP_NAME(%PARAM1, %PARAM2, %PARAM3) %q : !qc.qubit \ - * ``` \ - */ \ - struct ConvertQCO##OP_CLASS final : OpConversionPattern { \ - using OpConversionPattern::OpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qco::OP_CLASS op, OpAdaptor adaptor, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertOneTargetThreeParameter(op, adaptor, \ - rewriter); \ - } \ - }; - -DEFINE_ONE_TARGET_THREE_PARAMETER(UOp, u, theta, phi, lambda) - -#undef DEFINE_ONE_TARGET_THREE_PARAMETER - -// TwoTargetZeroParameter - -#define DEFINE_TWO_TARGET_ZERO_PARAMETER(OP_CLASS, OP_NAME) \ - /** \ - * @brief Converts qco.OP_NAME to qc.OP_NAME \ - * \ - * @par Example: \ - * ```mlir \ - * %q0_out, %q1_out = qco.OP_NAME %q0_in, %q1_in : !qco.qubit, !qco.qubit \ - * -> !qco.qubit, !qco.qubit \ - * ``` \ - * is converted to \ - * ```mlir \ - * qc.OP_NAME %q0, %q1 : !qc.qubit, !qc.qubit \ - * ``` \ - */ \ - struct ConvertQCO##OP_CLASS final : OpConversionPattern { \ - using OpConversionPattern::OpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qco::OP_CLASS op, OpAdaptor adaptor, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertTwoTargetZeroParameter(op, adaptor, \ - rewriter); \ - } \ - }; - -DEFINE_TWO_TARGET_ZERO_PARAMETER(SWAPOp, swap) -DEFINE_TWO_TARGET_ZERO_PARAMETER(iSWAPOp, iswap) -DEFINE_TWO_TARGET_ZERO_PARAMETER(DCXOp, dcx) -DEFINE_TWO_TARGET_ZERO_PARAMETER(ECROp, ecr) - -#undef DEFINE_TWO_TARGET_ZERO_PARAMETER - -// TwoTargetOneParameter - -#define DEFINE_TWO_TARGET_ONE_PARAMETER(OP_CLASS, OP_NAME, PARAM) \ - /** \ - * @brief Converts qco.OP_NAME to qc.OP_NAME \ - * \ - * @par Example: \ - * ```mlir \ - * %q0_out, %q1_out = qco.OP_NAME(%PARAM) %q0_in, %q1_in : !qco.qubit, \ - * !qco.qubit -> !qco.qubit, !qco.qubit \ - * ``` \ - * is converted to \ - * ```mlir \ - * qc.OP_NAME(%PARAM) %q0, %q1 : !qc.qubit, !qc.qubit \ - * ``` \ - */ \ - struct ConvertQCO##OP_CLASS final : OpConversionPattern { \ - using OpConversionPattern::OpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qco::OP_CLASS op, OpAdaptor adaptor, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertTwoTargetOneParameter(op, adaptor, \ - rewriter); \ - } \ - }; - -DEFINE_TWO_TARGET_ONE_PARAMETER(RXXOp, rxx, theta) -DEFINE_TWO_TARGET_ONE_PARAMETER(RYYOp, ryy, theta) -DEFINE_TWO_TARGET_ONE_PARAMETER(RZXOp, rzx, theta) -DEFINE_TWO_TARGET_ONE_PARAMETER(RZZOp, rzz, theta) - -#undef DEFINE_TWO_TARGET_ONE_PARAMETER - -// TwoTargetTwoParameter - -#define DEFINE_TWO_TARGET_TWO_PARAMETER(OP_CLASS, OP_NAME, PARAM1, PARAM2) \ - /** \ - * @brief Converts qco.OP_NAME to qc.OP_NAME \ - * \ - * @par Example: \ - * ```mlir \ - * %q0_out, %q1_out = qco.OP_NAME(%PARAM1, %PARAM2) %q0_in, %q1_in : \ - * !qco.qubit, !qco.qubit -> !qco.qubit, !qco.qubit \ - * ``` \ - * is converted to \ - * ```mlir \ - * qc.OP_NAME(%PARAM1, %PARAM2) %q0, %q1 : !qc.qubit, !qc.qubit \ - * ``` \ - */ \ - struct ConvertQCO##OP_CLASS final : OpConversionPattern { \ - using OpConversionPattern::OpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qco::OP_CLASS op, OpAdaptor adaptor, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertTwoTargetTwoParameter(op, adaptor, \ - rewriter); \ - } \ - }; - -DEFINE_TWO_TARGET_TWO_PARAMETER(XXPlusYYOp, xx_plus_yy, theta, beta) -DEFINE_TWO_TARGET_TWO_PARAMETER(XXMinusYYOp, xx_minus_yy, theta, beta) - -#undef DEFINE_TWO_TARGET_TWO_PARAMETER - -// BarrierOp +/** + * @brief Converts a zero-target, one-parameter QCO gate to QC + * + * @tparam QCOOpType The operation type of the QCO gate + * @tparam QCOpType The operation type of the QC gate + * + * @par Example: + * ```mlir + * qco.gphase(%theta) + * ``` + * is converted to + * ```mlir + * qc.gphase(%theta) + * ``` + */ +template +struct ConvertQCOZeroTargetOneParameterToQC final + : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(QCOOpType op, typename QCOOpType::Adaptor /*adaptor*/, + ConversionPatternRewriter& rewriter) const override { + QCOpType::create(rewriter, op.getLoc(), op.getParameter(0)); + rewriter.eraseOp(op); + return success(); + } +}; + +/** + * @brief Converts a one-target, zero-parameter QCO gate to QC + * + * @tparam QCOOpType The operation type of the QCO gate + * @tparam QCOpType The operation type of the QC gate + * + * @par Example: + * ```mlir + * %q_out = qco.x %q_in : !qco.qubit -> !qco.qubit + * ``` + * is converted to + * ```mlir + * qc.x %q : !qc.qubit + * ``` + */ +template +struct ConvertQCOOneTargetZeroParameterToQC final + : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(QCOOpType op, typename QCOOpType::Adaptor adaptor, + ConversionPatternRewriter& rewriter) const override { + // OpAdaptor provides the already type-converted input qubit + auto qcQubit = adaptor.getQubitIn(); + + // Create the QC operation (in-place, no result) + QCOpType::create(rewriter, op.getLoc(), qcQubit); + + // Replace the output qubit with the same QC reference + rewriter.replaceOp(op, qcQubit); + + return success(); + } +}; + +/** + * @brief Converts a one-target, one-parameter QCO gate to QC + * + * @tparam QCOOpType The operation type of the QCO gate + * @tparam QCOpType The operation type of the QC gate + * + * @par Example: + * ```mlir + * %q_out = qco.rx(%theta) %q_in : !qco.qubit -> !qco.qubit + * ``` + * is converted to + * ```mlir + * qc.rx(%theta) %q : !qc.qubit + * ``` + */ +template +struct ConvertQCOOneTargetOneParameterToQC final + : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(QCOOpType op, typename QCOOpType::Adaptor adaptor, + ConversionPatternRewriter& rewriter) const override { + // OpAdaptor provides the already type-converted input qubit + auto qcQubit = adaptor.getQubitIn(); + + // Create the QC operation (in-place, no result) + QCOpType::create(rewriter, op.getLoc(), qcQubit, op.getParameter(0)); + + // Replace the output qubit with the same QC reference + rewriter.replaceOp(op, qcQubit); + + return success(); + } +}; + +/** + * @brief Converts a one-target, two-parameter QCO gate to QC + * + * @tparam QCOOpType The operation type of the QCO gate + * @tparam QCOpType The operation type of the QC gate + * + * @par Example: + * ```mlir + * %q_out = qco.r(%theta, %phi) %q_in : !qco.qubit -> !qco.qubit + * ``` + * is converted to + * ```mlir + * qc.r(%theta, %phi) %q : !qc.qubit + * ``` + */ +template +struct ConvertQCOOneTargetTwoParameterToQC final + : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(QCOOpType op, typename QCOOpType::Adaptor adaptor, + ConversionPatternRewriter& rewriter) const override { + // OpAdaptor provides the already type-converted input qubit + auto qcQubit = adaptor.getQubitIn(); + + // Create the QC operation (in-place, no result) + QCOpType::create(rewriter, op.getLoc(), qcQubit, op.getParameter(0), + op.getParameter(1)); + + // Replace the output qubit with the same QC reference + rewriter.replaceOp(op, qcQubit); + + return success(); + } +}; + +/** + * @brief Converts a one-target, three-parameter QCO gate to QC + * + * @tparam QCOOpType The operation type of the QCO gate + * @tparam QCOpType The operation type of the QC gate + * + * @par Example: + * ```mlir + * %q_out = qco.u(%theta, %phi, %lambda) %q_in : !qco.qubit -> !qco.qubit + * ``` + * is converted to + * ```mlir + * qc.u(%theta, %phi, %lambda) %q : !qc.qubit + * ``` + */ +template +struct ConvertQCOOneTargetThreeParameterToQC final + : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(QCOOpType op, typename QCOOpType::Adaptor adaptor, + ConversionPatternRewriter& rewriter) const override { + // OpAdaptor provides the already type-converted input qubit + auto qcQubit = adaptor.getQubitIn(); + + // Create the QC operation (in-place, no result) + QCOpType::create(rewriter, op.getLoc(), qcQubit, op.getParameter(0), + op.getParameter(1), op.getParameter(2)); + + // Replace the output qubit with the same QC reference + rewriter.replaceOp(op, qcQubit); + + return success(); + } +}; + +/** + * @brief Converts a two-target, zero-parameter QCO gate to QC + * + * @tparam QCOOpType The operation type of the QCO gate + * @tparam QCOpType The operation type of the QC gate + * + * @par Example: + * ```mlir + * %q0_out, %q1_out = qco.swap %q0_in, %q1_in : !qco.qubit, !qco.qubit -> + * !qco.qubit, !qco.qubit + * ``` + * is converted to + * ```mlir + * qc.swap %q0, %q1 : !qc.qubit, !qc.qubit + * ``` + */ +template +struct ConvertQCOTwoTargetZeroParameterToQC final + : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(QCOOpType op, typename QCOOpType::Adaptor adaptor, + ConversionPatternRewriter& rewriter) const override { + // OpAdaptor provides the already type-converted input qubits + auto qcQubit0 = adaptor.getQubit0In(); + auto qcQubit1 = adaptor.getQubit1In(); + + // Create the QC operation (in-place, no result) + QCOpType::create(rewriter, op.getLoc(), qcQubit0, qcQubit1); + + // Replace the output qubits with the same QC references + rewriter.replaceOp(op, {qcQubit0, qcQubit1}); + + return success(); + } +}; + +/** + * @brief Converts a two-target, one-parameter QCO gate to QC + * + * @tparam QCOOpType The operation type of the QCO gate + * @tparam QCOpType The operation type of the QC gate + * + * @par Example: + * ```mlir + * %q0_out, %q1_out = qco.rxx(%theta) %q0_in, %q1_in : !qco.qubit, !qco.qubit -> + * !qco.qubit, !qco.qubit + * ``` + * is converted to + * ```mlir + * qc.rxx(%theta) %q0, %q1 : !qc.qubit, !qc.qubit + * ``` + */ +template +struct ConvertQCOTwoTargetOneParameterToQC final + : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(QCOOpType op, typename QCOOpType::Adaptor adaptor, + ConversionPatternRewriter& rewriter) const override { + // OpAdaptor provides the already type-converted input qubits + auto qcQubit0 = adaptor.getQubit0In(); + auto qcQubit1 = adaptor.getQubit1In(); + + // Create the QC operation (in-place, no result) + QCOpType::create(rewriter, op.getLoc(), qcQubit0, qcQubit1, + op.getParameter(0)); + + // Replace the output qubits with the same QC references + rewriter.replaceOp(op, {qcQubit0, qcQubit1}); + + return success(); + } +}; + +/** + * @brief Converts a two-target, two-parameter QCO gate to QC + * + * @tparam QCOOpType The operation type of the QCO gate + * @tparam QCOpType The operation type of the QC gate + * + * @par Example: + * ```mlir + * %q0_out, %q1_out = qco.xx_minus_yy(%theta, %beta) %q0_in, %q1_in : + * !qco.qubit, !qco.qubit -> !qco.qubit, !qco.qubit + * ``` + * is converted to + * ```mlir + * qc.xx_minus_yy(%theta, %beta) %q0, %q1 : !qc.qubit, !qc.qubit + * ``` + */ +template +struct ConvertQCOTwoTargetTwoParameterToQC final + : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(QCOOpType op, typename QCOOpType::Adaptor adaptor, + ConversionPatternRewriter& rewriter) const override { + // OpAdaptor provides the already type-converted input qubits + auto qcQubit0 = adaptor.getQubit0In(); + auto qcQubit1 = adaptor.getQubit1In(); + + // Create the QC operation (in-place, no result) + QCOpType::create(rewriter, op.getLoc(), qcQubit0, qcQubit1, + op.getParameter(0), op.getParameter(1)); + + // Replace the output qubits with the same QC references + rewriter.replaceOp(op, {qcQubit0, qcQubit1}); + + return success(); + } +}; /** * @brief Converts qco.barrier to qc.barrier @@ -741,7 +550,7 @@ struct ConvertQCOBarrierOp final : OpConversionPattern { auto qcQubits = adaptor.getQubitsIn(); // Create qc.barrier operation - rewriter.create(op.getLoc(), qcQubits); + qc::BarrierOp::create(rewriter, op.getLoc(), qcQubits); // Replace the output qubits with the same qc references rewriter.replaceOp(op, qcQubits); @@ -945,18 +754,39 @@ struct QCOToQC final : impl::QCOToQCBase { // Register operation conversion patterns // Note: No state tracking needed - OpAdaptors handle type conversion - patterns - .add(typeConverter, context); + patterns.add< + ConvertQCOAllocOp, ConvertQCODeallocOp, ConvertQCOStaticOp, + ConvertQCOMeasureOp, ConvertQCOResetOp, + ConvertQCOZeroTargetOneParameterToQC, + ConvertQCOOneTargetZeroParameterToQC, + ConvertQCOOneTargetZeroParameterToQC, + ConvertQCOOneTargetZeroParameterToQC, + ConvertQCOOneTargetZeroParameterToQC, + ConvertQCOOneTargetZeroParameterToQC, + ConvertQCOOneTargetZeroParameterToQC, + ConvertQCOOneTargetZeroParameterToQC, + ConvertQCOOneTargetZeroParameterToQC, + ConvertQCOOneTargetZeroParameterToQC, + ConvertQCOOneTargetZeroParameterToQC, + ConvertQCOOneTargetOneParameterToQC, + ConvertQCOOneTargetOneParameterToQC, + ConvertQCOOneTargetOneParameterToQC, + ConvertQCOOneTargetOneParameterToQC, + ConvertQCOOneTargetTwoParameterToQC, + ConvertQCOOneTargetTwoParameterToQC, + ConvertQCOOneTargetThreeParameterToQC, + ConvertQCOTwoTargetZeroParameterToQC, + ConvertQCOTwoTargetZeroParameterToQC, + ConvertQCOTwoTargetZeroParameterToQC, + ConvertQCOTwoTargetZeroParameterToQC, + ConvertQCOTwoTargetOneParameterToQC, + ConvertQCOTwoTargetOneParameterToQC, + ConvertQCOTwoTargetOneParameterToQC, + ConvertQCOTwoTargetOneParameterToQC, + ConvertQCOTwoTargetTwoParameterToQC, + ConvertQCOTwoTargetTwoParameterToQC, + ConvertQCOBarrierOp, ConvertQCOCtrlOp, ConvertQCOInvOp, + ConvertQCOYieldOp>(typeConverter, context); // Conversion of qco types in func.func signatures // Note: This currently has limitations with signature changes diff --git a/mlir/lib/Conversion/QCToQCO/CMakeLists.txt b/mlir/lib/Conversion/QCToQCO/CMakeLists.txt index 80a07eda6d..5a1c1b9797 100644 --- a/mlir/lib/Conversion/QCToQCO/CMakeLists.txt +++ b/mlir/lib/Conversion/QCToQCO/CMakeLists.txt @@ -8,8 +8,8 @@ file(GLOB CONVERSION_SOURCES *.cpp) -add_mlir_library( - QCToQCO +add_mlir_conversion_library( + MLIRQCToQCO ${CONVERSION_SOURCES} DEPENDS QCToQCOIncGen @@ -22,4 +22,4 @@ add_mlir_library( MLIRFuncTransforms DISABLE_INSTALL) -mqt_mlir_target_use_project_options(QCToQCO) +mqt_mlir_target_use_project_options(MLIRQCToQCO) diff --git a/mlir/lib/Conversion/QCToQCO/QCToQCO.cpp b/mlir/lib/Conversion/QCToQCO/QCToQCO.cpp index e3cdc55fa6..ab2c5bad3c 100644 --- a/mlir/lib/Conversion/QCToQCO/QCToQCO.cpp +++ b/mlir/lib/Conversion/QCToQCO/QCToQCO.cpp @@ -112,388 +112,6 @@ class StatefulOpConversionPattern : public OpConversionPattern { } // namespace -/** - * @brief Converts a zero-target, one-parameter QC operation to QCO - * - * @tparam QCOOpType The operation type of the QCO operation - * @tparam QCOpType The operation type of the QC operation - * @param op The QC operation instance to convert - * @param rewriter The pattern rewriter - * @param state The lowering state - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertZeroTargetOneParameter(QCOpType& op, ConversionPatternRewriter& rewriter, - LoweringState& state) { - const auto inNestedRegion = state.inNestedRegion; - - rewriter.create(op.getLoc(), op.getParameter(0)); - - // Update the state - if (inNestedRegion != 0) { - state.targetsIn.erase(inNestedRegion); - const SmallVector targetsOut; - state.targetsOut.try_emplace(inNestedRegion, targetsOut); - } - - rewriter.eraseOp(op); - - return success(); -} - -/** - * @brief Converts a one-target, zero-parameter QC operation to QCO - * - * @tparam QCOOpType The operation type of the QCO operation - * @tparam QCOpType The operation type of the QC operation - * @param op The QC operation instance to convert - * @param rewriter The pattern rewriter - * @param state The lowering state - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertOneTargetZeroParameter(QCOpType& op, ConversionPatternRewriter& rewriter, - LoweringState& state) { - auto& qubitMap = state.qubitMap; - const auto inNestedRegion = state.inNestedRegion; - - // Get the latest QCO qubit - auto qcQubit = op.getQubitIn(); - Value qcoQubit; - if (inNestedRegion == 0) { - assert(qubitMap.contains(qcQubit) && "QC qubit not found"); - qcoQubit = qubitMap[qcQubit]; - } else { - assert(state.targetsIn[inNestedRegion].size() == 1 && - "Invalid number of input targets"); - qcoQubit = state.targetsIn[inNestedRegion].front(); - } - - // Create the QCO operation (consumes input, produces output) - auto qcoOp = rewriter.create(op.getLoc(), qcoQubit); - - // Update the state map - if (inNestedRegion == 0) { - qubitMap[qcQubit] = qcoOp.getQubitOut(); - } else { - state.targetsIn.erase(inNestedRegion); - const SmallVector targetsOut({qcoOp.getQubitOut()}); - state.targetsOut.try_emplace(inNestedRegion, targetsOut); - } - - rewriter.eraseOp(op); - - return success(); -} - -/** - * @brief Converts a one-target, one-parameter QC operation to QCO - * - * @tparam QCOOpType The operation type of the QCO operation - * @tparam QCOpType The operation type of the QC operation - * @param op The QC operation instance to convert - * @param rewriter The pattern rewriter - * @param state The lowering state - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertOneTargetOneParameter(QCOpType& op, ConversionPatternRewriter& rewriter, - LoweringState& state) { - auto& qubitMap = state.qubitMap; - const auto inNestedRegion = state.inNestedRegion; - - // Get the latest QCO qubit - auto qcQubit = op.getQubitIn(); - Value qcoQubit; - if (inNestedRegion == 0) { - assert(qubitMap.contains(qcQubit) && "QC qubit not found"); - qcoQubit = qubitMap[qcQubit]; - } else { - assert(state.targetsIn[inNestedRegion].size() == 1 && - "Invalid number of input targets"); - qcoQubit = state.targetsIn[inNestedRegion].front(); - } - - // Create the QCO operation (consumes input, produces output) - auto qcoOp = - rewriter.create(op.getLoc(), qcoQubit, op.getParameter(0)); - - // Update the state map - if (inNestedRegion == 0) { - qubitMap[qcQubit] = qcoOp.getQubitOut(); - } else { - state.targetsIn.erase(inNestedRegion); - const SmallVector targetsOut({qcoOp.getQubitOut()}); - state.targetsOut.try_emplace(inNestedRegion, targetsOut); - } - - rewriter.eraseOp(op); - - return success(); -} - -/** - * @brief Converts a one-target, two-parameter QC operation to QCO - * - * @tparam QCOOpType The operation type of the QCO operation - * @tparam QCOpType The operation type of the QC operation - * @param op The QC operation instance to convert - * @param rewriter The pattern rewriter - * @param state The lowering state - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertOneTargetTwoParameter(QCOpType& op, ConversionPatternRewriter& rewriter, - LoweringState& state) { - auto& qubitMap = state.qubitMap; - const auto inNestedRegion = state.inNestedRegion; - - // Get the latest QCO qubit - auto qcQubit = op.getQubitIn(); - Value qcoQubit; - if (inNestedRegion == 0) { - assert(qubitMap.contains(qcQubit) && "QC qubit not found"); - qcoQubit = qubitMap[qcQubit]; - } else { - assert(state.targetsIn[inNestedRegion].size() == 1 && - "Invalid number of input targets"); - qcoQubit = state.targetsIn[inNestedRegion].front(); - } - - // Create the QCO operation (consumes input, produces output) - auto qcoOp = rewriter.create( - op.getLoc(), qcoQubit, op.getParameter(0), op.getParameter(1)); - - // Update the state map - if (inNestedRegion == 0) { - qubitMap[qcQubit] = qcoOp.getQubitOut(); - } else { - state.targetsIn.erase(inNestedRegion); - const SmallVector targetsOut({qcoOp.getQubitOut()}); - state.targetsOut.try_emplace(inNestedRegion, targetsOut); - } - - rewriter.eraseOp(op); - - return success(); -} - -/** - * @brief Converts a one-target, three-parameter QC operation to QCO - * - * @tparam QCOOpType The operation type of the QCO operation - * @tparam QCOpType The operation type of the QC operation - * @param op The QC operation instance to convert - * @param rewriter The pattern rewriter - * @param state The lowering state - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult convertOneTargetThreeParameter( - QCOpType& op, ConversionPatternRewriter& rewriter, LoweringState& state) { - auto& qubitMap = state.qubitMap; - const auto inNestedRegion = state.inNestedRegion; - - // Get the latest QCO qubit - auto qcQubit = op.getQubitIn(); - Value qcoQubit; - if (inNestedRegion == 0) { - assert(qubitMap.contains(qcQubit) && "QC qubit not found"); - qcoQubit = qubitMap[qcQubit]; - } else { - assert(state.targetsIn[inNestedRegion].size() == 1 && - "Invalid number of input targets"); - qcoQubit = state.targetsIn[inNestedRegion].front(); - } - - // Create the QCO operation (consumes input, produces output) - auto qcoOp = - rewriter.create(op.getLoc(), qcoQubit, op.getParameter(0), - op.getParameter(1), op.getParameter(2)); - - // Update the state map - if (inNestedRegion == 0) { - qubitMap[qcQubit] = qcoOp.getQubitOut(); - } else { - state.targetsIn.erase(inNestedRegion); - const SmallVector targetsOut({qcoOp.getQubitOut()}); - state.targetsOut.try_emplace(inNestedRegion, targetsOut); - } - - rewriter.eraseOp(op); - - return success(); -} - -/** - * @brief Converts a two-target, zero-parameter QC operation to QCO - * - * @tparam QCOOpType The operation type of the QCO operation - * @tparam QCOpType The operation type of the QC operation - * @param op The QC operation instance to convert - * @param rewriter The pattern rewriter - * @param state The lowering state - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertTwoTargetZeroParameter(QCOpType& op, ConversionPatternRewriter& rewriter, - LoweringState& state) { - auto& qubitMap = state.qubitMap; - const auto inNestedRegion = state.inNestedRegion; - - // Get the latest QCO qubits - auto qcQubit0 = op.getQubit0In(); - auto qcQubit1 = op.getQubit1In(); - Value qcoQubit0; - Value qcoQubit1; - if (inNestedRegion == 0) { - assert(qubitMap.contains(qcQubit0) && "QC qubit not found"); - assert(qubitMap.contains(qcQubit1) && "QC qubit not found"); - qcoQubit0 = qubitMap[qcQubit0]; - qcoQubit1 = qubitMap[qcQubit1]; - } else { - assert(state.targetsIn[inNestedRegion].size() == 2 && - "Invalid number of input targets"); - const auto& targetsIn = state.targetsIn[inNestedRegion]; - qcoQubit0 = targetsIn[0]; - qcoQubit1 = targetsIn[1]; - } - - // Create the QCO operation (consumes input, produces output) - auto qcoOp = rewriter.create(op.getLoc(), qcoQubit0, qcoQubit1); - - // Update the state map - if (inNestedRegion == 0) { - qubitMap[qcQubit0] = qcoOp.getQubit0Out(); - qubitMap[qcQubit1] = qcoOp.getQubit1Out(); - } else { - state.targetsIn.erase(inNestedRegion); - const SmallVector targetsOut( - {qcoOp.getQubit0Out(), qcoOp.getQubit1Out()}); - state.targetsOut.try_emplace(inNestedRegion, targetsOut); - } - - rewriter.eraseOp(op); - - return success(); -} - -/** - * @brief Converts a two-target, one-parameter QC operation to QCO - * - * @tparam QCOOpType The operation type of the QCO operation - * @tparam QCOpType The operation type of the QC operation - * @param op The QC operation instance to convert - * @param rewriter The pattern rewriter - * @param state The lowering state - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertTwoTargetOneParameter(QCOpType& op, ConversionPatternRewriter& rewriter, - LoweringState& state) { - auto& qubitMap = state.qubitMap; - const auto inNestedRegion = state.inNestedRegion; - - // Get the latest QCO qubits - auto qcQubit0 = op.getQubit0In(); - auto qcQubit1 = op.getQubit1In(); - Value qcoQubit0; - Value qcoQubit1; - if (inNestedRegion == 0) { - assert(qubitMap.contains(qcQubit0) && "QC qubit not found"); - assert(qubitMap.contains(qcQubit1) && "QC qubit not found"); - qcoQubit0 = qubitMap[qcQubit0]; - qcoQubit1 = qubitMap[qcQubit1]; - } else { - assert(state.targetsIn[inNestedRegion].size() == 2 && - "Invalid number of input targets"); - const auto& targetsIn = state.targetsIn[inNestedRegion]; - qcoQubit0 = targetsIn[0]; - qcoQubit1 = targetsIn[1]; - } - - // Create the QCO operation (consumes input, produces output) - auto qcoOp = rewriter.create(op.getLoc(), qcoQubit0, qcoQubit1, - op.getParameter(0)); - - // Update the state map - if (inNestedRegion == 0) { - qubitMap[qcQubit0] = qcoOp.getQubit0Out(); - qubitMap[qcQubit1] = qcoOp.getQubit1Out(); - } else { - state.targetsIn.erase(inNestedRegion); - const SmallVector targetsOut( - {qcoOp.getQubit0Out(), qcoOp.getQubit1Out()}); - state.targetsOut.try_emplace(inNestedRegion, targetsOut); - } - - rewriter.eraseOp(op); - - return success(); -} - -/** - * @brief Converts a two-target, two-parameter QC operation to QCO - * - * @tparam QCOOpType The operation type of the QCO operation - * @tparam QCOpType The operation type of the QC operation - * @param op The QC operation instance to convert - * @param rewriter The pattern rewriter - * @param state The lowering state - * @return LogicalResult Success or failure of the conversion - */ -template -static LogicalResult -convertTwoTargetTwoParameter(QCOpType& op, ConversionPatternRewriter& rewriter, - LoweringState& state) { - auto& qubitMap = state.qubitMap; - const auto inNestedRegion = state.inNestedRegion; - - // Get the latest QCO qubits - auto qcQubit0 = op.getQubit0In(); - auto qcQubit1 = op.getQubit1In(); - Value qcoQubit0; - Value qcoQubit1; - if (inNestedRegion == 0) { - assert(qubitMap.contains(qcQubit0) && "QC qubit not found"); - assert(qubitMap.contains(qcQubit1) && "QC qubit not found"); - qcoQubit0 = qubitMap[qcQubit0]; - qcoQubit1 = qubitMap[qcQubit1]; - } else { - assert(state.targetsIn[inNestedRegion].size() == 2 && - "Invalid number of input targets"); - const auto& targetsIn = state.targetsIn[inNestedRegion]; - qcoQubit0 = targetsIn[0]; - qcoQubit1 = targetsIn[1]; - } - - // Create the QCO operation (consumes input, produces output) - auto qcoOp = - rewriter.create(op.getLoc(), qcoQubit0, qcoQubit1, - op.getParameter(0), op.getParameter(1)); - - // Update the state map - if (inNestedRegion == 0) { - qubitMap[qcQubit0] = qcoOp.getQubit0Out(); - qubitMap[qcQubit1] = qcoOp.getQubit1Out(); - } else { - state.targetsIn.erase(inNestedRegion); - const SmallVector targetsOut( - {qcoOp.getQubit0Out(), qcoOp.getQubit1Out()}); - state.targetsOut.try_emplace(inNestedRegion, targetsOut); - } - - rewriter.eraseOp(op); - - return success(); -} - /** * @brief Type converter for QC-to-QCO conversion * @@ -623,7 +241,7 @@ struct ConvertQCStaticOp final : StatefulOpConversionPattern { auto qcQubit = op.getQubit(); // Create new qco.static operation with the same index - auto qcoOp = rewriter.create(op.getLoc(), op.getIndex()); + auto qcoOp = qco::StaticOp::create(rewriter, op.getLoc(), op.getIndex()); // Collect QCO qubit SSA value auto qcoQubit = qcoOp.getQubit(); @@ -675,8 +293,8 @@ struct ConvertQCMeasureOp final : StatefulOpConversionPattern { auto qcoQubit = qubitMap[qcQubit]; // Create qco.measure (returns both output qubit and bit result) - auto qcoOp = rewriter.create( - op.getLoc(), qcoQubit, op.getRegisterNameAttr(), + auto qcoOp = qco::MeasureOp::create( + rewriter, op.getLoc(), qcoQubit, op.getRegisterNameAttr(), op.getRegisterSizeAttr(), op.getRegisterIndexAttr()); auto outQcoQubit = qcoOp.getQubitOut(); @@ -726,7 +344,7 @@ struct ConvertQCResetOp final : StatefulOpConversionPattern { auto qcoQubit = qubitMap[qcQubit]; // Create qco.reset (consumes input, produces output) - auto qcoOp = rewriter.create(op.getLoc(), qcoQubit); + auto qcoOp = qco::ResetOp::create(rewriter, op.getLoc(), qcoQubit); // Update mapping: the QC qubit now corresponds to the reset output qubitMap[qcQubit] = qcoOp.getQubitOut(); @@ -738,282 +356,478 @@ struct ConvertQCResetOp final : StatefulOpConversionPattern { } }; -// ZeroTargetOneParameter - -#define DEFINE_ZERO_TARGET_ONE_PARAMETER(OP_CLASS, OP_NAME, PARAM) \ - /** \ - * @brief Converts qc.OP_NAME to qco.OP_NAME \ - * \ - * @par Example: \ - * ```mlir \ - * qc.OP_NAME(%PARAM) \ - * ``` \ - * is converted to \ - * ```mlir \ - * qco.OP_NAME(%PARAM) \ - * ``` \ - */ \ - struct ConvertQC##OP_CLASS final \ - : StatefulOpConversionPattern { \ - using StatefulOpConversionPattern::StatefulOpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qc::OP_CLASS op, OpAdaptor /*adaptor*/, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertZeroTargetOneParameter(op, rewriter, \ - getState()); \ - } \ - }; - -DEFINE_ZERO_TARGET_ONE_PARAMETER(GPhaseOp, gphase, theta) - -#undef DEFINE_ZERO_TARGET_ONE_PARAMETER - -// OneTargetZeroParameter - -#define DEFINE_ONE_TARGET_ZERO_PARAMETER(OP_CLASS, OP_NAME) \ - /** \ - * @brief Converts qc.OP_NAME to qco.OP_NAME \ - * \ - * @par Example: \ - * ```mlir \ - * qc.OP_NAME %q : !qc.qubit \ - * ``` \ - * is converted to \ - * ```mlir \ - * %q_out = qco.OP_NAME %q_in : !qco.qubit -> !qco.qubit \ - * ``` \ - */ \ - struct ConvertQC##OP_CLASS final \ - : StatefulOpConversionPattern { \ - using StatefulOpConversionPattern::StatefulOpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qc::OP_CLASS op, OpAdaptor /*adaptor*/, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertOneTargetZeroParameter(op, rewriter, \ - getState()); \ - } \ - }; - -DEFINE_ONE_TARGET_ZERO_PARAMETER(IdOp, id) -DEFINE_ONE_TARGET_ZERO_PARAMETER(XOp, x) -DEFINE_ONE_TARGET_ZERO_PARAMETER(YOp, y) -DEFINE_ONE_TARGET_ZERO_PARAMETER(ZOp, z) -DEFINE_ONE_TARGET_ZERO_PARAMETER(HOp, h) -DEFINE_ONE_TARGET_ZERO_PARAMETER(SOp, s) -DEFINE_ONE_TARGET_ZERO_PARAMETER(SdgOp, sdg) -DEFINE_ONE_TARGET_ZERO_PARAMETER(TOp, t) -DEFINE_ONE_TARGET_ZERO_PARAMETER(TdgOp, tdg) -DEFINE_ONE_TARGET_ZERO_PARAMETER(SXOp, sx) -DEFINE_ONE_TARGET_ZERO_PARAMETER(SXdgOp, sxdg) - -#undef DEFINE_ONE_TARGET_ZERO_PARAMETER - -// OneTargetOneParameter - -#define DEFINE_ONE_TARGET_ONE_PARAMETER(OP_CLASS, OP_NAME, PARAM) \ - /** \ - * @brief Converts qc.OP_NAME to qco.OP_NAME \ - * \ - * @par Example: \ - * ```mlir \ - * qc.OP_NAME(%PARAM) %q : !qc.qubit \ - * ``` \ - * is converted to \ - * ```mlir \ - * %q_out = qco.OP_NAME(%PARAM) %q_in : !qco.qubit -> !qco.qubit \ - * ``` \ - */ \ - struct ConvertQC##OP_CLASS final \ - : StatefulOpConversionPattern { \ - using StatefulOpConversionPattern::StatefulOpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qc::OP_CLASS op, OpAdaptor /*adaptor*/, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertOneTargetOneParameter(op, rewriter, \ - getState()); \ - } \ - }; - -DEFINE_ONE_TARGET_ONE_PARAMETER(RXOp, rx, theta) -DEFINE_ONE_TARGET_ONE_PARAMETER(RYOp, ry, theta) -DEFINE_ONE_TARGET_ONE_PARAMETER(RZOp, rz, theta) -DEFINE_ONE_TARGET_ONE_PARAMETER(POp, p, theta) - -#undef DEFINE_ONE_TARGET_ONE_PARAMETER - -// OneTargetTwoParameter - -#define DEFINE_ONE_TARGET_TWO_PARAMETER(OP_CLASS, OP_NAME, PARAM1, PARAM2) \ - /** \ - * @brief Converts qc.OP_NAME to qco.OP_NAME \ - * \ - * @par Example: \ - * ```mlir \ - * qc.OP_NAME(%PARAM1, %PARAM2) %q : !qc.qubit \ - * ``` \ - * is converted to \ - * ```mlir \ - * %q_out = qco.OP_NAME(%PARAM1, %PARAM2) %q_in : !qco.qubit -> \ - * !qco.qubit \ - * ``` \ - */ \ - struct ConvertQC##OP_CLASS final \ - : StatefulOpConversionPattern { \ - using StatefulOpConversionPattern::StatefulOpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qc::OP_CLASS op, OpAdaptor /*adaptor*/, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertOneTargetTwoParameter(op, rewriter, \ - getState()); \ - } \ - }; - -DEFINE_ONE_TARGET_TWO_PARAMETER(ROp, r, theta, phi) -DEFINE_ONE_TARGET_TWO_PARAMETER(U2Op, u2, phi, lambda) - -#undef DEFINE_ONE_TARGET_TWO_PARAMETER - -// OneTargetThreeParameter - -#define DEFINE_ONE_TARGET_THREE_PARAMETER(OP_CLASS, OP_NAME, PARAM1, PARAM2, \ - PARAM3) \ - /** \ - * @brief Converts qc.OP_NAME to qco.OP_NAME \ - * \ - * @par Example: \ - * ```mlir \ - * qc.OP_NAME(%PARAM1, %PARAM2, %PARAM3) %q : !qc.qubit \ - * ``` \ - * is converted to \ - * ```mlir \ - * %q_out = qco.OP_NAME(%PARAM1, %PARAM2, %PARAM3) %q_in : !qco.qubit \ - * -> !qco.qubit \ - * ``` \ - */ \ - struct ConvertQC##OP_CLASS final \ - : StatefulOpConversionPattern { \ - using StatefulOpConversionPattern::StatefulOpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qc::OP_CLASS op, OpAdaptor /*adaptor*/, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertOneTargetThreeParameter(op, rewriter, \ - getState()); \ - } \ - }; - -DEFINE_ONE_TARGET_THREE_PARAMETER(UOp, u, theta, phi, lambda) - -#undef DEFINE_ONE_TARGET_THREE_PARAMETER - -// TwoTargetZeroParameter - -#define DEFINE_TWO_TARGET_ZERO_PARAMETER(OP_CLASS, OP_NAME) \ - /** \ - * @brief Converts qc.OP_NAME to qco.OP_NAME \ - * \ - * @par Example: \ - * ```mlir \ - * qc.OP_NAME %q0, %q1 : !qc.qubit, !qc.qubit \ - * ``` \ - * is converted to \ - * ```mlir \ - * %q0_out, %q1_out = qco.OP_NAME %q0_in, %q1_in : !qco.qubit, !qco.qubit \ - * -> !qco.qubit, !qco.qubit \ - * ``` \ - */ \ - struct ConvertQC##OP_CLASS final \ - : StatefulOpConversionPattern { \ - using StatefulOpConversionPattern::StatefulOpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qc::OP_CLASS op, OpAdaptor /*adaptor*/, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertTwoTargetZeroParameter(op, rewriter, \ - getState()); \ - } \ - }; - -DEFINE_TWO_TARGET_ZERO_PARAMETER(SWAPOp, swap) -DEFINE_TWO_TARGET_ZERO_PARAMETER(iSWAPOp, iswap) -DEFINE_TWO_TARGET_ZERO_PARAMETER(DCXOp, dcx) -DEFINE_TWO_TARGET_ZERO_PARAMETER(ECROp, ecr) - -#undef DEFINE_TWO_TARGET_ZERO_PARAMETER - -// TwoTargetOneParameter - -#define DEFINE_TWO_TARGET_ONE_PARAMETER(OP_CLASS, OP_NAME, PARAM) \ - /** \ - * @brief Converts qc.OP_NAME to qco.OP_NAME \ - * \ - * @par Example: \ - * ```mlir \ - * qc.OP_NAME(%PARAM) %q0, %q1 : !qc.qubit, !qc.qubit \ - * ``` \ - * is converted to \ - * ```mlir \ - * %q0_out, %q1_out = qco.OP_NAME(%PARAM) %q0_in, %q1_in : !qco.qubit, \ - * !qco.qubit -> !qco.qubit, !qco.qubit \ - * ``` \ - */ \ - struct ConvertQC##OP_CLASS final \ - : StatefulOpConversionPattern { \ - using StatefulOpConversionPattern::StatefulOpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qc::OP_CLASS op, OpAdaptor /*adaptor*/, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertTwoTargetOneParameter(op, rewriter, \ - getState()); \ - } \ - }; - -DEFINE_TWO_TARGET_ONE_PARAMETER(RXXOp, rxx, theta) -DEFINE_TWO_TARGET_ONE_PARAMETER(RYYOp, ryy, theta) -DEFINE_TWO_TARGET_ONE_PARAMETER(RZXOp, rzx, theta) -DEFINE_TWO_TARGET_ONE_PARAMETER(RZZOp, rzz, theta) - -#undef DEFINE_TWO_TARGET_ONE_PARAMETER - -// TwoTargetTwoParameter - -#define DEFINE_TWO_TARGET_TWO_PARAMETER(OP_CLASS, OP_NAME, PARAM1, PARAM2) \ - /** \ - * @brief Converts qc.OP_NAME to qco.OP_NAME \ - * \ - * @par Example: \ - * ```mlir \ - * qc.OP_NAME(%PARAM1, %PARAM2) %q0, %q1 : !qc.qubit, !qc.qubit \ - * ``` \ - * is converted to \ - * ```mlir \ - * %q0_out, %q1_out = qco.OP_NAME(%PARAM1, %PARAM2) %q0_in, %q1_in : \ - * !qco.qubit, !qco.qubit -> !qco.qubit, !qco.qubit \ - * ``` \ - */ \ - struct ConvertQC##OP_CLASS final \ - : StatefulOpConversionPattern { \ - using StatefulOpConversionPattern::StatefulOpConversionPattern; \ - \ - LogicalResult \ - matchAndRewrite(qc::OP_CLASS op, OpAdaptor /*adaptor*/, \ - ConversionPatternRewriter& rewriter) const override { \ - return convertTwoTargetTwoParameter(op, rewriter, \ - getState()); \ - } \ - }; - -DEFINE_TWO_TARGET_TWO_PARAMETER(XXPlusYYOp, xx_plus_yy, theta, beta) -DEFINE_TWO_TARGET_TWO_PARAMETER(XXMinusYYOp, xx_minus_yy, theta, beta) - -#undef DEFINE_TWO_TARGET_TWO_PARAMETER - -// BarrierOp +/** + * @brief Converts a zero-target, one-parameter QC gate to QCO + * + * @tparam QCOpType The operation type of the QC gate + * @tparam QCOOpType The operation type of the QCO gate + * + * @par Example: + * ```mlir + * qc.gphase(%theta) + * ``` + * is converted to + * ```mlir + * qco.gphase(%theta) + * ``` + */ +template +struct ConvertQCZeroTargetOneParameterToQCO final + : StatefulOpConversionPattern { + using StatefulOpConversionPattern::StatefulOpConversionPattern; + + LogicalResult + matchAndRewrite(QCOpType op, typename QCOpType::Adaptor /*adaptor*/, + ConversionPatternRewriter& rewriter) const override { + auto& state = this->getState(); + const auto inNestedRegion = state.inNestedRegion; + + QCOOpType::create(rewriter, op.getLoc(), op.getParameter(0)); + + // Update the state + if (inNestedRegion != 0) { + state.targetsIn.erase(inNestedRegion); + const SmallVector targetsOut; + state.targetsOut.try_emplace(inNestedRegion, targetsOut); + } + + rewriter.eraseOp(op); + + return success(); + } +}; + +/** + * @brief Converts a one-target, zero-parameter QC gate to QCO + * + * @tparam QCOpType The operation type of the QC gate + * @tparam QCOOpType The operation type of the QCO gate + * + * @par Example: + * ```mlir + * qc.x %q : !qc.qubit + * ``` + * is converted to + * ```mlir + * %q_out = qco.x %q_in : !qco.qubit -> !qco.qubit + * ``` + */ +template +struct ConvertQCOneTargetZeroParameterToQCO final + : StatefulOpConversionPattern { + using StatefulOpConversionPattern::StatefulOpConversionPattern; + + LogicalResult + matchAndRewrite(QCOpType op, typename QCOpType::Adaptor /*adaptor*/, + ConversionPatternRewriter& rewriter) const override { + auto& state = this->getState(); + auto& qubitMap = state.qubitMap; + const auto inNestedRegion = state.inNestedRegion; + + // Get the latest QCO qubit + auto qcQubit = op.getQubitIn(); + Value qcoQubit; + if (inNestedRegion == 0) { + assert(qubitMap.contains(qcQubit) && "QC qubit not found"); + qcoQubit = qubitMap[qcQubit]; + } else { + assert(state.targetsIn[inNestedRegion].size() == 1 && + "Invalid number of input targets"); + qcoQubit = state.targetsIn[inNestedRegion].front(); + } + + // Create the QCO operation (consumes input, produces output) + auto qcoOp = QCOOpType::create(rewriter, op.getLoc(), qcoQubit); + + // Update the state map + if (inNestedRegion == 0) { + qubitMap[qcQubit] = qcoOp.getQubitOut(); + } else { + state.targetsIn.erase(inNestedRegion); + const SmallVector targetsOut({qcoOp.getQubitOut()}); + state.targetsOut.try_emplace(inNestedRegion, targetsOut); + } + + rewriter.eraseOp(op); + + return success(); + } +}; + +/** + * @brief Converts a one-target, one-parameter QC gate to QCO + * + * @tparam QCOpType The operation type of the QC gate + * @tparam QCOOpType The operation type of the QCO gate + * + * @par Example: + * ```mlir + * qc.rx(%theta) %q : !qc.qubit + * ``` + * is converted to + * ```mlir + * %q_out = qco.rx(%theta) %q_in : !qco.qubit -> !qco.qubit + * ``` + */ +template +struct ConvertQCOneTargetOneParameterToQCO final + : StatefulOpConversionPattern { + using StatefulOpConversionPattern::StatefulOpConversionPattern; + + LogicalResult + matchAndRewrite(QCOpType op, typename QCOpType::Adaptor /*adaptor*/, + ConversionPatternRewriter& rewriter) const override { + auto& state = this->getState(); + auto& qubitMap = state.qubitMap; + const auto inNestedRegion = state.inNestedRegion; + + // Get the latest QCO qubit + auto qcQubit = op.getQubitIn(); + Value qcoQubit; + if (inNestedRegion == 0) { + assert(qubitMap.contains(qcQubit) && "QC qubit not found"); + qcoQubit = qubitMap[qcQubit]; + } else { + assert(state.targetsIn[inNestedRegion].size() == 1 && + "Invalid number of input targets"); + qcoQubit = state.targetsIn[inNestedRegion].front(); + } + + // Create the QCO operation (consumes input, produces output) + auto qcoOp = + QCOOpType::create(rewriter, op.getLoc(), qcoQubit, op.getParameter(0)); + + // Update the state map + if (inNestedRegion == 0) { + qubitMap[qcQubit] = qcoOp.getQubitOut(); + } else { + state.targetsIn.erase(inNestedRegion); + const SmallVector targetsOut({qcoOp.getQubitOut()}); + state.targetsOut.try_emplace(inNestedRegion, targetsOut); + } + + rewriter.eraseOp(op); + + return success(); + } +}; + +/** + * @brief Converts a one-target, two-parameter QC gate to QCO + * + * @tparam QCOpType The operation type of the QC gate + * @tparam QCOOpType The operation type of the QCO gate + * + * @par Example: + * ```mlir + * qc.r(%theta, %phi) %q : !qc.qubit + * ``` + * is converted to + * ```mlir + * %q_out = qco.r(%theta, %phi) %q_in : !qco.qubit -> !qco.qubit + * ``` + */ +template +struct ConvertQCOneTargetTwoParameterToQCO final + : StatefulOpConversionPattern { + using StatefulOpConversionPattern::StatefulOpConversionPattern; + + LogicalResult + matchAndRewrite(QCOpType op, typename QCOpType::Adaptor /*adaptor*/, + ConversionPatternRewriter& rewriter) const override { + auto& state = this->getState(); + auto& qubitMap = state.qubitMap; + const auto inNestedRegion = state.inNestedRegion; + + // Get the latest QCO qubit + auto qcQubit = op.getQubitIn(); + Value qcoQubit; + if (inNestedRegion == 0) { + assert(qubitMap.contains(qcQubit) && "QC qubit not found"); + qcoQubit = qubitMap[qcQubit]; + } else { + assert(state.targetsIn[inNestedRegion].size() == 1 && + "Invalid number of input targets"); + qcoQubit = state.targetsIn[inNestedRegion].front(); + } + + // Create the QCO operation (consumes input, produces output) + auto qcoOp = QCOOpType::create(rewriter, op.getLoc(), qcoQubit, + op.getParameter(0), op.getParameter(1)); + + // Update the state map + if (inNestedRegion == 0) { + qubitMap[qcQubit] = qcoOp.getQubitOut(); + } else { + state.targetsIn.erase(inNestedRegion); + const SmallVector targetsOut({qcoOp.getQubitOut()}); + state.targetsOut.try_emplace(inNestedRegion, targetsOut); + } + + rewriter.eraseOp(op); + + return success(); + } +}; + +/** + * @brief Converts a one-target, three-parameter QC gate to QCO + * + * @tparam QCOpType The operation type of the QC gate + * @tparam QCOOpType The operation type of the QCO gate + * + * @par Example: + * ```mlir + * qc.u(%theta, %phi, %lambda) %q : !qc.qubit + * ``` + * is converted to + * ```mlir + * %q_out = qco.u(%theta, %phi, %lambda) %q_in : !qco.qubit -> !qco.qubit + * ``` + */ +template +struct ConvertQCOneTargetThreeParameterToQCO final + : StatefulOpConversionPattern { + using StatefulOpConversionPattern::StatefulOpConversionPattern; + + LogicalResult + matchAndRewrite(QCOpType op, typename QCOpType::Adaptor /*adaptor*/, + ConversionPatternRewriter& rewriter) const override { + auto& state = this->getState(); + auto& qubitMap = state.qubitMap; + const auto inNestedRegion = state.inNestedRegion; + + // Get the latest QCO qubit + auto qcQubit = op.getQubitIn(); + Value qcoQubit; + if (inNestedRegion == 0) { + assert(qubitMap.contains(qcQubit) && "QC qubit not found"); + qcoQubit = qubitMap[qcQubit]; + } else { + assert(state.targetsIn[inNestedRegion].size() == 1 && + "Invalid number of input targets"); + qcoQubit = state.targetsIn[inNestedRegion].front(); + } + + // Create the QCO operation (consumes input, produces output) + auto qcoOp = + QCOOpType::create(rewriter, op.getLoc(), qcoQubit, op.getParameter(0), + op.getParameter(1), op.getParameter(2)); + + // Update the state map + if (inNestedRegion == 0) { + qubitMap[qcQubit] = qcoOp.getQubitOut(); + } else { + state.targetsIn.erase(inNestedRegion); + const SmallVector targetsOut({qcoOp.getQubitOut()}); + state.targetsOut.try_emplace(inNestedRegion, targetsOut); + } + + rewriter.eraseOp(op); + + return success(); + } +}; + +/** + * @brief Converts a two-target, zero-parameter QC gate to QCO + * + * @tparam QCOpType The operation type of the QC gate + * @tparam QCOOpType The operation type of the QCO gate + * + * @par Example: + * ```mlir + * qc.swap %q0, %q1 : !qc.qubit, !qc.qubit + * ``` + * is converted to + * ```mlir + * %q0_out, %q1_out = qco.swap %q0_in, %q1_in : !qco.qubit, !qco.qubit -> + * !qco.qubit, !qco.qubit + * ``` + */ +template +struct ConvertQCTwoTargetZeroParameterToQCO final + : StatefulOpConversionPattern { + using StatefulOpConversionPattern::StatefulOpConversionPattern; + + LogicalResult + matchAndRewrite(QCOpType op, typename QCOpType::Adaptor /*adaptor*/, + ConversionPatternRewriter& rewriter) const override { + auto& state = this->getState(); + auto& qubitMap = state.qubitMap; + const auto inNestedRegion = state.inNestedRegion; + + // Get the latest QCO qubits + auto qcQubit0 = op.getQubit0In(); + auto qcQubit1 = op.getQubit1In(); + Value qcoQubit0; + Value qcoQubit1; + if (inNestedRegion == 0) { + assert(qubitMap.contains(qcQubit0) && "QC qubit not found"); + assert(qubitMap.contains(qcQubit1) && "QC qubit not found"); + qcoQubit0 = qubitMap[qcQubit0]; + qcoQubit1 = qubitMap[qcQubit1]; + } else { + assert(state.targetsIn[inNestedRegion].size() == 2 && + "Invalid number of input targets"); + const auto& targetsIn = state.targetsIn[inNestedRegion]; + qcoQubit0 = targetsIn[0]; + qcoQubit1 = targetsIn[1]; + } + + // Create the QCO operation (consumes input, produces output) + auto qcoOp = QCOOpType::create(rewriter, op.getLoc(), qcoQubit0, qcoQubit1); + + // Update the state map + if (inNestedRegion == 0) { + qubitMap[qcQubit0] = qcoOp.getQubit0Out(); + qubitMap[qcQubit1] = qcoOp.getQubit1Out(); + } else { + state.targetsIn.erase(inNestedRegion); + const SmallVector targetsOut( + {qcoOp.getQubit0Out(), qcoOp.getQubit1Out()}); + state.targetsOut.try_emplace(inNestedRegion, targetsOut); + } + + rewriter.eraseOp(op); + + return success(); + } +}; + +/** + * @brief Converts a two-target, one-parameter QC gate to QCO + * + * @tparam QCOpType The operation type of the QC gate + * @tparam QCOOpType The operation type of the QCO gate + * + * @par Example: + * ```mlir + * qc.rxx(%theta) %q0, %q1 : !qc.qubit, !qc.qubit + * ``` + * is converted to + * ```mlir + * %q0_out, %q1_out = qco.rxx(%theta) %q0_in, %q1_in : !qco.qubit, !qco.qubit -> + * !qco.qubit, !qco.qubit + * ``` + */ +template +struct ConvertQCTwoTargetOneParameterToQCO final + : StatefulOpConversionPattern { + using StatefulOpConversionPattern::StatefulOpConversionPattern; + + LogicalResult + matchAndRewrite(QCOpType op, typename QCOpType::Adaptor /*adaptor*/, + ConversionPatternRewriter& rewriter) const override { + auto& state = this->getState(); + auto& qubitMap = state.qubitMap; + const auto inNestedRegion = state.inNestedRegion; + + // Get the latest QCO qubits + auto qcQubit0 = op.getQubit0In(); + auto qcQubit1 = op.getQubit1In(); + Value qcoQubit0; + Value qcoQubit1; + if (inNestedRegion == 0) { + assert(qubitMap.contains(qcQubit0) && "QC qubit not found"); + assert(qubitMap.contains(qcQubit1) && "QC qubit not found"); + qcoQubit0 = qubitMap[qcQubit0]; + qcoQubit1 = qubitMap[qcQubit1]; + } else { + assert(state.targetsIn[inNestedRegion].size() == 2 && + "Invalid number of input targets"); + const auto& targetsIn = state.targetsIn[inNestedRegion]; + qcoQubit0 = targetsIn[0]; + qcoQubit1 = targetsIn[1]; + } + + // Create the QCO operation (consumes input, produces output) + auto qcoOp = QCOOpType::create(rewriter, op.getLoc(), qcoQubit0, qcoQubit1, + op.getParameter(0)); + + // Update the state map + if (inNestedRegion == 0) { + qubitMap[qcQubit0] = qcoOp.getQubit0Out(); + qubitMap[qcQubit1] = qcoOp.getQubit1Out(); + } else { + state.targetsIn.erase(inNestedRegion); + const SmallVector targetsOut( + {qcoOp.getQubit0Out(), qcoOp.getQubit1Out()}); + state.targetsOut.try_emplace(inNestedRegion, targetsOut); + } + + rewriter.eraseOp(op); + + return success(); + } +}; + +/** + * @brief Converts a two-target, two-parameter QC gate to QCO + * + * @tparam QCOpType The operation type of the QC gate + * @tparam QCOOpType The operation type of the QCO gate + * + * @par Example: + * ```mlir + * qc.xx_minus_yy(%theta, %beta) %q0, %q1 : !qc.qubit, !qc.qubit + * ``` + * is converted to + * ```mlir + * %q0_out, %q1_out = qco.xx_minus_yy(%theta, %beta) %q0_in, %q1_in : + * !qco.qubit, !qco.qubit -> !qco.qubit, !qco.qubit + * ``` + */ +template +struct ConvertQCTwoTargetTwoParameterToQCO final + : StatefulOpConversionPattern { + using StatefulOpConversionPattern::StatefulOpConversionPattern; + + LogicalResult + matchAndRewrite(QCOpType op, typename QCOpType::Adaptor /*adaptor*/, + ConversionPatternRewriter& rewriter) const override { + auto& state = this->getState(); + auto& qubitMap = state.qubitMap; + const auto inNestedRegion = state.inNestedRegion; + + // Get the latest QCO qubits + auto qcQubit0 = op.getQubit0In(); + auto qcQubit1 = op.getQubit1In(); + Value qcoQubit0; + Value qcoQubit1; + if (inNestedRegion == 0) { + assert(qubitMap.contains(qcQubit0) && "QC qubit not found"); + assert(qubitMap.contains(qcQubit1) && "QC qubit not found"); + qcoQubit0 = qubitMap[qcQubit0]; + qcoQubit1 = qubitMap[qcQubit1]; + } else { + assert(state.targetsIn[inNestedRegion].size() == 2 && + "Invalid number of input targets"); + const auto& targetsIn = state.targetsIn[inNestedRegion]; + qcoQubit0 = targetsIn[0]; + qcoQubit1 = targetsIn[1]; + } + + // Create the QCO operation (consumes input, produces output) + auto qcoOp = QCOOpType::create(rewriter, op.getLoc(), qcoQubit0, qcoQubit1, + op.getParameter(0), op.getParameter(1)); + + // Update the state map + if (inNestedRegion == 0) { + qubitMap[qcQubit0] = qcoOp.getQubit0Out(); + qubitMap[qcQubit1] = qcoOp.getQubit1Out(); + } else { + state.targetsIn.erase(inNestedRegion); + const SmallVector targetsOut( + {qcoOp.getQubit0Out(), qcoOp.getQubit1Out()}); + state.targetsOut.try_emplace(inNestedRegion, targetsOut); + } + + rewriter.eraseOp(op); + + return success(); + } +}; /** * @brief Converts qc.barrier to qco.barrier @@ -1047,7 +861,7 @@ struct ConvertQCBarrierOp final : StatefulOpConversionPattern { } // Create qco.barrier - auto qcoOp = rewriter.create(op.getLoc(), qcoQubits); + auto qcoOp = qco::BarrierOp::create(rewriter, op.getLoc(), qcoQubits); // Update the state map for (const auto& [qcQubit, qcoQubitOut] : @@ -1300,18 +1114,40 @@ struct QCToQCO final : impl::QCToQCOBase { target.addLegalDialect(); // Register operation conversion patterns with state tracking - patterns.add(typeConverter, context, - &state); + patterns.add< + ConvertQCAllocOp, ConvertQCDeallocOp, ConvertQCStaticOp, + ConvertQCMeasureOp, ConvertQCResetOp, + ConvertQCZeroTargetOneParameterToQCO, + ConvertQCOneTargetZeroParameterToQCO, + ConvertQCOneTargetZeroParameterToQCO, + ConvertQCOneTargetZeroParameterToQCO, + ConvertQCOneTargetZeroParameterToQCO, + ConvertQCOneTargetZeroParameterToQCO, + ConvertQCOneTargetZeroParameterToQCO, + ConvertQCOneTargetZeroParameterToQCO, + ConvertQCOneTargetZeroParameterToQCO, + ConvertQCOneTargetZeroParameterToQCO, + ConvertQCOneTargetZeroParameterToQCO, + ConvertQCOneTargetZeroParameterToQCO, + ConvertQCOneTargetOneParameterToQCO, + ConvertQCOneTargetOneParameterToQCO, + ConvertQCOneTargetOneParameterToQCO, + ConvertQCOneTargetOneParameterToQCO, + ConvertQCOneTargetTwoParameterToQCO, + ConvertQCOneTargetTwoParameterToQCO, + ConvertQCOneTargetThreeParameterToQCO, + ConvertQCTwoTargetZeroParameterToQCO, + ConvertQCTwoTargetZeroParameterToQCO, + ConvertQCTwoTargetZeroParameterToQCO, + ConvertQCTwoTargetZeroParameterToQCO, + ConvertQCTwoTargetOneParameterToQCO, + ConvertQCTwoTargetOneParameterToQCO, + ConvertQCTwoTargetOneParameterToQCO, + ConvertQCTwoTargetOneParameterToQCO, + ConvertQCTwoTargetTwoParameterToQCO, + ConvertQCTwoTargetTwoParameterToQCO, + ConvertQCBarrierOp, ConvertQCCtrlOp, ConvertQCInvOp, ConvertQCYieldOp>( + typeConverter, context, &state); // Conversion of qc types in func.func signatures // Note: This currently has limitations with signature changes diff --git a/mlir/lib/Conversion/QCToQIR/CMakeLists.txt b/mlir/lib/Conversion/QCToQIR/CMakeLists.txt index 7e72c5be04..f3b9bcbe98 100644 --- a/mlir/lib/Conversion/QCToQIR/CMakeLists.txt +++ b/mlir/lib/Conversion/QCToQIR/CMakeLists.txt @@ -8,8 +8,8 @@ file(GLOB CONVERSION_SOURCES *.cpp) -add_mlir_library( - QCToQIR +add_mlir_conversion_library( + MLIRQCToQIR ${CONVERSION_SOURCES} DEPENDS QCToQIRIncGen @@ -24,4 +24,4 @@ add_mlir_library( MLIRReconcileUnrealizedCasts DISABLE_INSTALL) -mqt_mlir_target_use_project_options(QCToQIR) +mqt_mlir_target_use_project_options(MLIRQCToQIR) diff --git a/mlir/lib/Conversion/QCToQIR/QCToQIR.cpp b/mlir/lib/Conversion/QCToQIR/QCToQIR.cpp index ad88f1230b..eb39bda1ad 100644 --- a/mlir/lib/Conversion/QCToQIR/QCToQIR.cpp +++ b/mlir/lib/Conversion/QCToQIR/QCToQIR.cpp @@ -456,8 +456,8 @@ struct ConvertQCMeasureQIR final : StatefulOpConversionPattern { getOrCreateFunctionDeclaration(rewriter, op, QIR_MEASURE, fnSignature); // Create CallOp and replace qc.measure with result pointer - rewriter.create(op.getLoc(), fnDecl, - ValueRange{adaptor.getQubit(), resultValue}); + LLVM::CallOp::create(rewriter, op.getLoc(), fnDecl, + ValueRange{adaptor.getQubit(), resultValue}); rewriter.replaceOp(op, resultValue); return success(); } diff --git a/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp b/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp index f1afdcd5d2..7c7e5b7bca 100644 --- a/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp @@ -133,7 +133,7 @@ struct ReduceCtrl final : OpRewritePattern { const OpBuilder::InsertionGuard guard(rewriter); rewriter.setInsertionPoint(gPhaseOp); auto pOp = - rewriter.create(gPhaseOp.getLoc(), arg, gPhaseOp.getTheta()); + POp::create(rewriter, gPhaseOp.getLoc(), arg, gPhaseOp.getTheta()); // Add the results of the POp to the yield operation auto yieldOp = llvm::cast(op.getBody()->back()); diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp index 54ce6f6ac1..d168624987 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp @@ -58,7 +58,7 @@ struct MergeSubsequentBarrier final : OpRewritePattern { return failure(); } - auto newBarrier = rewriter.create(op.getLoc(), newQubitsIn); + auto newBarrier = BarrierOp::create(rewriter, op.getLoc(), newQubitsIn); for (size_t i = 0; i < indicesToFill.size(); ++i) { newQubitsOutMap[indicesToFill[i]] = newBarrier.getQubitsOut()[i]; diff --git a/mlir/lib/Dialect/QCO/Transforms/Mapping/Mapping.cpp b/mlir/lib/Dialect/QCO/Transforms/Mapping/Mapping.cpp index 61108c1094..e72f0309f7 100644 --- a/mlir/lib/Dialect/QCO/Transforms/Mapping/Mapping.cpp +++ b/mlir/lib/Dialect/QCO/Transforms/Mapping/Mapping.cpp @@ -394,9 +394,9 @@ struct MappingPass : impl::MappingPassBase { for (std::size_t p = dynQubits.size(); p < layout.nqubits(); ++p) { rewriter.setInsertionPointToStart(&funcBody.front()); const auto hw = layout.getHardwareIndex(p); - auto op = rewriter.create(rewriter.getUnknownLoc(), hw); + auto op = StaticOp::create(rewriter, rewriter.getUnknownLoc(), hw); rewriter.setInsertionPoint(funcBody.back().getTerminator()); - rewriter.create(rewriter.getUnknownLoc(), op.getQubit()); + DeallocOp::create(rewriter, rewriter.getUnknownLoc(), op.getQubit()); statics[hw] = op.getQubit(); } @@ -616,7 +616,6 @@ struct MappingPass : impl::MappingPassBase { return failure(); } - const auto unknown = rewriter.getUnknownLoc(); for (const auto& [hw0, hw1] : *swaps) { Operation* op0 = wires[hw0].operation(); Operation* op1 = wires[hw1].operation(); @@ -632,7 +631,7 @@ struct MappingPass : impl::MappingPassBase { rewriter.setInsertionPointAfterValue(in0); } - auto op = rewriter.create(unknown, in0, in1); + auto op = SWAPOp::create(rewriter, rewriter.getUnknownLoc(), in0, in1); const auto out0 = op.getQubit0Out(); const auto out1 = op.getQubit1Out(); diff --git a/mlir/unittests/Conversion/JeffRoundTrip/CMakeLists.txt b/mlir/unittests/Conversion/JeffRoundTrip/CMakeLists.txt index 89400fc341..d308854a9a 100644 --- a/mlir/unittests/Conversion/JeffRoundTrip/CMakeLists.txt +++ b/mlir/unittests/Conversion/JeffRoundTrip/CMakeLists.txt @@ -19,8 +19,8 @@ target_link_libraries( MLIRQCOProgramBuilder MLIRSupportMQT MLIRTransforms - JeffToQCO - QCOToJeff) + MLIRJeffToQCO + MLIRQCOToJeff) target_include_directories(${target_name} PRIVATE ${jeff-mlir_SOURCE_DIR}/include ${jeff-mlir_BINARY_DIR}/include) diff --git a/mlir/unittests/Conversion/QCOToQC/CMakeLists.txt b/mlir/unittests/Conversion/QCOToQC/CMakeLists.txt index 61432be4de..29fd4dbca1 100644 --- a/mlir/unittests/Conversion/QCOToQC/CMakeLists.txt +++ b/mlir/unittests/Conversion/QCOToQC/CMakeLists.txt @@ -18,7 +18,7 @@ target_link_libraries( MLIRQCOProgramBuilder MLIRQCPrograms MLIRQCOPrograms - QCOToQC) + MLIRQCOToQC) mqt_mlir_configure_unittest_target(${target_name}) diff --git a/mlir/unittests/Conversion/QCToQCO/CMakeLists.txt b/mlir/unittests/Conversion/QCToQCO/CMakeLists.txt index 80c8188651..b595155600 100644 --- a/mlir/unittests/Conversion/QCToQCO/CMakeLists.txt +++ b/mlir/unittests/Conversion/QCToQCO/CMakeLists.txt @@ -18,7 +18,7 @@ target_link_libraries( MLIRQCOProgramBuilder MLIRQCPrograms MLIRQCOPrograms - QCToQCO) + MLIRQCToQCO) mqt_mlir_configure_unittest_target(${target_name}) diff --git a/mlir/unittests/Conversion/QCToQIR/CMakeLists.txt b/mlir/unittests/Conversion/QCToQIR/CMakeLists.txt index 0eda223139..d424ccdae5 100644 --- a/mlir/unittests/Conversion/QCToQIR/CMakeLists.txt +++ b/mlir/unittests/Conversion/QCToQIR/CMakeLists.txt @@ -18,7 +18,7 @@ target_link_libraries( MLIRQIRProgramBuilder MLIRQCPrograms MLIRQIRPrograms - QCToQIR) + MLIRQCToQIR) mqt_mlir_configure_unittest_target(${target_name}) diff --git a/mlir/unittests/Dialect/QCO/Transforms/Mapping/CMakeLists.txt b/mlir/unittests/Dialect/QCO/Transforms/Mapping/CMakeLists.txt index b3e5c4b4d9..3ea628104a 100644 --- a/mlir/unittests/Dialect/QCO/Transforms/Mapping/CMakeLists.txt +++ b/mlir/unittests/Dialect/QCO/Transforms/Mapping/CMakeLists.txt @@ -15,8 +15,8 @@ target_link_libraries( GTest::gtest_main MLIRQCProgramBuilder MLIRQCOUtils - QCToQCO - QCOToQC + MLIRQCToQCO + MLIRQCOToQC MLIRQCOTransforms) mqt_mlir_configure_unittest_target(${target_name})