diff --git a/CHANGELOG.md b/CHANGELOG.md index cbd46115cd..66f078f527 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ This project adheres to [Semantic Versioning], with the exception that minor rel ### Added - ✨ Add Sampler and Estimator Primitives to the QDMI-Qiskit Interface ([#1507]) ([**@marcelwa**]) -- ✨ Add conversions between Jeff and QCO ([#1479], [#1548]) ([**@denialhaag**]) +- ✨ Add conversions between Jeff and QCO ([#1479], [#1548], [#1565]) ([**@denialhaag**]) - ✨ Add a `place-and-route` pass for mapping circuits to architectures with restricted topologies ([#1537], [#1547], [#1568]) ([**@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], [#1548], [#1550], [#1554]) @@ -332,6 +332,7 @@ _📚 Refer to the [GitHub Release Notes](https://github.com/munich-quantum-tool [#1568]: https://github.com/munich-quantum-toolkit/core/pull/1568 +[#1565]: https://github.com/munich-quantum-toolkit/core/pull/1565 [#1554]: https://github.com/munich-quantum-toolkit/core/pull/1554 [#1550]: https://github.com/munich-quantum-toolkit/core/pull/1550 [#1549]: https://github.com/munich-quantum-toolkit/core/pull/1549 diff --git a/cmake/ExternalDependencies.cmake b/cmake/ExternalDependencies.cmake index 6b99e90e11..d3b33cb291 100644 --- a/cmake/ExternalDependencies.cmake +++ b/cmake/ExternalDependencies.cmake @@ -41,7 +41,7 @@ if(BUILD_MQT_CORE_MLIR) FetchContent_Declare( jeff-mlir GIT_REPOSITORY https://github.com/PennyLaneAI/jeff-mlir.git - GIT_TAG c22047e0ebe361126f042baf3c439e0042827a03) + GIT_TAG c7e0d0340e470c9097a79a430b633b97dcd864e9) list(APPEND FETCH_PACKAGES jeff-mlir) endif() diff --git a/mlir/include/mlir/Conversion/JeffToQCO/JeffToQCO.td b/mlir/include/mlir/Conversion/JeffToQCO/JeffToQCO.td index 43f6d306ed..9237a19aa4 100644 --- a/mlir/include/mlir/Conversion/JeffToQCO/JeffToQCO.td +++ b/mlir/include/mlir/Conversion/JeffToQCO/JeffToQCO.td @@ -12,24 +12,26 @@ def JeffToQCO : Pass<"jeff-to-qco"> { let summary = "Convert Jeff operations to QCO operations"; let description = [{ - This pass converts all operations from the Jeff dialect to their equivalent operations in the QCO dialect. - It ensures that the returned module is a valid QCO module. + This pass converts all operations from the Jeff dialect to their equivalent operations in the QCO dialect. + It ensures that the returned module is a valid QCO module. - Note that this pass is still in development as QCO and Jeff do not have full feature parity yet. + Note that this pass is still in development as QCO and Jeff do not have full feature parity yet. - Known limitations: + Known limitations: - - Gates with a non-trivial power are currently not supported - - Only specific `CustomOp`s are currently supported - - Only specific `PPROp`s are currently supported - - `Qureg_Op`s are currently not supported - - `SCF_Op`s are currently not supported - - Support for multiple functions is currently limited - }]; + - Gates with a non-trivial power are currently not supported + - Only specific `CustomOp`s are currently supported + - Only specific `PPROp`s are currently supported + - `Qureg_Op`s are currently not supported + - `SCF_Op`s are currently not supported + - Support for multiple functions is currently limited + }]; let dependentDialects = [ - "mlir::arith::ArithDialect", - "mlir::jeff::JeffDialect", - "mlir::qco::QCODialect", + "mlir::arith::ArithDialect", + "mlir::math::MathDialect", + "mlir::tensor::TensorDialect", + "mlir::jeff::JeffDialect", + "mlir::qco::QCODialect", ]; } diff --git a/mlir/include/mlir/Conversion/QCOToJeff/QCOToJeff.td b/mlir/include/mlir/Conversion/QCOToJeff/QCOToJeff.td index 03dff36a4c..e31f5bc5a1 100644 --- a/mlir/include/mlir/Conversion/QCOToJeff/QCOToJeff.td +++ b/mlir/include/mlir/Conversion/QCOToJeff/QCOToJeff.td @@ -12,14 +12,17 @@ def QCOToJeff : Pass<"qco-to-jeff"> { let summary = "Convert QCO operations to Jeff operations"; let description = [{ - This pass converts all operations from the QCO dialect to their equivalent operations in the Jeff dialect. - It ensures that the returned module is a valid Jeff module that can be serialized. + This pass converts all operations from the QCO dialect to their equivalent operations in the Jeff dialect. + It ensures that the returned module is a valid Jeff module that can be serialized. - Note that this pass is still in development as QCO and Jeff do not have full feature parity yet. - }]; + Note that this pass is still in development as QCO and Jeff do not have full feature parity yet. + }]; let dependentDialects = [ - "mlir::jeff::JeffDialect", - "mlir::qco::QCODialect", + "mlir::arith::ArithDialect", + "mlir::math::MathDialect", + "mlir::tensor::TensorDialect", + "mlir::jeff::JeffDialect", + "mlir::qco::QCODialect", ]; } diff --git a/mlir/lib/Conversion/JeffToQCO/CMakeLists.txt b/mlir/lib/Conversion/JeffToQCO/CMakeLists.txt index 0f0b0380aa..43d5c4caf9 100644 --- a/mlir/lib/Conversion/JeffToQCO/CMakeLists.txt +++ b/mlir/lib/Conversion/JeffToQCO/CMakeLists.txt @@ -15,9 +15,7 @@ add_mlir_conversion_library( JeffToQCOIncGen LINK_LIBS MLIRJeff + MLIRJeffToNative MLIRQCODialect MLIRTransforms DISABLE_INSTALL) - -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 80c7f6ac2f..cd3f1a29d0 100644 --- a/mlir/lib/Conversion/JeffToQCO/JeffToQCO.cpp +++ b/mlir/lib/Conversion/JeffToQCO/JeffToQCO.cpp @@ -13,6 +13,7 @@ #include "mlir/Dialect/QCO/IR/QCODialect.h" #include "mlir/Dialect/QCO/IR/QCOOps.h" +#include #include #include #include @@ -20,6 +21,8 @@ #include #include #include +#include +#include #include #include #include @@ -883,78 +886,6 @@ struct ConvertJeffMainToQCO final : OpConversionPattern { } }; -/** - * @brief Converts jeff.int_const1 to arith.constant - * - * @par Example: - * ```mlir - * %0 = jeff.int_const1(true) : i1 - * ``` - * is converted to - * ```mlir - * %0 = arith.constant true : i1 - * ``` - */ -struct ConvertJeffIntConst1OpToArith final - : OpConversionPattern { - using OpConversionPattern::OpConversionPattern; - - LogicalResult - matchAndRewrite(jeff::IntConst1Op op, OpAdaptor /*adaptor*/, - ConversionPatternRewriter& rewriter) const override { - rewriter.replaceOpWithNewOp(op, op.getValAttr()); - return success(); - } -}; - -/** - * @brief Converts jeff.int_const64 to arith.constant - * - * @par Example: - * ```mlir - * %0 = jeff.int_const64(3) : i64 - * ``` - * is converted to - * ```mlir - * %0 = arith.constant 3 : i64 - * ``` - */ -struct ConvertJeffIntConst64OpToArith final - : OpConversionPattern { - using OpConversionPattern::OpConversionPattern; - - LogicalResult - matchAndRewrite(jeff::IntConst64Op op, OpAdaptor /*adaptor*/, - ConversionPatternRewriter& rewriter) const override { - rewriter.replaceOpWithNewOp(op, op.getValAttr()); - return success(); - } -}; - -/** - * @brief Converts jeff.float_const64 to arith.constant - * - * @par Example: - * ```mlir - * %0 = jeff.float_const64(0.3) : f64 - * ``` - * is converted to - * ```mlir - * %0 = arith.constant 0.3 : f64 - * ``` - */ -struct ConvertJeffFloatConst64OpToArith final - : OpConversionPattern { - using OpConversionPattern::OpConversionPattern; - - LogicalResult - matchAndRewrite(jeff::FloatConst64Op op, OpAdaptor /*adaptor*/, - ConversionPatternRewriter& rewriter) const override { - rewriter.replaceOpWithNewOp(op, op.getValAttr()); - return success(); - } -}; - /** * @brief Type converter for Jeff-to-QCO conversion * @@ -990,7 +921,8 @@ struct JeffToQCO final : impl::JeffToQCOBase { // Configure conversion target target.addIllegalDialect(); - target.addLegalDialect(); + target.addLegalDialect(); target.addDynamicallyLegalOp([&](func::FuncOp op) { return !(op.getSymName() == getEntryPointName(module) && @@ -999,27 +931,25 @@ struct JeffToQCO final : impl::JeffToQCOBase { target.addLegalOp(); // Register operation conversion patterns - patterns - .add, - ConvertJeffOneTargetZeroParameterToQCO, - ConvertJeffOneTargetZeroParameterToQCO, - ConvertJeffOneTargetZeroParameterToQCO, - ConvertJeffOneTargetZeroParameterToQCO, - ConvertJeffOneTargetZeroParameterToQCO, - ConvertJeffOneTargetZeroParameterToQCO, - ConvertJeffOneTargetOneParameterToQCO, - ConvertJeffOneTargetOneParameterToQCO, - ConvertJeffOneTargetOneParameterToQCO, - ConvertJeffOneTargetOneParameterToQCO, - ConvertJeffUOpToQCO, ConvertJeffSwapOpToQCO, - ConvertJeffCustomOpToQCO, ConvertJeffPPROpToQCO, - ConvertJeffMainToQCO, ConvertJeffIntConst1OpToArith, - ConvertJeffIntConst64OpToArith, ConvertJeffFloatConst64OpToArith>( - typeConverter, context); + jeff::populateJeffToNativeConversionPatterns(patterns); + patterns.add< + ConvertJeffQubitAllocOpToQCO, ConvertJeffQubitFreeOpToQCO, + ConvertJeffQubitFreeZeroOpToQCO, ConvertJeffQubitMeasureOpToQCO, + ConvertJeffQubitMeasureNDOpToQCO, ConvertJeffQubitResetOpToQCO, + ConvertJeffGPhaseOpToQCO, + ConvertJeffOneTargetZeroParameterToQCO, + ConvertJeffOneTargetZeroParameterToQCO, + ConvertJeffOneTargetZeroParameterToQCO, + ConvertJeffOneTargetZeroParameterToQCO, + ConvertJeffOneTargetZeroParameterToQCO, + ConvertJeffOneTargetZeroParameterToQCO, + ConvertJeffOneTargetZeroParameterToQCO, + ConvertJeffOneTargetOneParameterToQCO, + ConvertJeffOneTargetOneParameterToQCO, + ConvertJeffOneTargetOneParameterToQCO, + ConvertJeffOneTargetOneParameterToQCO, + ConvertJeffUOpToQCO, ConvertJeffSwapOpToQCO, ConvertJeffCustomOpToQCO, + ConvertJeffPPROpToQCO, ConvertJeffMainToQCO>(typeConverter, context); // Apply the conversion if (applyPartialConversion(module, target, std::move(patterns)).failed()) { diff --git a/mlir/lib/Conversion/QCOToJeff/CMakeLists.txt b/mlir/lib/Conversion/QCOToJeff/CMakeLists.txt index 03c1b041d4..269af18c2b 100644 --- a/mlir/lib/Conversion/QCOToJeff/CMakeLists.txt +++ b/mlir/lib/Conversion/QCOToJeff/CMakeLists.txt @@ -16,13 +16,11 @@ add_mlir_conversion_library( LINK_LIBS MLIRDialect MLIRJeff + MLIRNativeToJeff MLIRQCODialect MLIRTransforms DISABLE_INSTALL) -target_include_directories(MLIRQCOToJeff PRIVATE ${jeff-mlir_SOURCE_DIR}/include - ${jeff-mlir_BINARY_DIR}/include) - if(TARGET MLIRQCOToJeff) target_compile_definitions(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 3541be7571..8796e834df 100644 --- a/mlir/lib/Conversion/QCOToJeff/QCOToJeff.cpp +++ b/mlir/lib/Conversion/QCOToJeff/QCOToJeff.cpp @@ -13,14 +13,16 @@ #include "mlir/Dialect/QCO/IR/QCODialect.h" #include "mlir/Dialect/QCO/IR/QCOOps.h" +#include #include #include #include #include -#include #include #include #include +#include +#include #include #include #include @@ -1312,63 +1314,6 @@ struct ConvertQCOMainToJeff final : StatefulOpConversionPattern { } }; -/** - * @brief Converts arith.constant to Jeff - * - * @par Example: - * ```mlir - * %0 = arith.constant 0 : i64 - * ``` - * is converted to - * ```mlir - * %0 = jeff.int_const64(0) : i64 - * ``` - */ -struct ConvertArithConstOpToJeff final - : StatefulOpConversionPattern { - using StatefulOpConversionPattern::StatefulOpConversionPattern; - - LogicalResult - matchAndRewrite(arith::ConstantOp op, OpAdaptor /*adaptor*/, - ConversionPatternRewriter& rewriter) const override { - auto value = op.getValue(); - return llvm::TypeSwitch(op.getType()) - .Case([&](auto type) -> LogicalResult { - auto floatAttr = llvm::dyn_cast(value); - if (!floatAttr) { - return rewriter.notifyMatchFailure(op, "Expected float attribute"); - } - switch (type.getWidth()) { - case 64: - rewriter.replaceOpWithNewOp(op, floatAttr); - return success(); - default: - return rewriter.notifyMatchFailure(op, "Unsupported type"); - } - }) - .Case([&](auto type) -> LogicalResult { - auto intAttr = llvm::dyn_cast(value); - if (!intAttr) { - return rewriter.notifyMatchFailure(op, - "Expected integer attribute"); - } - switch (type.getWidth()) { - case 1: - rewriter.replaceOpWithNewOp(op, intAttr); - return success(); - case 64: - rewriter.replaceOpWithNewOp(op, intAttr); - return success(); - default: - return rewriter.notifyMatchFailure(op, "Unsupported type"); - } - }) - .Default([&](auto) -> LogicalResult { - return rewriter.notifyMatchFailure(op, "Unsupported type"); - }); - } -}; - /** * @brief Type converter for QCO-to-Jeff conversion * @@ -1405,7 +1350,8 @@ struct QCOToJeff final : impl::QCOToJeffBase { LoweringState state; // Configure conversion target - target.addIllegalDialect(); + target.addIllegalDialect(); target.addLegalDialect(); target.addDynamicallyLegalOp( @@ -1413,6 +1359,7 @@ struct QCOToJeff final : impl::QCOToJeffBase { target.addLegalOp(); // Register operation conversion patterns + jeff::populateNativeToJeffConversionPatterns(patterns); patterns.add< ConvertQCOAllocOpToJeff, ConvertQCODeallocOpToJeff, ConvertQCOMeasureOpToJeff, ConvertQCOResetOpToJeff, @@ -1439,8 +1386,7 @@ struct QCOToJeff final : impl::QCOToJeffBase { ConvertQCORZZOpToJeff, ConvertQCOXXMinusYYOpToJeff, ConvertQCOXXPlusYYOpToJeff, ConvertQCOBarrierOpToJeff, ConvertQCOCtrlOpToJeff, ConvertQCOInvOpToJeff, ConvertQCOYieldOpToJeff, - ConvertQCOMainToJeff, ConvertArithConstOpToJeff>(typeConverter, context, - &state); + ConvertQCOMainToJeff>(typeConverter, context, &state); // Apply the conversion if (applyPartialConversion(module, target, std::move(patterns)).failed()) { diff --git a/mlir/unittests/Conversion/JeffRoundTrip/CMakeLists.txt b/mlir/unittests/Conversion/JeffRoundTrip/CMakeLists.txt index d308854a9a..868d4e5656 100644 --- a/mlir/unittests/Conversion/JeffRoundTrip/CMakeLists.txt +++ b/mlir/unittests/Conversion/JeffRoundTrip/CMakeLists.txt @@ -22,9 +22,6 @@ target_link_libraries( MLIRJeffToQCO MLIRQCOToJeff) -target_include_directories(${target_name} PRIVATE ${jeff-mlir_SOURCE_DIR}/include - ${jeff-mlir_BINARY_DIR}/include) - mqt_mlir_configure_unittest_target(${target_name}) gtest_discover_tests(${target_name} PROPERTIES LABELS mqt-mlir-unittests DISCOVERY_TIMEOUT 60)