From fc38576418aa0c95b2418873233ced5e69d4710c Mon Sep 17 00:00:00 2001 From: Thomas Alexander Date: Tue, 2 Jan 2024 16:01:53 -0400 Subject: [PATCH] Upgrade to LLVM 17 (#193) Closes #132. Upgrade the qss-compiler to LLVM 17.0.5. This is a major change and has a corresponding significant diff. Work to be done before coming out of draft - [x] Building - [x] Tests passing - [x] Tested internally with hardware --- CMakeLists.txt | 1 - cmake/AddQSSC.cmake | 11 - cmake/apple-clang.cmake | 10 + cmake/llvm-clang.cmake | 10 + conan/clang-tools-extra/conanfile.py | 4 +- conan/llvm/conanfile.py | 4 +- conandata.yml | 5 +- conanfile.py | 6 +- include/Arguments/Arguments.h | 2 +- include/Arguments/Signature.h | 4 +- include/Config/QSSConfig.h | 2 +- include/Conversion/QUIRToLLVM/QUIRToLLVM.h | 22 +- .../Conversion/QUIRToPulse/LoadPulseCals.h | 27 +- include/Conversion/QUIRToPulse/QUIRToPulse.h | 24 +- .../QUIRToStandard/TypeConversion.h | 10 +- include/Dialect/OQ3/IR/CMakeLists.txt | 2 +- include/Dialect/OQ3/IR/OQ3AngleOps.td | 9 +- include/Dialect/OQ3/IR/OQ3ArithmeticOps.td | 2 +- include/Dialect/OQ3/IR/OQ3ArrayOps.td | 12 +- include/Dialect/OQ3/IR/OQ3Base.td | 13 +- include/Dialect/OQ3/IR/OQ3CBitOps.td | 9 +- include/Dialect/OQ3/IR/OQ3CastOps.td | 2 +- include/Dialect/OQ3/IR/OQ3Dialect.h | 4 +- include/Dialect/OQ3/IR/OQ3GateOps.td | 2 +- include/Dialect/OQ3/IR/OQ3Patterns.td | 3 +- include/Dialect/OQ3/IR/OQ3VariableOps.td | 20 +- include/Dialect/Pulse/IR/CMakeLists.txt | 6 +- include/Dialect/Pulse/IR/PulseAttributes.h | 32 ++ include/Dialect/Pulse/IR/PulseAttributes.td | 25 + include/Dialect/Pulse/IR/PulseDialect.td | 16 + include/Dialect/Pulse/IR/PulseInterfaces.h | 6 +- include/Dialect/Pulse/IR/PulseInterfaces.td | 10 +- include/Dialect/Pulse/IR/PulseOps.h | 5 +- include/Dialect/Pulse/IR/PulseOps.td | 215 ++++---- include/Dialect/Pulse/IR/PulseTypes.td | 2 + .../Dialect/Pulse/Transforms/InlineRegion.h | 3 +- include/Dialect/Pulse/Utils/Utils.h | 2 +- include/Dialect/QCS/IR/CMakeLists.txt | 2 +- include/Dialect/QCS/IR/QCSBase.td | 2 + include/Dialect/QCS/IR/QCSOps.td | 17 +- include/Dialect/QUIR/IR/CMakeLists.txt | 2 +- include/Dialect/QUIR/IR/QUIRAttributes.td | 25 +- include/Dialect/QUIR/IR/QUIRDialect.h | 4 +- include/Dialect/QUIR/IR/QUIRDialect.td | 6 +- include/Dialect/QUIR/IR/QUIRInterfaces.h | 2 +- include/Dialect/QUIR/IR/QUIRInterfaces.td | 18 +- include/Dialect/QUIR/IR/QUIROps.h | 3 + include/Dialect/QUIR/IR/QUIROps.td | 226 +++++---- include/Dialect/QUIR/IR/QUIRTypes.td | 11 +- include/Dialect/QUIR/Transforms/AddShotLoop.h | 2 +- .../Dialect/QUIR/Transforms/AngleConversion.h | 3 +- include/Dialect/QUIR/Transforms/BreakReset.h | 4 +- .../FunctionArgumentSpecialization.h | 6 +- .../QUIR/Transforms/MergeParallelResets.h | 1 + .../QUIR/Transforms/RemoveQubitOperands.h | 2 +- .../QUIR/Transforms/VariableElimination.h | 4 +- include/Dialect/QUIR/Utils/Utils.h | 18 +- include/Dialect/RegisterDialects.h | 5 +- include/Dialect/RegisterPasses.h | 60 +++ .../Frontend/OpenQASM3/QUIRVariableBuilder.h | 12 +- .../HAL/Compile/TargetCompilationManager.h | 18 +- .../HAL/Compile/ThreadedCompilationManager.h | 52 +- include/HAL/SystemConfiguration.h | 1 - include/HAL/TargetOperationPass.h | 16 +- include/HAL/TargetSystem.h | 6 +- include/HAL/TargetSystemInfo.h | 2 +- include/Plugin/PluginInfo.h | 4 +- include/Plugin/PluginRegistry.h | 9 +- include/QSSC.h | 3 +- lib/API/api.cpp | 208 ++++---- lib/API/errors.cpp | 26 +- lib/Arguments/Arguments.cpp | 25 +- lib/Arguments/Signature.cpp | 23 +- lib/CMakeLists.txt | 5 +- lib/Config/CLIConfig.cpp | 23 +- lib/Config/EnvVarConfig.cpp | 3 + lib/Config/QSSConfig.cpp | 22 +- .../OQ3ToStandard/OQ3ToStandard.cpp | 123 ++--- lib/Conversion/QUIRToPulse/CMakeLists.txt | 2 +- lib/Conversion/QUIRToPulse/LoadPulseCals.cpp | 182 ++++--- lib/Conversion/QUIRToPulse/QUIRToPulse.cpp | 150 ++++-- .../QUIRToStandard/SwitchOpLowering.cpp | 41 +- .../QUIRToStandard/TypeConversion.cpp | 33 +- .../VariablesToGlobalMemRefConversion.cpp | 89 ++-- lib/Dialect/OQ3/IR/OQ3Dialect.cpp | 9 +- lib/Dialect/OQ3/IR/OQ3Ops.cpp | 113 ++++- lib/Dialect/OQ3/IR/OQ3Patterns.cpp | 42 +- lib/Dialect/OQ3/Transforms/LimitCBitWidth.cpp | 63 ++- lib/Dialect/OQ3/Transforms/Passes.cpp | 8 +- lib/Dialect/Pulse/IR/CMakeLists.txt | 3 +- lib/Dialect/Pulse/IR/PulseAttributes.cpp | 15 + lib/Dialect/Pulse/IR/PulseDialect.cpp | 23 +- lib/Dialect/Pulse/IR/PulseInterfaces.cpp | 19 +- lib/Dialect/Pulse/IR/PulseOps.cpp | 278 ++++++++--- lib/Dialect/Pulse/Transforms/CMakeLists.txt | 2 +- .../Transforms/ClassicalOnlyDetection.cpp | 18 +- lib/Dialect/Pulse/Transforms/InlineRegion.cpp | 25 +- lib/Dialect/Pulse/Transforms/MergeDelays.cpp | 22 +- lib/Dialect/Pulse/Transforms/Passes.cpp | 29 +- .../Transforms/RemoveUnusedArguments.cpp | 17 +- lib/Dialect/Pulse/Transforms/SchedulePort.cpp | 71 ++- lib/Dialect/Pulse/Transforms/Scheduling.cpp | 42 +- lib/Dialect/Pulse/Utils/Utils.cpp | 6 +- lib/Dialect/QCS/IR/QCSDialect.cpp | 6 + lib/Dialect/QCS/IR/QCSOps.cpp | 67 ++- .../Utils/ParameterInitialValueAnalysis.cpp | 21 +- lib/Dialect/QUIR/IR/CMakeLists.txt | 3 + lib/Dialect/QUIR/IR/QUIRAttributes.cpp | 15 +- lib/Dialect/QUIR/IR/QUIRDialect.cpp | 61 ++- lib/Dialect/QUIR/IR/QUIRInterfaces.cpp | 18 +- lib/Dialect/QUIR/IR/QUIROps.cpp | 332 +++++++------ lib/Dialect/QUIR/IR/QUIRTestInterfaces.cpp | 7 + lib/Dialect/QUIR/Transforms/AddShotLoop.cpp | 37 +- .../QUIR/Transforms/AffineScalRepCopy.cpp | 460 ------------------ lib/Dialect/QUIR/Transforms/Analysis.cpp | 9 +- .../QUIR/Transforms/AngleConversion.cpp | 48 +- lib/Dialect/QUIR/Transforms/BreakReset.cpp | 35 +- lib/Dialect/QUIR/Transforms/CMakeLists.txt | 1 - .../QUIR/Transforms/ConvertDurationUnits.cpp | 85 ++-- .../FunctionArgumentSpecialization.cpp | 34 +- .../QUIR/Transforms/LoadElimination.cpp | 12 +- lib/Dialect/QUIR/Transforms/MergeCircuits.cpp | 62 ++- lib/Dialect/QUIR/Transforms/MergeMeasures.cpp | 44 +- .../QUIR/Transforms/MergeParallelResets.cpp | 36 +- lib/Dialect/QUIR/Transforms/Passes.cpp | 60 ++- .../QUIR/Transforms/QUIRCircuitAnalysis.cpp | 40 +- .../QUIR/Transforms/QuantumDecoration.cpp | 34 +- .../QUIR/Transforms/RemoveQubitOperands.cpp | 42 +- .../QUIR/Transforms/ReorderCircuits.cpp | 20 +- .../QUIR/Transforms/ReorderMeasurements.cpp | 35 +- .../QUIR/Transforms/SubroutineCloning.cpp | 64 ++- .../QUIR/Transforms/UnusedVariable.cpp | 10 +- .../QUIR/Transforms/VariableElimination.cpp | 91 ++-- lib/Dialect/QUIR/Utils/Utils.cpp | 99 ++-- lib/Frontend/OpenQASM3/BaseQASM3Visitor.cpp | 41 +- lib/Frontend/OpenQASM3/OpenQASM3Frontend.cpp | 63 ++- lib/Frontend/OpenQASM3/PrintQASM3Visitor.cpp | 57 ++- .../OpenQASM3/QUIRGenQASM3Visitor.cpp | 290 ++++++----- .../OpenQASM3/QUIRVariableBuilder.cpp | 29 +- lib/HAL/Compile/TargetCompilationManager.cpp | 44 +- .../Compile/ThreadedCompilationManager.cpp | 169 ++++++- lib/HAL/PassRegistration.cpp | 4 + lib/HAL/TargetSystem.cpp | 12 +- lib/HAL/TargetSystemInfo.cpp | 13 +- lib/HAL/TargetSystemRegistry.cpp | 15 +- lib/Payload/Payload.cpp | 15 +- .../ZipPayload/PatchableZipPayload.cpp | 43 +- lib/Payload/ZipPayload/ZipPayload.cpp | 78 +-- lib/Payload/ZipPayload/ZipUtil.cpp | 5 + lib/QSSC.cpp | 14 +- lib/Utils/CMakeLists.txt | 4 +- python_lib/qss_compiler/lib.cpp | 30 +- python_lib/qss_compiler/lib_enums.cpp | 10 +- targets/systems/mock/CMakeLists.txt | 4 +- .../QUIRToStandard/QUIRToStandard.cpp | 103 ++-- targets/systems/mock/MockTarget.cpp | 103 ++-- targets/systems/mock/MockUtils.cpp | 6 +- .../mock/Transforms/FunctionLocalization.cpp | 136 +++--- .../mock/Transforms/FunctionLocalization.h | 4 +- .../mock/Transforms/QubitLocalization.cpp | 212 ++++---- .../mock/Transforms/QubitLocalization.h | 21 +- .../mock/test/python_lib/test_compile.py | 2 +- .../static/Conversion/QUIRToStd/llvmgen.mlir | 14 +- .../static/Transforms/qubit-localization.mlir | 44 +- .../test/static/integration/mlir/bell-v0.mlir | 8 +- .../mlir/scf-iterative-phase-estimation.mlir | 40 +- test/Dialect/OQ3/IR/fold-cbit-extractbit.mlir | 8 +- test/Dialect/OQ3/IR/math.mlir | 6 +- test/Dialect/OQ3/IR/ops.mlir | 4 +- .../OQ3/integration/openqasm3/cbit-width.qasm | 2 +- test/Dialect/Pulse/IR/ops-error-testing.mlir | 18 +- test/Dialect/Pulse/IR/ops.mlir | 2 +- .../Transforms/classical-only-detection.mlir | 18 +- .../Dialect/Pulse/Transforms/merge-delay.mlir | 8 +- .../Pulse/Transforms/pulse-inline.mlir | 84 ++-- .../Dialect/Pulse/Transforms/pulse-prune.mlir | 8 +- .../Dialect/Pulse/Transforms/pulse-slice.mlir | 26 +- .../Transforms/remove-unused-arguments.mlir | 2 +- .../Transforms/schedule-port-acquire.mlir | 4 +- .../Pulse/Transforms/schedule-port-drive.mlir | 2 +- test/Dialect/QUIR/IR/angle-cmp-ops.mlir | 8 +- test/Dialect/QUIR/IR/canonicalization.mlir | 12 +- test/Dialect/QUIR/IR/control-flow.mlir | 8 +- test/Dialect/QUIR/IR/declarations.mlir | 14 +- test/Dialect/QUIR/IR/error-testing.mlir | 27 +- test/Dialect/QUIR/IR/gate-tests.mlir | 16 +- test/Dialect/QUIR/IR/invalid.mlir | 19 +- test/Dialect/QUIR/IR/ops.mlir | 54 +- test/Dialect/QUIR/IR/qubit-op-interface.mlir | 10 +- test/Dialect/QUIR/IR/test.mlir | 38 +- .../QUIR/Transforms/add-shot-loop.mlir | 2 +- .../QUIR/Transforms/arg-specialization0.mlir | 26 +- .../QUIR/Transforms/arg-specialization1.mlir | 32 +- .../QUIR/Transforms/arg-specialization2.mlir | 22 +- .../Transforms/break-reset-multiqubit.mlir | 4 +- .../QUIR/Transforms/break-reset-nested.mlir | 2 +- test/Dialect/QUIR/Transforms/break-reset.mlir | 6 +- .../canonicalize-assign-cbit-bit.mlir | 2 +- .../Transforms/canonicalize-bit-eqeqone.mlir | 4 +- .../Transforms/classical-only-detection.mlir | 46 +- .../Transforms/convert-duration-units.mlir | 54 +- .../QUIR/Transforms/convert-quir-angles.mlir | 8 +- .../QUIR/Transforms/for-localization.mlir | 4 +- .../QUIR/Transforms/load-elimination.mlir | 2 +- .../QUIR/Transforms/load-elimination2.mlir | 12 +- .../QUIR/Transforms/merge-circuits.mlir | 6 +- .../merge-measurements-circuits.mlir | 2 +- .../QUIR/Transforms/merge-measures.mlir | 16 +- .../Dialect/QUIR/Transforms/merge-resets.mlir | 7 +- .../QUIR/Transforms/merge-resets2.mlir | 4 +- .../QUIR/Transforms/quantum-decoration.mlir | 2 +- .../Transforms/remove-unused-variables.mlir | 4 +- .../QUIR/Transforms/reorder-circuits.mlir | 6 +- .../Transforms/reorder-measurements-2.mlir | 10 +- .../reorder-measurements-issue-1730.mlir | 20 +- .../reorder-measurements-issue-910-2.mlir | 4 +- .../reorder-measurements-issue-910.mlir | 4 +- .../reorder-measurements-issue-921.mlir | 2 +- .../QUIR/Transforms/reorder-measurements.mlir | 8 +- .../QUIR/Transforms/subroutine-cloning.mlir | 34 +- .../Transforms/variable-elimination1.mlir | 6 +- .../Transforms/variable-elimination2.mlir | 6 +- .../Transforms/variable-elimination3.mlir | 4 +- .../iterative-phase-estimation.mlir | 54 +- .../QUIR/integration/measure-reset.mlir | 2 +- .../QUIR/integration/qasm-bell-v0.mlir | 8 +- .../QUIR/integration/qasm-bell-v1.mlir | 10 +- .../QUIR/integration/qasm-bell-v2.mlir | 14 +- .../QUIR/integration/qasm-reset-v1.mlir | 6 +- .../QUIR/integration/qasm-reset-v1b.mlir | 6 +- .../QUIR/integration/scf-teleportation.mlir | 8 +- test/Frontend/OpenQASM3/angles.qasm | 12 +- test/Frontend/OpenQASM3/assign.qasm | 2 +- test/Frontend/OpenQASM3/bell-v0.qasm | 6 +- test/Frontend/OpenQASM3/bell-v1.qasm | 12 +- test/Frontend/OpenQASM3/bitindices.qasm | 4 +- test/Frontend/OpenQASM3/bitops-reg.qasm | 2 +- test/Frontend/OpenQASM3/bitops.qasm | 2 +- test/Frontend/OpenQASM3/bitops2.qasm | 2 +- test/Frontend/OpenQASM3/conditionals.qasm | 28 +- .../OpenQASM3/delay-inside-controlflow.qasm | 18 +- test/Frontend/OpenQASM3/delay.qasm | 26 +- test/Frontend/OpenQASM3/extern.qasm | 18 +- test/Frontend/OpenQASM3/for-loop.qasm | 18 +- test/Frontend/OpenQASM3/gate.qasm | 18 +- .../Frontend/OpenQASM3/gates-issue-655-2.qasm | 26 +- test/Frontend/OpenQASM3/gates-issue-655.qasm | 72 +-- .../OpenQASM3/input-parameters-if.qasm | 6 +- .../OpenQASM3/input-parameters-while.qasm | 22 +- test/Frontend/OpenQASM3/input-parameters.qasm | 10 +- test/Frontend/OpenQASM3/main.qasm | 2 +- .../OpenQASM3/multi-param-gatedef.qasm | 4 +- .../OpenQASM3/multi-qubit-gatedef.qasm | 4 +- test/Frontend/OpenQASM3/nested-gatecalls.qasm | 16 +- test/Frontend/OpenQASM3/rz-issue-655.qasm | 12 +- test/Frontend/OpenQASM3/switch-1.qasm | 8 +- test/Frontend/OpenQASM3/switch-2.qasm | 16 +- test/Frontend/OpenQASM3/teleport.qasm | 12 +- test/Frontend/OpenQASM3/test-include.qasm | 2 +- test/Frontend/OpenQASM3/while-1.qasm | 17 +- test/Frontend/OpenQASM3/while-2.qasm | 8 +- test/Frontend/OpenQASM3/while-3.qasm | 7 +- .../unittest/HAL/TargetSystemRegistryTest.cpp | 10 +- test/unittest/Payload/PayloadRegistryTest.cpp | 5 +- test/unittest/quir-dialect.cpp | 11 +- tools/qss-opt/qss-opt.cpp | 204 ++++---- 266 files changed, 4516 insertions(+), 3372 deletions(-) create mode 100644 include/Dialect/Pulse/IR/PulseAttributes.h create mode 100644 include/Dialect/Pulse/IR/PulseAttributes.td create mode 100644 include/Dialect/RegisterPasses.h create mode 100644 lib/Dialect/Pulse/IR/PulseAttributes.cpp delete mode 100644 lib/Dialect/QUIR/Transforms/AffineScalRepCopy.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d9640026..b670b5c74 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -246,7 +246,6 @@ list(APPEND RUN_CLANG_TIDY_BIN_ARGS -clang-apply-replacements-binary ${CLANG_AR_BIN} -style=file -quiet - -header-filter="${CMAKE_SOURCE_DIR}/[^b].*" ) # run clang-tidy linter only when compiling with clang (compiler flags may be diff --git a/cmake/AddQSSC.cmake b/cmake/AddQSSC.cmake index 95183f33c..9edbd8aee 100644 --- a/cmake/AddQSSC.cmake +++ b/cmake/AddQSSC.cmake @@ -349,14 +349,3 @@ macro(package_add_test_with_libs TESTNAME) package_add_test(${TESTNAME} ${ARG_UNPARSED_ARGUMENTS}) target_link_libraries(${TESTNAME} GTest::gtest_main GTest::gtest ${ARG_LIBRARIES}) endmacro() - - -# Version adapter for add_mlir_doc during transition from LLVM 12 to newer -# (order of parameters differs) -function(qssc_add_mlir_doc doc_filename output_file output_directory command) - if("${LLVM_VERSION_MAJOR}" EQUAL "12") - add_mlir_doc(${doc_filename} ${command} ${output_file} ${output_directory}) - else() - add_mlir_doc(${doc_filename} ${output_file} ${output_directory} ${command}) - endif() -endfunction() diff --git a/cmake/apple-clang.cmake b/cmake/apple-clang.cmake index d2715eff8..39c21320b 100644 --- a/cmake/apple-clang.cmake +++ b/cmake/apple-clang.cmake @@ -17,6 +17,16 @@ set (CXX_FLAGS -fno-omit-frame-pointer -Werror ) + +option(DETECT_TARGET_TRIPLE "Automatically detect the target triple for clang" ON) +if (DETECT_TARGET_TRIPLE) +execute_process ( + COMMAND bash -c "llvm-config --host-target | tr -d '\n'" + OUTPUT_VARIABLE LLVM_TARGET_TRIPLE +) +list(APPEND CXX_FLAGS "-target ${LLVM_TARGET_TRIPLE}") +endif() + list (JOIN CXX_FLAGS " " CXX_FLAGS_STR) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_FLAGS_STR}") diff --git a/cmake/llvm-clang.cmake b/cmake/llvm-clang.cmake index 3c0bc2257..30950cdb2 100644 --- a/cmake/llvm-clang.cmake +++ b/cmake/llvm-clang.cmake @@ -19,6 +19,16 @@ set (CXX_FLAGS -Werror ) + +option(DETECT_TARGET_TRIPLE "Automatically detect the target triple for clang" ON) +if (DETECT_TARGET_TRIPLE) +execute_process ( + COMMAND bash -c "llvm-config --host-target | tr -d '\n'" + OUTPUT_VARIABLE LLVM_TARGET_TRIPLE +) +list(APPEND CXX_FLAGS "-target ${LLVM_TARGET_TRIPLE}") +endif() + list (JOIN CXX_FLAGS " " CXX_FLAGS_STR) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_FLAGS_STR}") diff --git a/conan/clang-tools-extra/conanfile.py b/conan/clang-tools-extra/conanfile.py index 74b5945af..7d8db343d 100644 --- a/conan/clang-tools-extra/conanfile.py +++ b/conan/clang-tools-extra/conanfile.py @@ -20,12 +20,12 @@ import os import shutil -LLVM_TAG = "llvmorg-14.0.6" +LLVM_TAG = "llvmorg-17.0.5" class ClangToolsExtraConan(ConanFile): name = "clang-tools-extra" - version = "14.0.6" + version = "17.0.5-0" description = "A toolkit for analysis of c++ projects." license = "Apache-2.0 WITH LLVM-exception" topics = ("conan", "llvm", "clang-tools-extra") diff --git a/conan/llvm/conanfile.py b/conan/llvm/conanfile.py index f52ea5051..63ae68452 100644 --- a/conan/llvm/conanfile.py +++ b/conan/llvm/conanfile.py @@ -21,12 +21,12 @@ from conan.tools.apple import is_apple_os -LLVM_TAG = "llvmorg-14.0.6" +LLVM_TAG = "llvmorg-17.0.5" class LLVMConan(ConanFile): name = "llvm" - version = "14.0.6-2" + version = "17.0.5-0" description = ( "A toolkit for the construction of highly optimized compilers," "optimizers, and runtime environments." diff --git a/conandata.yml b/conandata.yml index 30a1cd31a..c2494dba6 100644 --- a/conandata.yml +++ b/conandata.yml @@ -2,8 +2,9 @@ requirements: - gtest/1.11.0 - libzip/1.10.1 - zlib/1.2.13 + - zstd/1.5.5 - nlohmann_json/3.9.1 - pybind11/2.10.1 - - clang-tools-extra/14.0.6@ - - llvm/14.0.6-2@ + - clang-tools-extra/17.0.5-0@ + - llvm/17.0.5-0@ - qasm/0.3.0@qss/stable diff --git a/conanfile.py b/conanfile.py index 8ed9e5633..74ed4877c 100644 --- a/conanfile.py +++ b/conanfile.py @@ -34,7 +34,7 @@ class QSSCompilerConan(ConanFile): author = "IBM Quantum development team" topics = ("Compiler", "Scheduler", "OpenQASM3") description = "An LLVM- and MLIR-based Quantum compiler that consumes OpenQASM 3.0" - generators = ["CMakeToolchain", "CMakeDeps"] + generators = ["CMakeToolchain", "CMakeDeps", "VirtualBuildEnv"] exports_sources = "*" def requirements(self): @@ -46,6 +46,10 @@ def configure(self): if self.settings.os == "Macos": self.options["qasm"].shared = True + # LLVM prefers ZSTD shared libraries by default now so we force building + # https://github.com/llvm/llvm-project/commit/fc1da043f4f9198303abd6f643cf23439115ce73 + self.options["zstd"].shared = True + def build_requirements(self): tool_pkgs = ["llvm", "clang-tools-extra"] # Add packages necessary for build. diff --git a/include/Arguments/Arguments.h b/include/Arguments/Arguments.h index 8c26a7e99..bf7575240 100644 --- a/include/Arguments/Arguments.h +++ b/include/Arguments/Arguments.h @@ -34,7 +34,7 @@ namespace qssc::arguments { -using ArgumentType = std::variant>; +using ArgumentType = std::variant>; using OptDiagnosticCallback = std::optional; class ArgumentSource { diff --git a/include/Arguments/Signature.h b/include/Arguments/Signature.h index 991af8b63..441c563e2 100644 --- a/include/Arguments/Signature.h +++ b/include/Arguments/Signature.h @@ -29,6 +29,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" +#include #include #include @@ -58,7 +59,8 @@ using PatchPointVector = std::vector; struct Signature { // TODO consider deduplicating strings by using UniqueStringSaver - llvm::StringMap> patchPointsByBinary; + // Use std::map instead of StringMap to preserve order + std::map> patchPointsByBinary; public: void addParameterPatchPoint(llvm::StringRef expression, diff --git a/include/Config/QSSConfig.h b/include/Config/QSSConfig.h index 87e3187f1..5d21e23f8 100644 --- a/include/Config/QSSConfig.h +++ b/include/Config/QSSConfig.h @@ -54,7 +54,7 @@ std::ostream &operator<<(std::ostream &os, const QSSConfig &config); /// @param context The context to assign the configuration to. /// This must outlive all usages of the context registry. /// @param config The configuration to move for the context. -void setContextConfig(mlir::MLIRContext *context, QSSConfig config); +void setContextConfig(mlir::MLIRContext *context, const QSSConfig &config); /// @brief Get a constant reference to the configuration registered for this /// context. diff --git a/include/Conversion/QUIRToLLVM/QUIRToLLVM.h b/include/Conversion/QUIRToLLVM/QUIRToLLVM.h index 41c1ca16b..44aa271e2 100644 --- a/include/Conversion/QUIRToLLVM/QUIRToLLVM.h +++ b/include/Conversion/QUIRToLLVM/QUIRToLLVM.h @@ -25,13 +25,16 @@ #include "Dialect/QUIR/IR/QUIRDialect.h" #include "mlir/Conversion/AffineToStandard/AffineToStandard.h" -#include "mlir/Conversion/ArithmeticToLLVM/ArithmeticToLLVM.h" +#include "mlir/Conversion/ArithToLLVM/ArithToLLVM.h" +#include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h" +#include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h" +#include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVMPass.h" #include "mlir/Conversion/LLVMCommon/ConversionTarget.h" #include "mlir/Conversion/LLVMCommon/TypeConverter.h" #include "mlir/Conversion/MemRefToLLVM/MemRefToLLVM.h" -#include "mlir/Conversion/SCFToStandard/SCFToStandard.h" -#include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVM.h" +#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h" #include "mlir/IR/BuiltinOps.h" +#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h" #include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h" #include "mlir/Transforms/DialectConversion.h" @@ -54,6 +57,7 @@ static auto translateModuleToLLVMDialect(mlir::ModuleOp op, // Register LLVM dialect and all infrastructure required for translation to // LLVM IR + mlir::registerBuiltinDialectTranslation(*context); mlir::registerLLVMDialectTranslation(*context); mlir::LLVMConversionTarget target(*context); @@ -69,14 +73,14 @@ static auto translateModuleToLLVMDialect(mlir::ModuleOp op, mlir::LLVMTypeConverter typeConverter(context, options); mlir::RewritePatternSet patterns(context); - mlir::populateLoopToStdConversionPatterns(patterns); mlir::quir::populateSwitchOpLoweringPatterns(patterns); - mlir::arith::populateArithmeticToLLVMConversionPatterns(typeConverter, - patterns); mlir::populateAffineToStdConversionPatterns(patterns); - mlir::populateMemRefToLLVMConversionPatterns(typeConverter, patterns); - mlir::populateStdToLLVMFuncOpConversionPattern(typeConverter, patterns); - mlir::populateStdToLLVMConversionPatterns(typeConverter, patterns); + mlir::populateSCFToControlFlowConversionPatterns(patterns); + mlir::arith::populateArithToLLVMConversionPatterns(typeConverter, patterns); + mlir::populateFinalizeMemRefToLLVMConversionPatterns(typeConverter, patterns); + mlir::cf::populateControlFlowToLLVMConversionPatterns(typeConverter, + patterns); + mlir::populateFuncToLLVMConversionPatterns(typeConverter, patterns); if (mlir::applyFullConversion(op, target, std::move(patterns)).failed()) return llvm::createStringError(llvm::inconvertibleErrorCode(), diff --git a/include/Conversion/QUIRToPulse/LoadPulseCals.h b/include/Conversion/QUIRToPulse/LoadPulseCals.h index 146f9931b..14c89f2bc 100644 --- a/include/Conversion/QUIRToPulse/LoadPulseCals.h +++ b/include/Conversion/QUIRToPulse/LoadPulseCals.h @@ -66,23 +66,32 @@ struct LoadPulseCalsPass llvm::cl::desc("default pulse calibrations MLIR file"), llvm::cl::value_desc("filename"), llvm::cl::init("")}; - void loadPulseCals(mlir::quir::CallCircuitOp callCircuitOp, FuncOp funcOp); + void loadPulseCals(mlir::quir::CallCircuitOp callCircuitOp, + mlir::func::FuncOp funcOp); void loadPulseCals(mlir::quir::CallGateOp callGateOp, - mlir::quir::CallCircuitOp callCircuitOp, FuncOp funcOp); + mlir::quir::CallCircuitOp callCircuitOp, + mlir::func::FuncOp funcOp); void loadPulseCals(mlir::quir::BuiltinCXOp CXOp, - mlir::quir::CallCircuitOp callCircuitOp, FuncOp funcOp); + mlir::quir::CallCircuitOp callCircuitOp, + mlir::func::FuncOp funcOp); void loadPulseCals(mlir::quir::Builtin_UOp UOp, - mlir::quir::CallCircuitOp callCircuitOp, FuncOp funcOp); + mlir::quir::CallCircuitOp callCircuitOp, + mlir::func::FuncOp funcOp); void loadPulseCals(mlir::quir::MeasureOp measureOp, - mlir::quir::CallCircuitOp callCircuitOp, FuncOp funcOp); + mlir::quir::CallCircuitOp callCircuitOp, + mlir::func::FuncOp funcOp); void loadPulseCals(mlir::quir::BarrierOp barrierOp, - mlir::quir::CallCircuitOp callCircuitOp, FuncOp funcOp); + mlir::quir::CallCircuitOp callCircuitOp, + mlir::func::FuncOp funcOp); void loadPulseCals(mlir::quir::DelayOp delayOp, - mlir::quir::CallCircuitOp callCircuitOp, FuncOp funcOp); + mlir::quir::CallCircuitOp callCircuitOp, + mlir::func::FuncOp funcOp); void loadPulseCals(mlir::quir::ResetQubitOp resetOp, - mlir::quir::CallCircuitOp callCircuitOp, FuncOp funcOp); + mlir::quir::CallCircuitOp callCircuitOp, + mlir::func::FuncOp funcOp); - void addPulseCalToModule(FuncOp funcOp, mlir::pulse::SequenceOp sequenceOp); + void addPulseCalToModule(mlir::func::FuncOp funcOp, + mlir::pulse::SequenceOp sequenceOp); // parse the pulse cals and return the parsed module llvm::Error parsePulseCalsModuleOp(std::string &pulseCalsPath, diff --git a/include/Conversion/QUIRToPulse/QUIRToPulse.h b/include/Conversion/QUIRToPulse/QUIRToPulse.h index c2cc88018..cdaba06c9 100644 --- a/include/Conversion/QUIRToPulse/QUIRToPulse.h +++ b/include/Conversion/QUIRToPulse/QUIRToPulse.h @@ -62,7 +62,8 @@ struct QUIRToPulsePass // convert quir circuit to pulse sequence void convertCircuitToSequence(mlir::quir::CallCircuitOp callCircuitOp, - FuncOp &mainFunc, ModuleOp moduleOp); + mlir::func::FuncOp &mainFunc, + ModuleOp moduleOp); // helper datastructure for converting quir circuit to pulse sequence; these // will be reset every time convertCircuitToSequence is called and will be // used by several functions that are called within that function @@ -75,7 +76,8 @@ struct QUIRToPulsePass // converted pulse sequence op void processCircuitArgs(mlir::quir::CallCircuitOp callCircuitOp, mlir::quir::CircuitOp circuitOp, - SequenceOp convertedPulseSequenceOp, FuncOp &mainFunc, + SequenceOp convertedPulseSequenceOp, + mlir::func::FuncOp &mainFunc, mlir::OpBuilder &builder); // process the args of the pulse cal sequence op corresponding to quirOp @@ -83,7 +85,8 @@ struct QUIRToPulsePass SequenceOp pulseCalSequenceOp, SmallVector &pulseCalSeqArgs, SequenceOp convertedPulseSequenceOp, - FuncOp &mainFunc, mlir::OpBuilder &builder); + mlir::func::FuncOp &mainFunc, + mlir::OpBuilder &builder); void getQUIROpClassicalOperands(mlir::Operation *quirOp, std::queue &angleOperands, std::queue &durationOperands); @@ -91,17 +94,17 @@ struct QUIRToPulsePass std::string const &portName, SequenceOp convertedPulseSequenceOp, SmallVector &quirOpPulseCalSeqArgs, - Value argumentValue, FuncOp &mainFunc, + Value argumentValue, mlir::func::FuncOp &mainFunc, mlir::OpBuilder &builder); void processPortOpArg(std::string const &portName, SequenceOp convertedPulseSequenceOp, SmallVector &quirOpPulseCalSeqArgs, - Value argumentValue, FuncOp &mainFunc, + Value argumentValue, mlir::func::FuncOp &mainFunc, mlir::OpBuilder &builder); void processWfrOpArg(std::string const &wfrName, SequenceOp convertedPulseSequenceOp, SmallVector &quirOpPulseCalSeqArgs, - Value argumentValue, FuncOp &mainFunc, + Value argumentValue, mlir::func::FuncOp &mainFunc, mlir::OpBuilder &builder); void processAngleArg(Value nextAngleOperand, SequenceOp convertedPulseSequenceOp, @@ -117,7 +120,8 @@ struct QUIRToPulsePass // convert duration to I64 mlir::Value convertDurationToI64(mlir::quir::CallCircuitOp callCircuitOp, Operation *durOp, uint &cnt, - mlir::OpBuilder &builder, FuncOp &mainFunc); + mlir::OpBuilder &builder, + mlir::func::FuncOp &mainFunc); // map of the hashed location of quir angle/duration ops to their converted // pulse ops std::map classicalQUIROpLocToConvertedPulseOpMap; @@ -130,17 +134,17 @@ struct QUIRToPulsePass std::map openedWfrs; // add a port to IR if it's not already added and return the Port_CreateOp mlir::pulse::Port_CreateOp addPortOpToIR(std::string const &portName, - FuncOp &mainFunc, + mlir::func::FuncOp &mainFunc, mlir::OpBuilder &builder); // add a mixframe to IR if it's not already added and return the MixFrameOp mlir::pulse::MixFrameOp addMixFrameOpToIR(std::string const &mixFrameName, std::string const &portName, - FuncOp &mainFunc, + mlir::func::FuncOp &mainFunc, mlir::OpBuilder &builder); // add a waveform to IR if it's not already added and return the // Waveform_CreateOp mlir::pulse::Waveform_CreateOp addWfrOpToIR(std::string const &wfrName, - FuncOp &mainFunc, + mlir::func::FuncOp &mainFunc, mlir::OpBuilder &builder); void addCircuitToEraseList(mlir::Operation *op); diff --git a/include/Conversion/QUIRToStandard/TypeConversion.h b/include/Conversion/QUIRToStandard/TypeConversion.h index a654e1ed9..716ea577c 100644 --- a/include/Conversion/QUIRToStandard/TypeConversion.h +++ b/include/Conversion/QUIRToStandard/TypeConversion.h @@ -33,12 +33,12 @@ struct QuirTypeConverter : public TypeConverter { QuirTypeConverter(); - static Optional convertAngleType(Type t); // convertAngleType + static std::optional convertAngleType(Type t); // convertAngleType - static Optional angleSourceMaterialization(OpBuilder &builder, - quir::AngleType aType, - ValueRange valRange, - Location loc); + static std::optional angleSourceMaterialization(OpBuilder &builder, + quir::AngleType aType, + ValueRange valRange, + Location loc); }; // struct QuirTypeConverter diff --git a/include/Dialect/OQ3/IR/CMakeLists.txt b/include/Dialect/OQ3/IR/CMakeLists.txt index 1eeac7b8f..62057408d 100644 --- a/include/Dialect/OQ3/IR/CMakeLists.txt +++ b/include/Dialect/OQ3/IR/CMakeLists.txt @@ -5,7 +5,7 @@ # that they have been altered from the originals. add_mlir_dialect(OQ3Ops oq3) -qssc_add_mlir_doc(OQ3Ops OQ3Ops generated/Dialect/OQ3/ -gen-dialect-doc) +add_mlir_doc(OQ3Ops OQ3Ops generated/Dialect/OQ3/ -gen-dialect-doc -dialect=oq3) set(LLVM_TARGET_DEFINITIONS OQ3Dialect.td) diff --git a/include/Dialect/OQ3/IR/OQ3AngleOps.td b/include/Dialect/OQ3/IR/OQ3AngleOps.td index fa0243624..8bc025231 100644 --- a/include/Dialect/OQ3/IR/OQ3AngleOps.td +++ b/include/Dialect/OQ3/IR/OQ3AngleOps.td @@ -34,14 +34,7 @@ class OQ3_BinaryCmpOp traits = []> : attr-dict $lhs `,` $rhs `:` type($lhs) `->` type($result) }]; - let verifier = [{ - std::vector predicates = { "eq", "ne", "slt", "sle", "sgt", "sge", "ult", "ule", "ugt", "uge" }; - - if (std::find(predicates.begin(), predicates.end(), this->predicate()) != predicates.end()) - return success(); - else - return emitOpError("requires predicate \"eq\", \"ne\", \"slt\", \"sle\", \"sgt\", \"sge\", \"ult\", \"ule\", \"ugt\", \"uge\""); - }]; + let hasVerifier = 1; } // ----- diff --git a/include/Dialect/OQ3/IR/OQ3ArithmeticOps.td b/include/Dialect/OQ3/IR/OQ3ArithmeticOps.td index 232452914..f7c6b6afa 100644 --- a/include/Dialect/OQ3/IR/OQ3ArithmeticOps.td +++ b/include/Dialect/OQ3/IR/OQ3ArithmeticOps.td @@ -25,7 +25,7 @@ class OQ3_ArithmeticUnaryOp traits = []> : class OQ3_ArithmeticBinaryOp traits = []> : OQ3_BinaryOp { + [Pure, SameOperandsAndResultType])> { let arguments = (ins AnyClassical:$lhs, AnyClassical:$rhs); let results = (outs AnyClassical:$result); let assemblyFormat = [{ diff --git a/include/Dialect/OQ3/IR/OQ3ArrayOps.td b/include/Dialect/OQ3/IR/OQ3ArrayOps.td index 22ed2fda0..095ae48d3 100644 --- a/include/Dialect/OQ3/IR/OQ3ArrayOps.td +++ b/include/Dialect/OQ3/IR/OQ3ArrayOps.td @@ -41,13 +41,7 @@ def OQ3_DeclareArrayOp : OQ3_Op<"declare_array", [Symbol]> { attr-dict $sym_name `:` $type `[` $num_elements `]` }]; - let verifier = [{ - auto t = (*this).type(); - - if( t.isa<::mlir::quir::AngleType>() || t.isa<::mlir::quir::CBitType>() || t.isa<::mlir::quir::DurationType>() || t.isa<::mlir::quir::StretchType>() || t.isIntOrIndexOrFloat()) - return success(); - return failure(); - }]; + let hasVerifier = 1; } // ----- @@ -72,8 +66,6 @@ def OQ3_AssignArrayElementOp : OQ3_Op<"assign_array_element", let assemblyFormat = [{ attr-dict $variable_name `[` $index `]` `:` type($assigned_value) `=` $assigned_value }]; - // op is verified by its traits - let verifier = ?; } // ----- @@ -103,8 +95,6 @@ def OQ3_UseArrayElementOp : OQ3_Op<"use_array_element", let assemblyFormat = [{ $variable_name `[` $index `]` `:` type($res) attr-dict }]; - // op is verified by its traits - let verifier = ?; } #endif // OQ3_ARRAY_OPS diff --git a/include/Dialect/OQ3/IR/OQ3Base.td b/include/Dialect/OQ3/IR/OQ3Base.td index 8b887b86a..ec1ad8120 100644 --- a/include/Dialect/OQ3/IR/OQ3Base.td +++ b/include/Dialect/OQ3/IR/OQ3Base.td @@ -16,6 +16,7 @@ #ifndef OQ3_BASE_H #define OQ3_BASE_H +include "mlir/IR/AttrTypeBase.td" include "mlir/Interfaces/SideEffectInterfaces.td" //===----------------------------------------------------------------------===// @@ -31,7 +32,7 @@ def OQ3_Dialect : Dialect { }]; let cppNamespace = "::mlir::oq3"; let dependentDialects = [ - "mlir::arith::ArithmeticDialect", + "mlir::arith::ArithDialect", "mlir::LLVM::LLVMDialect" ]; } @@ -44,24 +45,18 @@ class OQ3_Op traits = []> : Op; class OQ3_UnaryOp traits = []> : - OQ3_Op { + OQ3_Op { let arguments = (ins AnyClassical:$operand); let results = (outs AnyClassical:$result); - let verifier = [{ return success(); }]; - // In LLVM 15+, - // let hasVerifier = 0; } class OQ3_BinaryOp traits = []> : - OQ3_Op { + OQ3_Op { let arguments = (ins AnyClassical:$operand1, AnyClassical:$operand2); let results = (outs AnyClassical:$result); let assemblyFormat = [{ attr-dict $lhs `,` $rhs `:` `(` type($lhs) `,` type($rhs) `)` `->` type($result) }]; - let verifier = [{ return success(); }]; - // In LLVM 15+, - // let hasVerifier = 0; } //===----------------------------------------------------------------------===// diff --git a/include/Dialect/OQ3/IR/OQ3CBitOps.td b/include/Dialect/OQ3/IR/OQ3CBitOps.td index 0a80c2a64..0cbac0493 100644 --- a/include/Dialect/OQ3/IR/OQ3CBitOps.td +++ b/include/Dialect/OQ3/IR/OQ3CBitOps.td @@ -64,8 +64,6 @@ def OQ3_CBitAssignBitOp : OQ3_Op<"cbit_assign_bit", let assemblyFormat = [{ attr-dict $variable_name `<` $cbit_width `>` `[` $index `]` `:` type($assigned_bit) `=` $assigned_bit }]; - // op is verified by its traits - let verifier = ?; } // ----- @@ -180,7 +178,7 @@ def OQ3_CBitLShiftOp : OQ3_BinaryOp<"cbit_lshift"> { // ----- -def OQ3_CBitExtractBitOp : OQ3_Op<"cbit_extractbit", [NoSideEffect]> { +def OQ3_CBitExtractBitOp : OQ3_Op<"cbit_extractbit", [Pure]> { let summary = "extract single bit from a bitmap"; let description = [{ The `oq3.cbit_extractbit` operations takes a bitmap operand (cbit or @@ -205,14 +203,13 @@ def OQ3_CBitExtractBitOp : OQ3_Op<"cbit_extractbit", [NoSideEffect]> { let hasFolder = 1; - // TODO in LLVM 15 + this can become just let hasVerifier = 1; - let verifier = [{ return ::verify(*this);}]; + let hasVerifier = 1; } // ----- def OQ3_CBitInsertBitOp : OQ3_Op<"cbit_insertbit", [ - NoSideEffect, + Pure, TypesMatchWith< "first operand and result have the same type", "operand", "result", "$_self">]> { diff --git a/include/Dialect/OQ3/IR/OQ3CastOps.td b/include/Dialect/OQ3/IR/OQ3CastOps.td index 742424d86..40f2d4052 100644 --- a/include/Dialect/OQ3/IR/OQ3CastOps.td +++ b/include/Dialect/OQ3/IR/OQ3CastOps.td @@ -15,7 +15,7 @@ #ifndef OQ3_CAST_OPS #define OQ3_CAST_OPS -def OQ3_CastOp : OQ3_Op<"cast", [NoSideEffect]> { +def OQ3_CastOp : OQ3_Op<"cast", [Pure]> { let summary = "Cast between classical types"; let description = [{ The `oq3.cast` operation represents a cast between different classical types, including non-OQ3 types. diff --git a/include/Dialect/OQ3/IR/OQ3Dialect.h b/include/Dialect/OQ3/IR/OQ3Dialect.h index c13a6d770..99b85d859 100644 --- a/include/Dialect/OQ3/IR/OQ3Dialect.h +++ b/include/Dialect/OQ3/IR/OQ3Dialect.h @@ -15,9 +15,9 @@ #ifndef DIALECT_OQ3_OQ3DIALECT_H_ #define DIALECT_OQ3_OQ3DIALECT_H_ -#include "mlir/Dialect/Arithmetic/IR/Arithmetic.h" +#include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" -#include "mlir/Dialect/SCF/SCF.h" +#include "mlir/Dialect/SCF/IR/SCF.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/Dialect.h" diff --git a/include/Dialect/OQ3/IR/OQ3GateOps.td b/include/Dialect/OQ3/IR/OQ3GateOps.td index b779f0828..29c671fb6 100644 --- a/include/Dialect/OQ3/IR/OQ3GateOps.td +++ b/include/Dialect/OQ3/IR/OQ3GateOps.td @@ -19,7 +19,7 @@ // Stretch ops //===----------------------------------------------------------------------===// -def OQ3_DeclareStretchOp : OQ3_Op<"declare_stretch", [NoSideEffect]> { +def OQ3_DeclareStretchOp : OQ3_Op<"declare_stretch", [Pure]> { let summary = "Declare a new stretch."; let description = [{ The `oq3.declare_stretch` operation creates a new QUIR `Stretch` type, representing an unknown duration of time. diff --git a/include/Dialect/OQ3/IR/OQ3Patterns.td b/include/Dialect/OQ3/IR/OQ3Patterns.td index ec7ab8d56..74f3ea5d0 100644 --- a/include/Dialect/OQ3/IR/OQ3Patterns.td +++ b/include/Dialect/OQ3/IR/OQ3Patterns.td @@ -16,7 +16,8 @@ #ifndef OQ3_PATTERNS #define OQ3_PATTERNS -include "mlir/Dialect/StandardOps/IR/Ops.td" +include "mlir/IR/BuiltinOps.td" +include "mlir/IR/PatternBase.td" include "Dialect/OQ3/IR/OQ3Ops.td" def CBitNotNotPat : Pat< diff --git a/include/Dialect/OQ3/IR/OQ3VariableOps.td b/include/Dialect/OQ3/IR/OQ3VariableOps.td index c10dc3305..a7da88ad5 100644 --- a/include/Dialect/OQ3/IR/OQ3VariableOps.td +++ b/include/Dialect/OQ3/IR/OQ3VariableOps.td @@ -53,21 +53,11 @@ def OQ3_DeclareVariableOp : OQ3_Op<"declare_variable", [Symbol]> { }]> ]; - let verifier = [{ - auto t = (*this).type(); - - if( t.isa<::mlir::quir::AngleType>() || t.isa<::mlir::quir::CBitType>() || t.isa<::mlir::quir::DurationType>() || t.isa<::mlir::quir::StretchType>() || t.isIntOrIndexOrFloat() || t.isa()) - return success(); - std::string str; - llvm::raw_string_ostream os(str); - t.print(os); - - return emitOpError("MLIR type " + str + " not supported for declarations."); - }]; + let hasVerifier = 1; let extraClassDeclaration = [{ - bool isInputVariable() { return input(); } - bool isOutputVariable() { return output(); } + bool isInputVariable() { return getInput(); } + bool isOutputVariable() { return getOutput(); } }]; } @@ -91,8 +81,6 @@ def OQ3_VariableAssignOp : OQ3_Op<"variable_assign", let assemblyFormat = [{ attr-dict $variable_name `:` type($assigned_value) `=` $assigned_value }]; - // op is verified by its traits - let verifier = ?; } // ----- @@ -121,8 +109,6 @@ def OQ3_VariableLoadOp : OQ3_Op<"variable_load", let assemblyFormat = [{ $variable_name `:` type($res) attr-dict }]; - // op is verified by its traits - let verifier = ?; } #endif // OQ3_VARIABLE_OPS diff --git a/include/Dialect/Pulse/IR/CMakeLists.txt b/include/Dialect/Pulse/IR/CMakeLists.txt index 1d730b7b5..c5efa6006 100644 --- a/include/Dialect/Pulse/IR/CMakeLists.txt +++ b/include/Dialect/Pulse/IR/CMakeLists.txt @@ -11,6 +11,10 @@ # that they have been altered from the originals. add_mlir_dialect(Pulse pulse) -qssc_add_mlir_doc(Pulse PulseDialect generated/Dialect/Pulse/ -gen-dialect-doc) +add_mlir_doc(Pulse PulseDialect generated/Dialect/Pulse/ -gen-dialect-doc -dialect=pulse) + +set(LLVM_TARGET_DEFINITIONS Pulse.td) +mlir_tablegen(PulseAttributes.h.inc -gen-attrdef-decls -attrdefs-dialect=pulse) +mlir_tablegen(PulseAttributes.cpp.inc -gen-attrdef-defs -attrdefs-dialect=pulse) add_mlir_interface(PulseInterfaces) diff --git a/include/Dialect/Pulse/IR/PulseAttributes.h b/include/Dialect/Pulse/IR/PulseAttributes.h new file mode 100644 index 000000000..f27b7655d --- /dev/null +++ b/include/Dialect/Pulse/IR/PulseAttributes.h @@ -0,0 +1,32 @@ +//===- PulseAttributes.h - Pulse dialect attributes -------------*- C++ -*-===// +// +// (C) Copyright IBM 2023. +// +// This code is part of Qiskit. +// +// This code is licensed under the Apache License, Version 2.0 with LLVM +// Exceptions. You may obtain a copy of this license in the LICENSE.txt +// file in the root directory of this source tree. +// +// Any modifications or derivative works of this code must retain this +// copyright notice, and modified files need to carry a notice indicating +// that they have been altered from the originals. +// +//===----------------------------------------------------------------------===// +/// +/// Attributes for the Pulse dialect +/// +//===----------------------------------------------------------------------===// + +#ifndef PULSE_PULSEATTRIBUTES_H +#define PULSE_PULSEATTRIBUTES_H + +#include "mlir/IR/Attributes.h" +#include "mlir/IR/DialectImplementation.h" + +namespace mlir::quir {} // namespace mlir::quir + +#define GET_ATTRDEF_CLASSES +#include "Dialect/Pulse/IR/PulseAttributes.h.inc" + +#endif // PULSE_PULSEATTRIBUTES_H diff --git a/include/Dialect/Pulse/IR/PulseAttributes.td b/include/Dialect/Pulse/IR/PulseAttributes.td new file mode 100644 index 000000000..cc21421df --- /dev/null +++ b/include/Dialect/Pulse/IR/PulseAttributes.td @@ -0,0 +1,25 @@ +//===- PulseAttributes.td - Pulse dialect attributes -------*- tablegen -*-===// +// +// (C) Copyright IBM 2023. +// +// This code is part of Qiskit. +// +// This code is licensed under the Apache License, Version 2.0 with LLVM +// Exceptions. You may obtain a copy of this license in the LICENSE.txt +// file in the root directory of this source tree. +// +// Any modifications or derivative works of this code must retain this +// copyright notice, and modified files need to carry a notice indicating +// that they have been altered from the originals. +// +//===----------------------------------------------------------------------===// + + +#ifndef PULSE_ATTRIBUTES +#define PULSE_ATTRIBUTES + + +include "mlir/IR/BuiltinAttributes.td" +include "mlir/IR/OpBase.td" + +#endif // PULSE_ATTRIBUTES diff --git a/include/Dialect/Pulse/IR/PulseDialect.td b/include/Dialect/Pulse/IR/PulseDialect.td index e4b56fb91..6843b7cda 100644 --- a/include/Dialect/Pulse/IR/PulseDialect.td +++ b/include/Dialect/Pulse/IR/PulseDialect.td @@ -17,8 +17,10 @@ #ifndef PULSE_DIALECT #define PULSE_DIALECT +include "mlir/IR/AttrTypeBase.td" include "mlir/IR/OpBase.td" + //===----------------------------------------------------------------------===// // Pulse dialect definition. //===----------------------------------------------------------------------===// @@ -32,6 +34,11 @@ def PulseDialect : Dialect { representation of QUIR gates. }]; let cppNamespace = "::mlir::pulse"; + + // TODO: Uncomment when attributes are added + // that require a default printer parser + //let useDefaultAttributePrinterParser = 1; + let useDefaultTypePrinterParser = 1; } //===----------------------------------------------------------------------===// @@ -41,6 +48,15 @@ def PulseDialect : Dialect { class Pulse_Op traits = []> : Op; +//===----------------------------------------------------------------------===// +// Base Pulse attribute definition. +//===----------------------------------------------------------------------===// + +class Pulse_Attr traits = []> + : AttrDef { + let mnemonic = attrMnemonic; +} + include "PulseTypes.td" include "PulseOps.td" diff --git a/include/Dialect/Pulse/IR/PulseInterfaces.h b/include/Dialect/Pulse/IR/PulseInterfaces.h index 9d007ad65..c0716ab5e 100644 --- a/include/Dialect/Pulse/IR/PulseInterfaces.h +++ b/include/Dialect/Pulse/IR/PulseInterfaces.h @@ -21,7 +21,7 @@ #ifndef PULSE_INTERFACES_H #define PULSE_INTERFACES_H -#include "mlir/Dialect/Arithmetic/IR/Arithmetic.h" +#include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/IR/OpDefinition.h" #include "llvm/Support/Error.h" @@ -36,9 +36,9 @@ namespace mlir::pulse::interfaces_impl { // PulseOpSchedulingInterface //===----------------------------------------------------------------------===// -llvm::Optional getTimepoint(mlir::Operation *op); +std::optional getTimepoint(mlir::Operation *op); void setTimepoint(mlir::Operation *op, int64_t timepoint); -llvm::Optional getSetupLatency(mlir::Operation *op); +std::optional getSetupLatency(mlir::Operation *op); void setSetupLatency(mlir::Operation *op, uint64_t setupLatency); llvm::Expected getDuration(mlir::Operation *op, mlir::Operation *callSequenceOp = nullptr); diff --git a/include/Dialect/Pulse/IR/PulseInterfaces.td b/include/Dialect/Pulse/IR/PulseInterfaces.td index 50c321054..c06a9e0e3 100644 --- a/include/Dialect/Pulse/IR/PulseInterfaces.td +++ b/include/Dialect/Pulse/IR/PulseInterfaces.td @@ -36,7 +36,7 @@ def PulseOpSchedulingInterface : OpInterface<"PulseOpSchedulingInterface"> { let methods = [ InterfaceMethod< /*desc=*/"Get the timpoint that a pulse operation becomes effective", - /*retTy=*/"::llvm::Optional", + /*retTy=*/"::std::optional", /*methodName=*/"getTimepoint", /*args=*/(ins), /*methodBody=*/[{}], @@ -58,7 +58,7 @@ def PulseOpSchedulingInterface : OpInterface<"PulseOpSchedulingInterface"> { >, InterfaceMethod< /*desc=*/"Get the setup latency of a pulse operation", - /*retTy=*/"::llvm::Optional", + /*retTy=*/"::std::optional", /*methodName=*/"getSetupLatency", /*args=*/(ins), /*methodBody=*/[{}], @@ -114,7 +114,7 @@ def PulseOpSchedulingInterface : OpInterface<"PulseOpSchedulingInterface"> { ]; let extraSharedClassDeclaration = [{ - static llvm::Optional getTimepoint(mlir::Operation *op) { + static std::optional getTimepoint(mlir::Operation *op) { return interfaces_impl::getTimepoint(op); } @@ -126,7 +126,7 @@ def PulseOpSchedulingInterface : OpInterface<"PulseOpSchedulingInterface"> { return interfaces_impl::setTimepoint(op, timepoint); } - static llvm::Optional getSetupLatency(mlir::Operation *op) { + static std::optional getSetupLatency(mlir::Operation *op) { return interfaces_impl::getSetupLatency(op); } @@ -147,7 +147,7 @@ def PulseOpSchedulingInterface : OpInterface<"PulseOpSchedulingInterface"> { static llvm::Expected getDuration(Operation *op) { auto castOp = dyn_cast(op); auto durDeclOp = dyn_cast_or_null( - castOp.dur().getDefiningOp()); + castOp.getDur().getDefiningOp()); if (durDeclOp) { if (durDeclOp.value() < 0) return llvm::createStringError(llvm::inconvertibleErrorCode(), diff --git a/include/Dialect/Pulse/IR/PulseOps.h b/include/Dialect/Pulse/IR/PulseOps.h index 231399b01..0b5fc6ee8 100644 --- a/include/Dialect/Pulse/IR/PulseOps.h +++ b/include/Dialect/Pulse/IR/PulseOps.h @@ -17,18 +17,21 @@ #ifndef PULSE_PULSEOPS_H #define PULSE_PULSEOPS_H +#include "Dialect/Pulse/IR/PulseAttributes.h" #include "Dialect/Pulse/IR/PulseInterfaces.h" #include "Dialect/Pulse/IR/PulseTraits.h" #include "Dialect/Pulse/IR/PulseTypes.h" #include "Dialect/QUIR/IR/QUIROps.h" #include "Dialect/QUIR/IR/QUIRTypes.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" #include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinOps.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/Dialect.h" #include "mlir/IR/DialectImplementation.h" +#include "mlir/IR/FunctionInterfaces.h" #include "mlir/IR/OpDefinition.h" +#include "mlir/Interfaces/CallInterfaces.h" #include "mlir/Interfaces/InferTypeOpInterface.h" #include "mlir/Interfaces/SideEffectInterfaces.h" diff --git a/include/Dialect/Pulse/IR/PulseOps.td b/include/Dialect/Pulse/IR/PulseOps.td index 8cd020c3e..d28d6f449 100644 --- a/include/Dialect/Pulse/IR/PulseOps.td +++ b/include/Dialect/Pulse/IR/PulseOps.td @@ -33,7 +33,7 @@ include "mlir/IR/OpBase.td" include "mlir/IR/SymbolInterfaces.td" -def Pulse_GaussianOp : Pulse_Op<"gaussian", [NoSideEffect, SequenceAllowed]> { +def Pulse_GaussianOp : Pulse_Op<"gaussian", [Pure, SequenceAllowed]> { let summary = "Create a Gaussian waveform."; let description = [{ The `pulse.gaussian` operation creates a Gaussian waveform. @@ -51,16 +51,11 @@ def Pulse_GaussianOp : Pulse_Op<"gaussian", [NoSideEffect, SequenceAllowed]> { attr-dict `(` $dur `,` $amp `,` $sigma `)` `:` `(` type($dur) `,` type($amp) `,` type($sigma) `)` `->` type($wfr) }]; - let verifier = [{ - auto durDeclOp = dyn_cast_or_null((*this).dur().getDefiningOp()); - if (durDeclOp && durDeclOp.value() < 0) - return emitOpError("duration must be >= 0."); - return success(); - }]; + let hasVerifier = 1; } -def Pulse_GaussianSquareOp : Pulse_Op<"gaussian_square", [NoSideEffect, SequenceAllowed]> { +def Pulse_GaussianSquareOp : Pulse_Op<"gaussian_square", [Pure, SequenceAllowed]> { let summary = "Create a Gaussian Square waveform."; let description = [{ The `pulse.gaussian_square` operation creates a Gaussian Square waveform. It is a Gaussian @@ -81,15 +76,11 @@ def Pulse_GaussianSquareOp : Pulse_Op<"gaussian_square", [NoSideEffect, Sequence attr-dict `(` $dur `,` $amp `,` $sigma `,` $width `)` `:` `(` type($dur) `,` type($amp) `,` type($sigma) `,` type($width) `)` `->` type($wfr) }]; - let verifier = [{ - auto durDeclOp = dyn_cast_or_null((*this).dur().getDefiningOp()); - if (durDeclOp && durDeclOp.value() < 0) - return emitOpError("duration must be >= 0."); - return success(); - }]; + let hasVerifier = 1; + } -def Pulse_DragOp : Pulse_Op<"drag", [NoSideEffect, SequenceAllowed]> { +def Pulse_DragOp : Pulse_Op<"drag", [Pure, SequenceAllowed]> { let summary = "Create a Drag waveform."; let description = [{ The `pulse.drag` operation creates a DRAG waveform. The DRAG waveform is composed of a @@ -111,15 +102,10 @@ def Pulse_DragOp : Pulse_Op<"drag", [NoSideEffect, SequenceAllowed]> { attr-dict `(` $dur `,` $amp `,` $sigma `,` $beta `)` `:` `(` type($dur) `,` type($amp) `,` type($sigma) `,` type($beta) `)` `->` type($wfr) }]; - let verifier = [{ - auto durDeclOp = dyn_cast_or_null((*this).dur().getDefiningOp()); - if (durDeclOp && durDeclOp.value() < 0) - return emitOpError("duration must be >= 0."); - return success(); - }]; + let hasVerifier = 1; } -def Pulse_ConstOp : Pulse_Op<"const_waveform", [NoSideEffect, SequenceAllowed]> { +def Pulse_ConstOp : Pulse_Op<"const_waveform", [Pure, SequenceAllowed]> { let summary = "Create a Constant waveform."; let description = [{ The `pulse.const_waveform` operation creates a constant waveform. This is a flat top waveform @@ -139,15 +125,10 @@ def Pulse_ConstOp : Pulse_Op<"const_waveform", [NoSideEffect, SequenceAllowed]> attr-dict `(` $dur `,` $amp `)` `:` `(` type($dur) `,` type($amp) `)` `->` type($wfr) }]; - let verifier = [{ - auto durDeclOp = dyn_cast_or_null((*this).dur().getDefiningOp()); - if (durDeclOp && durDeclOp.value() < 0) - return emitOpError("duration must be >= 0."); - return success(); - }]; + let hasVerifier = 1; } -def Pulse_Waveform_CreateOp : Pulse_Op<"create_waveform", [NoSideEffect, SequenceAllowed, +def Pulse_Waveform_CreateOp : Pulse_Op<"create_waveform", [Pure, SequenceAllowed, DeclareOpInterfaceMethods]> { let summary = "Creates a pulse waveform from a list of complex numbers."; let description = [{ @@ -168,11 +149,10 @@ def Pulse_Waveform_CreateOp : Pulse_Op<"create_waveform", [NoSideEffect, Sequenc attr-dict $samples `->` type($wfr) }]; - // TODO in LLVM 15 + this can become just let hasVerifier = 1; - let verifier = [{ return ::mlir::pulse::verify(*this); }]; + let hasVerifier = 1; } -def Pulse_WaveformContainerOp : Pulse_Op<"waveform_container", [NoSideEffect, NoTerminator]> { +def Pulse_WaveformContainerOp : Pulse_Op<"waveform_container", [Pure, NoTerminator]> { let summary = "Creates a container for pulse waveforms."; let description = [{ The `pulse.waveform_container` is a container for `pulse.create_waveform` operations. All the `pulse.create_waveform` @@ -191,13 +171,13 @@ def Pulse_WaveformContainerOp : Pulse_Op<"waveform_container", [NoSideEffect, No let regions = (region AnyRegion:$body); let assemblyFormat = [{ - attr-dict $body + attr-dict-with-keyword $body }]; - let verifier = [{ return ::mlir::pulse::verify(*this); }]; + let hasVerifier = 1; } -def Pulse_Frame_CreateOp : Pulse_Op<"create_frame", [NoSideEffect, SequenceAllowed, SameVariadicOperandSize]> { +def Pulse_Frame_CreateOp : Pulse_Op<"create_frame", [Pure, SequenceAllowed, SameVariadicOperandSize]> { let summary = "Creates a frame with a frequency and a phase."; let description = [{ The `pulse.frame` operation creates a frame with optional arguments to initialize amplitude, frequency, and phase. One can also @@ -214,7 +194,7 @@ def Pulse_Frame_CreateOp : Pulse_Op<"create_frame", [NoSideEffect, SequenceAllow let results = (outs Pulse_FrameType:$out); } -def Pulse_Port_CreateOp : Pulse_Op<"create_port", [NoSideEffect]> { +def Pulse_Port_CreateOp : Pulse_Op<"create_port", [Pure]> { let summary = "Creates a port for stimulus pulses or acquiring measurement output."; let description = [{ The `pulse.create_port` operation creates a port which acts as a host for @@ -227,7 +207,7 @@ def Pulse_Port_CreateOp : Pulse_Op<"create_port", [NoSideEffect]> { Example: ```mlir - %port = pulse.port() {uid = "a unique identifier"} : () -> !pulse.port + %port = pulse.getPort() {uid = "a unique identifier"} : () -> !pulse.port ``` }]; @@ -235,7 +215,7 @@ def Pulse_Port_CreateOp : Pulse_Op<"create_port", [NoSideEffect]> { let results = (outs Pulse_PortType:$out); } -def Pulse_MixFrameOp : Pulse_Op<"mix_frame", [NoSideEffect, SequenceAllowed, SameVariadicOperandSize]> { +def Pulse_MixFrameOp : Pulse_Op<"mix_frame", [Pure, SequenceAllowed, SameVariadicOperandSize]> { let summary = "Mixes a frame with a port."; let description = [{ The `pulse.mix_frame` operation creates a frame mixed with a port, with optional arguments to initialize amplitude, frequency, and phase. One can also @@ -256,7 +236,7 @@ def Pulse_MixFrameOp : Pulse_Op<"mix_frame", [NoSideEffect, SequenceAllowed, Sam let results = (outs Pulse_MixedFrameType:$out); } -def Pulse_Kernel_CreateOp : Pulse_Op<"create_kernel", [NoSideEffect, SequenceAllowed]> { +def Pulse_Kernel_CreateOp : Pulse_Op<"create_kernel", [Pure, SequenceAllowed]> { let summary = "Creates a kernel which defines the integration window."; let description = [{ The `pulse.create_kernel` operation creates a kernel which defines @@ -315,11 +295,7 @@ def Pulse_PlayOp : Pulse_Op<"play", [SequenceRequired, HasTargetFrame, llvm::Expected getWaveformHash(CallSequenceOp callOp); }]; - let verifier = [{ - if (!(*this).target().isa()) - return emitOpError("Target is not a block argument; Target needs to be an argument of pulse.sequence"); - return success(); - }]; + let hasVerifier = 1; } def Pulse_SetFrequencyOp : Pulse_Op<"set_frequency", [SequenceRequired, HasTargetFrame]> { @@ -345,19 +321,15 @@ def Pulse_SetFrequencyOp : Pulse_Op<"set_frequency", [SequenceRequired, HasTarge }]; let extraClassDeclaration = [{ - double getFreq() { + double getFreqFromDefiningOp() { // get op that defines frequency and return its value - auto freqConstOp = dyn_cast((*this).frequency().getDefiningOp()); + auto freqConstOp = dyn_cast((*this).getFrequency().getDefiningOp()); assert (freqConstOp && "assume frequency to be defined by ConstantFloatOp"); return freqConstOp.value().convertToDouble(); } }]; - let verifier = [{ - if (!(*this).target().isa()) - return emitOpError("Target is not a block argument; Target needs to be an argument of pulse.sequence"); - return success(); - }]; + let hasVerifier = 1; } def Pulse_ShiftFrequencyOp : Pulse_Op<"shift_frequency", [SequenceRequired, HasTargetFrame]> { @@ -383,19 +355,15 @@ def Pulse_ShiftFrequencyOp : Pulse_Op<"shift_frequency", [SequenceRequired, HasT }]; let extraClassDeclaration = [{ - double getFreqOffset() { + double getFreqOffsetFromDefiningOp() { // get op that defines frequency offset and return its value - auto freqOffsetConstOp = dyn_cast((*this).frequencyOffset().getDefiningOp()); + auto freqOffsetConstOp = dyn_cast((*this).getFrequencyOffset().getDefiningOp()); assert (freqOffsetConstOp && "assume frequency offset to be defined by ConstantFloatOp"); return freqOffsetConstOp.value().convertToDouble(); } }]; - let verifier = [{ - if (!(*this).target().isa()) - return emitOpError("Target is not a block argument; Target needs to be an argument of pulse.sequence"); - return success(); - }]; + let hasVerifier = 1; } def Pulse_SetPhaseOp : Pulse_Op<"set_phase", [SequenceRequired, HasTargetFrame]> { @@ -421,19 +389,15 @@ def Pulse_SetPhaseOp : Pulse_Op<"set_phase", [SequenceRequired, HasTargetFrame]> }]; let extraClassDeclaration = [{ - double getPhase() { + double getPhaseFromDefiningOp() { // get op that defines phase and return its value - auto phaseConstOp = dyn_cast((*this).phase().getDefiningOp()); + auto phaseConstOp = dyn_cast((*this).getPhase().getDefiningOp()); assert (phaseConstOp && "assume phase to be defined by ConstantFloatOp"); return phaseConstOp.value().convertToDouble(); } }]; - let verifier = [{ - if (!(*this).target().isa()) - return emitOpError("Target is not a block argument; Target needs to be an argument of pulse.sequence"); - return success(); - }]; + let hasVerifier = 1; } def Pulse_ShiftPhaseOp : Pulse_Op<"shift_phase", [SequenceRequired, HasTargetFrame]> { @@ -459,19 +423,15 @@ def Pulse_ShiftPhaseOp : Pulse_Op<"shift_phase", [SequenceRequired, HasTargetFra }]; let extraClassDeclaration = [{ - double getPhaseOffset() { + double getPhaseFromDefiningOpOffset() { // get op that defines phase offset and return its value - auto phaseOffsetConstOp = dyn_cast((*this).phaseOffset().getDefiningOp()); + auto phaseOffsetConstOp = dyn_cast((*this).getPhaseOffset().getDefiningOp()); assert (phaseOffsetConstOp && "assume phase offset to be defined by ConstantFloatOp"); return phaseOffsetConstOp.value().convertToDouble(); } }]; - let verifier = [{ - if (!(*this).target().isa()) - return emitOpError("Target is not a block argument; Target needs to be an argument of pulse.sequence"); - return success(); - }]; + let hasVerifier = 1; } def Pulse_SetAmplitudeOp : Pulse_Op<"set_amplitude", [SequenceRequired, HasTargetFrame]> { @@ -494,19 +454,15 @@ let summary = "Set a scaling factor for pulses of a frame."; }]; let extraClassDeclaration = [{ - double getAmp() { + double getAmpFromDefiningOp() { // get op that defines amp and return its value - auto ampConstOp = dyn_cast((*this).amp().getDefiningOp()); + auto ampConstOp = dyn_cast((*this).getAmp().getDefiningOp()); assert (ampConstOp && "assume amplitude to be defined by ConstantFloatOp"); return ampConstOp.value().convertToDouble(); } }]; - let verifier = [{ - if (!(*this).target().isa()) - return emitOpError("Target is not a block argument; Target needs to be an argument of pulse.sequence"); - return success(); - }]; + let hasVerifier = 1; } def Pulse_CaptureOp : Pulse_Op<"capture", [SequenceRequired, HasTargetFrame]> { @@ -533,11 +489,7 @@ def Pulse_CaptureOp : Pulse_Op<"capture", [SequenceRequired, HasTargetFrame]> { attr-dict `(` $target `)` `:` `(` type($target) `)` `->` type($out) }]; - let verifier = [{ - if (!(*this).target().isa()) - return emitOpError("Target is not a block argument; Target needs to be an argument of pulse.sequence"); - return success(); - }]; + let hasVerifier = 1; } def Pulse_DelayOp : Pulse_Op<"delay", [SequenceAllowed, HasTargetFrame]> { @@ -563,19 +515,10 @@ def Pulse_DelayOp : Pulse_Op<"delay", [SequenceAllowed, HasTargetFrame]> { attr-dict `(` $target `,` $dur `)` `:` `(` type($target) `,` type($dur) `)` }]; - let verifier = [{ - auto durDeclOp = dyn_cast_or_null((*this).dur().getDefiningOp()); - if (durDeclOp && durDeclOp.value() < 0) - return emitOpError("duration must be >= 0."); - - if (!(*this).target().isa()) - return emitOpError("Target is not a block argument; Target needs to be an argument of pulse.sequence"); - - return success(); - }]; + let hasVerifier = 1; } -def Pulse_BarrierOp : Pulse_Op<"barrier", [NoSideEffect, SequenceAllowed]> { +def Pulse_BarrierOp : Pulse_Op<"barrier", [Pure, SequenceAllowed]> { let summary = "Add a barrier operation on a set of pulse frames."; let description = [{ The `pulse.barrier` operation synchronizes the timing of all frames. It does this by inserting @@ -669,7 +612,7 @@ def Pulse_CallSequenceOp : Pulse_Op<"call_sequence", [CallOpInterface, MemRefsNo OpBuilder<(ins "SequenceOp":$callee, CArg<"ValueRange", "{}">:$operands), [{ $_state.addOperands(operands); $_state.addAttribute("callee",SymbolRefAttr::get(callee)); - $_state.addTypes(callee.getType().getResults()); + $_state.addTypes(callee.getFunctionType().getResults()); }]>, OpBuilder<(ins "SymbolRefAttr":$callee, "TypeRange":$res, CArg<"ValueRange", "{}">:$operands), [{ @@ -684,19 +627,29 @@ def Pulse_CallSequenceOp : Pulse_Op<"call_sequence", [CallOpInterface, MemRefsNo }]>]; let extraClassDeclaration = [{ - StringRef getCallee() { return callee(); } FunctionType getCalleeType(); + /// Get the argument operands to the called function. operand_range getArgOperands() { return {arg_operand_begin(), arg_operand_end()}; } + MutableOperandRange getArgOperandsMutable() { + return getOperandsMutable(); + } + operand_iterator arg_operand_begin() { return operand_begin(); } operand_iterator arg_operand_end() { return operand_end(); } + /// Return the callee of this operation. CallInterfaceCallable getCallableForCallee() { return (*this)->getAttrOfType("callee"); } + + /// Set the callee for this operation. + void setCalleeFromCallable(CallInterfaceCallable callee) { + (*this)->setAttr("callee", callee.get()); + } }]; } @@ -769,15 +722,25 @@ def Pulse_SequenceOp : Pulse_Op<"sequence", [ }]; let arguments = (ins SymbolNameAttr:$sym_name, - TypeAttr:$type, - OptionalAttr:$sym_visibility); + TypeAttrOf:$function_type, + OptionalAttr:$sym_visibility, + OptionalAttr:$arg_attrs, + OptionalAttr:$res_attrs); let regions = (region AnyRegion:$body); let builders = [OpBuilder<(ins "StringRef":$name, "FunctionType":$type, - CArg<"ArrayRef", "{}">:$attrs - )>]; + CArg<"ArrayRef", "{}">:$attrs, + CArg<"ArrayRef", "{}">:$argAttrs) + >]; let extraClassDeclaration = [{ + static SequenceOp create(Location location, StringRef name, FunctionType type, + ArrayRef attrs = {}); + static SequenceOp create(Location location, StringRef name, FunctionType type, + Operation::dialect_attr_range attrs); + static SequenceOp create(Location location, StringRef name, FunctionType type, + ArrayRef attrs, + ArrayRef argAttrs); /// Create a deep copy of this sequence and all of its blocks, remapping any /// operands that use values outside of the sequence using the map that is @@ -786,18 +749,14 @@ def Pulse_SequenceOp : Pulse_Op<"sequence", [ /// included in the new sequence. Replaces references to cloned sub-values /// with the corresponding value that is copied, and adds those mappings to /// the mapper. - SequenceOp clone(BlockAndValueMapping &mapper); + SequenceOp clone(IRMapping &mapper); SequenceOp clone(); /// Clone the internal blocks and attributes from this sequence into dest. /// Any cloned blocks are appended to the back of dest. This sequence /// asserts that the attributes of the current sequence and dest are /// compatible. - void cloneInto(SequenceOp dest, BlockAndValueMapping &mapper); - - FunctionType getType() { - return getTypeAttr().getValue().cast(); - } + void cloneInto(SequenceOp dest, IRMapping &mapper); //===------------------------------------------------------------------===// // CallableOpInterface @@ -810,27 +769,29 @@ def Pulse_SequenceOp : Pulse_Op<"sequence", [ /// Returns the results types that the callable region produces when /// executed. - ArrayRef getCallableResults() { return getType().cast<::mlir::FunctionType>().getResults(); } + ArrayRef getCallableResults() { return getFunctionType().getResults(); } + + /// Returns the argument attributes for all callable region arguments or + /// null if there are none. + ::mlir::ArrayAttr getCallableArgAttrs() { + return getArgAttrs().value_or(nullptr); + } + + /// Returns the result attributes for all callable region results or + /// null if there are none. + ::mlir::ArrayAttr getCallableResAttrs() { + return getResAttrs().value_or(nullptr); + } //===------------------------------------------------------------------===// // FunctionOpInterface Methods //===------------------------------------------------------------------===// /// Returns the argument types of this function. - ArrayRef getArgumentTypes() { return getType().getInputs(); } + ArrayRef getArgumentTypes() { return getFunctionType().getInputs(); } /// Returns the result types of this function. - ArrayRef getResultTypes() { return getType().getResults(); } - - /// Verify the type attribute of this function. Returns failure and emits - /// an error if the attribute is invalid. - LogicalResult verifyType() { - auto type = getTypeAttr().getValue(); - if (!type.isa()) - return emitOpError("requires '" + getTypeAttrName() + - "' attribute of function type"); - return success(); - } + ArrayRef getResultTypes() { return getFunctionType().getResults(); } //===------------------------------------------------------------------===// // SymbolOpInterface Methods @@ -838,13 +799,12 @@ def Pulse_SequenceOp : Pulse_Op<"sequence", [ bool isDeclaration() { return isExternal(); } }]; - let parser = [{ return ::mlir::pulse::parseSequenceOp(parser, result); }]; - let printer = [{ return ::mlir::pulse::print(*this, p); }]; - // TODO in LLVM 15 + this can become just let hasVerifier = 1; - let verifier = [{ return ::mlir::pulse::verify(*this); }]; + let hasCustomAssemblyFormat = 1; + let hasVerifier = 1; + } -def Pulse_ReturnOp : Pulse_Op<"return", [NoSideEffect, Terminator, ReturnLike, SequenceRequired]>, +def Pulse_ReturnOp : Pulse_Op<"return", [Pure, Terminator, ReturnLike, SequenceRequired]>, Arguments<(ins Variadic:$operands)>, Results<(outs)> { let summary = "Terminator for pulse.sequence."; let description = [{ @@ -860,10 +820,9 @@ def Pulse_ReturnOp : Pulse_Op<"return", [NoSideEffect, Terminator, ReturnLike, S pulse.return %0, %1: i1, i1 } }]; - let builders = [OpBuilder<(ins), [{ build($_builder, $_state, llvm::None); }]>]; + let builders = [OpBuilder<(ins), [{ build($_builder, $_state, std::nullopt); }]>]; let assemblyFormat = "attr-dict ($operands^ `:` type($operands))?"; - // TODO in LLVM 15 + this can become just let hasVerifier = 1; - let verifier = [{ return ::mlir::pulse::verify(*this); }]; + let hasVerifier = 1; } //===----------------------------------------------------------------------===// diff --git a/include/Dialect/Pulse/IR/PulseTypes.td b/include/Dialect/Pulse/IR/PulseTypes.td index 8945d850c..d279bb1e0 100644 --- a/include/Dialect/Pulse/IR/PulseTypes.td +++ b/include/Dialect/Pulse/IR/PulseTypes.td @@ -17,8 +17,10 @@ #ifndef PULSE_TYPES #define PULSE_TYPES +include "mlir/IR/AttrTypeBase.td" include "mlir/IR/OpBase.td" + class Pulse_Type traits = []> : TypeDef { let mnemonic = typeMnemonic; diff --git a/include/Dialect/Pulse/Transforms/InlineRegion.h b/include/Dialect/Pulse/Transforms/InlineRegion.h index 4d0091704..82d3cd14b 100644 --- a/include/Dialect/Pulse/Transforms/InlineRegion.h +++ b/include/Dialect/Pulse/Transforms/InlineRegion.h @@ -21,12 +21,13 @@ #ifndef PULSE_INLINE_REGION_H #define PULSE_INLINE_REGION_H +#include "mlir/IR/BuiltinOps.h" #include "mlir/Pass/Pass.h" namespace mlir::pulse { class InlineRegionPass - : public PassWrapper> { + : public PassWrapper> { public: void runOnOperation() override; diff --git a/include/Dialect/Pulse/Utils/Utils.h b/include/Dialect/Pulse/Utils/Utils.h index 083d741bd..633317499 100644 --- a/include/Dialect/Pulse/Utils/Utils.h +++ b/include/Dialect/Pulse/Utils/Utils.h @@ -40,7 +40,7 @@ template MixFrameOp getMixFrameOp(PulseOpTy pulseOp, CallSequenceOp callSequenceOp) { auto frameArgIndex = - pulseOp.target().template cast().getArgNumber(); + pulseOp.getTarget().template cast().getArgNumber(); auto frameOp = callSequenceOp.getOperand(frameArgIndex).getDefiningOp(); auto mixFrameOp = dyn_cast(frameOp); diff --git a/include/Dialect/QCS/IR/CMakeLists.txt b/include/Dialect/QCS/IR/CMakeLists.txt index 097ea569b..894f60886 100644 --- a/include/Dialect/QCS/IR/CMakeLists.txt +++ b/include/Dialect/QCS/IR/CMakeLists.txt @@ -11,6 +11,6 @@ # that they have been altered from the originals. add_mlir_dialect(QCSOps qcs) -qssc_add_mlir_doc(QCSOps QCSOps generated/Dialect/QCS/ -gen-dialect-doc) +add_mlir_doc(QCSOps QCSOps generated/Dialect/QCS/ -gen-dialect-doc -dialect=qcs) set(LLVM_TARGET_DEFINITIONS QCSDialect.td) diff --git a/include/Dialect/QCS/IR/QCSBase.td b/include/Dialect/QCS/IR/QCSBase.td index 94f6090ad..4ee4ceb53 100644 --- a/include/Dialect/QCS/IR/QCSBase.td +++ b/include/Dialect/QCS/IR/QCSBase.td @@ -22,6 +22,8 @@ #ifndef QCS_BASE_H #define QCS_BASE_H +include "mlir/IR/AttrTypeBase.td" + //===----------------------------------------------------------------------===// // Quantum Control System dialect definition //===----------------------------------------------------------------------===// diff --git a/include/Dialect/QCS/IR/QCSOps.td b/include/Dialect/QCS/IR/QCSOps.td index c1cd14278..e198d79e6 100644 --- a/include/Dialect/QCS/IR/QCSOps.td +++ b/include/Dialect/QCS/IR/QCSOps.td @@ -93,7 +93,7 @@ def QCS_BroadcastOp : QCS_Op<"broadcast", [NonInterferingNonDeadSideEffect]> { Example: ```mlir - %angle1 = quir.constant #quir.angle<0.2 : !quir.angle<20>> + %angle1 = quir.constant #quir.angle<0.2> : !quir.angle<20> qcs.broadcast %angle1 : !quir.angle<20> ``` }]; @@ -178,7 +178,7 @@ def QCS_RecvOp : QCS_Op<"recv", [NonInterferingNonDeadSideEffect]> { def QCS_ParallelControlFlowOp : QCS_Op<"parallel_control_flow", [ SingleBlockImplicitTerminator<"ParallelEndOp">, - RecursiveSideEffects]> { + RecursiveMemoryEffects]> { let summary = "Contain a group of control flow ops that can run in parallel"; let description = [{ The `qcs.parallel_control_flow` operation has a single region and block @@ -189,10 +189,10 @@ def QCS_ParallelControlFlowOp : QCS_Op<"parallel_control_flow", [ ```mlir qcs.parallel_control_flow { scf.if (%c0) { - quir.gate_call @x(%q0) : (!quir.qubit<1>) -> () + quir.gate_func.call @x(%q0) : (!quir.qubit<1>) -> () } {quir.physicalIds = [0 : i32]} scf.if (%c1) { - quir.gate_call @x(%q1) : (!quir.qubit<1>) -> () + quir.gate_func.call @x(%q1) : (!quir.qubit<1>) -> () } {quir.physicalIds = [1 : i32]} } ``` @@ -204,15 +204,14 @@ def QCS_ParallelControlFlowOp : QCS_Op<"parallel_control_flow", [ } def QCS_ParallelEndOp : QCS_Op<"parallel_control_flow_end", [ - Terminator, HasParent<"ParallelControlFlowOp">, NoSideEffect]> { + Terminator, HasParent<"ParallelControlFlowOp">, Pure]> { let summary = "A pseudo-op that marks the end of a `qcs.parallel_control_flow` op."; let description = [{ This op terminates the only block inside the only region of a `qcs.parallel_control_flow` op. }]; - let parser = "return success();"; - let printer = "p << getOperationName();"; + let hasCustomAssemblyFormat = 1; } def QCS_ShotInitOp : QCS_Op<"shot_init", [IsolatedFromAbove]> { @@ -230,7 +229,7 @@ def QCS_DeclareParameterOp : QCS_Op<"declare_parameter", [Symbol]> { let summary = "system input parameter subject to post compilation updates"; let description = [{ The `qcs.declare_parameter` operation adds a symbol defining an input parameter - which may be modified after compilation before/during program invocation. + which may be modified after compilation before/during program invocation. The value of the input parameter may be obtained using the qcs.use_input_parameter operation. @@ -298,8 +297,6 @@ def QCS_ParameterLoadOp : QCS_Op<"parameter_load", let assemblyFormat = [{ $parameter_name `:` type($res) attr-dict }]; - // op is verified by its traits - let verifier = ?; } diff --git a/include/Dialect/QUIR/IR/CMakeLists.txt b/include/Dialect/QUIR/IR/CMakeLists.txt index 4eaeb0baa..6d671429e 100644 --- a/include/Dialect/QUIR/IR/CMakeLists.txt +++ b/include/Dialect/QUIR/IR/CMakeLists.txt @@ -11,7 +11,7 @@ # that they have been altered from the originals. add_mlir_dialect(QUIR quir) -qssc_add_mlir_doc(QUIR QUIRDialect generated/Dialect/QUIR/ -gen-dialect-doc) +add_mlir_doc(QUIR QUIRDialect generated/Dialect/QUIR/ -gen-dialect-doc -dialect=quir) set(LLVM_TARGET_DEFINITIONS QUIR.td) mlir_tablegen(QUIRAttributes.h.inc -gen-attrdef-decls -attrdefs-dialect=quir) diff --git a/include/Dialect/QUIR/IR/QUIRAttributes.td b/include/Dialect/QUIR/IR/QUIRAttributes.td index 88677fd7d..18ef70c54 100644 --- a/include/Dialect/QUIR/IR/QUIRAttributes.td +++ b/include/Dialect/QUIR/IR/QUIRAttributes.td @@ -23,30 +23,30 @@ include "Dialect/QUIR/IR/QUIRTypes.td" include "mlir/IR/BuiltinAttributes.td" include "mlir/IR/OpBase.td" -def QUIR_AngleAttr : QUIR_Attr<"Angle", "angle"> { +def QUIR_AngleAttr : QUIR_Attr<"Angle", "angle", [TypedAttrInterface]> { let summary = "A floating point value in the range (0,2*pi]"; let description = [{ Angle attributes represent constant known floating point values within the range (0,2*pi] }]; - let parameters = (ins AttributeSelfTypeParameter<"">:$type, "APFloat":$value); + let parameters = (ins AttributeSelfTypeParameter<"", "AngleType">:$type, "APFloat":$value); let builders = [ - AttrBuilderWithInferredContext<(ins "Type":$type, + AttrBuilderWithInferredContext<(ins "AngleType":$type, "const APFloat &":$value), [{ return $_get(type.getContext(), type, value); }]>, - AttrBuilder<(ins "Type":$type, "const APFloat &":$value), [{ + AttrBuilder<(ins "AngleType":$type, "const APFloat &":$value), [{ return $_get(context, type, value); }]> ]; - let assemblyFormat = "`<` $value `:` $type `>`"; + let assemblyFormat = "`<` $value `>`"; let skipDefaultBuilders = 1; } -def QUIR_DurationAttr : QUIR_Attr<"Duration", "duration"> { +def QUIR_DurationAttr : QUIR_Attr<"Duration", "duration", [TypedAttrInterface]> { let summary = "A duration of time"; let description = [{ Duration attributes represent a duration of time. @@ -78,7 +78,18 @@ def QUIR_DurationAttr : QUIR_Attr<"Duration", "duration"> { DurationAttr getConvertedDurationAttr(const TimeUnits targetUnits, const double dt); }]; - let assemblyFormat = "`<` $duration `:` $type `>`"; + let builders = [ + AttrBuilderWithInferredContext<(ins "DurationType":$type, + "const APFloat &":$duration), [{ + return $_get(type.getContext(), type, duration); + }]>, + AttrBuilder<(ins "DurationType":$type, "const APFloat &":$duration), [{ + return $_get(context, type, duration); + }]> + ]; + + let assemblyFormat = "`<` $duration `>`"; + let skipDefaultBuilders = 1; } diff --git a/include/Dialect/QUIR/IR/QUIRDialect.h b/include/Dialect/QUIR/IR/QUIRDialect.h index aba126922..8b8940e2e 100644 --- a/include/Dialect/QUIR/IR/QUIRDialect.h +++ b/include/Dialect/QUIR/IR/QUIRDialect.h @@ -24,9 +24,9 @@ #include "Dialect/OQ3/IR/OQ3Dialect.h" #include "Dialect/QCS/IR/QCSDialect.h" -#include "mlir/Dialect/Arithmetic/IR/Arithmetic.h" +#include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" -#include "mlir/Dialect/SCF/SCF.h" +#include "mlir/Dialect/SCF/IR/SCF.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/Dialect.h" diff --git a/include/Dialect/QUIR/IR/QUIRDialect.td b/include/Dialect/QUIR/IR/QUIRDialect.td index 1c37ea2f2..921c00b01 100644 --- a/include/Dialect/QUIR/IR/QUIRDialect.td +++ b/include/Dialect/QUIR/IR/QUIRDialect.td @@ -17,7 +17,7 @@ #ifndef QUIR_DIALECT #define QUIR_DIALECT -include "mlir/Interfaces/CallInterfaces.td" +include "mlir/IR/AttrTypeBase.td" include "mlir/IR/OpBase.td" //===----------------------------------------------------------------------===// @@ -34,11 +34,13 @@ def QUIRDialect : Dialect { let dependentDialects = [ "mlir::oq3::OQ3Dialect", "mlir::qcs::QCSDialect", - "mlir::arith::ArithmeticDialect", + "mlir::arith::ArithDialect", "mlir::scf::SCFDialect", "mlir::LLVM::LLVMDialect" ]; let hasConstantMaterializer = 1; + let useDefaultAttributePrinterParser = 1; + let useDefaultTypePrinterParser = 1; } //===----------------------------------------------------------------------===// diff --git a/include/Dialect/QUIR/IR/QUIRInterfaces.h b/include/Dialect/QUIR/IR/QUIRInterfaces.h index 0dbaa8553..1ff434270 100644 --- a/include/Dialect/QUIR/IR/QUIRInterfaces.h +++ b/include/Dialect/QUIR/IR/QUIRInterfaces.h @@ -40,7 +40,7 @@ std::set getOperatedQubits(mlir::Operation *op, bool ignoreSelf = false); /// Get the next (lexographically) Qubit operation implementing this interface -llvm::Optional getNextQubitOp(Operation *op); +std::optional getNextQubitOp(Operation *op); /// @brief Get qubits that are shared between the two operations std::set getSharedQubits(std::set &first, diff --git a/include/Dialect/QUIR/IR/QUIRInterfaces.td b/include/Dialect/QUIR/IR/QUIRInterfaces.td index 291d81a3c..37390f738 100644 --- a/include/Dialect/QUIR/IR/QUIRInterfaces.td +++ b/include/Dialect/QUIR/IR/QUIRInterfaces.td @@ -79,7 +79,7 @@ def QubitOpInterface : OpInterface<"QubitOpInterface"> { } /// Get the next (lexicographically) Qubit operation implementing this interface - static llvm::Optional getNextQubitOp(Operation *op) { + static std::optional getNextQubitOp(Operation *op) { return interfaces_impl::getNextQubitOp(op); } @@ -111,7 +111,7 @@ def QubitOpInterface : OpInterface<"QubitOpInterface"> { /// Get the next (lexicographically) Qubit operation implementing this interface /// Accumulating the observed qubits along this path. template - static std::tuple, std::set> getNextQubitOpOfTypeWithQubits(Operation *op) { + static std::tuple, std::set> getNextQubitOpOfTypeWithQubits(Operation *op) { Operation *curOp = op; std::set operatedQubits; while (Operation *nextOp = curOp->getNextNode()) { @@ -122,14 +122,14 @@ def QubitOpInterface : OpInterface<"QubitOpInterface"> { operatedQubits.insert(nextOpQubits.begin(), nextOpQubits.end()); curOp = nextOp; } - return {llvm::None, operatedQubits}; + return {std::nullopt, operatedQubits}; } /// Get the next (lexicographically) operation (not necessarily of Qubit /// type) implementing this interface. /// Accumulating the observed qubits along this path. template - static std::tuple, std::set> getNextOpOfTypeWithQubits(Operation *op) { + static std::tuple, std::set> getNextOpOfTypeWithQubits(Operation *op) { Operation *curOp = op; std::set operatedQubits; while (Operation *nextOp = curOp->getNextNode()) { @@ -139,12 +139,12 @@ def QubitOpInterface : OpInterface<"QubitOpInterface"> { operatedQubits.insert(nextOpQubits.begin(), nextOpQubits.end()); curOp = nextOp; } - return {llvm::None, operatedQubits}; + return {std::nullopt, operatedQubits}; } /// Get the next (lexicographically) Qubit operation implementing this interface template - static llvm::Optional getNextQubitOpOfType(Operation *op) { + static std::optional getNextQubitOpOfType(Operation *op) { auto result = getNextQubitOpOfTypeWithQubits(op); return std::get<0>(result); } @@ -152,12 +152,12 @@ def QubitOpInterface : OpInterface<"QubitOpInterface"> { /// If the next (lexicographically) Qubit operation is the specififed /// type implementing this interface return it. template - static llvm::Optional getNextQubitOpIsType(Operation *op) { + static std::optional getNextQubitOpIsType(Operation *op) { auto nextOp = getNextQubitOp(op); - if (auto nextOpValue = nextOp.hasValue()) + if (auto nextOpValue = nextOp.has_value()) if (OpClass castOp = dyn_cast(nextOpValue)) return castOp; - return llvm::None; + return std::nullopt; } }]; } diff --git a/include/Dialect/QUIR/IR/QUIROps.h b/include/Dialect/QUIR/IR/QUIROps.h index 43593e989..fba6d49e6 100644 --- a/include/Dialect/QUIR/IR/QUIROps.h +++ b/include/Dialect/QUIR/IR/QUIROps.h @@ -22,12 +22,15 @@ #include "Dialect/QUIR/IR/QUIRTraits.h" #include "Dialect/QUIR/IR/QUIRTypes.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/Dialect.h" #include "mlir/IR/DialectImplementation.h" +#include "mlir/IR/FunctionInterfaces.h" #include "mlir/IR/OpDefinition.h" +#include "mlir/Interfaces/CallInterfaces.h" #include "mlir/Interfaces/ControlFlowInterfaces.h" #include "mlir/Interfaces/SideEffectInterfaces.h" #include "mlir/Transforms/InliningUtils.h" diff --git a/include/Dialect/QUIR/IR/QUIROps.td b/include/Dialect/QUIR/IR/QUIROps.td index da071affe..01c37797f 100644 --- a/include/Dialect/QUIR/IR/QUIROps.td +++ b/include/Dialect/QUIR/IR/QUIROps.td @@ -42,11 +42,9 @@ include "mlir/Dialect/LLVMIR/LLVMOpBase.td" def NonInterferingNonDeadSideEffect : MemoryEffects<[MemFree]>; def QUIR_ConstantOp : QUIR_Op<"constant", - [ConstantLike, NoSideEffect, + [ConstantLike, Pure, DeclareOpInterfaceMethods, - TypesMatchWith< - "result and attribute have the same type", - "value", "result", "$_self">]> { + AllTypesMatch<["value", "result"]>]> { let summary = "QUIR-specific (angle or duration) constants"; let description = [{ The `quir.constant` operation produces an SSA value equal to some constant @@ -57,19 +55,13 @@ def QUIR_ConstantOp : QUIR_Op<"constant", ``` // Angle constant - %1 = quir.constant #quir.angle<1.5 : !quir.angle> + %1 = quir.constant #quir.angle<1.5> : !quir.angle ``` }]; - let arguments = (ins AnyAttr:$value); + let arguments = (ins TypedAttrInterface:$value); let results = (outs AnyType:$result); - let builders = [ - OpBuilder<(ins "Attribute":$value), - [{ build($_builder, $_state, value.getType(), value); }]>, - OpBuilder<(ins "Attribute":$value, "Type":$type), - [{ build($_builder, $_state, type, value); }]>, - ]; let extraClassDeclaration = [{ /// Whether the constant op can be constructed with a particular value and @@ -78,6 +70,11 @@ def QUIR_ConstantOp : QUIR_Op<"constant", // Return the angle value from the value attribute APFloat getAngleValueFromConstant(); + + /// Build the constant op with `value` and `type` if possible, otherwise + /// returns null. + static ConstantOp materialize(OpBuilder &builder, Attribute value, + Type type, Location loc); }]; let hasFolder = 1; @@ -167,7 +164,7 @@ def QUIR_Builtin_UOp : QUIR_Op<"builtin_U", [ }]; } -def QUIR_CallGateOp : QUIR_Op<"call_gate", [DeclareOpInterfaceMethods, +def QUIR_CallGateOp : QUIR_Op<"call_gate", [CallOpInterface, UnitaryOp, DeclareOpInterfaceMethods, NonInterferingNonDeadSideEffect]> { @@ -191,7 +188,7 @@ def QUIR_CallGateOp : QUIR_Op<"call_gate", [DeclareOpInterfaceMethods:$operands), [{ + OpBuilder<(ins "mlir::func::FuncOp":$callee, CArg<"ValueRange", "{}">:$operands), [{ $_state.addOperands(operands); $_state.addAttribute("callee", SymbolRefAttr::get(callee)); }]>, @@ -206,17 +203,36 @@ def QUIR_CallGateOp : QUIR_Op<"call_gate", [DeclareOpInterfaceMethods]; let extraClassDeclaration = [{ - StringRef getCallee() { return callee(); } + FunctionType getCalleeType(); + /// Get the argument operands to the called function. + operand_range getArgOperands() { + return {arg_operand_begin(), arg_operand_end()}; + } + + MutableOperandRange getArgOperandsMutable() { + return getOperandsMutable(); + } + operand_iterator arg_operand_begin() { return operand_begin(); } operand_iterator arg_operand_end() { return operand_end(); } + /// Return the callee of this operation. + CallInterfaceCallable getCallableForCallee() { + return (*this)->getAttrOfType("callee"); + } + + /// Set the callee for this operation. + void setCalleeFromCallable(CallInterfaceCallable callee) { + (*this)->setAttr("callee", callee.get()); + } + }]; } def QUIR_CallDefCalGateOp : QUIR_Op<"call_defcal_gate", [ - DeclareOpInterfaceMethods, + CallOpInterface, UnitaryOp, NonInterferingNonDeadSideEffect]> { let summary = "A call to a user-defined defcal quantum gate that needs to be specialized for input operands"; @@ -239,7 +255,7 @@ def QUIR_CallDefCalGateOp : QUIR_Op<"call_defcal_gate", [ }]; let builders = [ - OpBuilder<(ins "FuncOp":$callee, CArg<"ValueRange", "{}">:$operands), [{ + OpBuilder<(ins "mlir::func::FuncOp":$callee, CArg<"ValueRange", "{}">:$operands), [{ $_state.addOperands(operands); $_state.addAttribute("callee", SymbolRefAttr::get(callee)); }]>, @@ -254,17 +270,31 @@ def QUIR_CallDefCalGateOp : QUIR_Op<"call_defcal_gate", [ }]>]; let extraClassDeclaration = [{ - StringRef getCallee() { return callee(); } FunctionType getCalleeType(); + /// Get the argument operands to the called function. + operand_range getArgOperands() { + return {arg_operand_begin(), arg_operand_end()}; + } + operand_iterator arg_operand_begin() { return operand_begin(); } operand_iterator arg_operand_end() { return operand_end(); } + /// Return the callee of this operation. + CallInterfaceCallable getCallableForCallee() { + return (*this)->getAttrOfType("callee"); + } + + /// Set the callee for this operation. + void setCalleeFromCallable(CallInterfaceCallable callee) { + (*this)->setAttr("callee", callee.get()); + } + }]; } def QUIR_CallDefcalMeasureOp : QUIR_Op<"call_defcal_measure", [ - DeclareOpInterfaceMethods, + CallOpInterface, CPTPOp, NonInterferingNonDeadSideEffect]> { let summary = "A call to a user-defined defcal qubit measurement that needs to be specialized for input operands"; @@ -282,14 +312,14 @@ def QUIR_CallDefcalMeasureOp : QUIR_Op<"call_defcal_measure", [ let results = (outs I1:$res); let assemblyFormat = [{ - $callee `(` $operands `)` attr-dict `:` functional-type(operands, results) + $callee `(` $operands `)` attr-dict `:` functional-type($operands, results) }]; let builders = [ - OpBuilder<(ins "FuncOp":$callee, CArg<"ValueRange", "{}">:$operands), [{ + OpBuilder<(ins "mlir::func::FuncOp":$callee, CArg<"ValueRange", "{}">:$operands), [{ $_state.addOperands(operands); $_state.addAttribute("callee", SymbolRefAttr::get(callee)); - $_state.addTypes(callee.getType().getResults()); + $_state.addTypes(callee.getFunctionType().getResults()); }]>, OpBuilder<(ins "SymbolRefAttr":$callee, "TypeRange":$res, CArg<"ValueRange", "{}">:$operands), [{ @@ -304,36 +334,32 @@ def QUIR_CallDefcalMeasureOp : QUIR_Op<"call_defcal_measure", [ }]>]; let extraClassDeclaration = [{ - StringRef getCallee() { return callee(); } FunctionType getCalleeType(); + /// Get the argument operands to the called function. + operand_range getArgOperands() { + return {arg_operand_begin(), arg_operand_end()}; + } + operand_iterator arg_operand_begin() { return operand_begin(); } operand_iterator arg_operand_end() { return operand_end(); } - }]; - - let verifier = [{ - bool qubitFound = false; - for (auto arg : (*this)->getOperands()) { - if(qubitFound) { - if(arg.getType().isa()) { - return emitOpError("requires exactly one qubit argument"); - } - } else { - if(arg.getType().isa()) { - qubitFound = true; - } - } + /// Return the callee of this operation. + CallInterfaceCallable getCallableForCallee() { + return (*this)->getAttrOfType("callee"); } - if (qubitFound) { - return success(); - } else { - return emitOpError("requires exactly one qubit"); + + /// Set the callee for this operation. + void setCalleeFromCallable(CallInterfaceCallable callee) { + (*this)->setAttr("callee", callee.get()); } + }]; + + let hasVerifier = 1; } -def QUIR_CallSubroutineOp : QUIR_Op<"call_subroutine", [DeclareOpInterfaceMethods]> { +def QUIR_CallSubroutineOp : QUIR_Op<"call_subroutine", [CallOpInterface]> { let summary = "A call to a user-defined subroutine function that needs to be specialized for input operands"; let description = [{ The `quir.call_subroutine` operation represents calls to user-defined subroutine functions @@ -358,10 +384,10 @@ def QUIR_CallSubroutineOp : QUIR_Op<"call_subroutine", [DeclareOpInterfaceMethod }]; let builders = [ - OpBuilder<(ins "FuncOp":$callee, CArg<"ValueRange", "{}">:$operands), [{ + OpBuilder<(ins "mlir::func::FuncOp":$callee, CArg<"ValueRange", "{}">:$operands), [{ $_state.addOperands(operands); $_state.addAttribute("callee", SymbolRefAttr::get(callee)); - $_state.addTypes(callee.getType().getResults()); + $_state.addTypes(callee.getFunctionType().getResults()); }]>, OpBuilder<(ins "SymbolRefAttr":$callee, "TypeRange":$res, CArg<"ValueRange", "{}">:$operands), [{ @@ -376,12 +402,26 @@ def QUIR_CallSubroutineOp : QUIR_Op<"call_subroutine", [DeclareOpInterfaceMethod }]>]; let extraClassDeclaration = [{ - StringRef getCallee() { return callee(); } FunctionType getCalleeType(); + /// Get the argument operands to the called function. + operand_range getArgOperands() { + return {arg_operand_begin(), arg_operand_end()}; + } + operand_iterator arg_operand_begin() { return operand_begin(); } operand_iterator arg_operand_end() { return operand_end(); } + /// Return the callee of this operation. + CallInterfaceCallable getCallableForCallee() { + return (*this)->getAttrOfType("callee"); + } + + /// Set the callee for this operation. + void setCalleeFromCallable(CallInterfaceCallable callee) { + (*this)->setAttr("callee", callee.get()); + } + }]; } @@ -416,7 +456,7 @@ def QUIR_CallCircuitOp : QUIR_Op<"call_circuit", [CallOpInterface, MemRefsNormal OpBuilder<(ins "CircuitOp":$callee, CArg<"ValueRange", "{}">:$operands), [{ $_state.addOperands(operands); $_state.addAttribute("callee", SymbolRefAttr::get(callee)); - $_state.addTypes(callee.getType().getResults()); + $_state.addTypes(callee.getFunctionType().getResults()); }]>, OpBuilder<(ins "SymbolRefAttr":$callee, "TypeRange":$res, CArg<"ValueRange", "{}">:$operands), [{ @@ -431,19 +471,29 @@ def QUIR_CallCircuitOp : QUIR_Op<"call_circuit", [CallOpInterface, MemRefsNormal }]>]; let extraClassDeclaration = [{ - StringRef getCallee() { return callee(); } FunctionType getCalleeType(); + /// Get the argument operands to the called function. operand_range getArgOperands() { return {arg_operand_begin(), arg_operand_end()}; } + MutableOperandRange getArgOperandsMutable() { + return getOperandsMutable(); + } + operand_iterator arg_operand_begin() { return operand_begin(); } operand_iterator arg_operand_end() { return operand_end(); } + /// Return the callee of this operation. CallInterfaceCallable getCallableForCallee() { return (*this)->getAttrOfType("callee"); } + + /// Set the callee for this operation. + void setCalleeFromCallable(CallInterfaceCallable callee) { + (*this)->setAttr("callee", callee.get()); + } }]; } @@ -485,7 +535,7 @@ def QUIR_DelayOp : QUIR_Op<"delay", [ Example: ```mlir - %dur1 = quir.constant #quir.duration<10.0 : !quir.duration
> + %dur1 = quir.constant #quir.duration<10.0> : !quir.duration
"quir.delay"(%dur1, %q1_1) : (!quir.duration
, !quir.qubit) ``` }]; @@ -536,7 +586,7 @@ def QUIR_CircuitOp : QUIR_Op<"circuit", [ AutomaticAllocationScope, CallableOpInterface, FunctionOpInterface, IsolatedFromAbove, Symbol, DeclareOpInterfaceMethods, - RecursiveSideEffects + RecursiveMemoryEffects ]> { let summary = "An operation with a name containing a single `SSACFG` region corresponding to a quantum circuit(block) execution"; let description = [{ @@ -591,7 +641,7 @@ def QUIR_CircuitOp : QUIR_Op<"circuit", [ quir.circuit @vqe(%angle: quir.angle<32>) -> i1 {quir.physicalId = 0 : i32} { %q0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> - quir.gate_call @rz(%0, %angle) : (!quir.qubit<1>, !quir.angle<32>) -> () + quir.gate_func.call @rz(%0, %angle) : (!quir.qubit<1>, !quir.angle<32>) -> () %result = "quir.measure"(%0) : (!quir.qubit<1>) -> i1 quir.return %result: i1 } @@ -599,15 +649,17 @@ def QUIR_CircuitOp : QUIR_Op<"circuit", [ }]; let arguments = (ins SymbolNameAttr:$sym_name, - TypeAttr:$type, - OptionalAttr:$sym_visibility); + TypeAttrOf:$function_type, + OptionalAttr:$sym_visibility, + OptionalAttr:$arg_attrs, + OptionalAttr:$res_attrs); let regions = (region AnyRegion:$body); let builders = [OpBuilder<(ins "StringRef":$name, "FunctionType":$type, CArg<"ArrayRef", "{}">:$attrs, - CArg<"ArrayRef", "{}">:$argAttrs - )>]; + CArg<"ArrayRef", "{}">:$argAttrs) + >]; let extraClassDeclaration = [{ static CircuitOp create(Location location, StringRef name, FunctionType type, ArrayRef attrs = {}); @@ -624,18 +676,14 @@ def QUIR_CircuitOp : QUIR_Op<"circuit", [ /// included in the new circuit. Replaces references to cloned sub-values /// with the corresponding value that is copied, and adds those mappings to /// the mapper. - CircuitOp clone(BlockAndValueMapping &mapper); + CircuitOp clone(IRMapping &mapper); CircuitOp clone(); /// Clone the internal blocks and attributes from this circuit into dest. /// Any cloned blocks are appended to the back of dest. This circuit /// asserts that the attributes of the current circuit and dest are /// compatible. - void cloneInto(CircuitOp dest, BlockAndValueMapping &mapper); - - FunctionType getType() { - return getTypeAttr().getValue().cast(); - } + void cloneInto(CircuitOp dest, IRMapping &mapper); //===------------------------------------------------------------------===// // CallableOpInterface @@ -648,27 +696,29 @@ def QUIR_CircuitOp : QUIR_Op<"circuit", [ /// Returns the results types that the callable region produces when /// executed. - ArrayRef getCallableResults() { return getType().getResults(); } + ArrayRef getCallableResults() { return getFunctionType().getResults(); } + + /// Returns the argument attributes for all callable region arguments or + /// null if there are none. + ::mlir::ArrayAttr getCallableArgAttrs() { + return getArgAttrs().value_or(nullptr); + } + + /// Returns the result attributes for all callable region results or + /// null if there are none. + ::mlir::ArrayAttr getCallableResAttrs() { + return getResAttrs().value_or(nullptr); + } //===------------------------------------------------------------------===// // FunctionOpInterface Methods //===------------------------------------------------------------------===// /// Returns the argument types of this function. - ArrayRef getArgumentTypes() { return getType().getInputs(); } + ArrayRef getArgumentTypes() { return getFunctionType().getInputs(); } /// Returns the result types of this function. - ArrayRef getResultTypes() { return getType().getResults(); } - - /// Verify the type attribute of this function. Returns failure and emits - /// an error if the attribute is invalid. - LogicalResult verifyType() { - auto type = getTypeAttr().getValue(); - if (!type.isa()) - return emitOpError("requires '" + getTypeAttrName() + - "' attribute of function type"); - return success(); - } + ArrayRef getResultTypes() { return getFunctionType().getResults(); } //===------------------------------------------------------------------===// // SymbolOpInterface Methods @@ -676,13 +726,12 @@ def QUIR_CircuitOp : QUIR_Op<"circuit", [ bool isDeclaration() { return isExternal(); } }]; - let parser = [{ return ::parseCircuitOp(parser, result); }]; - let printer = [{ return ::print(*this, p); }]; - // TODO in LLVM 15 + this can become just let hasVerifier = 1; - let verifier = [{ return ::verify(*this); }]; + + let hasCustomAssemblyFormat = 1; + let hasVerifier = 1; } -def QUIR_ReturnOp : QUIR_Op<"return", [HasParent<"CircuitOp">, NoSideEffect, Terminator, ReturnLike]>, +def QUIR_ReturnOp : QUIR_Op<"return", [HasParent<"CircuitOp">, Pure, Terminator, ReturnLike]>, Arguments<(ins Variadic:$operands)>, Results<(outs)> { let summary = "Terminator for quir.circuit."; let description = [{ @@ -698,15 +747,16 @@ def QUIR_ReturnOp : QUIR_Op<"return", [HasParent<"CircuitOp">, NoSideEffect, Ter quir.return %0, %1: i1, i1 } }]; - let builders = [OpBuilder<(ins), [{ build($_builder, $_state, llvm::None); }]>]; + let builders = [OpBuilder<(ins), [{ build($_builder, $_state, std::nullopt); }]>]; let assemblyFormat = "attr-dict ($operands^ `:` type($operands))?"; - // TODO in LLVM 15 + this can become just let hasVerifier = 1; - let verifier = [{ return ::verify(*this); }]; + let hasVerifier = 1; } +// TODO: Usage should be replaced with https://github.com/llvm/llvm-project/blob/cf1bde33423da5eb9b7dc95daac4aada3167de3c/mlir/include/mlir/Dialect/ControlFlow/IR/ControlFlowOps.td#L229 +// now that we are on llvm 15+ def QUIR_SwitchOp : QUIR_Op<"switch", [DeclareOpInterfaceMethods, - RecursiveSideEffects, + RecursiveMemoryEffects, SingleBlockImplicitTerminator<"quir::YieldOp">, NoRegionArguments ]> { @@ -754,14 +804,11 @@ def QUIR_SwitchOp : QUIR_Op<"switch", let regions = (region SizedRegion<1>:$defaultRegion, VariadicRegion>:$caseRegions); - // TODO in LLVM 15 + this can become just let hasVerifier = 1; - let verifier = [{ return ::verify(*this); }]; - let parser = [{ return ::parseSwitchOp(parser, result); }]; - let printer = [{ return ::print(p, *this); }]; - + let hasVerifier = 1; + let hasCustomAssemblyFormat = 1; } -def YieldOp : QUIR_Op<"yield", [NoSideEffect, ReturnLike, Terminator, ParentOneOf<["SwitchOp"]>]>{ +def YieldOp : QUIR_Op<"yield", [Pure, ReturnLike, Terminator, ParentOneOf<["SwitchOp"]>]>{ let summary = "yield and termination operation"; let description = [{ Duplication of "scf.yield" at https://github.com/llvm/llvm-project/blob @@ -782,9 +829,8 @@ def YieldOp : QUIR_Op<"yield", [NoSideEffect, ReturnLike, Terminator, ParentOneO let arguments = (ins Variadic:$results); let builders = [OpBuilder<(ins), [{ /* nothing to do */ }]>]; - // TODO in LLVM 15 + this can become just let hasVerifier = 1; - let verifier = [{ return ::verify(*this); }]; let assemblyFormat = "attr-dict ($results^ `:` type($results))?"; + let hasVerifier = 1; } diff --git a/include/Dialect/QUIR/IR/QUIRTypes.td b/include/Dialect/QUIR/IR/QUIRTypes.td index ccfd51e07..5967d5f88 100644 --- a/include/Dialect/QUIR/IR/QUIRTypes.td +++ b/include/Dialect/QUIR/IR/QUIRTypes.td @@ -19,6 +19,7 @@ include "Dialect/QUIR/IR/QUIREnums.td" +include "mlir/IR/AttrTypeBase.td" include "mlir/IR/BuiltinTypeInterfaces.td" include "mlir/IR/OpBase.td" @@ -56,9 +57,11 @@ def QUIR_AngleType : QUIR_Type<"Angle", "angle"> { A QUIR Angle represents a classical angle as a fixed-point number. }]; - let parameters = (ins "Optional":$width); - // TODO in LLVM 15+, the optional width could be handled with assembly declarative syntax. - // let assemblyFormat = "(`<` $width^ `>`)?"; + let parameters = (ins OptionalParameter<"std::optional">:$width); + + + let assemblyFormat = "(`<` $width^ `>`)?"; + let genVerifyDecl = 1; } @@ -73,7 +76,7 @@ def QUIR_DurationType : QUIR_Type<"Duration", "duration"> { ```mlir // Defaults to units at the scheduling rate (dt) %duration_dt = quir.constant #quir.duration<10.0 : !quir.duration> - %duration_s = quir.constant #quir.duration<3.14 : !quir.duration> + %duration_s = quir.constant #quir.duration<3.14> : !quir.duration ``` }]; diff --git a/include/Dialect/QUIR/Transforms/AddShotLoop.h b/include/Dialect/QUIR/Transforms/AddShotLoop.h index a54f91a47..048e2d9c6 100644 --- a/include/Dialect/QUIR/Transforms/AddShotLoop.h +++ b/include/Dialect/QUIR/Transforms/AddShotLoop.h @@ -54,7 +54,7 @@ struct AddShotLoopPass llvm::StringRef getArgument() const override; llvm::StringRef getDescription() const override; - void getDependentDialects(DialectRegistry ®istry) const override { + void getDependentDialects(mlir::DialectRegistry ®istry) const override { registry.insert(); } }; // struct AddShotLoopPass diff --git a/include/Dialect/QUIR/Transforms/AngleConversion.h b/include/Dialect/QUIR/Transforms/AngleConversion.h index 34d20c866..b4c7e1528 100644 --- a/include/Dialect/QUIR/Transforms/AngleConversion.h +++ b/include/Dialect/QUIR/Transforms/AngleConversion.h @@ -21,6 +21,7 @@ #ifndef QUIR_ANGLE_CONVERSION_H #define QUIR_ANGLE_CONVERSION_H +#include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Pass/Pass.h" #include "llvm/ADT/StringRef.h" @@ -37,7 +38,7 @@ struct QUIRAngleConversionPass llvm::StringRef getDescription() const override; private: - std::unordered_map functionOps; + std::unordered_map functionOps; }; // struct QUIRAngleConversionPass } // end namespace mlir::quir diff --git a/include/Dialect/QUIR/Transforms/BreakReset.h b/include/Dialect/QUIR/Transforms/BreakReset.h index f5576ef8b..707c11841 100644 --- a/include/Dialect/QUIR/Transforms/BreakReset.h +++ b/include/Dialect/QUIR/Transforms/BreakReset.h @@ -21,6 +21,7 @@ #ifndef QUIR_BREAK_RESET_H #define QUIR_BREAK_RESET_H +#include "mlir/IR/BuiltinOps.h" #include "mlir/Pass/Pass.h" namespace mlir::quir { @@ -28,7 +29,8 @@ namespace mlir::quir { /// This pass converts input ResetQubitOps to a parameterized number of /// measure and the conditionally called x gates, as well as an optional delay. struct BreakResetPass - : public mlir::PassWrapper> { + : public mlir::PassWrapper> { BreakResetPass() = default; BreakResetPass(const BreakResetPass &pass) : PassWrapper(pass) {} BreakResetPass(uint inNumIterations, uint inDelayCycles) { diff --git a/include/Dialect/QUIR/Transforms/FunctionArgumentSpecialization.h b/include/Dialect/QUIR/Transforms/FunctionArgumentSpecialization.h index 02a88884c..6bf5664e6 100644 --- a/include/Dialect/QUIR/Transforms/FunctionArgumentSpecialization.h +++ b/include/Dialect/QUIR/Transforms/FunctionArgumentSpecialization.h @@ -24,8 +24,8 @@ #define QUIR_FUNCTION_ARGUMENT_SPECIALIZATION_H #include "Dialect/QUIR/IR/QUIROps.h" -#include "mlir/Dialect/SCF/SCF.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" +#include "mlir/Dialect/SCF/IR/SCF.h" +#include "mlir/IR/BuiltinOps.h" #include "mlir/Pass/Pass.h" #include @@ -41,7 +41,7 @@ struct FunctionArgumentSpecializationPass void processCallOp(Operation *op, std::deque &callWorkList); template - void copyFuncAndSpecialize(FuncOp inFunc, CallOpTy callOp, + void copyFuncAndSpecialize(mlir::func::FuncOp inFunc, CallOpTy callOp, std::deque &callWorkList); void runOnOperation() override; diff --git a/include/Dialect/QUIR/Transforms/MergeParallelResets.h b/include/Dialect/QUIR/Transforms/MergeParallelResets.h index a72b71b32..4ac49e656 100644 --- a/include/Dialect/QUIR/Transforms/MergeParallelResets.h +++ b/include/Dialect/QUIR/Transforms/MergeParallelResets.h @@ -21,6 +21,7 @@ #ifndef QUIR_MERGE_PARALLEL_RESETS_H #define QUIR_MERGE_PARALLEL_RESETS_H +#include "mlir/IR/BuiltinOps.h" #include "mlir/Pass/Pass.h" namespace mlir::quir { diff --git a/include/Dialect/QUIR/Transforms/RemoveQubitOperands.h b/include/Dialect/QUIR/Transforms/RemoveQubitOperands.h index 7e1da74ed..625ed6d83 100644 --- a/include/Dialect/QUIR/Transforms/RemoveQubitOperands.h +++ b/include/Dialect/QUIR/Transforms/RemoveQubitOperands.h @@ -38,7 +38,7 @@ namespace mlir::quir { struct RemoveQubitOperandsPass : public PassWrapper> { auto lookupQubitId(const Value val) -> int; - void addQubitDeclarations(FuncOp funcOp); + void addQubitDeclarations(mlir::func::FuncOp funcOp); void processCallOp(Operation *op); void runOnOperation() override; diff --git a/include/Dialect/QUIR/Transforms/VariableElimination.h b/include/Dialect/QUIR/Transforms/VariableElimination.h index c92f3da57..af934ca5d 100644 --- a/include/Dialect/QUIR/Transforms/VariableElimination.h +++ b/include/Dialect/QUIR/Transforms/VariableElimination.h @@ -40,9 +40,9 @@ struct VariableEliminationPass llvm::StringRef getArgument() const override; llvm::StringRef getDescription() const override; - void getDependentDialects(DialectRegistry ®istry) const override { + void getDependentDialects(mlir::DialectRegistry ®istry) const override { registry.insert(); - registry.insert(); + registry.insert(); } }; // struct VariableEliminationPass diff --git a/include/Dialect/QUIR/Utils/Utils.h b/include/Dialect/QUIR/Utils/Utils.h index 17aaec4f9..1f2f6132e 100644 --- a/include/Dialect/QUIR/Utils/Utils.h +++ b/include/Dialect/QUIR/Utils/Utils.h @@ -91,49 +91,49 @@ template void qubitArgIndices(CallOpTy &callOp, llvm::BitVector &vec); /// Lookup a qubit id from a value. -llvm::Optional lookupQubitId(const Value &val); +std::optional lookupQubitId(const Value &val); /// Get the next Op that has the CPTPOp or UnitaryOp trait, or return null if /// none found // TODO: Should be replaced by an analysis compatable struct. -llvm::Optional nextQuantumOpOrNull(Operation *op); +std::optional nextQuantumOpOrNull(Operation *op); /// \brief Get the next Op that has the CPTPOp or UnitaryOp trait, return it if /// it is of type OpType, otherwise return null // TODO: Should be replaced by an analysis compatable struct. template -llvm::Optional nextQuantumOpOrNullOfType(Operation *op) { +std::optional nextQuantumOpOrNullOfType(Operation *op) { auto nextOperation = nextQuantumOpOrNull(op); if (nextOperation && isa(*nextOperation)) return dyn_cast(*nextOperation); - return llvm::None; + return std::nullopt; } /// Get the previous Op that has the CPTPOp or UnitaryOp trait, or return null /// if none found // TODO: Should be replaced by an analysis compatable struct. -llvm::Optional prevQuantumOpOrNull(Operation *op); +std::optional prevQuantumOpOrNull(Operation *op); /// \brief Get the previous Op that has the CPTPOp or UnitaryOp trait, return /// it if it is of type OpType, otherwise return null // TODO: Should be replaced by an analysis compatable struct. template -llvm::Optional prevQuantumOpOrNullOfType(Operation *op) { +std::optional prevQuantumOpOrNullOfType(Operation *op) { auto prevOperation = prevQuantumOpOrNull(op); if (prevOperation && isa(*prevOperation)) return dyn_cast(*prevOperation); - return llvm::None; + return std::nullopt; } /// Get the next Op that has the CPTPOp or UnitaryOp trait, or is control flow /// (has the RegionBranchOpInterface::Trait), or return null if none found // TODO: Should be replaced by an analysis compatable struct. -llvm::Optional nextQuantumOrControlFlowOrNull(Operation *op); +std::optional nextQuantumOrControlFlowOrNull(Operation *op); /// Get the previous Op that has the CPTPOp or UnitaryOp trait, or is control /// flow (has the RegionBranchOpInterface::Trait), or return null if none found // TODO: Should be replaced by an analysis compatable struct. -llvm::Optional prevQuantumOrControlFlowOrNull(Operation *op); +std::optional prevQuantumOrControlFlowOrNull(Operation *op); /// \brief Check if the operation is a quantum operation bool isQuantumOp(Operation *op); diff --git a/include/Dialect/RegisterDialects.h b/include/Dialect/RegisterDialects.h index a4a06c0be..9eb78cb7e 100644 --- a/include/Dialect/RegisterDialects.h +++ b/include/Dialect/RegisterDialects.h @@ -21,6 +21,7 @@ #ifndef UTILS_DIALECTUTILS_H #define UTILS_DIALECTUTILS_H +#include "mlir/IR/DialectRegistry.h" #include "mlir/InitAllDialects.h" #include "Dialect/OQ3/IR/OQ3Dialect.h" @@ -31,12 +32,10 @@ namespace qssc::dialect { /// Register all qss-compiler dialects returning a dialect registry -inline mlir::DialectRegistry registerDialects() { - mlir::DialectRegistry registry; +inline void registerDialects(mlir::DialectRegistry ®istry) { mlir::registerAllDialects(registry); registry.insert(); - return registry; } } // namespace qssc::dialect diff --git a/include/Dialect/RegisterPasses.h b/include/Dialect/RegisterPasses.h new file mode 100644 index 000000000..ab6b4678c --- /dev/null +++ b/include/Dialect/RegisterPasses.h @@ -0,0 +1,60 @@ +//===- OperationUtils.h -----------------------------------------*- C++ -*-===// +// +// (C) Copyright IBM 2023. +// +// This code is part of Qiskit. +// +// This code is licensed under the Apache License, Version 2.0 with LLVM +// Exceptions. You may obtain a copy of this license in the LICENSE.txt +// file in the root directory of this source tree. +// +// Any modifications or derivative works of this code must retain this +// copyright notice, and modified files need to carry a notice indicating +// that they have been altered from the originals. +// +//===----------------------------------------------------------------------===// +/// +/// Utility functions related to MLIR Dialect handling. +/// +//===----------------------------------------------------------------------===// + +#ifndef REGISTER_PASSES_H +#define REGISTER_PASSES_H + +#include "Dialect/OQ3/IR/OQ3Dialect.h" +#include "Dialect/OQ3/Transforms/Passes.h" +#include "Dialect/Pulse/IR/PulseDialect.h" +#include "Dialect/Pulse/Transforms/Passes.h" +#include "Dialect/QCS/IR/QCSDialect.h" +#include "Dialect/QCS/Utils/ParameterInitialValueAnalysis.h" +#include "Dialect/QUIR/IR/QUIRDialect.h" +#include "Dialect/QUIR/Transforms/Passes.h" +#include "HAL/PassRegistration.h" + +#include "mlir/InitAllPasses.h" + +namespace qssc::dialect { + +/// Register all qss-compiler passes +inline llvm::Error registerPasses() { + // TODO: Register standalone passes here. + llvm::Error err = llvm::Error::success(); + mlir::oq3::registerOQ3Passes(); + mlir::oq3::registerOQ3PassPipeline(); + mlir::qcs::registerQCSPasses(); + mlir::quir::registerQuirPasses(); + mlir::quir::registerQuirPassPipeline(); + mlir::pulse::registerPulsePasses(); + mlir::pulse::registerPulsePassPipeline(); + mlir::registerConversionPasses(); + + err = llvm::joinErrors(std::move(err), qssc::hal::registerTargetPasses()); + err = llvm::joinErrors(std::move(err), qssc::hal::registerTargetPipelines()); + + mlir::registerAllPasses(); + return err; +} + +} // namespace qssc::dialect + +#endif // REGISTER_PASSES_H diff --git a/include/Frontend/OpenQASM3/QUIRVariableBuilder.h b/include/Frontend/OpenQASM3/QUIRVariableBuilder.h index 88353a964..49397e74c 100644 --- a/include/Frontend/OpenQASM3/QUIRVariableBuilder.h +++ b/include/Frontend/OpenQASM3/QUIRVariableBuilder.h @@ -22,17 +22,15 @@ #ifndef OPENQASM3_QUIR_VARIABLE_BUILDER_H #define OPENQASM3_QUIR_VARIABLE_BUILDER_H -#include -#include -#include +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinOps.h" + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" #include #include -#include -#include -#include - #include namespace qssc::frontend::openqasm3 { diff --git a/include/HAL/Compile/TargetCompilationManager.h b/include/HAL/Compile/TargetCompilationManager.h index 994e431f4..28018aa11 100644 --- a/include/HAL/Compile/TargetCompilationManager.h +++ b/include/HAL/Compile/TargetCompilationManager.h @@ -43,12 +43,17 @@ class TargetCompilationManager { TargetCompilationManager(hal::TargetSystem &target, mlir::MLIRContext *context); - using WalkTargetFunction = + using WalkTargetModulesFunction = std::function; + using WalkTargetFunction = std::function; + // Depth first walker for a target system - llvm::Error walkTarget(Target *target, mlir::ModuleOp targetModuleOp, - const WalkTargetFunction &walkFunc, - const WalkTargetFunction &postChildrenCallbackFunc); + llvm::Error walkTarget(Target *target, const WalkTargetFunction &walkFunc); + // Depth first walker for a target system modules + llvm::Error + walkTargetModules(Target *target, mlir::ModuleOp targetModuleOp, + const WalkTargetModulesFunction &walkFunc, + const WalkTargetModulesFunction &postChildrenCallbackFunc); public: virtual ~TargetCompilationManager() = default; @@ -91,8 +96,9 @@ class TargetCompilationManager { return printAfterTargetCompileFailure; } - void printIR(llvm::StringRef msg, mlir::Operation *op, - llvm::raw_ostream &out); + /// Thread-safe implementation + virtual void printIR(llvm::StringRef msg, mlir::Operation *op, + llvm::raw_ostream &out); private: hal::TargetSystem ⌖ diff --git a/include/HAL/Compile/ThreadedCompilationManager.h b/include/HAL/Compile/ThreadedCompilationManager.h index aa6446575..fbc64b8a1 100644 --- a/include/HAL/Compile/ThreadedCompilationManager.h +++ b/include/HAL/Compile/ThreadedCompilationManager.h @@ -23,6 +23,7 @@ #include "HAL/Compile/TargetCompilationManager.h" +#include #include namespace qssc::hal::compile { @@ -45,11 +46,19 @@ class ThreadedCompilationManager : public TargetCompilationManager { /// Threaded depth first walker for a target system using the current /// MLIRContext's threadpool. llvm::Error walkTargetThreaded( + Target *target, + const TargetCompilationManager::WalkTargetFunction &walkFunc); + /// Threaded depth first walker for a target system modules using the current + /// MLIRContext's threadpool. + llvm::Error walkTargetModulesThreaded( Target *target, mlir::ModuleOp targetModuleOp, - const TargetCompilationManager::WalkTargetFunction &walkFunc, - const TargetCompilationManager::WalkTargetFunction + const TargetCompilationManager::WalkTargetModulesFunction &walkFunc, + const TargetCompilationManager::WalkTargetModulesFunction &postChildrenCallbackFunc); + virtual void printIR(llvm::StringRef msg, mlir::Operation *op, + llvm::raw_ostream &out) override; + public: using PMBuilder = std::function; @@ -68,16 +77,41 @@ class ThreadedCompilationManager : public TargetCompilationManager { } llvm::ThreadPool &getThreadPool() { return getContext()->getThreadPool(); } - llvm::Error buildTargetPassManager(mlir::PassManager &pm); - private: + // Used to store initialized and registered pass managers + // with the context prior to compilation. + std::map targetPassManagers_; + // target pass manager map mutex + std::shared_mutex targetPassManagersMutex_; + + // ensures we register passes with the context + // in a threadsafe way. + std::mutex contextMutex_; + + // ensures we print in order when threading + std::mutex printIRMutex_; + + /// Prepare pass managers in a threaded way + /// initializing them with the mlir context safely. + llvm::Error buildTargetPassManagers_(Target &target); + /// Threadsafe initialization of PM to work around + /// non-threadsafe registration of dependent dialects. + /// I (Thomas) believe this is related to the conversation here + /// https://discourse.llvm.org/t/caching-and-parallel-compilation/67907 + /// and will follow up in the thread. + void registerPassManagerWithContext_(mlir::PassManager &pm); + /// Thread safely get the passmanager for a target. + mlir::PassManager &getTargetPassManager_(Target *target); + /// Thread safely set the passmanager for a target. + mlir::PassManager &createTargetPassManager_(Target *target); + /// Compiles the input module for a single target. - llvm::Error compileMLIRTarget(Target &target, mlir::ModuleOp targetModuleOp); + llvm::Error compileMLIRTarget_(Target &target, mlir::ModuleOp targetModuleOp); /// Compiles the input payload for a single target. - llvm::Error compilePayloadTarget(Target &target, - mlir::ModuleOp targetModuleOp, - qssc::payload::Payload &payload, - bool doCompileMLIR); + llvm::Error compilePayloadTarget_(Target &target, + mlir::ModuleOp targetModuleOp, + qssc::payload::Payload &payload, + bool doCompileMLIR); PMBuilder pmBuilder; diff --git a/include/HAL/SystemConfiguration.h b/include/HAL/SystemConfiguration.h index 7c2f4c4e4..9f93fc9d4 100644 --- a/include/HAL/SystemConfiguration.h +++ b/include/HAL/SystemConfiguration.h @@ -24,7 +24,6 @@ #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" -#include "llvm/ADT/None.h" #include #include diff --git a/include/HAL/TargetOperationPass.h b/include/HAL/TargetOperationPass.h index 3d652fc07..0853d847f 100644 --- a/include/HAL/TargetOperationPass.h +++ b/include/HAL/TargetOperationPass.h @@ -61,16 +61,18 @@ class TargetOperationPass : public mlir::OperationPass { return nullptr; } - auto target = targetInfo.getValue()->getTarget( - &mlir::OperationPass::getContext()); + auto target = + targetInfo.value()->getTarget(&mlir::OperationPass::getContext()); if (!target) { // look for a child target that matches - for (const auto &childName : TargetT::childNames) - if ((targetInfo = - registry::TargetSystemRegistry::lookupPluginInfo(childName)) && - (target = targetInfo.getValue()->getTarget( - &mlir::OperationPass::getContext()))) + for (const auto &childName : TargetT::childNames) { + targetInfo = + registry::TargetSystemRegistry::lookupPluginInfo(childName); + target = targetInfo.value()->getTarget( + &mlir::OperationPass::getContext()); + if (targetInfo && target) break; + } if (!target) { llvm::errs() << "Error: failed to get target '" << TargetT::name << "':\n"; diff --git a/include/HAL/TargetSystem.h b/include/HAL/TargetSystem.h index 7bc53fb31..e49e68c51 100644 --- a/include/HAL/TargetSystem.h +++ b/include/HAL/TargetSystem.h @@ -22,7 +22,6 @@ #include "Arguments/Arguments.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/iterator_range.h" @@ -30,6 +29,7 @@ #include "mlir/Pass/PassManager.h" #include "mlir/Pass/PassRegistry.h" +#include #include #include @@ -160,9 +160,9 @@ class TargetSystem : public Target { children_.push_back(std::move(child)); } - virtual llvm::Optional + virtual std::optional getBindArgumentsImplementationFactory() { - return llvm::None; + return std::nullopt; }; llvm::Expected getInstrumentWithNodeId(uint nodeId) const; diff --git a/include/HAL/TargetSystemInfo.h b/include/HAL/TargetSystemInfo.h index 7f4e32496..1791d1f0f 100644 --- a/include/HAL/TargetSystemInfo.h +++ b/include/HAL/TargetSystemInfo.h @@ -42,7 +42,7 @@ class TargetSystemInfo /// Create the target system and register it under the given context. llvm::Expected createTarget(mlir::MLIRContext *context, - llvm::Optional configuration); + std::optional configuration); /// Get the target system registered for the given context. First checks for /// a target registered exactly for the given context. If no such context is diff --git a/include/Plugin/PluginInfo.h b/include/Plugin/PluginInfo.h index 74d0fdc36..c4eaa682b 100644 --- a/include/Plugin/PluginInfo.h +++ b/include/Plugin/PluginInfo.h @@ -26,7 +26,7 @@ class PluginInfo { using PluginConfiguration = typename PluginType::PluginConfiguration; using PluginFactoryFunction = std::function>( - llvm::Optional configuration)>; + std::optional configuration)>; public: PluginInfo(llvm::StringRef name, llvm::StringRef description, @@ -42,7 +42,7 @@ class PluginInfo { /// Returns a new instance of the registered PluginType llvm::Expected> - createPluginInstance(llvm::Optional configuration) { + createPluginInstance(std::optional configuration) { return factoryFunction(configuration); } diff --git a/include/Plugin/PluginRegistry.h b/include/Plugin/PluginRegistry.h index bf349acb5..c048ee998 100644 --- a/include/Plugin/PluginRegistry.h +++ b/include/Plugin/PluginRegistry.h @@ -14,10 +14,11 @@ #ifndef PLUGINREGISTRY_H #define PLUGINREGISTRY_H -#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/ManagedStatic.h" +#include + namespace qssc::plugin::registry { template @@ -35,12 +36,12 @@ struct PluginRegistry { return inserted; } - static llvm::Optional + static std::optional lookupPluginInfo(llvm::StringRef pluginName) { PluginRegistry &pluginRegistry = instance(); auto it = pluginRegistry.registry.find(pluginName); if (it == pluginRegistry.registry.end()) - return llvm::None; + return std::nullopt; return &it->second; } @@ -51,7 +52,7 @@ struct PluginRegistry { } static const llvm::StringMap ®isteredPlugins() { - PluginRegistry &pluginRegistry = instance(); + PluginRegistry const &pluginRegistry = instance(); return pluginRegistry.registry; } diff --git a/include/QSSC.h b/include/QSSC.h index ef4eda9a2..c577777d1 100644 --- a/include/QSSC.h +++ b/include/QSSC.h @@ -23,11 +23,12 @@ #ifndef QSSC_H #define QSSC_H -#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" #include +#include #include namespace qssc { diff --git a/lib/API/api.cpp b/lib/API/api.cpp index c78f19a2d..f2cba85e5 100644 --- a/lib/API/api.cpp +++ b/lib/API/api.cpp @@ -15,72 +15,85 @@ //===----------------------------------------------------------------------===// #include "API/api.h" + #include "API/errors.h" +#include "Arguments/Arguments.h" #include "Config/CLIConfig.h" #include "Config/EnvVarConfig.h" +#include "Config/QSSConfig.h" +#include "Dialect/OQ3/Transforms/Passes.h" +#include "Dialect/Pulse/Transforms/Passes.h" +#include "Dialect/QCS/Utils/ParameterInitialValueAnalysis.h" +#include "Dialect/QUIR/Transforms/Passes.h" +#include "Dialect/RegisterDialects.h" +#include "Dialect/RegisterPasses.h" +#include "Frontend/OpenQASM3/OpenQASM3Frontend.h" +#include "HAL/Compile/TargetCompilationManager.h" +#include "HAL/Compile/ThreadedCompilationManager.h" +#include "HAL/PassRegistration.h" +#include "HAL/TargetSystem.h" +#include "HAL/TargetSystemInfo.h" +#include "HAL/TargetSystemRegistry.h" +#include "Payload/Payload.h" +#include "Payload/PayloadRegistry.h" +#include "Plugin/PluginInfo.h" +#include "QSSC.h" +#include "mlir/Conversion/Passes.h" #include "mlir/IR/AsmState.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/Diagnostics.h" -#include "mlir/IR/Dialect.h" +#include "mlir/IR/DialectRegistry.h" +#include "mlir/IR/Location.h" #include "mlir/IR/MLIRContext.h" +#include "mlir/IR/OwningOpRef.h" +#include "mlir/InitAllExtensions.h" #include "mlir/InitAllPasses.h" -#include "mlir/Parser.h" +#include "mlir/Parser/Parser.h" #include "mlir/Pass/PassManager.h" +#include "mlir/Pass/PassRegistry.h" #include "mlir/Support/FileUtilities.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" #include "mlir/Support/Timing.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FileSystem.h" #include "llvm/Support/InitLLVM.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/ToolOutputFile.h" - -#include "Arguments/Arguments.h" -#include "Payload/Payload.h" -#include "Payload/PayloadRegistry.h" -#include "QSSC.h" - -#include "HAL/Compile/ThreadedCompilationManager.h" -#include "HAL/PassRegistration.h" -#include "HAL/TargetSystem.h" -#include "HAL/TargetSystemRegistry.h" - -#include "Dialect/OQ3/Transforms/Passes.h" -#include "Dialect/Pulse/IR/PulseDialect.h" -#include "Dialect/Pulse/Transforms/Passes.h" -#include "Dialect/QCS/Utils/ParameterInitialValueAnalysis.h" -#include "Dialect/QUIR/Transforms/Passes.h" -#include "Dialect/RegisterDialects.h" - -#include "Frontend/OpenQASM3/OpenQASM3Frontend.h" +#include "llvm/Support/raw_ostream.h" #include #include +#include +#include +#include +#include #include +#include #include using namespace mlir; -static llvm::cl::opt inputSource( +namespace { +llvm::cl::opt inputSource( llvm::cl::Positional, llvm::cl::desc("Input filename or program source"), llvm::cl::init("-"), llvm::cl::cat(qssc::config::getQSSCCategory())); -static llvm::cl::opt +llvm::cl::opt outputFilename("o", llvm::cl::desc("Output filename"), llvm::cl::value_desc("filename"), llvm::cl::init("-"), llvm::cl::cat(qssc::config::getQSSCCategory())); -static llvm::cl::opt +llvm::cl::opt directInput("direct", llvm::cl::desc("Accept the input program directly as a string"), llvm::cl::cat(qssc::config::getQSSCCategory())); -static llvm::cl::opt verifyDiagnostics( +llvm::cl::opt verifyDiagnostics( "verify-diagnostics", llvm::cl::desc("Check that emitted diagnostics match " "expected-* lines on the corresponding line"), @@ -92,49 +105,48 @@ static llvm::cl::opt verifyDiagnostics( #define VERIFY_PASSES_DEFAULT false #endif -static llvm::cl::opt verifyPasses( +llvm::cl::opt verifyPasses( "verify-each", llvm::cl::desc("Run the verifier after each transformation pass"), llvm::cl::init(VERIFY_PASSES_DEFAULT), llvm::cl::cat(qssc::config::getQSSCCategory())); -static llvm::cl::opt showDialects( +llvm::cl::opt showDialects( "show-dialects", llvm::cl::desc("Print the list of registered dialects"), llvm::cl::init(false), llvm::cl::cat(qssc::config::getQSSCCategory())); -static llvm::cl::opt showTargets( +llvm::cl::opt showTargets( "show-targets", llvm::cl::desc("Print the list of registered targets"), llvm::cl::init(false), llvm::cl::cat(qssc::config::getQSSCCategory())); -static llvm::cl::opt showPayloads( +llvm::cl::opt showPayloads( "show-payloads", llvm::cl::desc("Print the list of registered payloads"), llvm::cl::init(false), llvm::cl::cat(qssc::config::getQSSCCategory())); -static llvm::cl::opt showConfig( +llvm::cl::opt showConfig( "show-config", llvm::cl::desc("Print the loaded compiler configuration."), llvm::cl::init(false), llvm::cl::cat(qssc::config::getQSSCCategory())); -static llvm::cl::opt plaintextPayload( +llvm::cl::opt plaintextPayload( "plaintext-payload", llvm::cl::desc("Write the payload in plaintext"), llvm::cl::init(false), llvm::cl::cat(qssc::config::getQSSCCategory())); -static llvm::cl::opt includeSourceInPayload( +llvm::cl::opt includeSourceInPayload( "include-source", llvm::cl::desc("Write the input source into the payload"), llvm::cl::init(false), llvm::cl::cat(qssc::config::getQSSCCategory())); -static llvm::cl::opt compileTargetIr( +llvm::cl::opt compileTargetIr( "compile-target-ir", llvm::cl::desc("Apply the target's IR compilation"), llvm::cl::init(false), llvm::cl::cat(qssc::config::getQSSCCategory())); -static llvm::cl::opt bypassPayloadTargetCompilation( +llvm::cl::opt bypassPayloadTargetCompilation( "bypass-payload-target-compilation", llvm::cl::desc("Bypass target compilation during payload generation."), llvm::cl::init(false), llvm::cl::cat(qssc::config::getQSSCCategory())); -namespace { enum InputType { NONE, QASM, MLIR, QOBJ }; -} // anonymous namespace -static llvm::cl::opt inputType( + +llvm::cl::opt inputType( "X", llvm::cl::init(InputType::NONE), llvm::cl::desc("Specify the kind of input desired"), llvm::cl::values( @@ -145,7 +157,6 @@ static llvm::cl::opt inputType( llvm::cl::values(clEnumValN(QOBJ, "qobj", "load the input file as a QOBJ file"))); -namespace { enum Action { None, DumpAST, @@ -155,8 +166,8 @@ enum Action { GenQEM, GenQEQEM }; -} // anonymous namespace -static llvm::cl::opt emitAction( + +llvm::cl::opt emitAction( "emit", llvm::cl::init(Action::None), llvm::cl::desc("Select the kind of output desired"), llvm::cl::values(clEnumValN(DumpAST, "ast", "output the AST dump")), @@ -172,6 +183,7 @@ static llvm::cl::opt emitAction( GenQEQEM, "qe-qem", "generate a target-specific quantum executable module (qeqem) " "for execution on hardware"))); +} // anonymous namespace namespace qss { enum FileExtension { None, AST, ASTPRETTY, QASM, QOBJ, MLIR, WMEM, QEM, QEQEM }; @@ -300,7 +312,7 @@ llvm::Error registerPasses() { return err; } -auto registerCLOpts() { +auto registerPassManagerCLOpts() { mlir::registerAsmPrinterCLOptions(); mlir::registerMLIRContextCLOptions(); mlir::registerPassManagerCLOptions(); @@ -331,7 +343,7 @@ llvm::Error determineInputType() { void determineOutputType() { if (outputFilename != "-") { - Action extensionAction = + Action const extensionAction = fileExtensionToAction(getExtension(outputFilename)); if (extensionAction == Action::None && emitAction == Action::None) { llvm::errs() @@ -350,7 +362,8 @@ void determineOutputType() { } } -static void printVersion(llvm::raw_ostream &out) { +namespace { +void printVersion(llvm::raw_ostream &out) { out << "Quantum System Software (QSS) compiler version " << qssc::getQSSCVersion() << "\n"; } @@ -366,7 +379,7 @@ static void printVersion(llvm::raw_ostream &out) { /// @param context The context to build and register the configuration for. /// @return The constructed configuration that has been registered for the /// supplied context. -static llvm::Expected +llvm::Expected buildConfig_(mlir::MLIRContext *context) { // First populate the configuration from default values then // environment variables. @@ -383,21 +396,21 @@ buildConfig_(mlir::MLIRContext *context) { return std::move(err); // Set this as the configuration for the current context - qssc::config::setContextConfig(context, std::move(*config)); + qssc::config::setContextConfig(context, *config); // Return a constant reference to the managed configuration return qssc::config::getContextConfig(context); } /// @brief Emit the registered dialects to llvm::outs -static void showDialects_(const DialectRegistry ®istry) { +void showDialects_(const DialectRegistry ®istry) { llvm::outs() << "Registered Dialects:\n"; for (const auto ®isteredDialect : registry.getDialectNames()) llvm::outs() << registeredDialect << "\n"; } /// @brief Emit the registered targets to llvm::outs -static void showTargets_() { +void showTargets_() { llvm::outs() << "Registered Targets:\n"; for (const auto &target : qssc::hal::registry::TargetSystemRegistry::registeredPlugins()) { @@ -408,7 +421,7 @@ static void showTargets_() { } /// @brief Emit the registered payload to llvm::outs -static void showPayloads_() { +void showPayloads_() { llvm::outs() << "Registered Payloads:\n"; for (const auto &payload : qssc::payload::registry::PayloadRegistry::registeredPlugins()) { @@ -422,7 +435,7 @@ static void showPayloads_() { /// @param context The supplied context to build the target for. /// @param config The configuration defining the context to build. /// @return The constructed TargetSystem. -static llvm::Expected +llvm::Expected buildTarget_(MLIRContext *context, const qssc::config::QSSConfig &config) { const auto &targetName = config.targetName; const auto &targetConfigPath = config.targetConfigPath; @@ -442,10 +455,10 @@ buildTarget_(MLIRContext *context, const qssc::config::QSSConfig &config) { qssc::hal::registry::TargetSystemInfo &targetInfo = *qssc::hal::registry::TargetSystemRegistry::lookupPluginInfo( targetName.value_or("")) - .getValueOr(qssc::hal::registry::TargetSystemRegistry:: - nullTargetSystemInfo()); + .value_or(qssc::hal::registry::TargetSystemRegistry:: + nullTargetSystemInfo()); - llvm::Optional conf{}; + std::optional conf{}; if (targetConfigPath.has_value()) conf.emplace(*targetConfigPath); @@ -466,7 +479,7 @@ buildTarget_(MLIRContext *context, const qssc::config::QSSConfig &config) { /// @param moduleOp The module to build for /// @param ostream The output ostream to populate /// @return The output error if one occurred. -static llvm::Error generateQEM_( +llvm::Error generateQEM_( qssc::hal::compile::TargetCompilationManager *targetCompilationManager, std::unique_ptr payload, mlir::ModuleOp moduleOp, llvm::raw_ostream *ostream) { @@ -487,26 +500,31 @@ static llvm::Error generateQEM_( /// @brief Print the output to an ostream. /// @param ostream The ostream to populate. /// @param moduleOp The ModuleOp to dump. -static void dumpMLIR_(llvm::raw_ostream *ostream, mlir::ModuleOp moduleOp) { +void dumpMLIR_(llvm::raw_ostream *ostream, mlir::ModuleOp moduleOp) { moduleOp.print(*ostream); *ostream << '\n'; } using ErrorHandler = function_ref; -static void buildPassManager_(mlir::PassManager &pm) { - mlir::applyPassManagerCLOptions(pm); +llvm::Error buildPassManager_(mlir::PassManager &pm) { + if (mlir::failed(mlir::applyPassManagerCLOptions(pm))) + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Unable to apply pass manager command line options"); mlir::applyDefaultTimingPassManagerCLOptions(pm); // Configure verifier pm.enableVerifier(verifyPasses); + + return llvm::Error::success(); } -static llvm::Error -buildPassManager(mlir::PassManager &pm, - mlir::PassPipelineCLParser &passPipelineParser, - ErrorHandler errorHandler) { - buildPassManager_(pm); +llvm::Error buildPassManager(mlir::PassManager &pm, + mlir::PassPipelineCLParser &passPipelineParser, + ErrorHandler errorHandler) { + if (auto err = buildPassManager_(pm)) + return err; // Build the provided pipeline. if (failed(passPipelineParser.addToPipeline(pm, errorHandler))) return llvm::createStringError(llvm::inconvertibleErrorCode(), @@ -523,7 +541,7 @@ buildPassManager(mlir::PassManager &pm, /// @param passPipelineParser The Parser for the passpipeline /// @param errorHandler MLIR error handler /// @return -static llvm::Error emitMLIR_( +llvm::Error emitMLIR_( llvm::raw_ostream *ostream, mlir::MLIRContext &context, mlir::ModuleOp moduleOp, const qssc::config::QSSConfig &config, qssc::hal::compile::ThreadedCompilationManager &targetCompilationManager, @@ -550,7 +568,7 @@ static llvm::Error emitMLIR_( /// @param moduleOp The module operation to process and emit /// @param targetCompilationManager The target's compilation scheduler /// @return -static llvm::Error emitQEM_( +llvm::Error emitQEM_( llvm::raw_ostream *ostream, std::unique_ptr payload, mlir::ModuleOp moduleOp, qssc::hal::compile::ThreadedCompilationManager &targetCompilationManager) { @@ -592,9 +610,8 @@ static llvm::Error emitQEM_( /// Prints diagnostic to llvm::errs to mimic default handler. /// @param diagnostic MLIR diagnostic from the Diagnostic Engine /// @param diagnosticCb Handle to python diagnostic callback -static void -diagEngineHandler(mlir::Diagnostic &diagnostic, - std::optional diagnosticCb) { +void diagEngineHandler(mlir::Diagnostic &diagnostic, + std::optional diagnosticCb) { // map diagnostic severity to qssc severity auto severity = diagnostic.getSeverity(); @@ -638,24 +655,27 @@ diagEngineHandler(mlir::Diagnostic &diagnostic, return; } -static llvm::Error -compile_(int argc, char const **argv, std::string *outputString, - std::optional diagnosticCb) { +llvm::Error compile_(int argc, char const **argv, std::string *outputString, + std::optional diagnosticCb) { // Initialize LLVM to start. - llvm::InitLLVM y(argc, argv); + llvm::InitLLVM const y(argc, argv); // Register the standard passes with MLIR. // Must precede the command line parsing. - if (auto err = registerPasses()) + if (auto err = qssc::dialect::registerPasses()) return err; // Register the standard dialects with MLIR and prepare a registry and pass // pipeline - DialectRegistry registry = qssc::dialect::registerDialects(); + mlir::DialectRegistry registry; + qssc::dialect::registerDialects(registry); + + // Register all extensions + mlir::registerAllExtensions(registry); // Parse the command line options. mlir::PassPipelineCLParser passPipelineParser("", "Compiler passes to run"); - registerCLOpts(); + registerPassManagerCLOpts(); llvm::cl::SetVersionPrinter(&printVersion); llvm::cl::ParseCommandLineOptions( argc, argv, "Quantum System Software (QSS) Backend Compiler\n"); @@ -725,7 +745,7 @@ compile_(int argc, char const **argv, std::string *outputString, // Set up the output. llvm::raw_ostream *ostream; - llvm::Optional outStringStream; + std::optional outStringStream; auto outputFile = mlir::openOutputFile(outputFilename, &errorMessage); std::unique_ptr payload = nullptr; @@ -740,24 +760,25 @@ compile_(int argc, char const **argv, std::string *outputString, (emitAction == Action::GenQEM) ? "ZIP" : config.targetName.value(); auto payloadInfo = qssc::payload::registry::PayloadRegistry::lookupPluginInfo(payloadName); - if (payloadInfo == llvm::None) + if (payloadInfo == std::nullopt) return llvm::createStringError(llvm::inconvertibleErrorCode(), "Unsupported target-specific payload: " + payloadName); if (outputFilename == "-") { payload = std::move( - payloadInfo.getValue()->createPluginInstance(llvm::None).get()); + payloadInfo.value()->createPluginInstance(std::nullopt).get()); } else { const qssc::payload::PayloadConfig payloadConfig{fNamePrefix, fNamePrefix}; payload = std::move( - payloadInfo.getValue()->createPluginInstance(payloadConfig).get()); + payloadInfo.value()->createPluginInstance(payloadConfig).get()); } } if (outputString) { outStringStream.emplace(*outputString); - ostream = outStringStream.getPointer(); + if (outStringStream.has_value()) + ostream = std::addressof(*outStringStream); } else { if (!outputFile) return llvm::createStringError(llvm::inconvertibleErrorCode(), @@ -800,12 +821,12 @@ compile_(int argc, char const **argv, std::string *outputString, // Disable multi-threading when parsing the input file. This removes the // unnecessary/costly context synchronization when parsing. - bool wasThreadingEnabled = context.isMultithreadingEnabled(); + bool const wasThreadingEnabled = context.isMultithreadingEnabled(); context.disableMultithreading(); // Parse the input file and reset the context threading state. - mlir::OwningOpRef module( - mlir::parseSourceFile(sourceMgr, &context)); + mlir::OwningOpRef module = + mlir::parseSourceFile(sourceMgr, &context); context.enableMultithreading(wasThreadingEnabled); if (!module) return llvm::createStringError(llvm::inconvertibleErrorCode(), @@ -828,8 +849,9 @@ compile_(int argc, char const **argv, std::string *outputString, auto targetCompilationManager = qssc::hal::compile::ThreadedCompilationManager( - target, &context, [&](mlir::PassManager &pm) { - buildPassManager_(pm); + target, &context, [&](mlir::PassManager &pm) -> llvm::Error { + if (auto err = buildPassManager_(pm)) + return err; return llvm::Error::success(); }); if (mlir::failed(qssc::hal::compile::applyTargetCompilationManagerCLOptions( @@ -865,7 +887,6 @@ compile_(int argc, char const **argv, std::string *outputString, // Keep the output if no errors have occurred so far if (outputString) { - outStringStream.getValue().str(); if (outputFile && outputFilename != "-") outputFile->os() << *outputString; } @@ -874,6 +895,7 @@ compile_(int argc, char const **argv, std::string *outputString, return llvm::Error::success(); } +} // anonymous namespace int qssc::compile(int argc, char const **argv, std::string *outputString, std::optional diagnosticCb) { @@ -894,11 +916,11 @@ class MapAngleArgumentSource : public qssc::arguments::ArgumentSource { qssc::arguments::ArgumentType getArgumentValue(llvm::StringRef name) const override { - std::string name_{name}; + std::string const name_{name}; auto pos = parameterMap.find(name_); if (pos == parameterMap.end()) - return llvm::None; + return std::nullopt; return pos->second; } @@ -918,8 +940,8 @@ _bindArguments(std::string_view target, std::string_view configPath, qssc::hal::registry::TargetSystemInfo &targetInfo = *qssc::hal::registry::TargetSystemRegistry::lookupPluginInfo(target) - .getValueOr(qssc::hal::registry::TargetSystemRegistry:: - nullTargetSystemInfo()); + .value_or(qssc::hal::registry::TargetSystemRegistry:: + nullTargetSystemInfo()); auto created = targetInfo.createTarget(&context, llvm::StringRef(configPath)); if (auto err = created.takeError()) { @@ -937,17 +959,17 @@ _bindArguments(std::string_view target, std::string_view configPath, std::move(err)); } - MapAngleArgumentSource source(arguments); + MapAngleArgumentSource const source(arguments); auto factory = targetInst.get()->getBindArgumentsImplementationFactory(); - if ((!factory.hasValue()) || (factory.getValue() == nullptr)) { + if ((!factory.has_value()) || (factory.value() == nullptr)) { return qssc::emitDiagnostic( onDiagnostic, qssc::Severity::Error, qssc::ErrorCategory::QSSLinkerNotImplemented, "Unable to load bind arguments implementation for target."); } qssc::arguments::BindArgumentsImplementationFactory &factoryRef = - *factory.getValue(); + *factory.value(); return qssc::arguments::bindArguments( moduleInput, payloadOutputPath, source, treatWarningsAsErrors, enableInMemoryInput, inMemoryOutput, factoryRef, onDiagnostic); diff --git a/lib/API/errors.cpp b/lib/API/errors.cpp index 29a9dd65e..2585fcbc0 100644 --- a/lib/API/errors.cpp +++ b/lib/API/errors.cpp @@ -20,13 +20,19 @@ #include "API/errors.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include #include -namespace qssc { -static std::string_view getErrorCategoryAsString(ErrorCategory category) { +namespace { + +std::string_view getErrorCategoryAsString(qssc::ErrorCategory category) { using namespace qssc; switch (category) { case ErrorCategory::OpenQASM3ParseFailure: @@ -78,21 +84,25 @@ static std::string_view getErrorCategoryAsString(ErrorCategory category) { llvm_unreachable("unhandled category"); } -static llvm::StringRef getSeverityAsString(Severity sev) { +llvm::StringRef getSeverityAsString(qssc::Severity sev) { switch (sev) { - case Severity::Info: + case qssc::Severity::Info: return "Info"; - case Severity::Warning: + case qssc::Severity::Warning: return "Warning"; - case Severity::Error: + case qssc::Severity::Error: return "Error"; - case Severity::Fatal: + case qssc::Severity::Fatal: return "Fatal"; } llvm_unreachable("unhandled severity"); } +} // anonymous namespace + +namespace qssc { + std::string Diagnostic::toString() const { std::string str; llvm::raw_string_ostream ostream(str); @@ -109,7 +119,7 @@ llvm::Error emitDiagnostic(std::optional onDiagnostic, std::string message, std::error_code ec) { auto *diagnosticCallback = onDiagnostic.has_value() ? &onDiagnostic.value() : nullptr; - qssc::Diagnostic diag{severity, category, std::move(message)}; + qssc::Diagnostic const diag{severity, category, std::move(message)}; if (diagnosticCallback) (*diagnosticCallback)(diag); return llvm::createStringError(ec, diag.toString()); diff --git a/lib/Arguments/Arguments.cpp b/lib/Arguments/Arguments.cpp index 4733da6bb..e42047e87 100644 --- a/lib/Arguments/Arguments.cpp +++ b/lib/Arguments/Arguments.cpp @@ -20,17 +20,20 @@ #include "Arguments/Arguments.h" #include "API/errors.h" +#include "Arguments/Signature.h" #include "Payload/Payload.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" - -#include +#include "llvm/Support/raw_ostream.h" #include #include #include +#include +#include +#include #include namespace qssc::arguments { @@ -43,9 +46,7 @@ llvm::Error updateParameters(qssc::payload::PatchablePayload *payload, BindArgumentsImplementationFactory &factory, const OptDiagnosticCallback &onDiagnostic) { - for (auto &entry : sig.patchPointsByBinary) { - auto binaryName = entry.getKey(); - auto patchPoints = entry.getValue(); + for (const auto &[binaryName, patchPoints] : sig.patchPointsByBinary) { if (patchPoints.size() == 0) // no patch points continue; @@ -56,7 +57,7 @@ llvm::Error updateParameters(qssc::payload::PatchablePayload *payload, auto error = binaryDataOrErr.takeError(); return emitDiagnostic(onDiagnostic, qssc::Severity::Error, qssc::ErrorCategory::QSSLinkSignatureError, - "Error reading " + binaryName.str() + " " + + "Error reading " + binaryName + " " + toString(std::move(error))); } @@ -66,7 +67,7 @@ llvm::Error updateParameters(qssc::payload::PatchablePayload *payload, factory.create(binaryData, onDiagnostic)); binary->setTreatWarningsAsErrors(treatWarningsAsErrors); - for (auto const &patchPoint : entry.getValue()) + for (auto const &patchPoint : patchPoints) if (auto err = binary->patch(patchPoint, arguments)) return err; } @@ -82,7 +83,7 @@ llvm::Error bindArguments(llvm::StringRef moduleInput, BindArgumentsImplementationFactory &factory, const OptDiagnosticCallback &onDiagnostic) { - bool enableInMemoryOutput = payloadOutputPath == ""; + bool const enableInMemoryOutput = payloadOutputPath == ""; // placeholder string for data on disk if required std::string inputFromDisk; @@ -92,7 +93,7 @@ llvm::Error bindArguments(llvm::StringRef moduleInput, // copy to link payload if not returning in memory // load from disk into string if returning in memory if (!enableInMemoryOutput) { - std::error_code copyError = + std::error_code const copyError = llvm::sys::fs::copy_file(moduleInput, payloadOutputPath); if (copyError) return llvm::make_error( @@ -100,7 +101,7 @@ llvm::Error bindArguments(llvm::StringRef moduleInput, } else { // read from disk to process in memory std::ostringstream buf; - std::ifstream input(moduleInput.str().c_str()); + std::ifstream const input(moduleInput.str().c_str()); buf << input.rdbuf(); inputFromDisk = buf.str(); moduleInput = inputFromDisk; @@ -118,7 +119,7 @@ llvm::Error bindArguments(llvm::StringRef moduleInput, enableInMemoryInput = false; } - llvm::StringRef payloadData = + llvm::StringRef const payloadData = (enableInMemoryInput) ? moduleInput : payloadOutputPath; auto binary = std::unique_ptr( @@ -151,7 +152,7 @@ llvm::Error bindArguments(llvm::StringRef moduleInput, if (auto err = payload->writeString(inMemoryOutput)) return err; if (!enableInMemoryOutput) { - auto pathStr = payloadOutputPath.operator std::string(); + auto pathStr = payloadOutputPath.str(); std::ofstream out(pathStr); out << inMemoryOutput; out.close(); diff --git a/lib/Arguments/Signature.cpp b/lib/Arguments/Signature.cpp index 87e1d2951..5c555b245 100644 --- a/lib/Arguments/Signature.cpp +++ b/lib/Arguments/Signature.cpp @@ -23,11 +23,17 @@ #include "API/errors.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" #include "llvm/Support/raw_ostream.h" +#include +#include #include +#include +#include +#include namespace qssc::arguments { @@ -36,7 +42,7 @@ void Signature::addParameterPatchPoint(llvm::StringRef expression, llvm::StringRef binaryComponent, uint64_t offset) { - auto &patchPoints = patchPointsByBinary[binaryComponent]; + auto &patchPoints = patchPointsByBinary[binaryComponent.str()]; patchPoints.emplace_back(expression, patchType, offset); } @@ -44,18 +50,18 @@ void Signature::addParameterPatchPoint(llvm::StringRef expression, void Signature::addParameterPatchPoint(llvm::StringRef binaryComponent, const PatchPoint &p) { - auto &patchPoints = patchPointsByBinary[binaryComponent]; + auto &patchPoints = patchPointsByBinary[binaryComponent.str()]; patchPoints.push_back(p); } void Signature::dump() { llvm::errs() << "Circuit Signature:\n"; - for (auto const &entry : patchPointsByBinary) { + for (auto const &[binaryName, patchPoints] : patchPointsByBinary) { - llvm::errs() << "binary " << entry.getKey() << ":\n"; + llvm::errs() << "binary " << binaryName << ":\n"; - for (auto const &patchPoint : entry.getValue()) { + for (auto const &patchPoint : patchPoints) { llvm::errs() << " param expression " << patchPoint.expression() << " to be patched as " << patchPoint.patchType() << " at offset " << patchPoint.offset() << "\n"; @@ -69,9 +75,8 @@ std::string Signature::serialize() { s << "version 1\n"; s << "num_binaries: " << patchPointsByBinary.size() << "\n"; - for (auto const &entry : patchPointsByBinary) { - auto patchPoints = entry.getValue(); - s << "binary: " << entry.getKey().str() << "\n"; + for (auto const &[binaryName, patchPoints] : patchPointsByBinary) { + s << "binary: " << binaryName << "\n"; s << "num_patchpoints: " << patchPoints.size() << "\n"; for (auto const &patchPoint : patchPoints) { s << patchPoint.patchType().str() << " " << patchPoint.offset() << " " @@ -131,7 +136,7 @@ llvm::Expected Signature::deserialize( qssc::ErrorCategory::QSSLinkSignatureError, "Expected binary:"); } - llvm::StringRef binaryName = value; + llvm::StringRef const binaryName = value; std::tie(line, buffer) = buffer.split("\n"); std::tie(label, value) = line.split(' '); diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 827a55eb4..1d9b1c4e8 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -29,6 +29,7 @@ add_dependencies(QSSCCore mlir-headers) get_property(qssc_targets GLOBAL PROPERTY QSSC_TARGETS) get_property(mlir_dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS) get_property(mlir_conversion_libs GLOBAL PROPERTY MLIR_CONVERSION_LIBS) +get_property(mlir_extension_libs GLOBAL PROPERTY MLIR_EXTENSION_LIBS) # All libraries for the QSS-Compiler set(qssc_api_libs @@ -42,9 +43,11 @@ set(qssc_api_libs QSSCCore ${mlir_dialect_libs} ${mlir_conversion_libs} + ${mlir_extension_libs} MLIRCallInterfaces MLIRExecutionEngine MLIROptLib + MLIRLLVMDialect MLIROQ3Dialect MLIRQCSDialect MLIRQUIRDialect @@ -80,7 +83,7 @@ if(INSTALL_BUNDLED_STATIC_LIB) QSSCPayload QSSCPayloadZip QSSCCore - Utils + QSSCUtils ${mlir_dialect_libs} ${mlir_conversion_libs} ) diff --git a/lib/Config/CLIConfig.cpp b/lib/Config/CLIConfig.cpp index 49de6dc05..514053f69 100644 --- a/lib/Config/CLIConfig.cpp +++ b/lib/Config/CLIConfig.cpp @@ -13,39 +13,48 @@ //===----------------------------------------------------------------------===// #include "Config/CLIConfig.h" +#include "Config/QSSConfig.h" + +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Error.h" + +#include using namespace qssc::config; +namespace { // The space below at the front of the string causes this category to be printed // first -static llvm::cl::OptionCategory +llvm::cl::OptionCategory qsscCat_(" QSS Compiler Options", "Options that control high-level behavior of QSS Compiler"); -llvm::cl::OptionCategory &qssc::config::getQSSCCategory() { return qsscCat_; } - -static llvm::cl::opt configurationPath( +llvm::cl::opt configurationPath( "config", llvm::cl::desc("Path to configuration file or directory (depends on the " "target), - means use the config service"), llvm::cl::value_desc("path"), llvm::cl::cat(qsscCat_), llvm::cl::Optional); -static llvm::cl::opt +llvm::cl::opt targetStr("target", llvm::cl::desc( "Target architecture. Required for machine code generation."), llvm::cl::value_desc("targetName"), llvm::cl::cat(getQSSCCategory())); -static llvm::cl::opt allowUnregisteredDialects( +llvm::cl::opt allowUnregisteredDialects( "allow-unregistered-dialect", llvm::cl::desc("Allow operation with no registered dialects"), llvm::cl::init(false), llvm::cl::cat(getQSSCCategory())); -static llvm::cl::opt addTargetPasses( +llvm::cl::opt addTargetPasses( "add-target-passes", llvm::cl::desc("Add target-specific passes"), llvm::cl::init(true), llvm::cl::cat(qssc::config::getQSSCCategory())); +} // anonymous namespace + +llvm::cl::OptionCategory &qssc::config::getQSSCCategory() { return qsscCat_; } + llvm::Error CLIConfigBuilder::populateConfig(QSSConfig &config) { if (auto err = populateConfigurationPath_(config)) return err; diff --git a/lib/Config/EnvVarConfig.cpp b/lib/Config/EnvVarConfig.cpp index 9fe3c3531..f4546a549 100644 --- a/lib/Config/EnvVarConfig.cpp +++ b/lib/Config/EnvVarConfig.cpp @@ -13,6 +13,9 @@ //===----------------------------------------------------------------------===// #include "Config/EnvVarConfig.h" +#include "Config/QSSConfig.h" + +#include "llvm/Support/Error.h" #include diff --git a/lib/Config/QSSConfig.cpp b/lib/Config/QSSConfig.cpp index 44f1f5a02..f4c09a5e0 100644 --- a/lib/Config/QSSConfig.cpp +++ b/lib/Config/QSSConfig.cpp @@ -14,8 +14,16 @@ #include "Config/QSSConfig.h" +#include "mlir/IR/MLIRContext.h" + #include "llvm/ADT/DenseMap.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/raw_os_ostream.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include using namespace qssc::config; @@ -44,21 +52,25 @@ std::ostream &operator<<(std::ostream &os, return os; } +namespace { /// Mapping of registered MLIRContext configurations. /// QUESTION: Rather than a global registry it seems like it would be much /// better to inherit the MLIRContext as QSSContext and set the configuration on /// this? Alternatively the QSSContext could own the MLIRContext? -static llvm::DenseMap contextConfigs{}; +static llvm::ManagedStatic> + contextConfigs{}; + +} // anonymous namespace void qssc::config::setContextConfig(mlir::MLIRContext *context, - QSSConfig config) { - contextConfigs[context] = std::move(config); + const QSSConfig &config) { + (*contextConfigs)[context] = config; } llvm::Expected qssc::config::getContextConfig(mlir::MLIRContext *context) { - auto it = contextConfigs.find(context); - if (it != contextConfigs.end()) + auto it = contextConfigs->find(context); + if (it != contextConfigs->end()) return it->getSecond(); return llvm::createStringError( diff --git a/lib/Conversion/OQ3ToStandard/OQ3ToStandard.cpp b/lib/Conversion/OQ3ToStandard/OQ3ToStandard.cpp index 57cc789ed..e86d3037b 100644 --- a/lib/Conversion/OQ3ToStandard/OQ3ToStandard.cpp +++ b/lib/Conversion/OQ3ToStandard/OQ3ToStandard.cpp @@ -13,18 +13,27 @@ //===----------------------------------------------------------------------===// #include "Conversion/OQ3ToStandard/OQ3ToStandard.h" -#include "Dialect/QUIR/IR/QUIROps.h" -#include "Dialect/QUIR/Transforms/Passes.h" #include "Dialect/OQ3/IR/OQ3Ops.h" -#include "Dialect/QUIR/IR/QUIRDialect.h" +#include "Dialect/QUIR/IR/QUIRTypes.h" -#include "mlir/Dialect/Arithmetic/IR/Arithmetic.h" +#include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/Dialect/LLVMIR/LLVMAttrs.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" -#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/BuiltinTypes.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/IR/ValueRange.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" #include "mlir/Transforms/DialectConversion.h" +#include "llvm/Support/ErrorHandling.h" + +#include +#include +#include + using namespace mlir; using namespace oq3; using namespace quir; @@ -43,7 +52,7 @@ struct CBitBinaryOpConversionPattern : public OQ3ToStandardConversion { assert(operands.size() == 2 && "Expect binary CBit operation to have exactly two operands."); - for (Value operand : op->getOperands()) { + for (Value const operand : op->getOperands()) { auto operandType = operand.getType(); assert((operandType.isa() || operandType.isInteger(1)) && "Binary CBit operation pattern operands must be `CBit` or i1"); @@ -51,11 +60,11 @@ struct CBitBinaryOpConversionPattern : public OQ3ToStandardConversion { return failure(); } - for (Value operand : operands) + for (Value const operand : operands) if (!operand.getType().isSignlessInteger()) return failure(); - Type operandType = op.lhs().getType(); + Type const operandType = op.getLhs().getType(); if (auto cbitType = operandType.dyn_cast()) if (cbitType.getWidth() > 64) return failure(); @@ -77,13 +86,13 @@ struct CBitAssignBitOpConversionPattern ConversionPatternRewriter &rewriter) const override { auto const loc = op.getLoc(); - auto cbitWidth = op.cbit_width(); + auto cbitWidth = op.getCbitWidth(); // just a single bit? then generate a value assign if (cbitWidth == 1) { - rewriter.create(loc, op.variable_nameAttr(), - adaptor.assigned_bit()); + rewriter.create( + loc, op.getVariableNameAttr(), adaptor.getAssignedBit()); rewriter.replaceOp(op, mlir::ValueRange({})); return success(); @@ -94,20 +103,21 @@ struct CBitAssignBitOpConversionPattern auto oldRegisterValue = rewriter.create( loc, rewriter.getIntegerType(cbitWidth.getZExtValue()), - op.variable_name()); + op.getVariableName()); auto registerWithInsertedBit = rewriter.create( loc, oldRegisterValue.getType(), oldRegisterValue, - adaptor.assigned_bit(), adaptor.indexAttr()); + adaptor.getAssignedBit(), adaptor.getIndexAttr()); - rewriter.create(loc, op.variable_nameAttr(), + rewriter.create(loc, op.getVariableNameAttr(), registerWithInsertedBit); rewriter.replaceOp(op, mlir::ValueRange({})); return success(); } }; -static int getCBitOrIntBitWidth(mlir::Type t) { +namespace { +int getCBitOrIntBitWidth(mlir::Type t) { assert((t.isa() || t.isSignlessInteger()) && "expect CBitType or integer type"); @@ -119,6 +129,7 @@ static int getCBitOrIntBitWidth(mlir::Type t) { llvm::report_fatal_error("unhandled type"); } +} // anonymous namespace struct CBitInsertBitOpConversionPattern : public OQ3ToStandardConversion { @@ -129,29 +140,29 @@ struct CBitInsertBitOpConversionPattern ConversionPatternRewriter &rewriter) const override { auto const loc = op.getLoc(); - auto cbitWidth = getCBitOrIntBitWidth(adaptor.operand().getType()); + auto cbitWidth = getCBitOrIntBitWidth(adaptor.getOperand().getType()); // just a single bit? then replace whole bitmap if (cbitWidth == 1) { - rewriter.replaceOp(op, mlir::ValueRange({adaptor.assigned_bit()})); + rewriter.replaceOp(op, mlir::ValueRange({adaptor.getAssignedBit()})); return success(); } if (cbitWidth > 64) return failure(); - uint64_t mask = ~((1ull) << op.index().getZExtValue()); + uint64_t const mask = ~((1ull) << op.getIndex().getZExtValue()); auto maskOp = rewriter.create(loc, mask, cbitWidth); auto maskedBitmap = rewriter.create( - loc, maskOp.getType(), adaptor.operand(), maskOp); + loc, maskOp.getType(), adaptor.getOperand(), maskOp); mlir::Value extendedBit = rewriter.create( - loc, maskOp.getType(), adaptor.assigned_bit()); + loc, maskOp.getType(), adaptor.getAssignedBit()); - if (!op.index().isNonPositive()) { - APInt truncated = op.index(); + if (!op.getIndex().isNonPositive()) { + APInt truncated = op.getIndex(); if (static_cast(cbitWidth) < truncated.getBitWidth()) truncated = truncated.trunc(cbitWidth); auto shiftAmount = rewriter.create( @@ -175,14 +186,14 @@ struct CBitExtractBitOpConversionPattern matchAndRewrite(CBitExtractBitOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override { auto const location = op.getLoc(); - auto convertedOperand = adaptor.operand(); + auto convertedOperand = adaptor.getOperand(); - assert((op.operand().getType().isa() || - op.operand().getType().isSignlessInteger()) && + assert((op.getOperand().getType().isa() || + op.getOperand().getType().isSignlessInteger()) && "expect operand of CBitType for oq3.cbit_extractbit"); - auto bitWidth = getCBitOrIntBitWidth(op.operand().getType()); + auto bitWidth = getCBitOrIntBitWidth(op.getOperand().getType()); if (bitWidth == 1) { // just pass-through single bit values @@ -190,7 +201,7 @@ struct CBitExtractBitOpConversionPattern return success(); } - APInt truncated = op.index(); + APInt truncated = op.getIndex(); if (static_cast(bitWidth) < truncated.getBitWidth()) truncated = truncated.trunc(bitWidth); auto shiftAmount = rewriter.create( @@ -200,7 +211,7 @@ struct CBitExtractBitOpConversionPattern location, convertedOperand.getType(), convertedOperand, shiftAmount); auto extractedBit = rewriter.create( location, op.getType(), shiftedRegister); - rewriter.replaceOp(op, {extractedBit}); + rewriter.replaceOp(op, extractedBit); return success(); } @@ -219,7 +230,7 @@ struct CastIntToBoolConversionPattern : public OQ3ToStandardConversion { if (!isBoolType(op.getType())) return failure(); - auto argType = op.arg().getType(); + auto argType = op.getArg().getType(); if (argType.isIntOrIndex()) return success(); @@ -230,13 +241,13 @@ struct CastIntToBoolConversionPattern : public OQ3ToStandardConversion { void rewrite(CastOp op, CastOp::Adaptor adaptor, ConversionPatternRewriter &rewriter) const override { - auto argType = op.arg().getType(); + auto argType = op.getArg().getType(); // per OpenQASM3 spec, cast from int to bool by comparing val != 0 auto constInt0Op = rewriter.create( op.getLoc(), argType, rewriter.getIntegerAttr(argType, 0)); auto cmpOp = rewriter.create( - op.getLoc(), mlir::LLVM::ICmpPredicate::ne, op.arg(), + op.getLoc(), mlir::LLVM::ICmpPredicate::ne, op.getArg(), constInt0Op.getResult()); rewriter.replaceOp(op, ValueRange{cmpOp}); } @@ -249,13 +260,13 @@ struct CastCBitToIntConversionPattern : public OQ3ToStandardConversion { LogicalResult matchAndRewrite(CastOp op, CastOp::Adaptor adaptor, ConversionPatternRewriter &rewriter) const override { - if (!op.arg().getType().isa()) + if (!op.getArg().getType().isa()) return failure(); - if (!op.out().getType().isIntOrIndex()) + if (!op.getOut().getType().isIntOrIndex()) return failure(); - auto cbitType = op.arg().getType().dyn_cast(); - auto outWidth = op.out().getType().getIntOrFloatBitWidth(); + auto cbitType = op.getArg().getType().dyn_cast(); + auto outWidth = op.getOut().getType().getIntOrFloatBitWidth(); if (cbitType.getWidth() > outWidth) // cannot reinterpret without losing bits! @@ -263,15 +274,15 @@ struct CastCBitToIntConversionPattern : public OQ3ToStandardConversion { if (cbitType.getWidth() < outWidth) { // need to zero-extend to match output type width - rewriter.replaceOpWithNewOp(op, op.out().getType(), - adaptor.arg()); + rewriter.replaceOpWithNewOp( + op, op.getOut().getType(), adaptor.getArg()); return success(); } // 1:1 conversion of cbit (which is lowered to int) to int - assert(op.out().getType() == adaptor.arg().getType() && + assert(op.getOut().getType() == adaptor.getArg().getType() && "cbit lowers to int"); - rewriter.replaceOp(op, adaptor.arg()); + rewriter.replaceOp(op, adaptor.getArg()); return success(); } // matchAndRewrite }; // struct CastCBitToIntConversionPattern @@ -283,27 +294,27 @@ struct CastIntToCBitConversionPattern : public OQ3ToStandardConversion { LogicalResult matchAndRewrite(CastOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override { - if (!op.arg().getType().isIntOrIndexOrFloat()) + if (!op.getArg().getType().isIntOrIndexOrFloat()) return failure(); - if (!op.out().getType().isa()) + if (!op.getOut().getType().isa()) return failure(); - auto cbitType = op.out().getType().dyn_cast(); + auto cbitType = op.getOut().getType().dyn_cast(); // assign single bit from an integer if (cbitType.getWidth() == 1) { auto truncateOp = rewriter.create( - op.getLoc(), rewriter.getI1Type(), adaptor.arg()); + op.getLoc(), rewriter.getI1Type(), adaptor.getArg()); rewriter.replaceOp(op, mlir::ValueRange{truncateOp}); return success(); } - if (op.arg().getType().getIntOrFloatBitWidth() == cbitType.getWidth()) { + if (op.getArg().getType().getIntOrFloatBitWidth() == cbitType.getWidth()) { // 1:1 conversion of int to cbit if (cbitType.getWidth() > 64) return failure(); - rewriter.replaceOp(op, adaptor.arg()); + rewriter.replaceOp(op, adaptor.getArg()); return success(); } @@ -320,11 +331,11 @@ struct CastIndexToIntPattern : public OQ3ToStandardConversion { matchAndRewrite(CastOp op, CastOp::Adaptor adaptor, ConversionPatternRewriter &rewriter) const override { // check if the input is index type - if (!op.arg().getType().isIndex()) + if (!op.getArg().getType().isIndex()) return failure(); rewriter.replaceOpWithNewOp( - op, op.out().getType(), adaptor.arg()); + op, op.getOut().getType(), adaptor.getArg()); return success(); } // matchAndRewrite }; // struct CastIndexToIntPattern @@ -337,10 +348,10 @@ struct RemoveConvertedNilCastsPattern : public OQ3ToStandardConversion { LogicalResult matchAndRewrite(CastOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override { - if (op.getType() != adaptor.arg().getType()) + if (op.getType() != adaptor.getArg().getType()) return failure(); - rewriter.replaceOp(op, {adaptor.arg()}); + rewriter.replaceOp(op, {adaptor.getArg()}); return success(); } // matchAndRewrite @@ -353,7 +364,7 @@ struct CastFromFloatConstPattern : public OQ3ToStandardConversion { matchAndRewrite(CastOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override { - auto constOp = op.arg().getDefiningOp(); + auto constOp = op.getArg().getDefiningOp(); if (!constOp) return failure(); @@ -361,7 +372,7 @@ struct CastFromFloatConstPattern : public OQ3ToStandardConversion { if (!floatAttr) return failure(); - rewriter.replaceOp(op, {adaptor.arg()}); + rewriter.replaceOp(op, {adaptor.getArg()}); return success(); } // CastFromFloatConstPattern @@ -373,13 +384,13 @@ struct RemoveI1ToCBitCastsPattern : public OQ3ToStandardConversion { LogicalResult matchAndRewrite(CastOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override { - if (adaptor.arg().getType() != rewriter.getI1Type()) + if (adaptor.getArg().getType() != rewriter.getI1Type()) return failure(); auto cbitType = op.getType().dyn_cast(); if (!cbitType || cbitType.getWidth() != 1) return failure(); - rewriter.replaceOp(op, {adaptor.arg()}); + rewriter.replaceOp(op, {adaptor.getArg()}); return success(); } // matchAndRewrite @@ -396,7 +407,7 @@ struct WideningIntCastsPattern : public OQ3ToStandardConversion { if (!op.getType().isSignlessInteger()) return failure(); - assert(op.getOperand().getType() == adaptor.arg().getType() && + assert(op.getOperand().getType() == adaptor.getArg().getType() && "unexpected type conversion for built-in integer types"); if (op.getOperand().getType().getIntOrFloatBitWidth() >= @@ -404,7 +415,7 @@ struct WideningIntCastsPattern : public OQ3ToStandardConversion { return failure(); rewriter.replaceOpWithNewOp(op, op.getType(), - adaptor.arg()); + adaptor.getArg()); return success(); } // matchAndRewrite }; // struct WideningIntCastsPattern diff --git a/lib/Conversion/QUIRToPulse/CMakeLists.txt b/lib/Conversion/QUIRToPulse/CMakeLists.txt index 4a71b8d56..73e929102 100644 --- a/lib/Conversion/QUIRToPulse/CMakeLists.txt +++ b/lib/Conversion/QUIRToPulse/CMakeLists.txt @@ -23,7 +23,7 @@ Core LINK_LIBS PUBLIC MLIRIR -MLIRComplex +MLIRComplexDialect MLIROQ3Dialect MLIRPulseDialect MLIRQUIRDialect diff --git a/lib/Conversion/QUIRToPulse/LoadPulseCals.cpp b/lib/Conversion/QUIRToPulse/LoadPulseCals.cpp index 8630442a8..251fc09a8 100644 --- a/lib/Conversion/QUIRToPulse/LoadPulseCals.cpp +++ b/lib/Conversion/QUIRToPulse/LoadPulseCals.cpp @@ -20,14 +20,44 @@ #include "Conversion/QUIRToPulse/LoadPulseCals.h" +#include "Dialect/Pulse/IR/PulseOps.h" +#include "Dialect/QUIR/IR/QUIROps.h" +#include "Dialect/QUIR/IR/QUIRTraits.h" #include "Dialect/QUIR/Utils/Utils.h" -#include "mlir/IR/BlockAndValueMapping.h" -#include "mlir/Parser.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/IR/Attributes.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/BuiltinTypes.h" +#include "mlir/IR/IRMapping.h" +#include "mlir/IR/OwningOpRef.h" +#include "mlir/IR/SymbolTable.h" +#include "mlir/IR/Types.h" +#include "mlir/IR/Value.h" +#include "mlir/Parser/Parser.h" #include "mlir/Support/FileUtilities.h" - +#include "mlir/Support/LLVM.h" +#include + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SMLoc.h" #include "llvm/Support/SourceMgr.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + #define DEBUG_TYPE "LoadPulseCalsDebug" using namespace mlir; @@ -36,8 +66,9 @@ using namespace mlir::pulse; void LoadPulseCalsPass::runOnOperation() { - ModuleOp moduleOp = getOperation(); - FuncOp mainFunc = dyn_cast(quir::getMainFunction(moduleOp)); + mlir::ModuleOp const moduleOp = getOperation(); + mlir::func::FuncOp mainFunc = + dyn_cast(quir::getMainFunction(moduleOp)); assert(mainFunc && "could not find the main func"); // check for command line override of the path to default pulse cals @@ -54,7 +85,7 @@ void LoadPulseCalsPass::runOnOperation() { } // add sequence Ops to pulseCalsNameToSequenceMap defaultPulseCalsModule->walk([&](mlir::pulse::SequenceOp sequenceOp) { - auto sequenceName = sequenceOp.sym_name().str(); + auto sequenceName = sequenceOp.getSymName().str(); pulseCalsNameToSequenceMap[sequenceName] = sequenceOp; }); } else @@ -71,7 +102,7 @@ void LoadPulseCalsPass::runOnOperation() { } // add sequence Ops to pulseCalsNameToSequenceMap additionalPulseCalsModule->walk([&](mlir::pulse::SequenceOp sequenceOp) { - auto sequenceName = sequenceOp.sym_name().str(); + auto sequenceName = sequenceOp.getSymName().str(); pulseCalsNameToSequenceMap[sequenceName] = sequenceOp; }); } else @@ -81,7 +112,7 @@ void LoadPulseCalsPass::runOnOperation() { // parse the user specified pulse calibrations LLVM_DEBUG(llvm::dbgs() << "parsing user specified pulse calibrations.\n"); moduleOp->walk([&](mlir::pulse::SequenceOp sequenceOp) { - auto sequenceName = sequenceOp.sym_name().str(); + auto sequenceName = sequenceOp.getSymName().str(); pulseCalsNameToSequenceMap[sequenceName] = sequenceOp; pulseCalsAddedToIR.insert(sequenceName); }); @@ -91,7 +122,7 @@ void LoadPulseCalsPass::runOnOperation() { } void LoadPulseCalsPass::loadPulseCals(CallCircuitOp callCircuitOp, - FuncOp funcOp) { + mlir::func::FuncOp funcOp) { auto circuitOp = getCircuitOp(callCircuitOp); circuitOp->walk([&](Operation *op) { @@ -123,63 +154,63 @@ void LoadPulseCalsPass::loadPulseCals(CallCircuitOp callCircuitOp, void LoadPulseCalsPass::loadPulseCals(CallGateOp callGateOp, CallCircuitOp callCircuitOp, - FuncOp funcOp) { + mlir::func::FuncOp funcOp) { std::vector qubitOperands; qubitCallOperands(callGateOp, qubitOperands); std::vector qubits = getQubitOperands(qubitOperands, callCircuitOp); - std::string gateName = callGateOp.calleeAttr().getValue().str(); - std::string gateMangledName = getMangledName(gateName, qubits); + std::string gateName = callGateOp.getCalleeAttr().getValue().str(); + std::string const gateMangledName = getMangledName(gateName, qubits); assert(pulseCalsNameToSequenceMap.find(gateMangledName) != pulseCalsNameToSequenceMap.end() && "could not find any pulse calibration for call gate"); - OpBuilder builder(funcOp.body()); + OpBuilder builder = OpBuilder::atBlockBegin(&funcOp.getBody().front()); callGateOp->setAttr("pulse.calName", builder.getStringAttr(gateMangledName)); addPulseCalToModule(funcOp, pulseCalsNameToSequenceMap[gateMangledName]); } void LoadPulseCalsPass::loadPulseCals(BuiltinCXOp CXOp, CallCircuitOp callCircuitOp, - FuncOp funcOp) { + mlir::func::FuncOp funcOp) { std::vector qubitOperands; - qubitOperands.push_back(CXOp.control()); - qubitOperands.push_back(CXOp.target()); + qubitOperands.push_back(CXOp.getControl()); + qubitOperands.push_back(CXOp.getTarget()); std::vector qubits = getQubitOperands(qubitOperands, callCircuitOp); std::string gateName = "cx"; - std::string gateMangledName = getMangledName(gateName, qubits); + std::string const gateMangledName = getMangledName(gateName, qubits); assert(pulseCalsNameToSequenceMap.find(gateMangledName) != pulseCalsNameToSequenceMap.end() && "could not find any pulse calibration for the CX gate"); - OpBuilder builder(funcOp.body()); + OpBuilder builder = OpBuilder::atBlockBegin(&funcOp.getBody().front()); CXOp->setAttr("pulse.calName", builder.getStringAttr(gateMangledName)); addPulseCalToModule(funcOp, pulseCalsNameToSequenceMap[gateMangledName]); } void LoadPulseCalsPass::loadPulseCals(Builtin_UOp UOp, CallCircuitOp callCircuitOp, - FuncOp funcOp) { + mlir::func::FuncOp funcOp) { std::vector qubitOperands; - qubitOperands.push_back(UOp.target()); + qubitOperands.push_back(UOp.getTarget()); std::vector qubits = getQubitOperands(qubitOperands, callCircuitOp); std::string gateName = "u3"; - std::string gateMangledName = getMangledName(gateName, qubits); + std::string const gateMangledName = getMangledName(gateName, qubits); assert(pulseCalsNameToSequenceMap.find(gateMangledName) != pulseCalsNameToSequenceMap.end() && "could not find any pulse calibration for the U gate"); - OpBuilder builder(funcOp.body()); + OpBuilder builder = OpBuilder::atBlockBegin(&funcOp.getBody().front()); UOp->setAttr("pulse.calName", builder.getStringAttr(gateMangledName)); addPulseCalToModule(funcOp, pulseCalsNameToSequenceMap[gateMangledName]); } void LoadPulseCalsPass::loadPulseCals(MeasureOp measureOp, CallCircuitOp callCircuitOp, - FuncOp funcOp) { + mlir::func::FuncOp funcOp) { - OpBuilder builder(funcOp.body()); + OpBuilder builder = OpBuilder::atBlockBegin(&funcOp.getBody().front()); std::vector qubitOperands; qubitCallOperands(measureOp, qubitOperands); @@ -188,7 +219,7 @@ void LoadPulseCalsPass::loadPulseCals(MeasureOp measureOp, // check if the measurement is marked with quir.midCircuitMeasure if (measureOp->hasAttr("quir.midCircuitMeasure")) gateName = "mid_circuit_measure"; - std::string gateMangledName = getMangledName(gateName, qubits); + std::string const gateMangledName = getMangledName(gateName, qubits); measureOp->setAttr("pulse.calName", builder.getStringAttr(gateMangledName)); if (pulseCalsNameToSequenceMap.find(gateMangledName) != pulseCalsNameToSequenceMap.end()) { @@ -201,14 +232,15 @@ void LoadPulseCalsPass::loadPulseCals(MeasureOp measureOp, // yes, merge them and add the merged pulse sequence to the module std::vector sequenceOps; for (const auto &qubit : qubits) { - std::string individualGateMangledName = getMangledName(gateName, qubit); + std::string const individualGateMangledName = + getMangledName(gateName, qubit); assert(pulseCalsNameToSequenceMap.find(individualGateMangledName) != pulseCalsNameToSequenceMap.end() && "could not find pulse calibrations for the measurement gate"); sequenceOps.push_back( pulseCalsNameToSequenceMap[individualGateMangledName]); } - SequenceOp mergedPulseSequenceOp = + SequenceOp const mergedPulseSequenceOp = mergePulseSequenceOps(sequenceOps, gateMangledName); pulseCalsNameToSequenceMap[gateMangledName] = mergedPulseSequenceOp; addPulseCalToModule(funcOp, mergedPulseSequenceOp); @@ -216,15 +248,15 @@ void LoadPulseCalsPass::loadPulseCals(MeasureOp measureOp, void LoadPulseCalsPass::loadPulseCals(mlir::quir::BarrierOp barrierOp, CallCircuitOp callCircuitOp, - FuncOp funcOp) { + mlir::func::FuncOp funcOp) { - OpBuilder builder(funcOp.body()); + OpBuilder builder = OpBuilder::atBlockBegin(&funcOp.getBody().front()); std::vector qubitOperands; qubitCallOperands(barrierOp, qubitOperands); std::vector qubits = getQubitOperands(qubitOperands, callCircuitOp); std::string gateName = "barrier"; - std::string gateMangledName = getMangledName(gateName, qubits); + std::string const gateMangledName = getMangledName(gateName, qubits); barrierOp->setAttr("pulse.calName", builder.getStringAttr(gateMangledName)); if (pulseCalsNameToSequenceMap.find(gateMangledName) != pulseCalsNameToSequenceMap.end()) { @@ -237,14 +269,15 @@ void LoadPulseCalsPass::loadPulseCals(mlir::quir::BarrierOp barrierOp, // yes, merge them and add the merged pulse sequence to the module std::vector sequenceOps; for (const auto &qubit : qubits) { - std::string individualGateMangledName = getMangledName(gateName, qubit); + std::string const individualGateMangledName = + getMangledName(gateName, qubit); assert(pulseCalsNameToSequenceMap.find(individualGateMangledName) != pulseCalsNameToSequenceMap.end() && "could not find pulse calibrations for the barrier gate"); sequenceOps.push_back( pulseCalsNameToSequenceMap[individualGateMangledName]); } - SequenceOp mergedPulseSequenceOp = + SequenceOp const mergedPulseSequenceOp = mergePulseSequenceOps(sequenceOps, gateMangledName); pulseCalsNameToSequenceMap[gateMangledName] = mergedPulseSequenceOp; addPulseCalToModule(funcOp, mergedPulseSequenceOp); @@ -252,14 +285,15 @@ void LoadPulseCalsPass::loadPulseCals(mlir::quir::BarrierOp barrierOp, void LoadPulseCalsPass::loadPulseCals(mlir::quir::DelayOp delayOp, CallCircuitOp callCircuitOp, - FuncOp funcOp) { - OpBuilder builder(funcOp.body()); + mlir::func::FuncOp funcOp) { + + OpBuilder builder = OpBuilder::atBlockBegin(&funcOp.getBody().front()); std::vector qubitOperands; qubitCallOperands(delayOp, qubitOperands); std::vector qubits = getQubitOperands(qubitOperands, callCircuitOp); std::string gateName = "delay"; - std::string gateMangledName = getMangledName(gateName, qubits); + std::string const gateMangledName = getMangledName(gateName, qubits); delayOp->setAttr("pulse.calName", builder.getStringAttr(gateMangledName)); if (pulseCalsNameToSequenceMap.find(gateMangledName) != pulseCalsNameToSequenceMap.end()) { @@ -272,14 +306,15 @@ void LoadPulseCalsPass::loadPulseCals(mlir::quir::DelayOp delayOp, // yes, merge them and add the merged pulse sequence to the module std::vector sequenceOps; for (const auto &qubit : qubits) { - std::string individualGateMangledName = getMangledName(gateName, qubit); + std::string const individualGateMangledName = + getMangledName(gateName, qubit); assert(pulseCalsNameToSequenceMap.find(individualGateMangledName) != pulseCalsNameToSequenceMap.end() && "could not find pulse calibrations for the delay gate"); sequenceOps.push_back( pulseCalsNameToSequenceMap[individualGateMangledName]); } - SequenceOp mergedPulseSequenceOp = + SequenceOp const mergedPulseSequenceOp = mergePulseSequenceOps(sequenceOps, gateMangledName); removeRedundantDelayArgs(mergedPulseSequenceOp, builder); pulseCalsNameToSequenceMap[gateMangledName] = mergedPulseSequenceOp; @@ -288,15 +323,15 @@ void LoadPulseCalsPass::loadPulseCals(mlir::quir::DelayOp delayOp, void LoadPulseCalsPass::loadPulseCals(mlir::quir::ResetQubitOp resetOp, CallCircuitOp callCircuitOp, - FuncOp funcOp) { + mlir::func::FuncOp funcOp) { - OpBuilder builder(funcOp.body()); + OpBuilder builder = OpBuilder::atBlockBegin(&funcOp.getBody().front()); std::vector qubitOperands; qubitCallOperands(resetOp, qubitOperands); std::vector qubits = getQubitOperands(qubitOperands, callCircuitOp); std::string gateName = "reset"; - std::string gateMangledName = getMangledName(gateName, qubits); + std::string const gateMangledName = getMangledName(gateName, qubits); resetOp->setAttr("pulse.calName", builder.getStringAttr(gateMangledName)); if (pulseCalsNameToSequenceMap.find(gateMangledName) != pulseCalsNameToSequenceMap.end()) { @@ -309,35 +344,37 @@ void LoadPulseCalsPass::loadPulseCals(mlir::quir::ResetQubitOp resetOp, // yes, merge them and add the merged pulse sequence to the module std::vector sequenceOps; for (const auto &qubit : qubits) { - std::string individualGateMangledName = getMangledName(gateName, qubit); + std::string const individualGateMangledName = + getMangledName(gateName, qubit); assert(pulseCalsNameToSequenceMap.find(individualGateMangledName) != pulseCalsNameToSequenceMap.end() && "could not find pulse calibrations for the reset gate"); sequenceOps.push_back( pulseCalsNameToSequenceMap[individualGateMangledName]); } - SequenceOp mergedPulseSequenceOp = + SequenceOp const mergedPulseSequenceOp = mergePulseSequenceOps(sequenceOps, gateMangledName); pulseCalsNameToSequenceMap[gateMangledName] = mergedPulseSequenceOp; addPulseCalToModule(funcOp, mergedPulseSequenceOp); } void LoadPulseCalsPass::addPulseCalToModule( - FuncOp funcOp, mlir::pulse::SequenceOp sequenceOp) { - if (pulseCalsAddedToIR.find(sequenceOp.sym_name().str()) == + mlir::func::FuncOp funcOp, mlir::pulse::SequenceOp sequenceOp) { + if (pulseCalsAddedToIR.find(sequenceOp.getSymName().str()) == pulseCalsAddedToIR.end()) { - OpBuilder builder(funcOp.body()); + OpBuilder builder = OpBuilder::atBlockBegin(&funcOp.getBody().front()); auto *clonedPulseCalOp = builder.clone(*sequenceOp); auto clonedPulseCalSequenceOp = static_cast(clonedPulseCalOp); clonedPulseCalSequenceOp->moveBefore(funcOp); - pulseCalsAddedToIR.insert(sequenceOp.sym_name().str()); + pulseCalsAddedToIR.insert(sequenceOp.getSymName().str()); } else - LLVM_DEBUG(llvm::dbgs() << "pulse cal " << sequenceOp.sym_name().str() + LLVM_DEBUG(llvm::dbgs() << "pulse cal " << sequenceOp.getSymName().str() << " is already added to IR.\n"); } llvm::Error LoadPulseCalsPass::parsePulseCalsModuleOp( - std::string &pulseCalsPath, mlir::OwningOpRef &owningOpRef) { + std::string &pulseCalsPath, + mlir::OwningOpRef &owningOpRef) { std::string errorMessage; llvm::SourceMgr sourceMgr; std::unique_ptr pulseCalsFile = @@ -347,7 +384,7 @@ llvm::Error LoadPulseCalsPass::parsePulseCalsModuleOp( "Failed to open pulse calibrations file: " + errorMessage); sourceMgr.AddNewSourceBuffer(std::move(pulseCalsFile), llvm::SMLoc()); - owningOpRef = mlir::parseSourceFile(sourceMgr, &getContext()); + owningOpRef = mlir::parseSourceFile(sourceMgr, &getContext()); if (!owningOpRef) return llvm::createStringError(llvm::inconvertibleErrorCode(), "Failed to parse pulse calibrations file: " + @@ -361,12 +398,12 @@ mlir::pulse::SequenceOp LoadPulseCalsPass::mergePulseSequenceOps( assert(sequenceOps.size() && "sequence op vector is empty; nothing to merge"); - SequenceOp firstSequenceOp = sequenceOps[0]; + SequenceOp const firstSequenceOp = sequenceOps[0]; OpBuilder builder(firstSequenceOp); llvm::SmallVector inputTypes; - llvm::SmallVector inputValues; + llvm::SmallVector const inputValues; llvm::SmallVector outputTypes; llvm::SmallVector outputValues; @@ -384,7 +421,7 @@ mlir::pulse::SequenceOp LoadPulseCalsPass::mergePulseSequenceOps( // map original arguments for new sequence based on original sequences' // argument numbers - BlockAndValueMapping mapper; + IRMapping mapper; auto baseArgNum = mergedSequenceOp.getNumArguments(); for (std::size_t seqNum = 1; seqNum < sequenceOps.size(); seqNum++) { for (uint cnt = 0; cnt < sequenceOps[seqNum].getNumArguments(); cnt++) { @@ -420,7 +457,7 @@ mlir::pulse::SequenceOp LoadPulseCalsPass::mergePulseSequenceOps( outputValues); // change the input / output types for the merged sequence op - auto opType = mergedSequenceOp.getType(); + auto opType = mergedSequenceOp.getFunctionType(); mergedSequenceOp.setType(builder.getFunctionType( /*inputs=*/opType.getInputs(), /*results=*/ArrayRef(outputTypes))); @@ -431,7 +468,7 @@ mlir::pulse::SequenceOp LoadPulseCalsPass::mergePulseSequenceOps( // this case. // If yes, no further action is required because the duration is already // cloned when we clone the first sequence - bool allSequenceOpsHasSameDuration = + bool const allSequenceOpsHasSameDuration = doAllSequenceOpsHaveSameDuration(sequenceOps); if (!allSequenceOpsHasSameDuration and mergedSequenceOp->hasAttr("pulse.duration")) @@ -441,19 +478,20 @@ mlir::pulse::SequenceOp LoadPulseCalsPass::mergePulseSequenceOps( // merge the attributes and add them to the merged sequence op std::vector pulseSequenceOpArgs; std::vector pulseSequenceOpArgPorts; - bool allSequenceOpsHasArgsAttr = + bool const allSequenceOpsHasArgsAttr = mergeAttributes(sequenceOps, "pulse.args", pulseSequenceOpArgs); - bool allSequenceOpsHasArgPortsAttr = + bool const allSequenceOpsHasArgPortsAttr = mergeAttributes(sequenceOps, "pulse.argPorts", pulseSequenceOpArgPorts); if (allSequenceOpsHasArgsAttr) { - mlir::ArrayAttr arrayAttr = builder.getArrayAttr(pulseSequenceOpArgs); + mlir::ArrayAttr const arrayAttr = builder.getArrayAttr(pulseSequenceOpArgs); mergedSequenceOp->setAttr("pulse.args", arrayAttr); } else if (mergedSequenceOp->hasAttr("pulse.args")) mergedSequenceOp->removeAttr("pulse.args"); if (allSequenceOpsHasArgPortsAttr) { - mlir::ArrayAttr arrayAttr = builder.getArrayAttr(pulseSequenceOpArgPorts); + mlir::ArrayAttr const arrayAttr = + builder.getArrayAttr(pulseSequenceOpArgPorts); mergedSequenceOp->setAttr("pulse.argPorts", arrayAttr); } else if (mergedSequenceOp->hasAttr("pulse.argPorts")) mergedSequenceOp->removeAttr("pulse.argPorts"); @@ -471,7 +509,7 @@ void LoadPulseCalsPass::removeRedundantDelayArgs( std::vector redundantArgsToRemove; std::vector redundantArgIndicesToRemove; for (uint argIndex = 0; argIndex < sequenceOp.getNumArguments(); argIndex++) { - BlockArgument arg = sequenceOp.getArgument(argIndex); + BlockArgument const arg = sequenceOp.getArgument(argIndex); if (arg.getType().isa()) { if (delayArgEncountered) { redundantArgsToRemove.push_back(arg); @@ -487,9 +525,9 @@ void LoadPulseCalsPass::removeRedundantDelayArgs( // need to update pulse.args and pulse.argPorts if it exists std::vector argAttrVec; std::vector argPortsAttrVec; - bool sequenceOpHasPulseArgs = + bool const sequenceOpHasPulseArgs = sequenceOp->hasAttrOfType("pulse.args"); - bool sequenceOpHasPulseArgPorts = + bool const sequenceOpHasPulseArgPorts = sequenceOp->hasAttrOfType("pulse.argPorts"); if (sequenceOpHasPulseArgs) for (auto attr : sequenceOp->getAttrOfType("pulse.args")) @@ -532,7 +570,7 @@ bool LoadPulseCalsPass::doAllSequenceOpsHaveSameDuration( if (!sequenceOp->hasAttrOfType("pulse.duration")) return false; - uint sequenceDuration = static_cast( + uint const sequenceDuration = static_cast( sequenceOp->getAttrOfType("pulse.duration").getInt()); if (!prevSequenceEncountered) { prevSequenceEncountered = true; @@ -565,7 +603,7 @@ bool LoadPulseCalsPass::mergeAttributes( std::string LoadPulseCalsPass::getMangledName(std::string &gateName, std::vector &qubits) { std::string gateMangledName = gateName; - for (int qubit : qubits) { + for (int const qubit : qubits) { gateMangledName += "_"; gateMangledName += std::to_string(qubit); } @@ -585,18 +623,24 @@ LoadPulseCalsPass::getQubitOperands(std::vector &qubitOperands, std::vector qubits; for (auto &qubit : qubitOperands) { if (auto declOp = qubit.getDefiningOp()) { - uint qubitId = *quir::lookupQubitId(declOp); - qubits.push_back(qubitId); + auto qubitId = quir::lookupQubitId(declOp); + if (qubitId.has_value()) + qubits.push_back(qubitId.value()); + else + declOp->emitError() << "Could not find qubit id."; } else { // qubit is a block argument auto blockArg = qubit.dyn_cast(); - unsigned argIdx = blockArg.getArgNumber(); + unsigned const argIdx = blockArg.getArgNumber(); auto qubitOperand = callCircuitOp->getOperand(argIdx); assert(qubitOperand.getDefiningOp() && "could not find the qubit op"); - uint qubitId = *quir::lookupQubitId( - qubitOperand.getDefiningOp()); - qubits.push_back(qubitId); + auto opDeclOp = qubitOperand.getDefiningOp(); + auto qubitId = quir::lookupQubitId(opDeclOp); + if (qubitId.has_value()) + qubits.push_back(qubitId.value()); + else + opDeclOp->emitError() << "Could not find qubit id."; } } return qubits; diff --git a/lib/Conversion/QUIRToPulse/QUIRToPulse.cpp b/lib/Conversion/QUIRToPulse/QUIRToPulse.cpp index d36079aaa..97303a7e3 100644 --- a/lib/Conversion/QUIRToPulse/QUIRToPulse.cpp +++ b/lib/Conversion/QUIRToPulse/QUIRToPulse.cpp @@ -21,15 +21,52 @@ #include "Conversion/QUIRToPulse/QUIRToPulse.h" +#include "Dialect/OQ3/IR/OQ3Ops.h" +#include "Dialect/Pulse/IR/PulseInterfaces.h" +#include "Dialect/Pulse/IR/PulseOps.h" +#include "Dialect/Pulse/IR/PulseTypes.h" +#include "Dialect/QCS/IR/QCSOps.h" +#include "Dialect/QUIR/IR/QUIREnums.h" +#include "Dialect/QUIR/IR/QUIROps.h" +#include "Dialect/QUIR/IR/QUIRTypes.h" #include "Dialect/QUIR/Utils/Utils.h" -#include "mlir/IR/BlockAndValueMapping.h" -#include "mlir/Parser.h" +#include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/BuiltinTypes.h" +#include "mlir/IR/Location.h" +#include "mlir/IR/OwningOpRef.h" +#include "mlir/IR/SymbolTable.h" +#include "mlir/IR/TypeRange.h" +#include "mlir/IR/Types.h" +#include "mlir/IR/Value.h" +#include "mlir/IR/ValueRange.h" +#include "mlir/Parser/Parser.h" #include "mlir/Support/FileUtilities.h" -#include "mlir/Transforms/GreedyPatternRewriteDriver.h" - +#include "mlir/Support/LLVM.h" + +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SMLoc.h" #include "llvm/Support/SourceMgr.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #define DEBUG_TYPE "QUIRToPulseDebug" using namespace mlir; @@ -48,10 +85,11 @@ void QUIRToPulsePass::runOnOperation() { parsePulseWaveformContainerOps(WAVEFORM_CONTAINER); ModuleOp moduleOp = getOperation(); - FuncOp mainFunc = dyn_cast(quir::getMainFunction(moduleOp)); + mlir::func::FuncOp mainFunc = + dyn_cast(quir::getMainFunction(moduleOp)); assert(mainFunc && "could not find the main func"); - mainFuncFirstOp = &mainFunc.body().front().front(); + mainFuncFirstOp = &mainFunc.getBody().front().front(); // convert all QUIR circuits to Pulse sequences moduleOp->walk([&](CallCircuitOp callCircOp) { @@ -81,12 +119,12 @@ void QUIRToPulsePass::runOnOperation() { } void QUIRToPulsePass::convertCircuitToSequence(CallCircuitOp callCircuitOp, - FuncOp &mainFunc, + mlir::func::FuncOp &mainFunc, ModuleOp moduleOp) { mlir::OpBuilder builder(mainFunc); auto circuitOp = getCircuitOp(callCircuitOp); - std::string circName = circuitOp.sym_name().str(); + std::string const circName = circuitOp.getSymName().str(); LLVM_DEBUG(llvm::dbgs() << "\nConverting QUIR circuit " << circName << ":\n"); assert(callCircuitOp && "callCircuit op is null"); assert(circuitOp && "circuit op is null"); @@ -96,12 +134,12 @@ void QUIRToPulsePass::convertCircuitToSequence(CallCircuitOp callCircuitOp, // build an empty pulse sequence SmallVector arguments; auto argumentsValueRange = ValueRange(arguments.data(), arguments.size()); - auto funcType = builder.getFunctionType(TypeRange(argumentsValueRange), {}); + mlir::FunctionType const funcType = + builder.getFunctionType(TypeRange(argumentsValueRange), {}); llvm::SmallVector convertedPulseSequenceOpReturnTypes; llvm::SmallVector convertedPulseSequenceOpReturnValues; auto convertedPulseSequenceOp = builder.create( - circuitOp.getLoc(), StringRef(circName + "_sequence"), funcType, - mlir::StringAttr{}); + circuitOp.getLoc(), StringRef(circName + "_sequence"), funcType); auto *entryBlock = convertedPulseSequenceOp.addEntryBlock(); auto entryBuilder = builder.atBlockBegin(entryBlock); @@ -119,7 +157,7 @@ void QUIRToPulsePass::convertCircuitToSequence(CallCircuitOp callCircuitOp, circuitOp->walk([&](Operation *quirOp) { if (quirOp->hasAttr("pulse.calName")) { - std::string pulseCalName = + std::string const pulseCalName = quirOp->getAttrOfType("pulse.calName").getValue().str(); SmallVector pulseCalSequenceArgs; Operation *findOp = SymbolTable::lookupSymbolIn(moduleOp, pulseCalName); @@ -141,14 +179,15 @@ void QUIRToPulsePass::convertCircuitToSequence(CallCircuitOp callCircuitOp, pulseCalSequenceOp->getAttrOfType("pulse.args")); for (auto type : pulseCalCallSequenceOp.getResultTypes()) convertedPulseSequenceOpReturnTypes.push_back(type); - for (auto val : pulseCalCallSequenceOp.res()) + for (auto val : pulseCalCallSequenceOp.getRes()) convertedPulseSequenceOpReturnValues.push_back(val); // add starting timepoint for delayOp if (auto delayOp = dyn_cast(quirOp)) { uint64_t durValue = 0; - if (delayOp.time().isa()) { - uint argNum = delayOp.time().dyn_cast().getArgNumber(); + if (delayOp.getTime().isa()) { + const uint argNum = + delayOp.getTime().dyn_cast().getArgNumber(); auto durOpConstantOp = callCircuitOp.getOperand(argNum) .getDefiningOp(); auto durOp = quir::getDuration(durOpConstantOp).get(); @@ -199,12 +238,12 @@ void QUIRToPulsePass::convertCircuitToSequence(CallCircuitOp callCircuitOp, void QUIRToPulsePass::processCircuitArgs( mlir::quir::CallCircuitOp callCircuitOp, mlir::quir::CircuitOp circuitOp, - SequenceOp convertedPulseSequenceOp, FuncOp &mainFunc, + SequenceOp convertedPulseSequenceOp, mlir::func::FuncOp &mainFunc, mlir::OpBuilder &builder) { for (uint cnt = 0; cnt < circuitOp.getNumArguments(); cnt++) { auto arg = circuitOp.getArgument(cnt); auto dictArg = circuitOp.getArgAttrDict(cnt); - mlir::Type argumentType = arg.getType(); + mlir::Type const argumentType = arg.getType(); if (argumentType.isa()) { auto *angleOp = callCircuitOp.getOperand(cnt).getDefiningOp(); LLVM_DEBUG(llvm::dbgs() << "angle argument "); @@ -245,7 +284,7 @@ void QUIRToPulsePass::processCircuitArgs( void QUIRToPulsePass::processPulseCalArgs( mlir::Operation *quirOp, SequenceOp pulseCalSequenceOp, SmallVector &pulseCalSequenceArgs, - SequenceOp convertedPulseSequenceOp, FuncOp &mainFunc, + SequenceOp convertedPulseSequenceOp, mlir::func::FuncOp &mainFunc, mlir::OpBuilder &builder) { // get the classical operands of the quir op @@ -265,10 +304,10 @@ void QUIRToPulsePass::processPulseCalArgs( for (auto const &argumentResult : llvm::enumerate(pulseCalSequenceOp.getArguments())) { auto index = argumentResult.index(); - mlir::Type argumentType = argumentResult.value().getType(); - mlir::Value argumentValue = argumentResult.value(); + mlir::Type const argumentType = argumentResult.value().getType(); + mlir::Value const argumentValue = argumentResult.value(); if (argumentType.isa()) { - std::string wfrName = + std::string const wfrName = argAttr[index].dyn_cast().getValue().str(); LLVM_DEBUG(llvm::dbgs() << "waveform argument " << wfrName << "\n"); processWfrOpArg(wfrName, convertedPulseSequenceOp, pulseCalSequenceArgs, @@ -323,11 +362,11 @@ void QUIRToPulsePass::getQUIROpClassicalOperands( if (auto castOp = dyn_cast(quirOp)) classicalCallOperands(castOp, classicalOperands); else if (auto castOp = dyn_cast(quirOp)) - classicalOperands.push_back(castOp.time()); + classicalOperands.push_back(castOp.getTime()); else if (auto castOp = dyn_cast(quirOp)) { - classicalOperands.push_back(castOp.theta()); - classicalOperands.push_back(castOp.phi()); - classicalOperands.push_back(castOp.lambda()); + classicalOperands.push_back(castOp.getTheta()); + classicalOperands.push_back(castOp.getPhi()); + classicalOperands.push_back(castOp.getLambda()); } for (auto operand : classicalOperands) @@ -343,7 +382,7 @@ void QUIRToPulsePass::processMixFrameOpArg( std::string const &mixFrameName, std::string const &portName, SequenceOp convertedPulseSequenceOp, SmallVector &pulseCalSequenceArgs, Value argumentValue, - FuncOp &mainFunc, mlir::OpBuilder &builder) { + mlir::func::FuncOp &mainFunc, mlir::OpBuilder &builder) { auto mixedFrameOp = addMixFrameOpToIR(mixFrameName, portName, mainFunc, builder); auto it = std::find(convertedPulseCallSequenceOpOperandNames.begin(), @@ -361,7 +400,7 @@ void QUIRToPulsePass::processMixFrameOpArg( convertedPulseSequenceOp.getArguments()[convertedSequenceOpArgIndex]); convertedSequenceOpArgIndex += 1; } else { - uint mixFrameOperandIndex = + uint const mixFrameOperandIndex = std::distance(convertedPulseCallSequenceOpOperandNames.begin(), it); pulseCalSequenceArgs.push_back( convertedPulseSequenceOp.getArguments()[mixFrameOperandIndex]); @@ -371,7 +410,8 @@ void QUIRToPulsePass::processMixFrameOpArg( void QUIRToPulsePass::processPortOpArg(std::string const &portName, SequenceOp convertedPulseSequenceOp, SmallVector &pulseCalSequenceArgs, - Value argumentValue, FuncOp &mainFunc, + Value argumentValue, + mlir::func::FuncOp &mainFunc, mlir::OpBuilder &builder) { auto portOp = addPortOpToIR(portName, mainFunc, builder); auto it = std::find(convertedPulseCallSequenceOpOperandNames.begin(), @@ -388,7 +428,7 @@ void QUIRToPulsePass::processPortOpArg(std::string const &portName, convertedPulseSequenceOp.getArguments()[convertedSequenceOpArgIndex]); convertedSequenceOpArgIndex += 1; } else { - uint portOperandIndex = + uint const portOperandIndex = std::distance(convertedPulseCallSequenceOpOperandNames.begin(), it); pulseCalSequenceArgs.push_back( convertedPulseSequenceOp.getArguments()[portOperandIndex]); @@ -398,7 +438,8 @@ void QUIRToPulsePass::processPortOpArg(std::string const &portName, void QUIRToPulsePass::processWfrOpArg(std::string const &wfrName, SequenceOp convertedPulseSequenceOp, SmallVector &pulseCalSequenceArgs, - Value argumentValue, FuncOp &mainFunc, + Value argumentValue, + mlir::func::FuncOp &mainFunc, mlir::OpBuilder &builder) { auto wfrOp = addWfrOpToIR(wfrName, mainFunc, builder); auto it = std::find(convertedPulseCallSequenceOpOperandNames.begin(), @@ -416,7 +457,7 @@ void QUIRToPulsePass::processWfrOpArg(std::string const &wfrName, convertedPulseSequenceOp.getArguments()[convertedSequenceOpArgIndex]); convertedSequenceOpArgIndex += 1; } else { - uint wfrOperandIndex = + uint const wfrOperandIndex = std::distance(convertedPulseCallSequenceOpOperandNames.begin(), it); pulseCalSequenceArgs.push_back( convertedPulseSequenceOp.getArguments()[wfrOperandIndex]); @@ -428,17 +469,19 @@ void QUIRToPulsePass::processAngleArg(Value nextAngleOperand, SmallVector &pulseCalSequenceArgs, mlir::OpBuilder &entryBuilder) { if (nextAngleOperand.isa()) { - uint circNum = nextAngleOperand.dyn_cast().getArgNumber(); + uint const circNum = + nextAngleOperand.dyn_cast().getArgNumber(); pulseCalSequenceArgs.push_back( convertedPulseSequenceOp .getArguments()[circuitArgToConvertedSequenceArgMap[circNum]]); } else { auto angleOp = nextAngleOperand.getDefiningOp(); - std::string angleLocHash = + std::string const angleLocHash = std::to_string(mlir::hash_value(angleOp->getLoc())); if (classicalQUIROpLocToConvertedPulseOpMap.find(angleLocHash) == classicalQUIROpLocToConvertedPulseOpMap.end()) { - double angleVal = angleOp.getAngleValueFromConstant().convertToDouble(); + double const angleVal = + angleOp.getAngleValueFromConstant().convertToDouble(); auto f64Angle = entryBuilder.create( angleOp.getLoc(), entryBuilder.getFloatAttr(entryBuilder.getF64Type(), llvm::APFloat(angleVal))); @@ -453,14 +496,15 @@ void QUIRToPulsePass::processDurationArg( Value nextDurationOperand, SequenceOp convertedPulseSequenceOp, SmallVector &pulseCalSequenceArgs, mlir::OpBuilder &entryBuilder) { if (nextDurationOperand.isa()) { - uint circNum = nextDurationOperand.dyn_cast().getArgNumber(); + uint const circNum = + nextDurationOperand.dyn_cast().getArgNumber(); pulseCalSequenceArgs.push_back( convertedPulseSequenceOp .getArguments()[circuitArgToConvertedSequenceArgMap[circNum]]); } else { auto durationOp = nextDurationOperand.getDefiningOp(); - std::string durLocHash = + std::string const durLocHash = std::to_string(mlir::hash_value(nextDurationOperand.getLoc())); auto durVal = quir::getDuration(durationOp).get().getDuration().convertToDouble(); @@ -484,13 +528,14 @@ void QUIRToPulsePass::processDurationArg( mlir::Value QUIRToPulsePass::convertAngleToF64(Operation *angleOp, mlir::OpBuilder &builder) { assert(angleOp && "angle op is null"); - std::string angleLocHash = + std::string const angleLocHash = std::to_string(mlir::hash_value(angleOp->getLoc())); if (classicalQUIROpLocToConvertedPulseOpMap.find(angleLocHash) == classicalQUIROpLocToConvertedPulseOpMap.end()) { if (auto castOp = dyn_cast(angleOp)) { addCircuitOperandToEraseList(angleOp); - double angleVal = castOp.getAngleValueFromConstant().convertToDouble(); + double const angleVal = + castOp.getAngleValueFromConstant().convertToDouble(); auto f64Angle = builder.create( castOp->getLoc(), builder.getFloatAttr(builder.getF64Type(), llvm::APFloat(angleVal))); @@ -498,16 +543,16 @@ mlir::Value QUIRToPulsePass::convertAngleToF64(Operation *angleOp, classicalQUIROpLocToConvertedPulseOpMap[angleLocHash] = f64Angle; } else if (auto castOp = dyn_cast(angleOp)) { auto angleCastedOp = builder.create( - castOp->getLoc(), builder.getF64Type(), castOp.res()); + castOp->getLoc(), builder.getF64Type(), castOp.getRes()); angleCastedOp->moveAfter(castOp); classicalQUIROpLocToConvertedPulseOpMap[angleLocHash] = angleCastedOp; } else if (auto castOp = dyn_cast(angleOp)) { addCircuitOperandToEraseList(angleOp); - auto castOpArg = castOp.arg(); + auto castOpArg = castOp.getArg(); if (auto paramCastOp = dyn_cast(castOpArg.getDefiningOp())) { auto angleCastedOp = builder.create( - paramCastOp->getLoc(), builder.getF64Type(), paramCastOp.res()); + paramCastOp->getLoc(), builder.getF64Type(), paramCastOp.getRes()); angleCastedOp->moveAfter(paramCastOp); classicalQUIROpLocToConvertedPulseOpMap[angleLocHash] = angleCastedOp; } else @@ -520,9 +565,9 @@ mlir::Value QUIRToPulsePass::convertAngleToF64(Operation *angleOp, mlir::Value QUIRToPulsePass::convertDurationToI64( mlir::quir::CallCircuitOp callCircuitOp, Operation *durationOp, uint &cnt, - mlir::OpBuilder &builder, FuncOp &mainFunc) { + mlir::OpBuilder &builder, mlir::func::FuncOp &mainFunc) { assert(durationOp && "duration op is null"); - std::string durLocHash = + std::string const durLocHash = std::to_string(mlir::hash_value(durationOp->getLoc())); if (classicalQUIROpLocToConvertedPulseOpMap.find(durLocHash) == classicalQUIROpLocToConvertedPulseOpMap.end()) { @@ -546,7 +591,8 @@ mlir::Value QUIRToPulsePass::convertDurationToI64( } mlir::pulse::Port_CreateOp -QUIRToPulsePass::addPortOpToIR(std::string const &portName, FuncOp &mainFunc, +QUIRToPulsePass::addPortOpToIR(std::string const &portName, + mlir::func::FuncOp &mainFunc, mlir::OpBuilder &builder) { if (openedPorts.find(portName) == openedPorts.end()) { auto portOp = @@ -557,10 +603,9 @@ QUIRToPulsePass::addPortOpToIR(std::string const &portName, FuncOp &mainFunc, return openedPorts[portName]; } -mlir::pulse::MixFrameOp -QUIRToPulsePass::addMixFrameOpToIR(std::string const &mixFrameName, - std::string const &portName, - FuncOp &mainFunc, mlir::OpBuilder &builder) { +mlir::pulse::MixFrameOp QUIRToPulsePass::addMixFrameOpToIR( + std::string const &mixFrameName, std::string const &portName, + mlir::func::FuncOp &mainFunc, mlir::OpBuilder &builder) { if (openedMixFrames.find(mixFrameName) == openedMixFrames.end()) { auto portOp = addPortOpToIR(portName, mainFunc, builder); auto mixedFrameOp = builder.create( @@ -573,7 +618,8 @@ QUIRToPulsePass::addMixFrameOpToIR(std::string const &mixFrameName, } mlir::pulse::Waveform_CreateOp -QUIRToPulsePass::addWfrOpToIR(std::string const &wfrName, FuncOp &mainFunc, +QUIRToPulsePass::addWfrOpToIR(std::string const &wfrName, + mlir::func::FuncOp &mainFunc, mlir::OpBuilder &builder) { if (openedWfrs.find(wfrName) == openedWfrs.end()) { auto *clonedOp = builder.clone(*pulseNameToWaveformMap[wfrName]); @@ -614,10 +660,12 @@ void QUIRToPulsePass::parsePulseWaveformContainerOps( std::unique_ptr waveformContainerFile = mlir::openInputFile(waveformContainerPath, &errorMessage); sourceMgr.AddNewSourceBuffer(std::move(waveformContainerFile), llvm::SMLoc()); - mlir::OwningOpRef waveformContainerFileModule( - mlir::parseSourceFile(sourceMgr, &getContext())); + + mlir::OwningOpRef waveformContainerFileModule = + mlir::parseSourceFile(sourceMgr, &getContext()); assert(waveformContainerFileModule and "problem parsing waveform container file"); + auto waveformContainerFileModuleRelease = waveformContainerFileModule.release(); waveformContainerFileModuleRelease->walk([&](mlir::pulse::Waveform_CreateOp diff --git a/lib/Conversion/QUIRToStandard/SwitchOpLowering.cpp b/lib/Conversion/QUIRToStandard/SwitchOpLowering.cpp index 8fb8b4597..5598416cd 100644 --- a/lib/Conversion/QUIRToStandard/SwitchOpLowering.cpp +++ b/lib/Conversion/QUIRToStandard/SwitchOpLowering.cpp @@ -20,10 +20,18 @@ //===----------------------------------------------------------------------===// #include "Dialect/QUIR/IR/QUIROps.h" + +#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/IR/ValueRange.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" #include "mlir/Transforms/DialectConversion.h" +#include +#include + namespace mlir::quir { // llvm.switch i32 %flag, label switchEnd [ @@ -33,13 +41,13 @@ namespace mlir::quir { // ] // caseRegion_default: // // gates -// br switchEnd +// cf.br switchEnd // caseRegion_1: // // gates -// br switchEnd +// cf.br switchEnd // caseRegion_2: // // gates -// br switchEnd +// cf.br switchEnd // ... // switchEnd: // ... @@ -63,17 +71,17 @@ SwitchOpLowering::matchAndRewrite(SwitchOp switchOp, Block *continueBlock = rewriter.splitBlock(condBlock, opPosition); SmallVector results; results.reserve(switchOp.getNumResults()); - for (Type resultType : switchOp.getResultTypes()) + for (auto resultType : switchOp.getResultTypes()) results.push_back( - continueBlock->addArgument(resultType, switchOp.getLoc())); + continueBlock->addArgument(resultType.getType(), switchOp.getLoc())); // Move blocks from the "default" region to the region containing // 'quir.switch', place it before the continuation block, and branch to it. - auto &defaultRegion = switchOp.defaultRegion(); + auto &defaultRegion = switchOp.getDefaultRegion(); auto *defaultBlock = &defaultRegion.front(); Operation *defaultTerminator = defaultRegion.back().getTerminator(); - ValueRange defaultTerminatorOperands = defaultTerminator->getOperands(); + ValueRange const defaultTerminatorOperands = defaultTerminator->getOperands(); rewriter.setInsertionPointToEnd(&defaultRegion.back()); - rewriter.create(loc, continueBlock, defaultTerminatorOperands); + rewriter.create(loc, continueBlock, defaultTerminatorOperands); rewriter.eraseOp(defaultTerminator); rewriter.inlineRegionBefore(defaultRegion, continueBlock); @@ -83,24 +91,25 @@ SwitchOpLowering::matchAndRewrite(SwitchOp switchOp, auto caseBlocks = std::vector(); auto *currBlock = continueBlock; auto caseOperands = std::vector(); - for (auto ®ion : switchOp.caseRegions()) + for (auto ®ion : switchOp.getCaseRegions()) if (!region.empty()) { - caseOperands.emplace_back(ValueRange()); + caseOperands.emplace_back(); currBlock = ®ion.front(); caseBlocks.push_back(currBlock); Operation *caseTerminator = region.back().getTerminator(); - ValueRange caseTerminatorOperands = caseTerminator->getOperands(); + ValueRange const caseTerminatorOperands = caseTerminator->getOperands(); rewriter.setInsertionPointToEnd(®ion.back()); - rewriter.create(loc, continueBlock, caseTerminatorOperands); + rewriter.create(loc, continueBlock, caseTerminatorOperands); rewriter.eraseOp(caseTerminator); rewriter.inlineRegionBefore(region, continueBlock); } rewriter.setInsertionPointToEnd(condBlock); rewriter.create( - loc, switchOp.flag(), /*defaultOperands=*/ValueRange(), - /*caseOperands=*/caseOperands, switchOp.caseValues(), - /*branchWeights=*/ElementsAttr(), defaultBlock, caseBlocks); + loc, /*flag=*/switchOp.getFlag(), /*defaultDestination=*/defaultBlock, + /*defaultOperands=*/ValueRange(), + /*caseValues=*/switchOp.getCaseValues(), /*caseDestinations=*/caseBlocks, + /*caseOperands=*/caseOperands); // Ok, we're done! rewriter.replaceOp(switchOp, continueBlock->getArguments()); diff --git a/lib/Conversion/QUIRToStandard/TypeConversion.cpp b/lib/Conversion/QUIRToStandard/TypeConversion.cpp index b3b1a85bb..d7a41d08a 100644 --- a/lib/Conversion/QUIRToStandard/TypeConversion.cpp +++ b/lib/Conversion/QUIRToStandard/TypeConversion.cpp @@ -20,20 +20,31 @@ #include "Conversion/QUIRToStandard/TypeConversion.h" #include "Dialect/OQ3/IR/OQ3Ops.h" -#include "Dialect/QUIR/IR/QUIROps.h" +#include "Dialect/QUIR/IR/QUIRTypes.h" + +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinTypes.h" +#include "mlir/IR/Location.h" +#include "mlir/IR/Types.h" +#include "mlir/IR/Value.h" +#include "mlir/IR/ValueRange.h" + +#include "llvm/Support/raw_ostream.h" + +#include namespace mlir { namespace { -Optional convertCBitType(quir::CBitType t) { +std::optional convertCBitType(quir::CBitType t) { if (t.getWidth() <= 64) return IntegerType::get(t.getContext(), t.getWidth()); - return llvm::None; + return std::nullopt; } -Optional legalizeIndexType(mlir::IndexType t) { return t; } +std::optional legalizeIndexType(mlir::IndexType t) { return t; } } // anonymous namespace QuirTypeConverter::QuirTypeConverter() { @@ -44,13 +55,13 @@ QuirTypeConverter::QuirTypeConverter() { addConversion(legalizeIndexType); } -Optional QuirTypeConverter::convertAngleType(Type t) { +std::optional QuirTypeConverter::convertAngleType(Type t) { auto *context = t.getContext(); if (auto angleType = t.dyn_cast()) { auto width = angleType.getWidth(); - if (!width.hasValue()) { + if (!width.has_value()) { llvm::errs() << "Cannot lower an angle with no width!\n"; return {}; } @@ -68,16 +79,16 @@ Optional QuirTypeConverter::convertAngleType(Type t) { // for function types in func defs and calls return floatType; } - return llvm::None; + return std::nullopt; } // convertAngleType -Optional QuirTypeConverter::angleSourceMaterialization( +std::optional QuirTypeConverter::angleSourceMaterialization( OpBuilder &builder, quir::AngleType aType, ValueRange valRange, Location loc) { - for (Value val : valRange) { + for (Value const val : valRange) { auto castOp = builder.create(loc, aType, val); - return castOp.out(); + return castOp.getOut(); } // for val : valRange - return llvm::None; + return std::nullopt; } // angleSourceMaterialization } // namespace mlir diff --git a/lib/Conversion/QUIRToStandard/VariablesToGlobalMemRefConversion.cpp b/lib/Conversion/QUIRToStandard/VariablesToGlobalMemRefConversion.cpp index f69971e84..705ce4b65 100644 --- a/lib/Conversion/QUIRToStandard/VariablesToGlobalMemRefConversion.cpp +++ b/lib/Conversion/QUIRToStandard/VariablesToGlobalMemRefConversion.cpp @@ -24,36 +24,46 @@ //===----------------------------------------------------------------------===// #include "Conversion/QUIRToStandard/VariablesToGlobalMemRefConversion.h" + #include "Dialect/OQ3/IR/OQ3Ops.h" -#include "Dialect/QUIR/IR/QUIROps.h" -#include "Dialect/QUIR/Transforms/Passes.h" #include "mlir/Dialect/Affine/IR/AffineOps.h" -#include "mlir/Dialect/Arithmetic/IR/Arithmetic.h" +#include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/IR/SymbolTable.h" +#include "mlir/IR/ValueRange.h" +#include "mlir/Support/LogicalResult.h" #include "mlir/Transforms/DialectConversion.h" +#include + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" + +#include +#include +#include using namespace mlir; using namespace mlir::oq3; using namespace mlir::quir; namespace { -llvm::Optional +std::optional createGlobalMemrefOp(mlir::OpBuilder &builder, mlir::Location loc, mlir::Operation *insertionAnchor, mlir::MemRefType type, llvm::StringRef name) { // place memref::GlobalOps at the top of the surrounding module. // (note: required by llvm.mlir.global, which this is lowered to) - mlir::OpBuilder::InsertionGuard g(builder); + mlir::OpBuilder::InsertionGuard const g(builder); auto containingModule = insertionAnchor->getParentOfType(); if (!containingModule) { insertionAnchor->emitOpError("Missing a global ModuleOp container."); - return llvm::None; + return std::nullopt; } builder.setInsertionPoint(&containingModule.front()); @@ -85,8 +95,8 @@ struct VariableDeclarationConversionPattern matchAndRewrite(DeclareVariableOp declareOp, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override { - auto declarationType = declareOp.type(); - auto convertedType = typeConverter->convertType(declareOp.type()); + auto declarationType = declareOp.getType(); + auto convertedType = typeConverter->convertType(declareOp.getType()); if (convertedType) declarationType = convertedType; @@ -102,7 +112,7 @@ struct VariableDeclarationConversionPattern if (!gmoOrNone) return failure(); - auto gmo = gmoOrNone.getValue(); + auto gmo = gmoOrNone.value(); if (externalizeOutputVariables && declareOp.isOutputVariable()) { // for generating defined symbols, global memrefs need an initializer @@ -113,7 +123,7 @@ struct VariableDeclarationConversionPattern rankedTensorType, llvm::ArrayRef{elementInitializerAttr}); - gmo.initial_valueAttr(initializerAttr); + gmo.setInitialValueAttr(initializerAttr); gmo.setPublic(); } @@ -133,14 +143,14 @@ struct ArrayDeclarationConversionPattern matchAndRewrite(DeclareArrayOp declareOp, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override { - auto declarationType = declareOp.type(); - auto convertedType = typeConverter->convertType(declareOp.type()); + auto declarationType = declareOp.getType(); + auto convertedType = typeConverter->convertType(declareOp.getType()); if (convertedType) declarationType = convertedType; - uint64_t num_elements = declareOp.num_elements().getZExtValue(); + uint64_t const numElements = declareOp.getNumElements().getZExtValue(); auto const memRefType = mlir::MemRefType::get( - llvm::ArrayRef{(int64_t)num_elements}, declareOp.type()); + llvm::ArrayRef{(int64_t)numElements}, declareOp.getType()); assert(memRefType && "failed to instantiate a MemRefType, likely trying " "with invalid element type"); @@ -162,42 +172,43 @@ struct ArrayDeclarationConversionPattern /// GetGlobalMemrefOp for /// @return a GetGlobalMemrefOp for the given variable op template -llvm::Optional +std::optional findOrCreateGetGlobalMemref(QUIRVariableOp variableOp, ConversionPatternRewriter &builder) { - mlir::OpBuilder::InsertionGuard g(builder); + mlir::OpBuilder::InsertionGuard const g(builder); auto globalMemrefOp = SymbolTable::lookupNearestSymbolFrom( - variableOp, variableOp.variable_nameAttr()); + variableOp, variableOp.getVariableNameAttr()); if (!globalMemrefOp) { variableOp.emitOpError("Cannot lookup a variable declaration for " + - variableOp.variable_name()); - return llvm::None; + variableOp.getVariableName()); + return std::nullopt; } auto surroundingFunction = - variableOp->template getParentOfType(); + variableOp->template getParentOfType(); if (!surroundingFunction) { - variableOp.emitOpError("Variable use of " + variableOp.variable_name() + + variableOp.emitOpError("Variable use of " + variableOp.getVariableName() + " outside functions not supported"); - return llvm::None; + return std::nullopt; } // Search for an existing memref::GetGlobalOp in the surrounding function by // walking all the GlobalMemref's symbol uses. if (auto rangeOrNone = mlir::SymbolTable::getSymbolUses( /* symbol */ globalMemrefOp, /* inside */ surroundingFunction)) - for (auto &use : rangeOrNone.getValue()) + for (auto &use : rangeOrNone.value()) if (llvm::isa(use.getUser())) return llvm::cast(use.getUser()); // Create new one at the top of the start of the function builder.setInsertionPointToStart(&surroundingFunction.getBody().front()); - return builder.create( - variableOp.getLoc(), globalMemrefOp.type(), globalMemrefOp.sym_name()); + return builder.create(variableOp.getLoc(), + globalMemrefOp.getType(), + globalMemrefOp.getSymName()); } struct VariableUseConversionPattern @@ -215,11 +226,11 @@ struct VariableUseConversionPattern if (!varRefOrNone) return failure(); - auto varRef = varRefOrNone.getValue(); - auto loadOp = - rewriter.create(useOp.getLoc(), varRef.getResult()); + auto varRef = varRefOrNone.value(); + auto loadOp = rewriter.create( + useOp.getLoc(), varRef.getResult()); - rewriter.replaceOp(useOp, {loadOp}); + rewriter.replaceOp(useOp, loadOp); return success(); } }; @@ -238,14 +249,14 @@ struct ArrayElementUseConversionPattern auto varRefOrNone = findOrCreateGetGlobalMemref(useOp, rewriter); if (!varRefOrNone) return failure(); - auto varRef = varRefOrNone.getValue(); + auto varRef = varRefOrNone.value(); auto indexOp = rewriter.create( - useOp.getLoc(), rewriter.getIndexType(), useOp.indexAttr()); + useOp.getLoc(), rewriter.getIndexType(), useOp.getIndexAttr()); auto loadOp = rewriter.create( useOp.getLoc(), varRef.getResult(), mlir::ValueRange{indexOp}); - rewriter.replaceOp(useOp, {loadOp}); + rewriter.replaceOp(useOp, loadOp); return success(); } }; @@ -263,10 +274,10 @@ struct VariableAssignConversionPattern auto varRefOrNone = findOrCreateGetGlobalMemref(assignOp, rewriter); if (!varRefOrNone) return failure(); - auto varRef = varRefOrNone.getValue(); + auto varRef = varRefOrNone.value(); - rewriter.create( - assignOp.getLoc(), adaptor.assigned_value(), varRef.getResult(), + rewriter.create( + assignOp.getLoc(), adaptor.getAssignedValue(), varRef.getResult(), mlir::ValueRange{}); rewriter.eraseOp(assignOp); @@ -288,13 +299,13 @@ struct ArrayElementAssignConversionPattern if (!varRefOrNone) return failure(); - auto varRef = varRefOrNone.getValue(); + auto varRef = varRefOrNone.value(); auto indexOp = rewriter.create( - assignOp.getLoc(), rewriter.getIndexType(), assignOp.indexAttr()); + assignOp.getLoc(), rewriter.getIndexType(), assignOp.getIndexAttr()); rewriter.create( - assignOp.getLoc(), adaptor.assigned_value(), varRef.getResult(), + assignOp.getLoc(), adaptor.getAssignedValue(), varRef.getResult(), mlir::ValueRange{indexOp}); rewriter.replaceOp(assignOp, mlir::ValueRange{}); diff --git a/lib/Dialect/OQ3/IR/OQ3Dialect.cpp b/lib/Dialect/OQ3/IR/OQ3Dialect.cpp index 5eb801b0d..89cd1a4a6 100644 --- a/lib/Dialect/OQ3/IR/OQ3Dialect.cpp +++ b/lib/Dialect/OQ3/IR/OQ3Dialect.cpp @@ -13,7 +13,10 @@ //===----------------------------------------------------------------------===// #include "Dialect/OQ3/IR/OQ3Dialect.h" + +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/OQ3/IR/OQ3Ops.h" +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/OQ3/IR/OQ3Types.h" #include "mlir/Transforms/InliningUtils.h" @@ -22,6 +25,7 @@ using namespace mlir; using namespace mlir::oq3; /// Tablegen Definitions +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/OQ3/IR/OQ3OpsDialect.cpp.inc" //===----------------------------------------------------------------------===// @@ -45,8 +49,8 @@ struct OQ3InlinerInterface : public DialectInlinerInterface { // This hook checks to see if the given `Operation` is legal to inline into // the given region. For OQ3, this hook can simply return true, as all OQ3 // operations are currently inlinable. - auto isLegalToInline(Operation *, Region *, bool, - BlockAndValueMapping &) const -> bool final { + auto isLegalToInline(Operation *, Region *, bool, IRMapping &) const + -> bool final { return true; } }; @@ -55,6 +59,7 @@ void OQ3Dialect::initialize() { addOperations< #define GET_OP_LIST +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/OQ3/IR/OQ3Ops.cpp.inc" >(); diff --git a/lib/Dialect/OQ3/IR/OQ3Ops.cpp b/lib/Dialect/OQ3/IR/OQ3Ops.cpp index 3a5765dca..ac3f4e6be 100644 --- a/lib/Dialect/OQ3/IR/OQ3Ops.cpp +++ b/lib/Dialect/OQ3/IR/OQ3Ops.cpp @@ -13,13 +13,31 @@ //===----------------------------------------------------------------------===// #include "Dialect/OQ3/IR/OQ3Ops.h" -#include "Dialect/OQ3/IR/OQ3Dialect.h" -#include "Dialect/OQ3/IR/OQ3Types.h" + +#include "Dialect/QUIR/IR/QUIRTypes.h" + +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/BuiltinTypes.h" +#include "mlir/IR/OpDefinition.h" +#include "mlir/IR/Operation.h" +#include "mlir/IR/SymbolTable.h" +#include "mlir/IR/Value.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" + +#include "llvm/Support/raw_ostream.h" + +#include +#include +#include +#include +#include using namespace mlir; using namespace mlir::oq3; -static LogicalResult +namespace { +mlir::LogicalResult verifyOQ3VariableOpSymbolUses(SymbolTableCollection &symbolTable, mlir::Operation *op, bool operandMustMatchSymbolType = false) { @@ -42,7 +60,7 @@ verifyOQ3VariableOpSymbolUses(SymbolTableCollection &symbolTable, // Check that type of variables matches result type of this Op if (op->getNumResults() == 1) { - if (op->getResult(0).getType() != declOp.type()) + if (op->getResult(0).getType() != declOp.getType()) return op->emitOpError( "type mismatch between variable declaration and variable use"); } @@ -50,7 +68,7 @@ verifyOQ3VariableOpSymbolUses(SymbolTableCollection &symbolTable, if (op->getNumOperands() > 0 && operandMustMatchSymbolType) { assert(op->getNumOperands() == 1 && "type check only supported for a single operand"); - if (op->getOperand(0).getType() != declOp.type()) + if (op->getOperand(0).getType() != declOp.getType()) return op->emitOpError( "type mismatch between variable declaration and variable assignment"); } @@ -60,13 +78,15 @@ verifyOQ3VariableOpSymbolUses(SymbolTableCollection &symbolTable, return success(); } +} // anonymous namespace //===----------------------------------------------------------------------===// // CBit ops //===----------------------------------------------------------------------===// -static llvm::Optional -findDefiningBitInBitmap(mlir::Value val, mlir::IntegerAttr bitIndex) { +namespace { +std::optional findDefiningBitInBitmap(mlir::Value val, + mlir::IntegerAttr bitIndex) { // for single-bit registers, CBitExtractBitOp is the identity. if (val.getType().isInteger(1)) @@ -77,44 +97,45 @@ findDefiningBitInBitmap(mlir::Value val, mlir::IntegerAttr bitIndex) { // follow chains of CBit_InsertBit operations and try to find one matching the // requested bit while (auto insertBitOp = mlir::dyn_cast_or_null(op)) { - if (insertBitOp.indexAttr() == bitIndex) - return insertBitOp.assigned_bit(); + if (insertBitOp.getIndexAttr() == bitIndex) + return insertBitOp.getAssignedBit(); - op = insertBitOp.operand().getDefiningOp(); + op = insertBitOp.getOperand().getDefiningOp(); } // did we identify an op that provides the single bit? if (op && op->getResult(0).getType().isInteger(1)) return op->getResult(0); - return llvm::None; + return std::nullopt; } +} // anonymous namespace -::mlir::OpFoldResult -CBitExtractBitOp::fold(::llvm::ArrayRef<::mlir::Attribute> operands) { +::mlir::OpFoldResult CBitExtractBitOp::fold(FoldAdaptor adaptor) { - auto foundDefiningBitOrNone = findDefiningBitInBitmap(operand(), indexAttr()); + auto foundDefiningBitOrNone = + findDefiningBitInBitmap(getOperand(), getIndexAttr()); if (foundDefiningBitOrNone) - return foundDefiningBitOrNone.getValue(); + return foundDefiningBitOrNone.value(); return nullptr; } -static LogicalResult verify(CBitExtractBitOp op) { +mlir::LogicalResult CBitExtractBitOp::verify() { - auto t = op.getOperand().getType(); + auto t = getOperand().getType(); if (auto cbitType = t.dyn_cast(); - cbitType && op.index().ult(cbitType.getWidth())) + cbitType && getIndex().ult(cbitType.getWidth())) return success(); - if (t.isIntOrIndex() && op.index().ult(t.getIntOrFloatBitWidth())) + if (t.isIntOrIndex() && getIndex().ult(t.getIntOrFloatBitWidth())) return success(); - return op.emitOpError("index must be less than the width of the operand."); + return emitOpError("index must be less than the width of the operand."); } -LogicalResult +mlir::LogicalResult CBitAssignBitOp::verifySymbolUses(SymbolTableCollection &symbolTable) { return verifyOQ3VariableOpSymbolUses(symbolTable, getOperation()); @@ -124,13 +145,28 @@ CBitAssignBitOp::verifySymbolUses(SymbolTableCollection &symbolTable) { // Variable ops //===----------------------------------------------------------------------===// -LogicalResult +mlir::LogicalResult DeclareVariableOp::verify() { + auto t = (*this).getType(); + + if (t.isa<::mlir::quir::AngleType>() || t.isa<::mlir::quir::CBitType>() || + t.isa<::mlir::quir::DurationType>() || + t.isa<::mlir::quir::StretchType>() || t.isIntOrIndexOrFloat() || + t.isa()) + return success(); + std::string str; + llvm::raw_string_ostream os(str); + t.print(os); + + return emitOpError("MLIR type " + str + " not supported for declarations."); +} + +mlir::LogicalResult VariableAssignOp::verifySymbolUses(SymbolTableCollection &symbolTable) { return verifyOQ3VariableOpSymbolUses(symbolTable, getOperation(), true); } -LogicalResult +mlir::LogicalResult VariableLoadOp::verifySymbolUses(SymbolTableCollection &symbolTable) { return verifyOQ3VariableOpSymbolUses(symbolTable, getOperation()); @@ -140,15 +176,42 @@ VariableLoadOp::verifySymbolUses(SymbolTableCollection &symbolTable) { // Array ops //===----------------------------------------------------------------------===// -LogicalResult +mlir::LogicalResult DeclareArrayOp::verify() { + auto t = (*this).getType(); + + if (t.isa<::mlir::quir::AngleType>() || t.isa<::mlir::quir::CBitType>() || + t.isa<::mlir::quir::DurationType>() || + t.isa<::mlir::quir::StretchType>() || t.isIntOrIndexOrFloat()) + return success(); + return failure(); +} + +mlir::LogicalResult AssignArrayElementOp::verifySymbolUses(SymbolTableCollection &symbolTable) { return verifyOQ3VariableOpSymbolUses(symbolTable, getOperation()); } -LogicalResult +mlir::LogicalResult UseArrayElementOp::verifySymbolUses(SymbolTableCollection &symbolTable) { return verifyOQ3VariableOpSymbolUses(symbolTable, getOperation()); } +//===----------------------------------------------------------------------===// +// Binary / Unary Ops +//===----------------------------------------------------------------------===// + +mlir::LogicalResult AngleCmpOp::verify() { + std::vector predicates = {"eq", "ne", "slt", "sle", "sgt", + "sge", "ult", "ule", "ugt", "uge"}; + + if (std::find(predicates.begin(), predicates.end(), getPredicate()) != + predicates.end()) + return success(); + + return emitOpError("requires predicate \"eq\", \"ne\", \"slt\", \"sle\", " + "\"sgt\", \"sge\", \"ult\", \"ule\", \"ugt\", \"uge\""); +} + #define GET_OP_CLASSES +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/OQ3/IR/OQ3Ops.cpp.inc" diff --git a/lib/Dialect/OQ3/IR/OQ3Patterns.cpp b/lib/Dialect/OQ3/IR/OQ3Patterns.cpp index 4c672140a..33eeb96c6 100644 --- a/lib/Dialect/OQ3/IR/OQ3Patterns.cpp +++ b/lib/Dialect/OQ3/IR/OQ3Patterns.cpp @@ -19,17 +19,21 @@ /// //===----------------------------------------------------------------------===// -#include "Dialect/OQ3/IR/OQ3Dialect.h" #include "Dialect/OQ3/IR/OQ3Ops.h" -#include "Dialect/OQ3/IR/OQ3Types.h" -#include "Dialect/QUIR/IR/QUIROps.h" -#include "mlir/Dialect/Arithmetic/IR/Arithmetic.h" -#include "mlir/Dialect/SCF/SCF.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" -#include "mlir/IR/BlockAndValueMapping.h" +#include "Dialect/QUIR/IR/QUIRTypes.h" + +#include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/MLIRContext.h" +#include "mlir/IR/Operation.h" #include "mlir/IR/PatternMatch.h" -#include "mlir/IR/SymbolTable.h" +#include "mlir/IR/Value.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" + +#include +#include using namespace mlir; using namespace oq3; @@ -38,13 +42,13 @@ namespace { /// Include the patterns defined in the Declarative Rewrite framework. #include "Dialect/OQ3/IR/OQ3Patterns.inc" -static llvm::Optional +static std::optional getI1InputFromExtensionOp(mlir::Operation *op) { if (!op) - return llvm::None; + return std::nullopt; if (!mlir::isa(op) && !mlir::isa(op)) - return llvm::None; + return std::nullopt; assert(op->getNumOperands() == 1 && "Cannot extract I1 operand from operations that don't have exactly 1 " @@ -54,7 +58,7 @@ getI1InputFromExtensionOp(mlir::Operation *op) { if (operand.getType().isSignlessInteger(1)) return operand; - return llvm::None; + return std::nullopt; } // This pattern detects DAGs that result from qasm `bit x; bool y = (x==1);` @@ -93,10 +97,10 @@ struct EqEqOnePat : public OpRewritePattern { auto extendedI1OrNone = getI1InputFromExtensionOp(cmpOp.getLhs().getDefiningOp()); - if (!extendedI1OrNone.hasValue()) + if (!extendedI1OrNone.has_value()) return failure(); - rewriter.replaceOp(cmpOp, {extendedI1OrNone.getValue()}); + rewriter.replaceOp(cmpOp, {extendedI1OrNone.value()}); return success(); } // matchAndRewrite }; // EqEqOnePat @@ -108,10 +112,10 @@ struct CastToSameType : public OpRewritePattern { : OpRewritePattern(context, /*benefit=*/1) {} auto matchAndRewrite(CastOp castOp, mlir::PatternRewriter &rewriter) const -> LogicalResult override { - if (castOp.arg().getType() != castOp.out().getType()) + if (castOp.getArg().getType() != castOp.getOut().getType()) return failure(); - rewriter.replaceOp(castOp, castOp.arg()); + rewriter.replaceOp(castOp, castOp.getArg()); return success(); } // matchAndRewrite }; // struct CastToSameType @@ -128,15 +132,15 @@ struct AssignSingleCBitToAssignVariablePattern matchAndRewrite(oq3::CBitAssignBitOp op, mlir::PatternRewriter &rewriter) const override { - if (op.cbit_width() != 1) + if (op.getCbitWidth() != 1) return failure(); auto *context = rewriter.getContext(); auto castOp = rewriter.create( - op.getLoc(), quir::CBitType::get(context, 1), op.assigned_bit()); + op.getLoc(), quir::CBitType::get(context, 1), op.getAssignedBit()); rewriter.replaceOpWithNewOp( - op, op.variable_nameAttr(), castOp.getResult()); + op, op.getVariableNameAttr(), castOp.getResult()); return success(); } diff --git a/lib/Dialect/OQ3/Transforms/LimitCBitWidth.cpp b/lib/Dialect/OQ3/Transforms/LimitCBitWidth.cpp index 12aa3cc26..859fe277f 100644 --- a/lib/Dialect/OQ3/Transforms/LimitCBitWidth.cpp +++ b/lib/Dialect/OQ3/Transforms/LimitCBitWidth.cpp @@ -18,17 +18,23 @@ #include "Dialect/OQ3/IR/OQ3Ops.h" -#include "mlir/Dialect/Arithmetic/IR/Arithmetic.h" +#include "Dialect/QUIR/IR/QUIRTypes.h" +#include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinAttributes.h" -#include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/SymbolTable.h" +#include "mlir/Support/LLVM.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" +#include +#include #include +#include +#include +#include #define DEBUG_TYPE "LimitCBitWidth" @@ -39,7 +45,7 @@ void LimitCBitWidthPass::addNewDeclareVariableOps( uint numRemainingBits, llvm::SmallVector &newRegisters, mlir::SymbolTableCollection &symbolTableCol) { - auto variableName = op.sym_name(); + auto variableName = op.getSymName(); // create new registers with _# added to end // add additional "_" if symbol name is found @@ -52,14 +58,14 @@ void LimitCBitWidthPass::addNewDeclareVariableOps( symbolTableCol.getSymbolTable(module).lookup(newVariableName); if (findOp) { uint extraInt = 0; - std::string baseVariableName = newVariableName; + std::string const baseVariableName = newVariableName; while (findOp) { newVariableName = baseVariableName + std::to_string(extraInt++); findOp = symbolTableCol.getSymbolTable(module).lookup(newVariableName); } } - uint bitWidth = + uint const bitWidth = getNewRegisterWidth(regNum, numRegistersRequired, numRemainingBits); auto newCbitType = builder.getType(bitWidth); newRegisters.push_back(builder.create( @@ -73,15 +79,16 @@ void LimitCBitWidthPass::processOp( llvm::SmallVector &newRegisters) { uint64_t index; uint64_t reg; - std::tie(reg, index) = remapBit(cbitAssignOp.index()); - auto width = newRegisters[reg].type().dyn_cast().getWidth(); - auto value = cbitAssignOp.assigned_bit(); + std::tie(reg, index) = remapBit(cbitAssignOp.getIndex()); + auto width = + newRegisters[reg].getType().dyn_cast().getWidth(); + auto value = cbitAssignOp.getAssignedBit(); OpBuilder builder(cbitAssignOp); builder.create( cbitAssignOp->getLoc(), mlir::SymbolRefAttr::get( - builder.getStringAttr(newRegisters[reg].sym_name())), + builder.getStringAttr(newRegisters[reg].getSymName())), builder.getIndexAttr(index), builder.getIndexAttr(width), value); eraseList_.push_back(cbitAssignOp); @@ -91,14 +98,15 @@ void LimitCBitWidthPass::processOp( VariableAssignOp variableAssignOp, uint orgWidth, uint numRegistersRequired, uint numRemainingBits, llvm::SmallVector &newRegisters) { - auto castOp = - dyn_cast(variableAssignOp.assigned_value().getDefiningOp()); + auto castOp = dyn_cast( + variableAssignOp.getAssignedValue().getDefiningOp()); if (!castOp) { variableAssignOp.emitError( "expect assigned_value() to be defined by a CastOp"); signalPassFailure(); } - auto constantOp = dyn_cast(castOp.arg().getDefiningOp()); + auto constantOp = + dyn_cast(castOp.getArg().getDefiningOp()); if (!constantOp) { castOp.emitError("expect cast arg() to be a constant op"); signalPassFailure(); @@ -116,10 +124,10 @@ void LimitCBitWidthPass::processOp( signalPassFailure(); } - APInt apInt = intAttr.getValue(); + APInt const apInt = intAttr.getValue(); for (uint regNum = 0; regNum < numRegistersRequired; regNum++) { - uint bitWidth = + uint const bitWidth = getNewRegisterWidth(regNum, numRegistersRequired, numRemainingBits); auto subPart = apInt.extractBits(bitWidth, regNum * MAX_CBIT_WIDTH); auto initializerVal = builder.create( @@ -130,8 +138,9 @@ void LimitCBitWidthPass::processOp( constantOp->getLoc(), builder.getType(bitWidth), initializerVal); - builder.create( - variableAssignOp->getLoc(), newRegisters[regNum].sym_name(), newCastOp); + builder.create(variableAssignOp->getLoc(), + newRegisters[regNum].getSymName(), + newCastOp); } eraseList_.push_back(variableAssignOp); } @@ -144,12 +153,12 @@ void LimitCBitWidthPass::processOp( llvm::SmallVector newVariableLoads; OpBuilder builder(variableLoadOp); for (uint regNum = 0; regNum < numRegistersRequired; regNum++) { - uint bitWidth = + uint const bitWidth = getNewRegisterWidth(regNum, numRegistersRequired, numRemainingBits); newVariableLoads.push_back(builder.create( variableLoadOp.getLoc(), builder.getType(bitWidth), - newRegisters[regNum].sym_name())); + newRegisters[regNum].getSymName())); } for (auto *loadUse : variableLoadOp->getUsers()) { @@ -157,7 +166,7 @@ void LimitCBitWidthPass::processOp( if (extractBitOp) { uint64_t reg; uint64_t remain; - std::tie(reg, remain) = remapBit(extractBitOp.index()); + std::tie(reg, remain) = remapBit(extractBitOp.getIndex()); auto newExtract = builder.create( extractBitOp->getLoc(), builder.getI1Type(), newVariableLoads[reg], builder.getIndexAttr(remain)); @@ -175,7 +184,7 @@ void LimitCBitWidthPass::processOp( std::pair LimitCBitWidthPass::remapBit(const llvm::APInt &indexInt) { uint64_t index = indexInt.getZExtValue(); - uint64_t reg = index / MAX_CBIT_WIDTH; + uint64_t const reg = index / MAX_CBIT_WIDTH; index = index - (reg * MAX_CBIT_WIDTH); return std::make_pair(reg, index); } @@ -183,7 +192,7 @@ LimitCBitWidthPass::remapBit(const llvm::APInt &indexInt) { uint LimitCBitWidthPass::getNewRegisterWidth(uint regNum, uint numRegistersRequired, uint numRemainingBits) { - uint bitWidth = + uint const bitWidth = regNum == (numRegistersRequired - 1) ? numRemainingBits : MAX_CBIT_WIDTH; return bitWidth; } @@ -202,20 +211,20 @@ void LimitCBitWidthPass::runOnOperation() { module->walk([&](DeclareVariableOp op) { // look for declare variables of CBitType and Width > 64 - auto cbitType = op.type().dyn_cast(); + auto cbitType = op.getType().dyn_cast(); if (!cbitType || cbitType.getWidth() <= MAX_CBIT_WIDTH) return; - uint orgWidth = cbitType.getWidth(); - uint numRegistersRequired = cbitType.getWidth() / MAX_CBIT_WIDTH + 1; - uint numRemainingBits = cbitType.getWidth() % MAX_CBIT_WIDTH; + uint const orgWidth = cbitType.getWidth(); + uint const numRegistersRequired = cbitType.getWidth() / MAX_CBIT_WIDTH + 1; + uint const numRemainingBits = cbitType.getWidth() % MAX_CBIT_WIDTH; llvm::SmallVector newRegisters; addNewDeclareVariableOps(module, op, numRegistersRequired, numRemainingBits, newRegisters, symbolTableCol); if (auto rangeOrNone = SymbolTable::getSymbolUses(op, module)) - for (auto &use : rangeOrNone.getValue()) { + for (auto &use : rangeOrNone.value()) { auto *user = use.getUser(); if (auto variableAssignOp = dyn_cast(user)) processOp(variableAssignOp, orgWidth, numRegistersRequired, diff --git a/lib/Dialect/OQ3/Transforms/Passes.cpp b/lib/Dialect/OQ3/Transforms/Passes.cpp index 70fd866fa..772e09cbb 100644 --- a/lib/Dialect/OQ3/Transforms/Passes.cpp +++ b/lib/Dialect/OQ3/Transforms/Passes.cpp @@ -15,10 +15,12 @@ //===----------------------------------------------------------------------===// #include "Dialect/OQ3/Transforms/Passes.h" - #include "Dialect/OQ3/Transforms/LimitCBitWidth.h" -#include "mlir/Pass/Pass.h" + #include "mlir/Pass/PassManager.h" +#include "mlir/Pass/PassRegistry.h" + +#include namespace mlir::oq3 { @@ -34,7 +36,7 @@ void registerOQ3Passes() { } void registerOQ3PassPipeline() { - PassPipelineRegistration<> pipeline( + PassPipelineRegistration<> const pipeline( "oq3Opt", "Enable OQ3-specific optimizations", oq3PassPipelineBuilder); } } // end namespace mlir::oq3 diff --git a/lib/Dialect/Pulse/IR/CMakeLists.txt b/lib/Dialect/Pulse/IR/CMakeLists.txt index fc7901b53..d51e16740 100644 --- a/lib/Dialect/Pulse/IR/CMakeLists.txt +++ b/lib/Dialect/Pulse/IR/CMakeLists.txt @@ -12,6 +12,7 @@ add_mlir_dialect_library(MLIRPulseDialect + PulseAttributes.cpp PulseDialect.cpp PulseInterfaces.cpp PulseOps.cpp @@ -24,5 +25,5 @@ add_mlir_dialect_library(MLIRPulseDialect LINK_LIBS PUBLIC MLIRIR - Utils + QSSCUtils ) diff --git a/lib/Dialect/Pulse/IR/PulseAttributes.cpp b/lib/Dialect/Pulse/IR/PulseAttributes.cpp new file mode 100644 index 000000000..eb5de0452 --- /dev/null +++ b/lib/Dialect/Pulse/IR/PulseAttributes.cpp @@ -0,0 +1,15 @@ +//===- PulseAttributes.cpp - Pulse dialect attributes -----------*- C++ -*-===// +// +// (C) Copyright IBM 2023. +// +// This code is part of Qiskit. +// +// This code is licensed under the Apache License, Version 2.0 with LLVM +// Exceptions. You may obtain a copy of this license in the LICENSE.txt +// file in the root directory of this source tree. +// +// Any modifications or derivative works of this code must retain this +// copyright notice, and modified files need to carry a notice indicating +// that they have been altered from the originals. +// +//===----------------------------------------------------------------------===// diff --git a/lib/Dialect/Pulse/IR/PulseDialect.cpp b/lib/Dialect/Pulse/IR/PulseDialect.cpp index 15e9dbda8..c53d7a7fd 100644 --- a/lib/Dialect/Pulse/IR/PulseDialect.cpp +++ b/lib/Dialect/Pulse/IR/PulseDialect.cpp @@ -19,30 +19,45 @@ //===----------------------------------------------------------------------===// #include "Dialect/Pulse/IR/PulseDialect.h" + +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations +#include "Dialect/Pulse/IR/PulseAttributes.h" +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/Pulse/IR/PulseOps.h" +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/Pulse/IR/PulseTypes.h" -#include "mlir/IR/Dialect.h" - -#include "llvm/ADT/TypeSwitch.h" - /// Tablegen Definitions +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/Pulse/IR/PulseDialect.cpp.inc" #define GET_TYPEDEF_CLASSES +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/Pulse/IR/PulseTypes.cpp.inc" +#define GET_ATTRDEF_CLASSES +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations +#include "Dialect/Pulse/IR/PulseAttributes.cpp.inc" + namespace mlir::pulse { void pulse::PulseDialect::initialize() { addTypes< #define GET_TYPEDEF_LIST +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/Pulse/IR/PulseTypes.cpp.inc" >(); addOperations< #define GET_OP_LIST +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations +#include "Dialect/Pulse/IR/Pulse.cpp.inc" + >(); + + addAttributes< +#define GET_ATTRDEF_LIST +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/Pulse/IR/Pulse.cpp.inc" >(); } diff --git a/lib/Dialect/Pulse/IR/PulseInterfaces.cpp b/lib/Dialect/Pulse/IR/PulseInterfaces.cpp index 4fc6b8bbf..9f12b9052 100644 --- a/lib/Dialect/Pulse/IR/PulseInterfaces.cpp +++ b/lib/Dialect/Pulse/IR/PulseInterfaces.cpp @@ -20,24 +20,31 @@ #include "Dialect/Pulse/IR/PulseInterfaces.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/Operation.h" + +#include "llvm/Support/Error.h" + +#include +#include using namespace mlir::pulse; //===----------------------------------------------------------------------===// // Tablegen Interface Definitions //===----------------------------------------------------------------------===// - +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/Pulse/IR/PulseInterfaces.cpp.inc" //===----------------------------------------------------------------------===// // PulseOpSchedulingInterface //===----------------------------------------------------------------------===// -llvm::Optional interfaces_impl::getTimepoint(mlir::Operation *op) { +std::optional interfaces_impl::getTimepoint(mlir::Operation *op) { if (op->hasAttr("pulse.timepoint")) return op->getAttrOfType("pulse.timepoint").getInt(); - return llvm::None; + return std::nullopt; } void interfaces_impl::setTimepoint(mlir::Operation *op, int64_t timepoint) { @@ -47,11 +54,11 @@ void interfaces_impl::setTimepoint(mlir::Operation *op, int64_t timepoint) { // MLIR does does not have a setUI64IntegerAttr so duration and setup latency // are stored as I64IntegerAttr but should be treated as a uint64_t -llvm::Optional interfaces_impl::getSetupLatency(Operation *op) { +std::optional interfaces_impl::getSetupLatency(Operation *op) { if (op->hasAttr("pulse.setupLatency")) return static_cast( op->getAttrOfType("pulse.setupLatency").getInt()); - return llvm::None; + return std::nullopt; } void interfaces_impl::setSetupLatency(Operation *op, uint64_t setupLatency) { diff --git a/lib/Dialect/Pulse/IR/PulseOps.cpp b/lib/Dialect/Pulse/IR/PulseOps.cpp index c3f9c62ef..6b2d46c22 100644 --- a/lib/Dialect/Pulse/IR/PulseOps.cpp +++ b/lib/Dialect/Pulse/IR/PulseOps.cpp @@ -15,29 +15,145 @@ //===----------------------------------------------------------------------===// #include "Dialect/Pulse/IR/PulseOps.h" -#include "Dialect/Pulse/IR/PulseDialect.h" +#include "Dialect/Pulse/IR/PulseTraits.h" +#include "Dialect/QUIR/IR/QUIROps.h" + +#include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/Complex/IR/Complex.h" -#include "mlir/IR/BlockAndValueMapping.h" +#include "mlir/IR/Attributes.h" +#include "mlir/IR/Block.h" #include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/BuiltinTypeInterfaces.h" #include "mlir/IR/FunctionImplementation.h" +#include "mlir/IR/IRMapping.h" +#include "mlir/IR/Location.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/Operation.h" #include "mlir/IR/OperationSupport.h" -#include "mlir/Interfaces/CallInterfaces.h" +#include "mlir/IR/SymbolTable.h" +#include "mlir/IR/Value.h" +#include "mlir/IR/Visitors.h" +#include "mlir/Support/LLVM.h" #include "mlir/Support/LogicalResult.h" + #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/Error.h" + +#include +#include +#include +#include +#include namespace mlir::pulse { +//===----------------------------------------------------------------------===// +// Waveform Ops +//===----------------------------------------------------------------------===// + +mlir::LogicalResult GaussianOp::verify() { + auto durDeclOp = dyn_cast_or_null( + (*this).getDur().getDefiningOp()); + if (durDeclOp && durDeclOp.value() < 0) + return emitOpError("duration must be >= 0."); + return success(); +} + +mlir::LogicalResult GaussianSquareOp::verify() { + auto durDeclOp = dyn_cast_or_null( + (*this).getDur().getDefiningOp()); + if (durDeclOp && durDeclOp.value() < 0) + return emitOpError("duration must be >= 0."); + return success(); +} + +mlir::LogicalResult DragOp::verify() { + auto durDeclOp = dyn_cast_or_null( + (*this).getDur().getDefiningOp()); + if (durDeclOp && durDeclOp.value() < 0) + return emitOpError("duration must be >= 0."); + return success(); +} + +mlir::LogicalResult ConstOp::verify() { + auto durDeclOp = dyn_cast_or_null( + (*this).getDur().getDefiningOp()); + if (durDeclOp && durDeclOp.value() < 0) + return emitOpError("duration must be >= 0."); + return success(); +} + +//===----------------------------------------------------------------------===// +// Waveform Ops +//===----------------------------------------------------------------------===// + +mlir::LogicalResult SetFrequencyOp::verify() { + if (!(*this).getTarget().isa()) + return emitOpError("Target is not a block argument; Target needs to be an " + "argument of pulse.sequence"); + return success(); +} + +mlir::LogicalResult ShiftFrequencyOp::verify() { + if (!(*this).getTarget().isa()) + return emitOpError("Target is not a block argument; Target needs to be an " + "argument of pulse.sequence"); + return success(); +} + +mlir::LogicalResult SetPhaseOp::verify() { + if (!(*this).getTarget().isa()) + return emitOpError("Target is not a block argument; Target needs to be an " + "argument of pulse.sequence"); + return success(); +} + +mlir::LogicalResult ShiftPhaseOp::verify() { + if (!(*this).getTarget().isa()) + return emitOpError("Target is not a block argument; Target needs to be an " + "argument of pulse.sequence"); + return success(); +} + +mlir::LogicalResult SetAmplitudeOp::verify() { + if (!(*this).getTarget().isa()) + return emitOpError("Target is not a block argument; Target needs to be an " + "argument of pulse.sequence"); + return success(); +} + +mlir::LogicalResult CaptureOp::verify() { + if (!(*this).getTarget().isa()) + return emitOpError("Target is not a block argument; Target needs to be an " + "argument of pulse.sequence"); + return success(); +} + +mlir::LogicalResult DelayOp::verify() { + auto durDeclOp = dyn_cast_or_null( + (*this).getDur().getDefiningOp()); + if (durDeclOp && durDeclOp.value() < 0) + return emitOpError("duration must be >= 0."); + + if (!(*this).getTarget().isa()) + return emitOpError("Target is not a block argument; Target needs to be an " + "argument of pulse.sequence"); + + return success(); +} + //===----------------------------------------------------------------------===// // Waveform_CreateOp //===----------------------------------------------------------------------===// llvm::Expected Waveform_CreateOp::getDuration(mlir::Operation *callSequenceOp = nullptr) { - auto shape = (*this).samples().getType().getShape(); + auto shape = (*this).getSamples().getType().getShape(); if (shape[0] < 0) return llvm::createStringError(llvm::inconvertibleErrorCode(), "duration must be >= 0."); @@ -45,25 +161,25 @@ Waveform_CreateOp::getDuration(mlir::Operation *callSequenceOp = nullptr) { } /// Verifier for pulse.waveform operation. -static auto verify(Waveform_CreateOp &op) -> mlir::LogicalResult { +mlir::LogicalResult Waveform_CreateOp::verify() { // Check that samples has two dimensions: outer is the number of // samples, inner is complex numbers with two elements [real, imag] - auto attrType = op.samples().getType().cast(); + auto attrType = getSamples().getType().cast(); auto attrShape = attrType.getShape(); if (attrShape.size() != 2) { - return op.emitOpError() << ", which declares a sample waveform, must be " - "composed of a two dimensional tensor."; + return emitOpError() << ", which declares a sample waveform, must be " + "composed of a two dimensional tensor."; } if (attrShape[1] != 2) { - return op.emitOpError() + return emitOpError() << ", which declares a sample waveform, must have inner dimension " "two corresponding to complex elements of the form [real, imag]."; } // Check duration - auto durOrError = op.getDuration(nullptr /*callSequenceOp*/); + auto durOrError = getDuration(nullptr /*callSequenceOp*/); if (auto err = durOrError.takeError()) - return op.emitOpError(toString(std::move(err))); + return emitOpError(toString(std::move(err))); return mlir::success(); } @@ -79,9 +195,9 @@ static auto verify(Waveform_CreateOp &op) -> mlir::LogicalResult { //===----------------------------------------------------------------------===// /// Verifier for pulse.waveform_container operation. -static auto verify(WaveformContainerOp &wfrContainerOp) -> mlir::LogicalResult { +LogicalResult WaveformContainerOp::verify() { - for (Block &block : wfrContainerOp.body().getBlocks()) { + for (Block &block : getBody().getBlocks()) { for (Operation &op : block.getOperations()) { // Check that all the operations in the body of the waveform_container are // of type Waveform_CreateOp @@ -129,7 +245,7 @@ CallSequenceOp::verifySymbolUses(SymbolTableCollection &symbolTable) { << "' does not reference a valid sequence"; // Verify the types match - auto sequenceType = sequence.getType(); + auto sequenceType = sequence.getFunctionType(); if (sequenceType.getNumInputs() != getNumOperands()) return emitOpError("incorrect number of operands for the callee sequence"); @@ -201,45 +317,47 @@ SequenceOp::getDuration(mlir::Operation *callSequenceOp = nullptr) { "Operation does not have a pulse.duration attribute."); } -static ParseResult parseSequenceOp(OpAsmParser &parser, - OperationState &result) { - auto buildSequenceType = +mlir::ParseResult SequenceOp::parse(mlir::OpAsmParser &parser, + mlir::OperationState &result) { + auto buildFuncType = [](Builder &builder, ArrayRef argTypes, ArrayRef results, function_interface_impl::VariadicFlag, std::string &) { return builder.getFunctionType(argTypes, results); }; + return function_interface_impl::parseFunctionOp( - parser, result, /*allowVariadic=*/false, buildSequenceType); + parser, result, /*allowVariadic=*/false, + getFunctionTypeAttrName(result.name), buildFuncType, + getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name)); } -static void print(SequenceOp op, OpAsmPrinter &p) { - FunctionType fnType = op.getType(); +void SequenceOp::print(mlir::OpAsmPrinter &printer) { function_interface_impl::printFunctionOp( - p, op, fnType.getInputs(), /*isVariadic=*/false, fnType.getResults()); + printer, *this, /*isVariadic=*/false, getFunctionTypeAttrName(), + getArgAttrsAttrName(), getResAttrsAttrName()); } +namespace { /// Verify the argument list and entry block are in agreement. -static LogicalResult verifyArgumentAndEntry_(SequenceOp op) { - auto fnInputTypes = op.getType().getInputs(); +LogicalResult verifyArgumentAndEntry_(SequenceOp op) { + auto fnInputTypes = op.getFunctionType().getInputs(); Block &entryBlock = op.front(); - for (unsigned i = 0; i != entryBlock.getNumArguments(); ++i) { + for (unsigned i = 0; i != entryBlock.getNumArguments(); ++i) if (fnInputTypes[i] != entryBlock.getArgument(i).getType()) return op.emitOpError("type of entry block argument #") << i << '(' << entryBlock.getArgument(i).getType() << ") must match the type of the corresponding argument in " << "function signature(" << fnInputTypes[i] << ')'; - } return success(); } /// Verify that no classical values are created/used in the sequence outside of /// values that originate as argument values or the result of a measurement. -static LogicalResult verifyClassical_(SequenceOp op) { +LogicalResult verifyClassical_(SequenceOp op) { mlir::Operation *classicalOp = nullptr; - WalkResult result = op->walk([&](Operation *subOp) { - if (isa(subOp) || isa(subOp) || - isa(subOp) || isa(subOp) || - isa(subOp) || isa(subOp) || - isa(subOp) || + WalkResult const result = op->walk([&](Operation *subOp) { + if (isa(subOp) || isa(subOp) || + isa(subOp) || isa(subOp) || + isa(subOp) || isa(subOp) || subOp->hasTrait() || subOp->hasTrait()) return WalkResult::advance(); @@ -252,24 +370,65 @@ static LogicalResult verifyClassical_(SequenceOp op) { << "is not valid within a real-time pulse sequence."; return success(); } +} // anonymous namespace -static LogicalResult verify(SequenceOp op) { +LogicalResult SequenceOp::verify() { // If external will be linked in later and nothing to do - if (op.isExternal()) + if (isExternal()) return success(); - if (failed(verifyArgumentAndEntry_(op))) + if (failed(verifyArgumentAndEntry_(*this))) return mlir::failure(); - if (failed(verifyClassical_(op))) + if (failed(verifyClassical_(*this))) return mlir::failure(); return success(); } +SequenceOp SequenceOp::create(Location location, StringRef name, + FunctionType type, + ArrayRef attrs) { + OpBuilder builder(location->getContext()); + OperationState state(location, getOperationName()); + SequenceOp::build(builder, state, name, type, attrs); + return cast(Operation::create(state)); +} +SequenceOp SequenceOp::create(Location location, StringRef name, + FunctionType type, + Operation::dialect_attr_range attrs) { + SmallVector const attrRef(attrs); + return create(location, name, type, attrRef); +} +SequenceOp SequenceOp::create(Location location, StringRef name, + FunctionType type, ArrayRef attrs, + ArrayRef argAttrs) { + SequenceOp circ = create(location, name, type, attrs); + circ.setAllArgAttrs(argAttrs); + return circ; +} + +void SequenceOp::build(OpBuilder &builder, OperationState &state, + StringRef name, FunctionType type, + ArrayRef attrs, + ArrayRef argAttrs) { + state.addAttribute(SymbolTable::getSymbolAttrName(), + builder.getStringAttr(name)); + state.addAttribute(getFunctionTypeAttrName(state.name), TypeAttr::get(type)); + state.attributes.append(attrs.begin(), attrs.end()); + state.addRegion(); + + if (argAttrs.empty()) + return; + assert(type.getNumInputs() == argAttrs.size()); + function_interface_impl::addArgAndResultAttrs( + builder, state, argAttrs, /*resultAttrs=*/std::nullopt, + getArgAttrsAttrName(state.name), getResAttrsAttrName(state.name)); +} + /// Clone the internal blocks and attributes from this sequence to the /// destination sequence. -void SequenceOp::cloneInto(SequenceOp dest, BlockAndValueMapping &mapper) { +void SequenceOp::cloneInto(SequenceOp dest, IRMapping &mapper) { // Add the attributes of this function to dest. llvm::MapVector newAttrMap; for (const auto &attr : dest->getAttrs()) @@ -292,13 +451,13 @@ void SequenceOp::cloneInto(SequenceOp dest, BlockAndValueMapping &mapper) { /// Using the provider mapper. Replace references to /// cloned sub-values with the corresponding copied value and /// add to the mapper -SequenceOp SequenceOp::clone(BlockAndValueMapping &mapper) { - FunctionType newType = getType(); +SequenceOp SequenceOp::clone(IRMapping &mapper) { + FunctionType newType = getFunctionType(); // If the function contains a body, then its possible arguments // may be deleted in the mapper. Verify this so they aren't // added to the input type vector. - bool isExternalSequence = isExternal(); + bool const isExternalSequence = isExternal(); if (!isExternalSequence) { SmallVector inputTypes; inputTypes.reserve(newType.getNumInputs()); @@ -318,7 +477,7 @@ SequenceOp SequenceOp::clone(BlockAndValueMapping &mapper) { } SequenceOp SequenceOp::clone() { - BlockAndValueMapping mapper; + IRMapping mapper; return clone(mapper); } @@ -334,14 +493,14 @@ SequenceOp SequenceOp::clone() { // //===----------------------------------------------------------------------===// -static LogicalResult verify(ReturnOp op) { - auto sequence = op->getParentOfType(); - FunctionType sequenceType = sequence.getType(); +LogicalResult ReturnOp::verify() { + auto sequence = (*this)->getParentOfType(); + FunctionType const sequenceType = sequence.getFunctionType(); auto numResults = sequenceType.getNumResults(); // Verify number of operands match type signature - if (numResults != op.operands().size()) { - return op.emitError() + if (numResults != getOperands().size()) { + return emitError() .append("expected ", numResults, " result operands") .attachNote(sequence.getLoc()) .append("return type declared here"); @@ -349,11 +508,11 @@ static LogicalResult verify(ReturnOp op) { int i = 0; for (const auto [type, operand] : - llvm::zip(sequenceType.getResults(), op.operands())) { + llvm::zip(sequenceType.getResults(), getOperands())) { auto opType = operand.getType(); if (type != opType) { - return op.emitOpError() - << "unexpected type `" << opType << "' for operand #" << i; + return emitOpError() << "unexpected type `" << opType << "' for operand #" + << i; } i++; } @@ -389,8 +548,8 @@ PlayOp::getDuration(mlir::Operation *callSequenceOp = nullptr) { // check if wfr is of type Waveform_CreateOp; this is the case if wfrOp is // defined in the same block as playOp e.g., if both are defined inside a // sequenceOp - if (auto castOp = - dyn_cast_or_null((*this).wfr().getDefiningOp())) { + if (auto castOp = dyn_cast_or_null( + (*this).getWfr().getDefiningOp())) { llvm::Expected durOrError = castOp.getDuration(nullptr /*callSequenceOp*/); if (auto err = durOrError.takeError()) @@ -399,7 +558,7 @@ PlayOp::getDuration(mlir::Operation *callSequenceOp = nullptr) { return durOrError.get(); } - auto argIndex = (*this).wfr().cast().getArgNumber(); + auto argIndex = (*this).getWfr().cast().getArgNumber(); auto *argOp = callOp->getOperand(argIndex).getDefiningOp(); auto wfrOp = dyn_cast_or_null(argOp); if (wfrOp) { @@ -420,14 +579,15 @@ llvm::Expected PlayOp::getWaveformHash(CallSequenceOp callOp) { Operation *wfrOp; Operation *targetOp; - wfrOp = dyn_cast_or_null(wfr().getDefiningOp()); - targetOp = dyn_cast_or_null(target().getDefiningOp()); + wfrOp = dyn_cast_or_null(getWfr().getDefiningOp()); + targetOp = dyn_cast_or_null(getTarget().getDefiningOp()); if (!wfrOp && !targetOp) { - auto wfrArgIndex = wfr().dyn_cast().getArgNumber(); + auto wfrArgIndex = getWfr().dyn_cast().getArgNumber(); wfrOp = callOp.getOperand(wfrArgIndex) .getDefiningOp(); - auto mixFrameArgIndex = target().dyn_cast().getArgNumber(); + auto mixFrameArgIndex = + getTarget().dyn_cast().getArgNumber(); targetOp = callOp.getOperand(mixFrameArgIndex) .getDefiningOp(); } @@ -443,6 +603,13 @@ llvm::Expected PlayOp::getWaveformHash(CallSequenceOp callOp) { "Failed to hash waveform name from play operation"); } +mlir::LogicalResult PlayOp::verify() { + if (!(*this).getTarget().isa()) + return emitOpError("Target is not a block argument; Target needs to be an " + "argument of pulse.sequence"); + return success(); +} + //===----------------------------------------------------------------------===// // // end PlayOp @@ -457,4 +624,5 @@ llvm::Expected PlayOp::getWaveformHash(CallSequenceOp callOp) { } // namespace mlir::pulse #define GET_OP_CLASSES +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/Pulse/IR/Pulse.cpp.inc" diff --git a/lib/Dialect/Pulse/Transforms/CMakeLists.txt b/lib/Dialect/Pulse/Transforms/CMakeLists.txt index bb19c0a52..7eeea83d6 100644 --- a/lib/Dialect/Pulse/Transforms/CMakeLists.txt +++ b/lib/Dialect/Pulse/Transforms/CMakeLists.txt @@ -26,5 +26,5 @@ add_mlir_dialect_library(MLIRPulseTransforms LINK_LIBS PUBLIC MLIRIR - Utils + QSSCUtils ) diff --git a/lib/Dialect/Pulse/Transforms/ClassicalOnlyDetection.cpp b/lib/Dialect/Pulse/Transforms/ClassicalOnlyDetection.cpp index dc7de3d03..ed47b060e 100644 --- a/lib/Dialect/Pulse/Transforms/ClassicalOnlyDetection.cpp +++ b/lib/Dialect/Pulse/Transforms/ClassicalOnlyDetection.cpp @@ -20,13 +20,21 @@ //===----------------------------------------------------------------------===// #include "Dialect/Pulse/Transforms/ClassicalOnlyDetection.h" + #include "Dialect/Pulse/IR/PulseDialect.h" #include "Dialect/Pulse/IR/PulseOps.h" -#include "Dialect/Pulse/IR/PulseTypes.h" +#include "Dialect/QUIR/IR/QUIROps.h" + +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/Dialect/SCF/IR/SCF.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/Operation.h" +#include "mlir/IR/Visitors.h" +#include "mlir/Support/LLVM.h" -#include "Dialect/QUIR/IR/QUIRTypes.h" -#include "mlir/Dialect/SCF/SCF.h" -#include +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" using namespace mlir; using namespace mlir::pulse; @@ -55,7 +63,7 @@ void ClassicalOnlyDetectionPass::runOnOperation() { moduleOperation->walk([&](Operation *op) { if (dyn_cast(op) || dyn_cast(op) || dyn_cast(op) || dyn_cast(op) || - dyn_cast(op)) { + dyn_cast(op)) { // check for a pre-existing classicalOnly attribute // only update if the attribute does not exist or it is true // indicating that no quantum ops have been identified yet diff --git a/lib/Dialect/Pulse/Transforms/InlineRegion.cpp b/lib/Dialect/Pulse/Transforms/InlineRegion.cpp index ac796f688..45b5963a1 100644 --- a/lib/Dialect/Pulse/Transforms/InlineRegion.cpp +++ b/lib/Dialect/Pulse/Transforms/InlineRegion.cpp @@ -20,11 +20,18 @@ #include "Dialect/Pulse/Transforms/InlineRegion.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" -#include "mlir/IR/BlockAndValueMapping.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/DialectInterface.h" +#include "mlir/IR/IRMapping.h" #include "mlir/IR/Visitors.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" #include "mlir/Transforms/InliningUtils.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" + namespace mlir::pulse { class DialectAgnosticInlinerInterface : public InlinerInterface { @@ -37,12 +44,12 @@ class DialectAgnosticInlinerInterface : public InlinerInterface { } bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned, - BlockAndValueMapping &) const final { + IRMapping &) const final { return true; } bool isLegalToInline(Operation *op, Region *dest, bool wouldBeCloned, - BlockAndValueMapping &) const final { + IRMapping &) const final { return true; } }; @@ -51,14 +58,16 @@ void InlineRegionPass::runOnOperation() { auto module = getOperation(); - for (auto function : llvm::make_early_inc_range(module.getOps())) { + for (auto function : + llvm::make_early_inc_range(module.getOps())) { // Build the inliner interface. DialectAgnosticInlinerInterface interface(&getContext()); - for (auto caller : llvm::make_early_inc_range(function.getOps())) { - auto callee = - dyn_cast_or_null(module.lookupSymbol(caller.getCallee())); + for (auto caller : + llvm::make_early_inc_range(function.getOps())) { + auto callee = dyn_cast_or_null( + module.lookupSymbol(caller.getCallee())); if (!callee) continue; diff --git a/lib/Dialect/Pulse/Transforms/MergeDelays.cpp b/lib/Dialect/Pulse/Transforms/MergeDelays.cpp index 35c403a17..818c18082 100644 --- a/lib/Dialect/Pulse/Transforms/MergeDelays.cpp +++ b/lib/Dialect/Pulse/Transforms/MergeDelays.cpp @@ -21,14 +21,20 @@ //===----------------------------------------------------------------------===// #include "Dialect/Pulse/Transforms/MergeDelays.h" -#include "Dialect/Pulse/IR/PulseDialect.h" + #include "Dialect/Pulse/IR/PulseOps.h" -#include "mlir/IR/Builders.h" -#include "mlir/IR/BuiltinOps.h" +#include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" #include "mlir/Transforms/DialectConversion.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" +#include "llvm/ADT/StringRef.h" + +#include + using namespace mlir; using namespace mlir::pulse; @@ -45,7 +51,7 @@ struct DelayAndDelayPattern : public OpRewritePattern { PatternRewriter &rewriter) const override { // TODO: determine how to pass ignoreTarget to the pass as an option - bool ignoreTarget = false; + bool const ignoreTarget = false; // get next operation and test for Delay Operation *nextOp = delayOp->getNextNode(); @@ -59,16 +65,16 @@ struct DelayAndDelayPattern : public OpRewritePattern { // found a delay and a delay // verify port | frame (second operand) is the same // this verification will be ignored if ignoreTarget is set to true - auto firstDelayPortOrFrame = delayOp.target(); - auto secondDelayPortOrFrame = nextDelayOp.target(); + auto firstDelayPortOrFrame = delayOp.getTarget(); + auto secondDelayPortOrFrame = nextDelayOp.getTarget(); if (!ignoreTarget && (firstDelayPortOrFrame != secondDelayPortOrFrame)) return failure(); // get delay times and sum as int 32 // TODO: check to see if int 32 is sufficient - auto firstDelay = delayOp.dur(); - auto secondDelay = nextDelayOp.dur(); + auto firstDelay = delayOp.getDur(); + auto secondDelay = nextDelayOp.getDur(); auto firstDelayOp = dyn_cast(firstDelay.getDefiningOp()); diff --git a/lib/Dialect/Pulse/Transforms/Passes.cpp b/lib/Dialect/Pulse/Transforms/Passes.cpp index 7ae5e76a7..b843a3877 100644 --- a/lib/Dialect/Pulse/Transforms/Passes.cpp +++ b/lib/Dialect/Pulse/Transforms/Passes.cpp @@ -19,19 +19,18 @@ //===----------------------------------------------------------------------===// #include "Dialect/Pulse/Transforms/Passes.h" -#include "Dialect/Pulse/IR/PulseDialect.h" -#include "Dialect/Pulse/IR/PulseOps.h" -#include "Dialect/Pulse/IR/PulseTypes.h" - -#include "Dialect/QUIR/IR/QUIRDialect.h" -#include "Dialect/QUIR/IR/QUIROps.h" -#include "Dialect/QUIR/IR/QUIRTypes.h" - -#include "mlir/Dialect/SCF/SCF.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" -#include "mlir/IR/BuiltinOps.h" -#include "mlir/Pass/Pass.h" + +#include "Conversion/QUIRToPulse/LoadPulseCals.h" +#include "Conversion/QUIRToPulse/QUIRToPulse.h" + +#include "Dialect/Pulse/Transforms/ClassicalOnlyDetection.h" +#include "Dialect/Pulse/Transforms/MergeDelays.h" +#include "Dialect/Pulse/Transforms/RemoveUnusedArguments.h" +#include "Dialect/Pulse/Transforms/SchedulePort.h" + +#include "Dialect/Pulse/Transforms/Scheduling.h" #include "mlir/Pass/PassManager.h" +#include "mlir/Pass/PassRegistry.h" namespace mlir::pulse { @@ -48,9 +47,9 @@ void registerPulsePasses() { } void registerPulsePassPipeline() { - PassPipelineRegistration<> pipeline("pulseOpt", - "Enable Pulse IR specific optimizations", - pulse::pulsePassPipelineBuilder); + PassPipelineRegistration<> const pipeline( + "pulseOpt", "Enable Pulse IR specific optimizations", + pulse::pulsePassPipelineBuilder); } } // namespace mlir::pulse diff --git a/lib/Dialect/Pulse/Transforms/RemoveUnusedArguments.cpp b/lib/Dialect/Pulse/Transforms/RemoveUnusedArguments.cpp index 7e307e101..1a7c168e1 100644 --- a/lib/Dialect/Pulse/Transforms/RemoveUnusedArguments.cpp +++ b/lib/Dialect/Pulse/Transforms/RemoveUnusedArguments.cpp @@ -20,13 +20,26 @@ //===----------------------------------------------------------------------===// #include "Dialect/Pulse/Transforms/RemoveUnusedArguments.h" + #include "Dialect/Pulse/IR/PulseOps.h" +#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/MLIRContext.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/IR/SymbolTable.h" #include "mlir/IR/Visitors.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include +#include #include #define DEBUG_TYPE "RemoveUnusedArguments" @@ -47,7 +60,7 @@ struct RemoveUnusedArgumentsPattern LLVM_DEBUG(callSequenceOp.dump()); Operation *findOp = SymbolTable::lookupNearestSymbolFrom( - callSequenceOp, callSequenceOp.calleeAttr()); + callSequenceOp, callSequenceOp.getCalleeAttr()); if (!findOp) return failure(); @@ -85,7 +98,7 @@ struct RemoveUnusedArgumentsPattern moduleOp->walk([&](pulse::CallSequenceOp op) { if (op == callSequenceOp) return; - if (op.callee() != sequenceOp.sym_name()) + if (op.getCallee() != sequenceOp.getSymName()) return; // verify that the sequence and the new callSequenceOp are in // the same module diff --git a/lib/Dialect/Pulse/Transforms/SchedulePort.cpp b/lib/Dialect/Pulse/Transforms/SchedulePort.cpp index aa36c1e7d..118701deb 100644 --- a/lib/Dialect/Pulse/Transforms/SchedulePort.cpp +++ b/lib/Dialect/Pulse/Transforms/SchedulePort.cpp @@ -24,9 +24,28 @@ //===----------------------------------------------------------------------===// #include "Dialect/Pulse/Transforms/SchedulePort.h" +#include "Dialect/Pulse/IR/PulseInterfaces.h" +#include "Dialect/Pulse/IR/PulseOps.h" +#include "Dialect/Pulse/IR/PulseTraits.h" +#include "Dialect/Pulse/IR/PulseTypes.h" #include "Dialect/Pulse/Utils/Utils.h" +#include "Utils/DebugIndent.h" -#include "llvm/Support/Debug.h" +#include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/IR/Block.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/Region.h" +#include "mlir/IR/Value.h" +#include "mlir/Support/LLVM.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" + +#include +#include +#include #define DEBUG_TYPE "SchedulePortPass" @@ -112,8 +131,8 @@ uint64_t SchedulePortPass::updateSequence(SequenceOp sequenceOp) { int64_t timepoint = 0; auto existingTimepoint = PulseOpSchedulingInterface::getTimepoint(&op); - if (existingTimepoint.hasValue()) { - timepoint = existingTimepoint.getValue() + updateDelta; + if (existingTimepoint.has_value()) { + timepoint = existingTimepoint.value() + updateDelta; PulseOpSchedulingInterface::setTimepoint(&op, timepoint); } @@ -123,7 +142,7 @@ uint64_t SchedulePortPass::updateSequence(SequenceOp sequenceOp) { // a nested sequence should only have a duration if it has been // updated by this method already if (!castOp->hasAttr("pulse.duration")) { - uint64_t calleeDuration = + uint64_t const calleeDuration = processCall(castOp, /*updateNested*/ true); PulseOpSchedulingInterface::setDuration(castOp, calleeDuration); updateDelta += calleeDuration; @@ -168,21 +187,21 @@ SchedulePortPass::buildMixedFrameMap(SequenceOp &sequenceOp, Value target; // get mixed_frames if (auto castOp = dyn_cast(op)) - target = castOp.target(); + target = castOp.getTarget(); else if (auto castOp = dyn_cast(op)) - target = castOp.target(); + target = castOp.getTarget(); else if (auto castOp = dyn_cast(op)) - target = castOp.target(); + target = castOp.getTarget(); else if (auto castOp = dyn_cast(op)) - target = castOp.target(); + target = castOp.getTarget(); else if (auto castOp = dyn_cast(op)) - target = castOp.target(); + target = castOp.getTarget(); else if (auto castOp = dyn_cast(op)) - target = castOp.target(); + target = castOp.getTarget(); else if (auto castOp = dyn_cast(op)) - target = castOp.target(); + target = castOp.getTarget(); else if (auto castOp = dyn_cast(op)) - target = castOp.target(); + target = castOp.getTarget(); auto blockArg = target.cast(); auto index = blockArg.getArgNumber(); @@ -191,7 +210,7 @@ SchedulePortPass::buildMixedFrameMap(SequenceOp &sequenceOp, } else if (auto castOp = dyn_cast(op)) { // add a call sequence to all mixedFrameSequences for // mixedFrames passed to it - for (auto operand : castOp.operands()) { + for (auto operand : castOp.getOperands()) { auto operandType = operand.getType(); if (operandType.isa()) { auto blockArg = operand.cast(); @@ -220,9 +239,9 @@ void SchedulePortPass::addTimepoints(mlir::OpBuilder &builder, int64_t currentTimepoint = 0; for (auto *op : index.second) { auto existingTimepoint = PulseOpSchedulingInterface::getTimepoint(op); - if (existingTimepoint.hasValue()) - if (existingTimepoint.getValue() > currentTimepoint) - currentTimepoint = existingTimepoint.getValue(); + if (existingTimepoint.has_value()) + if (existingTimepoint.value() > currentTimepoint) + currentTimepoint = existingTimepoint.value(); // set attribute on op with current timepoint PulseOpSchedulingInterface::setTimepoint(op, currentTimepoint); @@ -266,31 +285,31 @@ void SchedulePortPass::sortOpsByTimepoint(SequenceOp &sequenceOp) { !isa(op2)) return true; - bool testOp1 = (op1.hasTrait() || - isa(op1)); - bool testOp2 = (op2.hasTrait() || - isa(op2)); + bool const testOp1 = (op1.hasTrait() || + isa(op1)); + bool const testOp2 = (op2.hasTrait() || + isa(op2)); if (!testOp1 || !testOp2) return false; - llvm::Optional currentTimepoint = + std::optional currentTimepoint = PulseOpSchedulingInterface::getTimepoint(&op1); - if (!currentTimepoint.hasValue()) { + if (!currentTimepoint.has_value()) { op1.emitError() << "Operation does not have a pulse.timepoint attribute."; signalPassFailure(); } - llvm::Optional nextTimepoint = + std::optional nextTimepoint = PulseOpSchedulingInterface::getTimepoint(&op2); - if (!nextTimepoint.hasValue()) { + if (!nextTimepoint.has_value()) { op2.emitError() << "Operation does not have a pulse.timepoint attribute."; signalPassFailure(); } // order by timepoint - return currentTimepoint.getValue() < nextTimepoint.getValue(); + return currentTimepoint.value() < nextTimepoint.value(); }); // blockOps.sort } } @@ -301,7 +320,7 @@ void SchedulePortPass::runOnOperation() { Operation *module = getOperation(); module->walk( - [&](mlir::pulse::SequenceOp op) { sequenceOps[op.sym_name()] = op; }); + [&](mlir::pulse::SequenceOp op) { sequenceOps[op.getSymName()] = op; }); INDENT_DEBUG("===== SchedulePortPass - start ==========\n"); diff --git a/lib/Dialect/Pulse/Transforms/Scheduling.cpp b/lib/Dialect/Pulse/Transforms/Scheduling.cpp index 2f1eb006b..08b3b471e 100644 --- a/lib/Dialect/Pulse/Transforms/Scheduling.cpp +++ b/lib/Dialect/Pulse/Transforms/Scheduling.cpp @@ -20,8 +20,25 @@ //===----------------------------------------------------------------------===// #include "Dialect/Pulse/Transforms/Scheduling.h" +#include "Dialect/Pulse/IR/PulseInterfaces.h" +#include "Dialect/Pulse/IR/PulseOps.h" #include "Dialect/QUIR/Utils/Utils.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/SymbolTable.h" +#include "mlir/Support/LLVM.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" + +#include +#include +#include +#include + #define DEBUG_TYPE "SchedulingDebug" using namespace mlir; @@ -38,7 +55,7 @@ void quantumCircuitPulseSchedulingPass::runOnOperation() { llvm_unreachable("scheduling method not supported currently"); } - ModuleOp moduleOp = getOperation(); + ModuleOp const moduleOp = getOperation(); // schedule all the quantum circuits which are root call sequence ops moduleOp->walk([&](mlir::pulse::CallSequenceOp callSequenceOp) { @@ -59,14 +76,15 @@ void quantumCircuitPulseSchedulingPass::scheduleAlap( mlir::pulse::CallSequenceOp quantumCircuitCallSequenceOp) { auto quantumCircuitSequenceOp = getSequenceOp(quantumCircuitCallSequenceOp); - std::string sequenceName = quantumCircuitSequenceOp.sym_name().str(); + std::string const sequenceName = quantumCircuitSequenceOp.getSymName().str(); LLVM_DEBUG(llvm::dbgs() << "\nscheduling " << sequenceName << "\n"); int totalDurationOfQuantumCircuitNegative = 0; portNameToNextAvailabilityMap.clear(); // get the MLIR block of the quantum circuit - auto quantumCircuitSequenceOpBlock = quantumCircuitSequenceOp.body().begin(); + auto quantumCircuitSequenceOpBlock = + quantumCircuitSequenceOp.getBody().begin(); // go over the MLIR operation of the block in reverse order, and find // CallSequenceOps, each of which corresponds to a quantum gate. for each // CallSequenceOps, we add a timepoint based on the availability of involved @@ -81,8 +99,8 @@ void quantumCircuitPulseSchedulingPass::scheduleAlap( dyn_cast(op)) { // find quantum gate SequenceOp auto quantumGateSequenceOp = getSequenceOp(quantumGateCallSequenceOp); - std::string quantumGateSequenceName = - quantumGateSequenceOp.sym_name().str(); + const std::string quantumGateSequenceName = + quantumGateSequenceOp.getSymName().str(); LLVM_DEBUG(llvm::dbgs() << "\tprocessing inner sequence " << quantumGateSequenceName << "\n"); @@ -102,18 +120,19 @@ void quantumCircuitPulseSchedulingPass::scheduleAlap( quantumGateSequenceOp.emitError() << toString(std::move(err)); signalPassFailure(); } - uint64_t quantumGateCallSequenceOpDuration = durOrError.get(); + const uint64_t quantumGateCallSequenceOpDuration = durOrError.get(); LLVM_DEBUG(llvm::dbgs() << "\t\tduration " << quantumGateCallSequenceOpDuration << "\n"); // find next available time for all the ports - int nextAvailableTimeOfAllPorts = getNextAvailableTimeOfPorts(ports); + const int nextAvailableTimeOfAllPorts = + getNextAvailableTimeOfPorts(ports); LLVM_DEBUG(llvm::dbgs() << "\t\tnext availability is at " << nextAvailableTimeOfAllPorts << "\n"); // find the updated available time, i.e., when the current quantum gate // will be scheduled - int updatedAvailableTime = + const int updatedAvailableTime = nextAvailableTimeOfAllPorts - quantumGateCallSequenceOpDuration; LLVM_DEBUG(llvm::dbgs() << "\t\tcurrent gate scheduled at " << updatedAvailableTime << "\n"); @@ -131,7 +150,8 @@ void quantumCircuitPulseSchedulingPass::scheduleAlap( } // multiply by -1 so that quantum circuit duration becomes positive - int totalDurationOfQuantumCircuit = -totalDurationOfQuantumCircuitNegative; + const int totalDurationOfQuantumCircuit = + -totalDurationOfQuantumCircuitNegative; LLVM_DEBUG(llvm::dbgs() << "\ttotal duration of quantum circuit " << totalDurationOfQuantumCircuit << "\n"); @@ -152,7 +172,7 @@ int quantumCircuitPulseSchedulingPass::getNextAvailableTimeOfPorts( mlir::ArrayAttr ports) { int nextAvailableTimeOfAllPorts = 0; for (auto attr : ports) { - std::string portName = attr.dyn_cast().getValue().str(); + const std::string portName = attr.dyn_cast().getValue().str(); if (portName.empty()) continue; if (portNameToNextAvailabilityMap.find(portName) != @@ -167,7 +187,7 @@ int quantumCircuitPulseSchedulingPass::getNextAvailableTimeOfPorts( void quantumCircuitPulseSchedulingPass::updatePortAvailabilityMap( mlir::ArrayAttr ports, int updatedAvailableTime) { for (auto attr : ports) { - std::string portName = attr.dyn_cast().getValue().str(); + const std::string portName = attr.dyn_cast().getValue().str(); if (portName.empty()) continue; portNameToNextAvailabilityMap[portName] = updatedAvailableTime; diff --git a/lib/Dialect/Pulse/Utils/Utils.cpp b/lib/Dialect/Pulse/Utils/Utils.cpp index 0c28c322a..cd7f77aa1 100644 --- a/lib/Dialect/Pulse/Utils/Utils.cpp +++ b/lib/Dialect/Pulse/Utils/Utils.cpp @@ -19,13 +19,17 @@ //===----------------------------------------------------------------------===// #include "Dialect/Pulse/Utils/Utils.h" + #include "Dialect/Pulse/IR/PulseOps.h" +#include "mlir/IR/Value.h" + namespace mlir::pulse { Waveform_CreateOp getWaveformOp(PlayOp pulsePlayOp, CallSequenceOp callSequenceOp) { - auto wfrArgIndex = pulsePlayOp.wfr().dyn_cast().getArgNumber(); + auto wfrArgIndex = + pulsePlayOp.getWfr().dyn_cast().getArgNumber(); auto wfrOp = callSequenceOp.getOperand(wfrArgIndex) .getDefiningOp(); return wfrOp; diff --git a/lib/Dialect/QCS/IR/QCSDialect.cpp b/lib/Dialect/QCS/IR/QCSDialect.cpp index 0974385e9..78cb38c88 100644 --- a/lib/Dialect/QCS/IR/QCSDialect.cpp +++ b/lib/Dialect/QCS/IR/QCSDialect.cpp @@ -19,14 +19,19 @@ //===----------------------------------------------------------------------===// #include "Dialect/QCS/IR/QCSDialect.h" + +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/QCS/IR/QCSAttributes.h" +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/QCS/IR/QCSOps.h" +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/QCS/IR/QCSTypes.h" using namespace mlir; using namespace mlir::qcs; /// Tablegen Definitions +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/QCS/IR/QCSOpsDialect.cpp.inc" //===----------------------------------------------------------------------===// @@ -37,6 +42,7 @@ void QCSDialect::initialize() { addOperations< #define GET_OP_LIST +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/QCS/IR/QCSOps.cpp.inc" >(); } diff --git a/lib/Dialect/QCS/IR/QCSOps.cpp b/lib/Dialect/QCS/IR/QCSOps.cpp index 86639f9e0..579d9b7ef 100644 --- a/lib/Dialect/QCS/IR/QCSOps.cpp +++ b/lib/Dialect/QCS/IR/QCSOps.cpp @@ -19,26 +19,30 @@ //===----------------------------------------------------------------------===// #include "Dialect/QCS/IR/QCSOps.h" -#include "Dialect/QCS/IR/QCSDialect.h" + #include "Dialect/QCS/IR/QCSTypes.h" #include "Dialect/QUIR/IR/QUIRAttributes.h" -#include "Dialect/QCS/Utils/ParameterInitialValueAnalysis.h" - -#include "mlir/Dialect/StandardOps/IR/Ops.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/SymbolTable.h" +#include +#include +#include + #include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" + +#include using namespace mlir; using namespace mlir::qcs; #define GET_OP_CLASSES +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/QCS/IR/QCSOps.cpp.inc" -static LogicalResult +namespace { +LogicalResult verifyQCSParameterOpSymbolUses(SymbolTableCollection &symbolTable, mlir::Operation *op, bool operandMustMatchSymbolType = false) { @@ -73,7 +77,7 @@ verifyQCSParameterOpSymbolUses(SymbolTableCollection &symbolTable, // Check that type of variables matches result type of this Op if (op->getNumResults() == 1) { - if (op->getResult(0).getType() != declOp.type()) + if (op->getResult(0).getType() != declOp.getType()) return op->emitOpError( "type mismatch between variable declaration and variable use"); } @@ -81,13 +85,15 @@ verifyQCSParameterOpSymbolUses(SymbolTableCollection &symbolTable, if (op->getNumOperands() > 0 && operandMustMatchSymbolType) { assert(op->getNumOperands() == 1 && "type check only supported for a single operand"); - if (op->getOperand(0).getType() != declOp.type()) + if (op->getOperand(0).getType() != declOp.getType()) return op->emitOpError( "type mismatch between variable declaration and variable assignment"); } return success(); } +} // anonymous namespace + //===----------------------------------------------------------------------===// // ParameterLoadOp //===----------------------------------------------------------------------===// @@ -122,23 +128,29 @@ ParameterType ParameterLoadOp::getInitialValue() { double retVal; - auto angleAttr = - declOp.initial_value().getValue().dyn_cast(); - auto floatAttr = declOp.initial_value().getValue().dyn_cast(); + auto iniValue = declOp.getInitialValue(); + if (iniValue.has_value()) { + auto angleAttr = iniValue.value().dyn_cast(); - if (!(angleAttr || floatAttr)) { - op->emitError( - "Parameters are currently limited to angles or float[64] only."); - return 0.0; - } + auto floatAttr = iniValue.value().dyn_cast(); + + if (!(angleAttr || floatAttr)) { + op->emitError( + "Parameters are currently limited to angles or float[64] only."); + return 0.0; + } - if (angleAttr) - retVal = angleAttr.getValue().convertToDouble(); + if (angleAttr) + retVal = angleAttr.getValue().convertToDouble(); - if (floatAttr) - retVal = floatAttr.getValue().convertToDouble(); + if (floatAttr) + retVal = floatAttr.getValue().convertToDouble(); - return retVal; + return retVal; + } + + op->emitError("Does not have initial value set."); + return 0.0; } // Returns the float value from the initial value of this parameter @@ -164,3 +176,16 @@ ParameterType ParameterLoadOp::getInitialValue( //===----------------------------------------------------------------------===// // End ParameterLoadOp //===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// ParallelEndOp +//===----------------------------------------------------------------------===// + +mlir::ParseResult ParallelEndOp::parse(mlir::OpAsmParser &parser, + mlir::OperationState &result) { + return mlir::success(); +} + +void ParallelEndOp::print(mlir::OpAsmPrinter &printer) { + printer << getOperationName(); +} diff --git a/lib/Dialect/QCS/Utils/ParameterInitialValueAnalysis.cpp b/lib/Dialect/QCS/Utils/ParameterInitialValueAnalysis.cpp index fc8a168f8..699a29a4b 100644 --- a/lib/Dialect/QCS/Utils/ParameterInitialValueAnalysis.cpp +++ b/lib/Dialect/QCS/Utils/ParameterInitialValueAnalysis.cpp @@ -19,8 +19,15 @@ #include "Dialect/QCS/Utils/ParameterInitialValueAnalysis.h" #include "Dialect/QCS/IR/QCSOps.h" -#include "Dialect/QUIR/IR/QUIROps.h" +#include "Dialect/QUIR/IR/QUIRAttributes.h" + +#include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/Operation.h" +#include "mlir/Pass/PassRegistry.h" +#include "mlir/Support/LLVM.h" + +#include "llvm/ADT/StringRef.h" #define DEBUG_TYPE "ParameterInitialValueAnalysis" @@ -54,12 +61,12 @@ ParameterInitialValueAnalysis::ParameterInitialValueAnalysis( // moduleOp->walk([&](DeclareParameterOp declareParameterOp) { double initial_value = 0.0; - if (declareParameterOp.initial_value().hasValue()) { - auto angleAttr = declareParameterOp.initial_value() - .getValue() + if (declareParameterOp.getInitialValue().has_value()) { + auto angleAttr = declareParameterOp.getInitialValue() + .value() .dyn_cast(); - auto floatAttr = declareParameterOp.initial_value() - .getValue() + auto floatAttr = declareParameterOp.getInitialValue() + .value() .dyn_cast(); if (!(angleAttr || floatAttr)) declareParameterOp.emitError("Parameters are currently limited to " @@ -71,7 +78,7 @@ ParameterInitialValueAnalysis::ParameterInitialValueAnalysis( if (floatAttr) initial_value = floatAttr.getValue().convertToDouble(); } - initial_values_[declareParameterOp.sym_name()] = initial_value; + initial_values_[declareParameterOp.getSymName()] = initial_value; } invalid_ = false; } diff --git a/lib/Dialect/QUIR/IR/CMakeLists.txt b/lib/Dialect/QUIR/IR/CMakeLists.txt index 57fc3c1be..7b3d1a526 100644 --- a/lib/Dialect/QUIR/IR/CMakeLists.txt +++ b/lib/Dialect/QUIR/IR/CMakeLists.txt @@ -25,6 +25,9 @@ add_mlir_dialect_library(MLIRQUIRDialect LINK_LIBS PUBLIC MLIRIR + MLIRArithDialect + MLIRLLVMDialect MLIROQ3Dialect MLIRQCSDialect + MLIRSCFDialect ) diff --git a/lib/Dialect/QUIR/IR/QUIRAttributes.cpp b/lib/Dialect/QUIR/IR/QUIRAttributes.cpp index 9f8a35355..fd197ed3c 100644 --- a/lib/Dialect/QUIR/IR/QUIRAttributes.cpp +++ b/lib/Dialect/QUIR/IR/QUIRAttributes.cpp @@ -15,9 +15,14 @@ //===----------------------------------------------------------------------===// #include "Dialect/QUIR/IR/QUIRAttributes.h" -#include "Dialect/QUIR/IR/QUIRDialect.h" + +#include "Dialect/QUIR/IR/QUIREnums.h" #include "Dialect/QUIR/IR/QUIRTypes.h" -#include "Dialect/QUIR/Utils/Utils.h" + +#include "llvm/ADT/APFloat.h" +#include "llvm/Support/ErrorHandling.h" + +#include using namespace mlir; using namespace mlir::quir; @@ -101,12 +106,12 @@ double DurationAttr::convertUnitsToUnits(double value, TimeUnits inputUnits, // Check if we can avoid the conversion. if (inputUnits == outputUnits) return value; - double seconds = convertToSeconds(value, inputUnits, dt); + double const seconds = convertToSeconds(value, inputUnits, dt); return convertFromSeconds(seconds, outputUnits, dt); } uint64_t DurationAttr::getSchedulingCycles(const double dt) { - double duration = convertUnits(TimeUnits::dt, dt); + double const duration = convertUnits(TimeUnits::dt, dt); // Convert through int64_t first to handle platform dependence return static_cast(duration); @@ -114,7 +119,7 @@ uint64_t DurationAttr::getSchedulingCycles(const double dt) { double DurationAttr::convertUnits(const TimeUnits targetUnits, const double dt) { - double duration = getDuration().convertToDouble(); + double const duration = getDuration().convertToDouble(); return DurationAttr::convertUnitsToUnits( duration, getType().dyn_cast().getUnits(), targetUnits, dt); } diff --git a/lib/Dialect/QUIR/IR/QUIRDialect.cpp b/lib/Dialect/QUIR/IR/QUIRDialect.cpp index ab6d2a85e..1dcfb95e0 100644 --- a/lib/Dialect/QUIR/IR/QUIRDialect.cpp +++ b/lib/Dialect/QUIR/IR/QUIRDialect.cpp @@ -19,17 +19,34 @@ //===----------------------------------------------------------------------===// #include "Dialect/QUIR/IR/QUIRDialect.h" + +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/QUIR/IR/QUIRAttributes.h" +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/QUIR/IR/QUIREnums.h" +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/QUIR/IR/QUIROps.h" +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/QUIR/IR/QUIRTypes.h" -#include "llvm/ADT/TypeSwitch.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/Diagnostics.h" +#include "mlir/IR/Operation.h" +#include "mlir/IR/Region.h" +#include "mlir/IR/Types.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" +#include "mlir/Transforms/InliningUtils.h" + +#include +#include /// Tablegen Definitions +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/QUIR/IR/QUIRDialect.cpp.inc" #define GET_TYPEDEF_CLASSES +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/QUIR/IR/QUIRTypes.cpp.inc" namespace mlir { @@ -38,8 +55,8 @@ namespace mlir { // so anything that requires more precision will need an update or definition // for parseFloat() that takes APFloat or gnu mpfr. template -struct FieldParser< - FloatT, std::enable_if_t::value, FloatT>> { +struct FieldParser, FloatT>> { static FailureOr parse(AsmParser &parser) { double value; if (parser.parseFloat(value)) @@ -47,6 +64,7 @@ struct FieldParser< return APFloat(value); } }; + } // namespace mlir //===----------------------------------------------------------------------===// @@ -54,6 +72,7 @@ struct FieldParser< //===----------------------------------------------------------------------===// #define GET_ATTRDEF_CLASSES +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/QUIR/IR/QUIRAttributes.cpp.inc" namespace mlir::quir { @@ -76,8 +95,8 @@ struct QuirInlinerInterface : public DialectInlinerInterface { } /// For now all operations within quir can be inlined. - auto isLegalToInline(Operation *, Region *, bool, - BlockAndValueMapping &) const -> bool final { + auto isLegalToInline(Operation *, Region *, bool, IRMapping &) const + -> bool final { return true; } }; @@ -86,16 +105,19 @@ void quir::QUIRDialect::initialize() { addTypes< #define GET_TYPEDEF_LIST +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/QUIR/IR/QUIRTypes.cpp.inc" >(); addOperations< #define GET_OP_LIST +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/QUIR/IR/QUIR.cpp.inc" >(); addAttributes< #define GET_ATTRDEF_LIST +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/QUIR/IR/QUIRAttributes.cpp.inc" >(); @@ -108,7 +130,7 @@ mlir::Type parseOptionalWidth(mlir::AsmParser &parser) { // non-parameterized Qubit type? if (parser.parseOptionalLess()) - return QUIRType::get(parser.getContext(), llvm::None); + return QUIRType::get(parser.getContext(), std::nullopt); // incorrect syntax if (parser.parseInteger(width) || parser.parseGreater()) @@ -122,23 +144,6 @@ mlir::Type parseOptionalWidth(mlir::AsmParser &parser) { return QUIRType::get(parser.getContext(), width); } -mlir::Type AngleType::parse(mlir::AsmParser &parser) { - return parseOptionalWidth(parser); -} - -static void printOptionalWidth(llvm::Optional width, - mlir::AsmPrinter &printer) { - if (width.hasValue()) { - printer << "<"; - printer.printStrippedAttrOrType(width); - printer << ">"; - } -} - -void AngleType::print(mlir::AsmPrinter &printer) const { - printOptionalWidth(getImpl()->width, printer); -} - LogicalResult QubitType::verify(function_ref emitError, int width) { if (width <= 0) @@ -147,16 +152,10 @@ LogicalResult QubitType::verify(function_ref emitError, } LogicalResult AngleType::verify(function_ref emitError, - llvm::Optional width) { - if (width.hasValue() && width.getValue() <= 0) + std::optional width) { + if (width.has_value() && width.value() <= 0) return emitError() << "width must be > 0"; return success(); } -/// Materialize a constant, can be any buildable type, used by canonicalization -Operation *QUIRDialect::materializeConstant(OpBuilder &builder, Attribute value, - Type type, Location loc) { - return builder.create(loc, value, type); -} - } // namespace mlir::quir diff --git a/lib/Dialect/QUIR/IR/QUIRInterfaces.cpp b/lib/Dialect/QUIR/IR/QUIRInterfaces.cpp index da324ebf3..17db35247 100644 --- a/lib/Dialect/QUIR/IR/QUIRInterfaces.cpp +++ b/lib/Dialect/QUIR/IR/QUIRInterfaces.cpp @@ -20,12 +20,22 @@ #include "Dialect/QUIR/IR/QUIRInterfaces.h" +#include "mlir/IR/Operation.h" +#include "mlir/IR/Visitors.h" +#include "mlir/Support/LLVM.h" + +#include +#include +#include +#include +#include + using namespace mlir::quir; //===----------------------------------------------------------------------===// // Tablegen Interface Definitions //===----------------------------------------------------------------------===// - +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/QUIR/IR/QUIRInterfaces.cpp.inc" //===----------------------------------------------------------------------===// @@ -49,7 +59,7 @@ std::set interfaces_impl::getOperatedQubits(mlir::Operation *op, return opQubits; } -llvm::Optional +std::optional interfaces_impl::getNextQubitOp(mlir::Operation *op) { mlir::Operation *curOp = op; while (mlir::Operation *nextOp = curOp->getNextNode()) { @@ -57,7 +67,7 @@ interfaces_impl::getNextQubitOp(mlir::Operation *op) { return nextOp; curOp = nextOp; } - return llvm::None; + return std::nullopt; } std::set @@ -84,7 +94,7 @@ std::set interfaces_impl::getUnionQubits(std::set &first, bool interfaces_impl::qubitSetsOverlap(std::set &first, std::set &second) { - std::set sharedQubits = getSharedQubits(first, second); + std::set const sharedQubits = getSharedQubits(first, second); return !sharedQubits.empty(); } diff --git a/lib/Dialect/QUIR/IR/QUIROps.cpp b/lib/Dialect/QUIR/IR/QUIROps.cpp index 4dfdf0f4f..29bef7d33 100644 --- a/lib/Dialect/QUIR/IR/QUIROps.cpp +++ b/lib/Dialect/QUIR/IR/QUIROps.cpp @@ -15,37 +15,63 @@ //===----------------------------------------------------------------------===// #include "Dialect/QUIR/IR/QUIROps.h" -#include "Dialect/OQ3/IR/OQ3Ops.h" + #include "Dialect/QCS/IR/QCSOps.h" #include "Dialect/QUIR/IR/QUIRAttributes.h" #include "Dialect/QUIR/IR/QUIRDialect.h" +#include "Dialect/QUIR/IR/QUIRTraits.h" #include "Dialect/QUIR/IR/QUIRTypes.h" #include "Dialect/QUIR/Utils/Utils.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" -#include "mlir/IR/BlockAndValueMapping.h" +#include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/IR/Attributes.h" +#include "mlir/IR/Block.h" #include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinAttributeInterfaces.h" +#include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/Diagnostics.h" #include "mlir/IR/FunctionImplementation.h" +#include "mlir/IR/IRMapping.h" +#include "mlir/IR/Location.h" +#include "mlir/IR/OpDefinition.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/Operation.h" #include "mlir/IR/OperationSupport.h" -#include "mlir/Interfaces/CallInterfaces.h" +#include "mlir/IR/SymbolTable.h" +#include "mlir/IR/Visitors.h" +#include "mlir/Interfaces/ControlFlowInterfaces.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" + #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" + +#include +#include +#include +#include +#include +#include +#include +#include using namespace mlir; using namespace mlir::quir; -static uint lookupQubitIdHandleError_(const Value &val) { +namespace { +uint lookupQubitIdHandleError_(const Value &val) { auto id = lookupQubitId(val); - if (!id.hasValue()) { + if (!id.has_value()) { auto &diagEngine = val.getContext()->getDiagEngine(); diagEngine.emit(val.getLoc(), mlir::DiagnosticSeverity::Error) << "Qubit does not have a valid ID."; val.getDefiningOp()->emitError() << "Qubit does not have a valid ID."; + assert(false && "Qubit does not have a valid id."); } - return id.getValue(); + return id.value(); } // lookupQubitIdHandleError_ +} // anonymous namespace template std::set getQubitIds(Op &op) { @@ -65,8 +91,8 @@ std::set getQubitIds(Op &op) { std::set BuiltinCXOp::getOperatedQubits() { std::set opQubits; - opQubits.insert(lookupQubitIdHandleError_(control())); - opQubits.insert(lookupQubitIdHandleError_(target())); + opQubits.insert(lookupQubitIdHandleError_(getControl())); + opQubits.insert(lookupQubitIdHandleError_(getTarget())); return opQubits; } @@ -76,7 +102,7 @@ std::set BuiltinCXOp::getOperatedQubits() { std::set Builtin_UOp::getOperatedQubits() { std::set opQubits; - opQubits.insert(lookupQubitIdHandleError_(target())); + opQubits.insert(lookupQubitIdHandleError_(getTarget())); return opQubits; } @@ -88,6 +114,10 @@ std::set CallGateOp::getOperatedQubits() { return getQubitIds(*this); } +auto CallGateOp::getCalleeType() -> FunctionType { + return FunctionType::get(getContext(), getOperandTypes(), {}); +} + //===----------------------------------------------------------------------===// // MeasureOp //===----------------------------------------------------------------------===// @@ -144,11 +174,6 @@ std::set BarrierOp::getOperatedQubits() { // ConstantOp //===----------------------------------------------------------------------===// -OpFoldResult quir::ConstantOp::fold(ArrayRef operands) { - assert(operands.empty() && "constant has no operands"); - return value(); -} - void quir::ConstantOp::getAsmResultNames( function_ref setNameFn) { auto type = getType(); @@ -164,7 +189,7 @@ void quir::ConstantOp::getAsmResultNames( /// result type. bool quir::ConstantOp::isBuildableWith(Attribute value, Type type) { // The value's type must be the same as the provided type. - if (value.getType().isa() && !type.isa()) + if (value.isa() && !type.isa()) return false; // Currently only supports angle attributes to create angle constants return value.isa(); @@ -172,63 +197,66 @@ bool quir::ConstantOp::isBuildableWith(Attribute value, Type type) { // Returns the float value from the attribute on this constant op APFloat quir::ConstantOp::getAngleValueFromConstant() { - auto attr = value().dyn_cast(); + auto attr = getValue().dyn_cast(); assert(attr && "Trying to get the angle attribute of a non-angle constantOp"); return attr.getValue(); } -/// Return the callee of the call_gate operation, this is -/// required by the call interface. -auto CallGateOp::getCallableForCallee() -> CallInterfaceCallable { - return (*this)->getAttrOfType("callee"); -} +LogicalResult CallDefcalMeasureOp::verify() { + bool qubitFound = false; + for (auto arg : (*this)->getOperands()) { + if (qubitFound) { + if (arg.getType().isa()) + return emitOpError("requires exactly one qubit argument"); + } else { + if (arg.getType().isa()) + qubitFound = true; + } + } + if (qubitFound) + return success(); -/// Get the argument operands to the called function, this is required by the -/// call interface. -auto CallGateOp::getArgOperands() -> Operation::operand_range { - return operands(); + return emitOpError("requires exactly one qubit"); } -auto CallGateOp::getCalleeType() -> FunctionType { - return FunctionType::get(getContext(), getOperandTypes(), TypeRange{}); +mlir::OpFoldResult ConstantOp::fold(FoldAdaptor adaptor) { + assert(adaptor.getOperands().empty() && "constant has no operands"); + return getValue(); } -// CallDefCalGateOp, CallDefcalMeasureOp -auto CallDefCalGateOp::getCallableForCallee() -> CallInterfaceCallable { - return (*this)->getAttrOfType("callee"); -} -auto CallDefcalMeasureOp::getCallableForCallee() -> CallInterfaceCallable { - return (*this)->getAttrOfType("callee"); +/// Materialize a constant, can be any buildable type, used by canonicalization +ConstantOp ConstantOp::materialize(OpBuilder &builder, Attribute value, + Type type, Location loc) { + return builder.create(loc, cast(value)); } -auto CallDefCalGateOp::getArgOperands() -> Operation::operand_range { - return operands(); -} -auto CallDefcalMeasureOp::getArgOperands() -> Operation::operand_range { - return operands(); +/// Materialize a constant, can be any buildable type, used by canonicalization +Operation *QUIRDialect::materializeConstant(OpBuilder &builder, Attribute value, + Type type, Location loc) { + return builder.create(loc, type, cast(value)); } -auto CallDefCalGateOp::getCalleeType() -> FunctionType { - return FunctionType::get(getContext(), getOperandTypes(), TypeRange{}); -} +//===----------------------------------------------------------------------===// +// CallDefcalMeasureOp +//===----------------------------------------------------------------------===// auto CallDefcalMeasureOp::getCalleeType() -> FunctionType { return FunctionType::get(getContext(), getOperandTypes(), - getOperation()->getResultTypes()); + getResult().getType()); } -/// Return the callee of the call_gate operation, this is -/// required by the call interface. -auto CallSubroutineOp::getCallableForCallee() -> CallInterfaceCallable { - return (*this)->getAttrOfType("callee"); -} +//===----------------------------------------------------------------------===// +// CallDefCalGateOp +//===----------------------------------------------------------------------===// -/// Get the argument operands to the called function, this is required by the -/// call interface. -auto CallSubroutineOp::getArgOperands() -> Operation::operand_range { - return operands(); +auto CallDefCalGateOp::getCalleeType() -> FunctionType { + return FunctionType::get(getContext(), getOperandTypes(), {}); } +//===----------------------------------------------------------------------===// +// CallSubroutineOp +//===----------------------------------------------------------------------===// + auto CallSubroutineOp::getCalleeType() -> FunctionType { return FunctionType::get(getContext(), getOperandTypes(), getResultTypes()); } @@ -255,7 +283,7 @@ CallCircuitOp::verifySymbolUses(SymbolTableCollection &symbolTable) { << "' does not reference a valid circuit"; // Verify the types match - auto circuitType = circuit.getType(); + auto circuitType = circuit.getFunctionType(); if (circuitType.getNumInputs() != getNumOperands()) return emitOpError("incorrect number of operands for the callee circuit"); @@ -313,44 +341,47 @@ std::set CallCircuitOp::getOperatedQubits() { // //===----------------------------------------------------------------------===// -static ParseResult parseCircuitOp(OpAsmParser &parser, OperationState &result) { - auto buildCircuitType = +mlir::ParseResult CircuitOp::parse(mlir::OpAsmParser &parser, + mlir::OperationState &result) { + auto buildFuncType = [](Builder &builder, ArrayRef argTypes, ArrayRef results, function_interface_impl::VariadicFlag, std::string &) { return builder.getFunctionType(argTypes, results); }; + return function_interface_impl::parseFunctionOp( - parser, result, /*allowVariadic=*/false, buildCircuitType); + parser, result, /*allowVariadic=*/false, + getFunctionTypeAttrName(result.name), buildFuncType, + getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name)); } -static void print(CircuitOp op, OpAsmPrinter &p) { - FunctionType fnType = op.getType(); +void CircuitOp::print(mlir::OpAsmPrinter &printer) { function_interface_impl::printFunctionOp( - p, op, fnType.getInputs(), /*isVariadic=*/false, fnType.getResults()); + printer, *this, /*isVariadic=*/false, getFunctionTypeAttrName(), + getArgAttrsAttrName(), getResAttrsAttrName()); } +namespace { /// Verify the argument list and entry block are in agreement. -static LogicalResult verifyArgumentAndEntry_(CircuitOp op) { - auto fnInputTypes = op.getType().getInputs(); +LogicalResult verifyArgumentAndEntry_(CircuitOp op) { + auto fnInputTypes = op.getFunctionType().getInputs(); Block &entryBlock = op.front(); - for (unsigned i = 0; i != entryBlock.getNumArguments(); ++i) { + for (unsigned i = 0; i != entryBlock.getNumArguments(); ++i) if (fnInputTypes[i] != entryBlock.getArgument(i).getType()) return op.emitOpError("type of entry block argument #") << i << '(' << entryBlock.getArgument(i).getType() << ") must match the type of the corresponding argument in " << "function signature(" << fnInputTypes[i] << ')'; - } return success(); } /// Verify that no classical values are created/used in the circuit outside of /// values that originate as argument values or the result of a measurement. -static LogicalResult verifyClassical_(CircuitOp op) { +LogicalResult verifyClassical_(CircuitOp op) { mlir::Operation *classicalOp = nullptr; - WalkResult result = op->walk([&](Operation *subOp) { - if (isa(subOp) || isa(subOp) || - isa(subOp) || isa(subOp) || - isa(subOp) || isa(subOp) || - subOp->hasTrait() || + WalkResult const result = op->walk([&](Operation *subOp) { + if (isa(subOp) || isa(subOp) || + isa(subOp) || isa(subOp) || + isa(subOp) || subOp->hasTrait() || subOp->hasTrait()) return WalkResult::advance(); classicalOp = subOp; @@ -362,16 +393,17 @@ static LogicalResult verifyClassical_(CircuitOp op) { << "is classical and should not be inside a circuit."; return success(); } +} // anonymous namespace -static LogicalResult verify(CircuitOp op) { +LogicalResult CircuitOp::verify() { // If external will be linked in later and nothing to do - if (op.isExternal()) + if (isExternal()) return success(); - if (failed(verifyArgumentAndEntry_(op))) + if (failed(verifyArgumentAndEntry_(*this))) return mlir::failure(); - if (failed(verifyClassical_(op))) + if (failed(verifyClassical_(*this))) return mlir::failure(); return success(); @@ -387,8 +419,8 @@ CircuitOp CircuitOp::create(Location location, StringRef name, CircuitOp CircuitOp::create(Location location, StringRef name, FunctionType type, Operation::dialect_attr_range attrs) { - SmallVector attrRef(attrs); - return create(location, name, type, llvm::makeArrayRef(attrRef)); + SmallVector const attrRef(attrs); + return create(location, name, type, attrRef); } CircuitOp CircuitOp::create(Location location, StringRef name, FunctionType type, ArrayRef attrs, @@ -403,20 +435,21 @@ void CircuitOp::build(OpBuilder &builder, OperationState &state, StringRef name, ArrayRef argAttrs) { state.addAttribute(SymbolTable::getSymbolAttrName(), builder.getStringAttr(name)); - state.addAttribute(getTypeAttrName(), TypeAttr::get(type)); + state.addAttribute(getFunctionTypeAttrName(state.name), TypeAttr::get(type)); state.attributes.append(attrs.begin(), attrs.end()); state.addRegion(); if (argAttrs.empty()) return; assert(type.getNumInputs() == argAttrs.size()); - function_interface_impl::addArgAndResultAttrs(builder, state, argAttrs, - /*resultAttrs=*/llvm::None); + function_interface_impl::addArgAndResultAttrs( + builder, state, argAttrs, /*resultAttrs=*/std::nullopt, + getArgAttrsAttrName(state.name), getResAttrsAttrName(state.name)); } /// Clone the internal blocks and attributes from this circuit to the /// destination circuit. -void CircuitOp::cloneInto(CircuitOp dest, BlockAndValueMapping &mapper) { +void CircuitOp::cloneInto(CircuitOp dest, IRMapping &mapper) { // Add the attributes of this function to dest. llvm::MapVector newAttrMap; for (const auto &attr : dest->getAttrs()) @@ -439,13 +472,13 @@ void CircuitOp::cloneInto(CircuitOp dest, BlockAndValueMapping &mapper) { /// Using the provider mapper. Replace references to /// cloned sub-values with the corresponding copied value and /// add to the mapper -CircuitOp CircuitOp::clone(BlockAndValueMapping &mapper) { - FunctionType newType = getType(); +CircuitOp CircuitOp::clone(IRMapping &mapper) { + FunctionType newType = getFunctionType(); // If the function contains a body, then its possible arguments // may be deleted in the mapper. Verify this so they aren't // added to the input type vector. - bool isExternalCircuit = isExternal(); + bool const isExternalCircuit = isExternal(); if (!isExternalCircuit) { SmallVector inputTypes; inputTypes.reserve(newType.getNumInputs()); @@ -465,7 +498,7 @@ CircuitOp CircuitOp::clone(BlockAndValueMapping &mapper) { } CircuitOp CircuitOp::clone() { - BlockAndValueMapping mapper; + IRMapping mapper; return clone(mapper); } @@ -482,15 +515,15 @@ CircuitOp CircuitOp::clone() { // //===----------------------------------------------------------------------===// -static LogicalResult verify(mlir::quir::ReturnOp op) { - auto circuit = op->getParentOfType(); +LogicalResult mlir::quir::ReturnOp::verify() { + auto circuit = (*this)->getParentOfType(); - FunctionType circuitType = circuit.getType(); + FunctionType const circuitType = circuit.getFunctionType(); auto numResults = circuitType.getNumResults(); // Verify number of operands match type signature - if (numResults != op.operands().size()) { - return op.emitError() + if (numResults != getOperands().size()) { + return emitError() .append("expected ", numResults, " result operands") .attachNote(circuit.getLoc()) .append("return type declared here"); @@ -498,11 +531,11 @@ static LogicalResult verify(mlir::quir::ReturnOp op) { int i = 0; for (const auto [type, operand] : - llvm::zip(circuitType.getResults(), op.operands())) { + llvm::zip(circuitType.getResults(), getOperands())) { auto opType = operand.getType(); if (type != opType) { - return op.emitOpError() - << "unexpected type `" << opType << "' for operand #" << i; + return emitOpError() << "unexpected type `" << opType << "' for operand #" + << i; } i++; } @@ -523,11 +556,10 @@ static LogicalResult verify(mlir::quir::ReturnOp op) { //===----------------------------------------------------------------------===// // SwitchOp //===----------------------------------------------------------------------===// - -static ParseResult parseSwitchOp(OpAsmParser &parser, OperationState &result) { - +mlir::ParseResult SwitchOp::parse(mlir::OpAsmParser &parser, + mlir::OperationState &result) { Builder &builder = parser.getBuilder(); - OpAsmParser::OperandType flag; + OpAsmParser::UnresolvedOperand flag; Region *defaultRegion; SmallVector caseValues; ElementsAttr caseValuesAttr; @@ -552,9 +584,9 @@ static ParseResult parseSwitchOp(OpAsmParser &parser, OperationState &result) { while (parser.parseOptionalRSquare()) { uint32_t caseVal; - OptionalParseResult integerParseResult = + OptionalParseResult const integerParseResult = parser.parseOptionalInteger(caseVal); - if (!integerParseResult.hasValue() || integerParseResult.getValue()) + if (!integerParseResult.has_value() || integerParseResult.value()) // getValue() returns the success() or failure() return failure(); caseValues.push_back(caseVal); @@ -581,65 +613,63 @@ static ParseResult parseSwitchOp(OpAsmParser &parser, OperationState &result) { return success(); } +void SwitchOp::print(mlir::OpAsmPrinter &printer) { + bool printBlockTerminators = false; + + printer << " " << getFlag(); + if (!getResultTypes().empty()) { + printer << " -> (" << getResultTypes().getTypes() << ")"; + // Print yield explicitly if the op defines values. + printBlockTerminators = true; + } + printer.printRegion(getDefaultRegion(), + /*printEntryBlockOperands=*/false, + /*printBlockTerminators=*/printBlockTerminators); + + printer << "["; + + uint64_t id = 0; + + for (auto ®ion : getCaseRegions()) + if (!(region.empty())) { + printer.printAttributeWithoutType( + getCaseValuesAttr().getValues()[id]); + id += 1; + printer << " : "; + printer.printRegion(region, + /*printEntryBlockOperands=*/false, + /*printBlockTerminators=*/printBlockTerminators); + } + printer << "]"; + printer.printOptionalAttrDict((*this)->getAttrs().drop_front(1)); +} + /// Given the region at `index`, or the parent operation if `index` is None, /// return the successor regions. These are the regions that may be selected /// during the flow of control. `operands` is a set of optional attributes that /// correspond to a constant value for each operand, or null if that operand is /// not a constant. void quir::SwitchOp::getSuccessorRegions( - Optional index, ArrayRef operands, + std::optional index, ArrayRef operands, SmallVectorImpl ®ions) { // regions branch back to parent operation - if (index.hasValue()) { + if (index.has_value()) { regions.push_back(RegionSuccessor(getResults())); return; } // all regions are possible to be the successor - regions.push_back(RegionSuccessor(&defaultRegion())); - for (auto *region = caseRegions().begin(); region != caseRegions().end(); - region++) + regions.push_back(RegionSuccessor(&getDefaultRegion())); + for (auto *region = getCaseRegions().begin(); + region != getCaseRegions().end(); region++) regions.push_back(region); } -static void print(OpAsmPrinter &p, quir::SwitchOp op) { - bool printBlockTerminators = false; - - p << " " << op.flag(); - if (!op.resultTypes().empty()) { - p << " -> (" << op.getResultTypes() << ")"; - // Print yield explicitly if the op defines values. - printBlockTerminators = true; - } - p.printRegion(op.defaultRegion(), - /*printEntryBlockOperands=*/false, - /*printBlockTerminators=*/printBlockTerminators); - - p << "["; - - uint64_t id = 0; - - for (auto *region = (op.caseRegions()).begin(); - region != (op.caseRegions()).end(); region++) - if (!(region->empty())) { - p.printAttributeWithoutType( - op.caseValuesAttr().getValues()[id]); - id += 1; - p << " : "; - p.printRegion(*region, - /*printEntryBlockOperands=*/false, - /*printBlockTerminators=*/printBlockTerminators); - } - p << "]"; - p.printOptionalAttrDict(op->getAttrs().drop_front(1)); -} - -static LogicalResult verify(quir::SwitchOp op) { - if ((!op.caseValues() && !op.caseRegions().empty()) || - (op.caseValues() && - op.caseValues().size() != static_cast(op.caseRegions().size()))) - return op.emitOpError( - "expects same number of case values and case regions"); +LogicalResult quir::SwitchOp::verify() { + if ((!getCaseValues() && !getCaseRegions().empty()) || + (getCaseValues() && + getCaseValues().size() != static_cast(getCaseRegions().size()))) + return emitOpError("expects same number of case values and case regions"); return success(); } @@ -652,21 +682,19 @@ static LogicalResult verify(quir::SwitchOp op) { // YieldOp //===----------------------------------------------------------------------===// -static LogicalResult verify(quir::YieldOp op) { - auto *parentOp = op->getParentOp(); +LogicalResult quir::YieldOp::verify() { + auto *parentOp = (*this)->getParentOp(); auto results = parentOp->getResults(); - auto operands = op.getOperands(); + auto operands = getOperands(); if (!isa(parentOp)) - return op.emitOpError() << "only terminates quir.switch regions"; - if (parentOp->getNumResults() != op.getNumOperands()) - return op.emitOpError() << "parent of yield must have same number of " - "results as the yield operands"; - for (auto it : llvm::zip(results, operands)) { + return emitOpError() << "only terminates quir.switch regions"; + if (parentOp->getNumResults() != getNumOperands()) + return emitOpError() << "parent of yield must have same number of " + "results as the yield operands"; + for (auto it : llvm::zip(results, operands)) if (std::get<0>(it).getType() != std::get<1>(it).getType()) - return op.emitOpError() - << "types mismatch between yield op and its parent"; - } + return emitOpError() << "types mismatch between yield op and its parent"; return success(); } @@ -680,7 +708,9 @@ static LogicalResult verify(quir::YieldOp op) { //===----------------------------------------------------------------------===// #define GET_OP_CLASSES +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/QUIR/IR/QUIR.cpp.inc" #define GET_ENUM_CLASSES +// NOLINTNEXTLINE(misc-include-cleaner): Required for MLIR registrations #include "Dialect/QUIR/IR/QUIREnums.cpp.inc" diff --git a/lib/Dialect/QUIR/IR/QUIRTestInterfaces.cpp b/lib/Dialect/QUIR/IR/QUIRTestInterfaces.cpp index 02a9427b1..e107fda42 100644 --- a/lib/Dialect/QUIR/IR/QUIRTestInterfaces.cpp +++ b/lib/Dialect/QUIR/IR/QUIRTestInterfaces.cpp @@ -23,6 +23,13 @@ #include "Dialect/QUIR/IR/QUIRInterfaces.h" #include "mlir/IR/Builders.h" +#include "mlir/IR/Operation.h" +#include "mlir/Support/LLVM.h" + +#include "llvm/ADT/StringRef.h" + +#include +#include using namespace mlir::quir; diff --git a/lib/Dialect/QUIR/Transforms/AddShotLoop.cpp b/lib/Dialect/QUIR/Transforms/AddShotLoop.cpp index 521ac14bf..a4588f10f 100644 --- a/lib/Dialect/QUIR/Transforms/AddShotLoop.cpp +++ b/lib/Dialect/QUIR/Transforms/AddShotLoop.cpp @@ -19,23 +19,26 @@ // //===----------------------------------------------------------------------===// -#include - #include "Dialect/QUIR/Transforms/AddShotLoop.h" #include "Dialect/QCS/IR/QCSAttributes.h" #include "Dialect/QCS/IR/QCSOps.h" -#include "Dialect/QUIR/IR/QUIRDialect.h" -#include "Dialect/QUIR/IR/QUIROps.h" -#include "Dialect/QUIR/IR/QUIRTypes.h" #include "Dialect/QUIR/Utils/Utils.h" -#include "mlir/Dialect/Arithmetic/IR/Arithmetic.h" -#include "mlir/Dialect/SCF/SCF.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" -#include "mlir/IR/BlockAndValueMapping.h" +#include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/Dialect/SCF/IR/SCF.h" +#include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/IRMapping.h" +#include "mlir/IR/Location.h" #include "mlir/Pass/PassManager.h" +#include "mlir/Support/LLVM.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" + +#include using namespace mlir; using namespace mlir::quir; @@ -45,7 +48,8 @@ using namespace mlir::qcs; void AddShotLoopPass::runOnOperation() { // This pass is only called on module Ops ModuleOp moduleOp = getOperation(); - FuncOp mainFunc = dyn_cast(getMainFunction(moduleOp)); + mlir::func::FuncOp mainFunc = + dyn_cast(getMainFunction(moduleOp)); if (!mainFunc) { signalPassFailure(); @@ -55,8 +59,8 @@ void AddShotLoopPass::runOnOperation() { // start the builder outside the main function so we aren't cloning or // building into the same region that we are copying from - OpBuilder build(moduleOp.body()); - Location opLoc = mainFunc.getLoc(); + OpBuilder build = OpBuilder::atBlockBegin(moduleOp.getBody()); + Location const opLoc = mainFunc.getLoc(); auto startOp = build.create( opLoc, build.getIndexType(), build.getIndexAttr(0)); @@ -72,13 +76,14 @@ void AddShotLoopPass::runOnOperation() { shotInit->setAttr(getNumShotsAttrName(), build.getI32IntegerAttr(numShots)); std::list toErase; - BlockAndValueMapping mapper; + IRMapping mapper; Operation *lastOp = nullptr; - for (Operation &op : mainFunc.body().getOps()) { + for (Operation &op : mainFunc.getBody().getOps()) { if (dyn_cast(&op)) continue; - if (dyn_cast(&op) || dyn_cast(&op)) { + if (dyn_cast(&op) || + dyn_cast(&op)) { lastOp = &op; break; } @@ -93,7 +98,7 @@ void AddShotLoopPass::runOnOperation() { if (!lastOp) { // if last op wasn't detected while iterating // set it to the last op in the one block of the mainFunc body region - lastOp = &mainFunc.body().front().back(); + lastOp = &mainFunc.getBody().front().back(); } startOp->moveBefore(lastOp); diff --git a/lib/Dialect/QUIR/Transforms/AffineScalRepCopy.cpp b/lib/Dialect/QUIR/Transforms/AffineScalRepCopy.cpp deleted file mode 100644 index b7bfae533..000000000 --- a/lib/Dialect/QUIR/Transforms/AffineScalRepCopy.cpp +++ /dev/null @@ -1,460 +0,0 @@ -//===- AffineScalRepCopy.cpp - Utilities for affine dialect transformation ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements miscellaneous transformation utilities for the Affine -// dialect. -// This is a copy from LLVM with replacements and fixes that we currently -// require. Later revisions of LLVM contain changes that will allow us to use -// them directly. Specifically, the affine-loop alias analysis will check for -// the presence of affine loops (the unmodified version is too optimistic and -// makes mistakes in our use case). -// -//===----------------------------------------------------------------------===// - -#include "mlir/Dialect/Affine/Utils.h" - -#include "mlir/Dialect/Affine/Analysis/Utils.h" -#include "mlir/Dialect/Affine/IR/AffineOps.h" -#include "mlir/Dialect/Affine/IR/AffineValueMap.h" -#include "mlir/Dialect/Affine/LoopUtils.h" -#include "mlir/Dialect/MemRef/IR/MemRef.h" -#include "mlir/IR/BlockAndValueMapping.h" -#include "mlir/IR/Dominance.h" - -#define DEBUG_TYPE "affine-utils" - -using namespace mlir; - -/// Ensure that all operations that could be executed after `start` -/// (noninclusive) and prior to `memOp` (e.g. on a control flow/op path -/// between the operations) do not have the potential memory effect -/// `EffectType` on `memOp`. `memOp` is an operation that reads or writes to -/// a memref. For example, if `EffectType` is MemoryEffects::Write, this method -/// will check if there is no write to the memory between `start` and `memOp` -/// that would change the read within `memOp`. -template -static bool hasNoInterveningEffect(Operation *start, T memOp) { - Value memref = memOp.getMemRef(); - bool isOriginalAllocation = memref.getDefiningOp() || - memref.getDefiningOp(); - - // A boolean representing whether an intervening operation could have impacted - // memOp. - bool hasSideEffect = false; - - // Check whether the effect on memOp can be caused by a given operation op. - std::function checkOperation = [&](Operation *op) { - // If the effect has alreay been found, early exit, - if (hasSideEffect) - return; - - if (auto memEffect = dyn_cast(op)) { - SmallVector effects; - memEffect.getEffects(effects); - - bool opMayHaveEffect = false; - for (auto effect : effects) { - // If op causes EffectType on a potentially aliasing location for - // memOp, mark as having the effect. - - if (isa(effect.getEffect())) { - if (isOriginalAllocation && effect.getValue() && - (effect.getValue().getDefiningOp() || - effect.getValue().getDefiningOp())) { - if (effect.getValue() != memref) - continue; - } - opMayHaveEffect = true; - break; - } - } - - if (!opMayHaveEffect) - return; - -// Disabled affine dependence analysis, since it is not applicable in this use -// case and would produce incorrect results. Note that LLVM 15+ has a fix that -// only applies this analysis when both ops under consideration are clearly part -// of the same affine context. -#if 0 - // If the side effect comes from an affine read or write, try to - // prove the side effecting `op` cannot reach `memOp`. - if (isa(op)) { - MemRefAccess srcAccess(op); - MemRefAccess destAccess(memOp); - // Dependence analysis is only correct if both ops operate on the same - // memref. - if (srcAccess.memref == destAccess.memref) { - FlatAffineValueConstraints dependenceConstraints; - - // Number of loops containing the start op and the ending operation. - unsigned minSurroundingLoops = - getNumCommonSurroundingLoops(*start, *memOp); - - // Number of loops containing the operation `op` which has the - // potential memory side effect and can occur on a path between - // `start` and `memOp`. - unsigned nsLoops = getNumCommonSurroundingLoops(*op, *memOp); - - // For ease, let's consider the case that `op` is a store and we're - // looking for other potential stores (e.g `op`) that overwrite memory - // after `start`, and before being read in `memOp`. In this case, we - // only need to consider other potential stores with depth > - // minSurrounding loops since `start` would overwrite any store with a - // smaller number of surrounding loops before. - unsigned d; - for (d = nsLoops + 1; d > minSurroundingLoops; d--) { - DependenceResult result = checkMemrefAccessDependence( - srcAccess, destAccess, d, &dependenceConstraints, - /*dependenceComponents=*/nullptr); - if (hasDependence(result)) { - hasSideEffect = true; - return; - } - } - - // No side effect was seen, simply return. - return; - } - } -#endif - hasSideEffect = true; - return; - } - - if (op->hasTrait()) { - // Recurse into the regions for this op and check whether the internal - // operations may have the side effect `EffectType` on memOp. - for (Region ®ion : op->getRegions()) - for (Block &block : region) - for (Operation &op : block) - checkOperation(&op); - return; - } - - // Otherwise, conservatively assume generic operations have the effect - // on the operation - hasSideEffect = true; - }; - - // Check all paths from ancestor op `parent` to the operation `to` for the - // effect. It is known that `to` must be contained within `parent`. - auto until = [&](Operation *parent, Operation *to) { - // TODO check only the paths from `parent` to `to`. - // Currently we fallback and check the entire parent op, rather than - // just the paths from the parent path, stopping after reaching `to`. - // This is conservatively correct, but could be made more aggressive. - assert(parent->isAncestor(to)); - checkOperation(parent); - }; - - // Check for all paths from operation `from` to operation `untilOp` for the - // given memory effect. - std::function recur = - [&](Operation *from, Operation *untilOp) { - assert( - from->getParentRegion()->isAncestor(untilOp->getParentRegion()) && - "Checking for side effect between two operations without a common " - "ancestor"); - - // If the operations are in different regions, recursively consider all - // path from `from` to the parent of `to` and all paths from the parent - // of `to` to `to`. - if (from->getParentRegion() != untilOp->getParentRegion()) { - recur(from, untilOp->getParentOp()); - until(untilOp->getParentOp(), untilOp); - return; - } - - // Now, assuming that `from` and `to` exist in the same region, perform - // a CFG traversal to check all the relevant operations. - - // Additional blocks to consider. - SmallVector todoBlocks; - { - // First consider the parent block of `from` an check all operations - // after `from`. - for (auto iter = ++from->getIterator(), end = from->getBlock()->end(); - iter != end && &*iter != untilOp; ++iter) { - checkOperation(&*iter); - } - - // If the parent of `from` doesn't contain `to`, add the successors - // to the list of blocks to check. - if (untilOp->getBlock() != from->getBlock()) - for (Block *succ : from->getBlock()->getSuccessors()) - todoBlocks.push_back(succ); - } - - SmallPtrSet done; - // Traverse the CFG until hitting `to`. - while (!todoBlocks.empty()) { - Block *blk = todoBlocks.pop_back_val(); - if (done.count(blk)) - continue; - done.insert(blk); - for (auto &op : *blk) { - if (&op == untilOp) - break; - checkOperation(&op); - if (&op == blk->getTerminator()) - for (Block *succ : blk->getSuccessors()) - todoBlocks.push_back(succ); - } - } - }; - recur(start, memOp); - return !hasSideEffect; -} - -/// Attempt to eliminate loadOp by replacing it with a value stored into memory -/// which the load is guaranteed to retrieve. This check involves three -/// components: 1) The store and load must be on the same location 2) The store -/// must dominate (and therefore must always occur prior to) the load 3) No -/// other operations will overwrite the memory loaded between the given load -/// and store. If such a value exists, the replaced `loadOp` will be added to -/// `loadOpsToErase` and its memref will be added to `memrefsToErase`. -static LogicalResult forwardStoreToLoad( - AffineReadOpInterface loadOp, SmallVectorImpl &loadOpsToErase, - SmallPtrSetImpl &memrefsToErase, DominanceInfo &domInfo) { - - // The store op candidate for forwarding that satisfies all conditions - // to replace the load, if any. - Operation *lastWriteStoreOp = nullptr; - - for (auto *user : loadOp.getMemRef().getUsers()) { - auto storeOp = dyn_cast(user); - if (!storeOp) - continue; - MemRefAccess srcAccess(storeOp); - MemRefAccess destAccess(loadOp); - - // 1. Check if the store and the load have mathematically equivalent - // affine access functions; this implies that they statically refer to the - // same single memref element. As an example this filters out cases like: - // store %A[%i0 + 1] - // load %A[%i0] - // store %A[%M] - // load %A[%N] - // Use the AffineValueMap difference based memref access equality checking. - if (srcAccess != destAccess) - continue; - - // 2. The store has to dominate the load op to be candidate. - if (!domInfo.dominates(storeOp, loadOp)) - continue; - - // 3. Ensure there is no intermediate operation which could replace the - // value in memory. - if (!hasNoInterveningEffect(storeOp, loadOp)) - continue; - - // We now have a candidate for forwarding. - assert(lastWriteStoreOp == nullptr && - "multiple simulataneous replacement stores"); - lastWriteStoreOp = storeOp; - } - - if (!lastWriteStoreOp) - return failure(); - - // Perform the actual store to load forwarding. - Value storeVal = - cast(lastWriteStoreOp).getValueToStore(); - // Check if 2 values have the same shape. This is needed for affine vector - // loads and stores. - if (storeVal.getType() != loadOp.getValue().getType()) - return failure(); - loadOp.getValue().replaceAllUsesWith(storeVal); - // Record the memref for a later sweep to optimize away. - memrefsToErase.insert(loadOp.getMemRef()); - // Record this to erase later. - loadOpsToErase.push_back(loadOp); - return success(); -} - -// This attempts to find stores which have no impact on the final result. -// A writing op writeA will be eliminated if there exists an op writeB if -// 1) writeA and writeB have mathematically equivalent affine access functions. -// 2) writeB postdominates writeA. -// 3) There is no potential read between writeA and writeB. -static void findUnusedStore(AffineWriteOpInterface writeA, - SmallVectorImpl &opsToErase, - SmallPtrSetImpl &memrefsToErase, - PostDominanceInfo &postDominanceInfo) { - - for (Operation *user : writeA.getMemRef().getUsers()) { - // Only consider writing operations. - auto writeB = dyn_cast(user); - if (!writeB) - continue; - - // The operations must be distinct. - if (writeB == writeA) - continue; - - // Both operations must lie in the same region. - if (writeB->getParentRegion() != writeA->getParentRegion()) - continue; - - // Both operations must write to the same memory. - MemRefAccess srcAccess(writeB); - MemRefAccess destAccess(writeA); - - if (srcAccess != destAccess) - continue; - - // writeB must postdominate writeA. - if (!postDominanceInfo.postDominates(writeB, writeA)) - continue; - - // There cannot be an operation which reads from memory between - // the two writes. - if (!hasNoInterveningEffect(writeA, writeB)) - continue; - - opsToErase.push_back(writeA); - break; - } -} - -// The load to load forwarding / redundant load elimination is similar to the -// store to load forwarding. -// loadA will be be replaced with loadB if: -// 1) loadA and loadB have mathematically equivalent affine access functions. -// 2) loadB dominates loadA. -// 3) There is no write between loadA and loadB. -static void loadCSE(AffineReadOpInterface loadA, - SmallVectorImpl &loadOpsToErase, - DominanceInfo &domInfo) { - SmallVector loadCandidates; - for (auto *user : loadA.getMemRef().getUsers()) { - auto loadB = dyn_cast(user); - if (!loadB || loadB == loadA) - continue; - - MemRefAccess srcAccess(loadB); - MemRefAccess destAccess(loadA); - - // 1. The accesses have to be to the same location. - if (srcAccess != destAccess) - continue; - - // 2. The store has to dominate the load op to be candidate. - if (!domInfo.dominates(loadB, loadA)) - continue; - - // 3. There is no write between loadA and loadB. - if (!hasNoInterveningEffect(loadB.getOperation(), - loadA)) - continue; - - // Check if two values have the same shape. This is needed for affine vector - // loads. - if (loadB.getValue().getType() != loadA.getValue().getType()) - continue; - - loadCandidates.push_back(loadB); - } - - // Of the legal load candidates, use the one that dominates all others - // to minimize the subsequent need to loadCSE - Value loadB; - for (AffineReadOpInterface option : loadCandidates) { - if (llvm::all_of(loadCandidates, [&](AffineReadOpInterface depStore) { - return depStore == option || - domInfo.dominates(option.getOperation(), - depStore.getOperation()); - })) { - loadB = option.getValue(); - break; - } - } - - if (loadB) { - loadA.getValue().replaceAllUsesWith(loadB); - // Record this to erase later. - loadOpsToErase.push_back(loadA); - } -} - -namespace mlir { -// The store to load forwarding and load CSE rely on three conditions: -// -// 1) store/load providing a replacement value and load being replaced need to -// have mathematically equivalent affine access functions (checked after full -// composition of load/store operands); this implies that they access the same -// single memref element for all iterations of the common surrounding loop, -// -// 2) the store/load op should dominate the load op, -// -// 3) no operation that may write to memory read by the load being replaced can -// occur after executing the instruction (load or store) providing the -// replacement value and before the load being replaced (thus potentially -// allowing overwriting the memory read by the load). -// -// The above conditions are simple to check, sufficient, and powerful for most -// cases in practice - they are sufficient, but not necessary --- since they -// don't reason about loops that are guaranteed to execute at least once or -// multiple sources to forward from. -// -// TODO: more forwarding can be done when support for -// loop/conditional live-out SSA values is available. -// TODO: do general dead store elimination for memref's. This pass -// currently only eliminates the stores only if no other loads/uses (other -// than dealloc) remain. -// -void affineScalarReplaceCopy(FuncOp f, DominanceInfo &domInfo, - PostDominanceInfo &postDomInfo) { - // Load op's whose results were replaced by those forwarded from stores. - SmallVector opsToErase; - - // A list of memref's that are potentially dead / could be eliminated. - SmallPtrSet memrefsToErase; - - // Walk all load's and perform store to load forwarding. - f.walk([&](AffineReadOpInterface loadOp) { - if (failed(forwardStoreToLoad(loadOp, opsToErase, memrefsToErase, domInfo))) - loadCSE(loadOp, opsToErase, domInfo); - }); - - // Erase all load op's whose results were replaced with store fwd'ed ones. - for (auto *op : opsToErase) - op->erase(); - opsToErase.clear(); - - // Walk all store's and perform unused store elimination - f.walk([&](AffineWriteOpInterface storeOp) { - findUnusedStore(storeOp, opsToErase, memrefsToErase, postDomInfo); - }); - // Erase all store op's which don't impact the program - for (auto *op : opsToErase) - op->erase(); - - // Check if the store fwd'ed memrefs are now left with only stores and can - // thus be completely deleted. Note: the canonicalize pass should be able - // to do this as well, but we'll do it here since we collected these anyway. - for (auto memref : memrefsToErase) { - // If the memref hasn't been alloc'ed in this function, skip. - Operation *defOp = memref.getDefiningOp(); - if (!defOp || !isa(defOp)) - // TODO: if the memref was returned by a 'call' operation, we - // could still erase it if the call had no side-effects. - continue; - if (llvm::any_of(memref.getUsers(), [&](Operation *ownerOp) { - return !isa(ownerOp); - })) - continue; - - // Erase all stores, the dealloc, and the alloc on the memref. - for (auto *user : llvm::make_early_inc_range(memref.getUsers())) - user->erase(); - defOp->erase(); - } -} -} // namespace mlir diff --git a/lib/Dialect/QUIR/Transforms/Analysis.cpp b/lib/Dialect/QUIR/Transforms/Analysis.cpp index b5af66d05..75a7fbe8a 100644 --- a/lib/Dialect/QUIR/Transforms/Analysis.cpp +++ b/lib/Dialect/QUIR/Transforms/Analysis.cpp @@ -21,13 +21,18 @@ #include "Dialect/QUIR/Transforms/Analysis.h" #include "Dialect/QUIR/IR/QUIROps.h" +#include "Dialect/QUIR/IR/QUIRTraits.h" -#include "mlir/Dialect/SCF/SCF.h" +#include "mlir/Dialect/SCF/IR/SCF.h" +#include "mlir/IR/Operation.h" +#include "mlir/IR/Visitors.h" + +#include "llvm/Support/Casting.h" namespace mlir::quir { PurelyUnitaryAnalysis::PurelyUnitaryAnalysis(mlir::Operation *op) { - mlir::WalkResult result = op->walk([&](mlir::Operation *op) { + mlir::WalkResult const result = op->walk([&](mlir::Operation *op) { if (op->hasTrait() or llvm::isa(op) or // declaring CallCircuitOp may be cheating diff --git a/lib/Dialect/QUIR/Transforms/AngleConversion.cpp b/lib/Dialect/QUIR/Transforms/AngleConversion.cpp index d6326848b..de25a9687 100644 --- a/lib/Dialect/QUIR/Transforms/AngleConversion.cpp +++ b/lib/Dialect/QUIR/Transforms/AngleConversion.cpp @@ -20,16 +20,26 @@ #include "Dialect/QUIR/Transforms/AngleConversion.h" +#include "Dialect/QUIR/IR/QUIRAttributes.h" #include "Dialect/QUIR/IR/QUIROps.h" +#include "Dialect/QUIR/IR/QUIRTypes.h" #include "Dialect/QUIR/Utils/Utils.h" -#include "mlir/IR/BuiltinOps.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/IR/BuiltinTypes.h" +#include "mlir/IR/MLIRContext.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/IR/Types.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include #include +#include using namespace mlir; using namespace mlir::quir; @@ -37,30 +47,33 @@ using namespace mlir::quir; namespace { struct AngleConversion : public OpRewritePattern { - explicit AngleConversion(MLIRContext *ctx, - std::unordered_map &functionOps) + explicit AngleConversion( + MLIRContext *ctx, + std::unordered_map &functionOps) : OpRewritePattern(ctx), functionOps_(functionOps) {} LogicalResult matchAndRewrite(quir::CallGateOp callGateOp, PatternRewriter &rewriter) const override { - // find the corresponding FuncOp - auto findOp = functionOps_.find(callGateOp.calleeAttr().getValue().str()); + // find the corresponding mlir::func::FuncOp + auto findOp = + functionOps_.find(callGateOp.getCalleeAttr().getValue().str()); if (findOp == functionOps_.end()) return failure(); - FuncOp funcOp = findOp->second; - FunctionType fType = funcOp.getType(); + mlir::func::FuncOp funcOp = findOp->second; + FunctionType const fType = funcOp.getFunctionType(); - for (auto &pair : llvm::enumerate(callGateOp.getArgOperands())) { + for (const auto &pair : llvm::enumerate(callGateOp.getArgOperands())) { auto value = pair.value(); auto index = pair.index(); if (auto declOp = value.getDefiningOp()) { - // compare the angle type in FuncOp and callGateOp + // compare the angle type in mlir::func::FuncOp and callGateOp // and change the angle type in callGateOp if the types are different - Type funcType = fType.getInput(index); + Type const funcType = fType.getInput(index); if (value.getType() != funcType) { - APFloat constVal = declOp.getAngleValueFromConstant(); - declOp.valueAttr( - AngleAttr::get(callGateOp.getContext(), funcType, constVal)); + APFloat const constVal = declOp.getAngleValueFromConstant(); + declOp.setValueAttr(AngleAttr::get(callGateOp.getContext(), + funcType.dyn_cast(), + constVal)); value.setType(funcType); } } @@ -69,7 +82,7 @@ struct AngleConversion : public OpRewritePattern { } private: - std::unordered_map &functionOps_; + std::unordered_map &functionOps_; }; // struct AngleConversion } // end anonymous namespace @@ -78,8 +91,9 @@ struct AngleConversion : public OpRewritePattern { void QUIRAngleConversionPass::runOnOperation() { auto *op = getOperation(); - op->walk( - [&](FuncOp funcOp) { functionOps[funcOp.sym_name().str()] = funcOp; }); + op->walk([&](mlir::func::FuncOp funcOp) { + functionOps[funcOp.getSymName().str()] = funcOp; + }); RewritePatternSet patterns(&getContext()); patterns.add(&getContext(), functionOps); @@ -100,5 +114,5 @@ llvm::StringRef QUIRAngleConversionPass::getArgument() const { } llvm::StringRef QUIRAngleConversionPass::getDescription() const { return "Convert the angle types in CallGateOp " - "based on the corresponding FuncOp args"; + "based on the corresponding mlir::func::FuncOp args"; } diff --git a/lib/Dialect/QUIR/Transforms/BreakReset.cpp b/lib/Dialect/QUIR/Transforms/BreakReset.cpp index 9ee653bcf..4453c7b4d 100644 --- a/lib/Dialect/QUIR/Transforms/BreakReset.cpp +++ b/lib/Dialect/QUIR/Transforms/BreakReset.cpp @@ -21,19 +21,32 @@ #include "Dialect/QUIR/Transforms/BreakReset.h" -#include "Dialect/OQ3/IR/OQ3Ops.h" +#include "Dialect/QUIR/IR/QUIRAttributes.h" +#include "Dialect/QUIR/IR/QUIREnums.h" #include "Dialect/QUIR/IR/QUIROps.h" +#include "Dialect/QUIR/IR/QUIRTypes.h" #include "Dialect/QUIR/Utils/Utils.h" -#include "mlir/Dialect/SCF/SCF.h" -#include "mlir/IR/BuiltinOps.h" +#include "mlir/Dialect/SCF/IR/SCF.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/IR/TypeRange.h" +#include "mlir/IR/ValueRange.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" #include "mlir/Transforms/DialectConversion.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" -#include +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include +#include +#include +#include using namespace mlir; -using namespace mlir::oq3; using namespace mlir::quir; namespace { @@ -70,21 +83,21 @@ struct BreakResetsPattern : public OpRewritePattern { } // result of measurement in each iteration is number of qubits * i1 - std::vector typeVec(resetOp.qubits().size(), - rewriter.getI1Type()); + std::vector const typeVec(resetOp.getQubits().size(), + rewriter.getI1Type()); for (uint iteration = 0; iteration < numIterations_; iteration++) { if (delayCycles_ > 0 && iteration > 0) - for (auto qubit : resetOp.qubits()) + for (auto qubit : resetOp.getQubits()) rewriter.create(resetOp.getLoc(), - constantDurationOp.result(), qubit); + constantDurationOp.getResult(), qubit); auto measureOp = rewriter.create( - resetOp.getLoc(), TypeRange(typeVec), resetOp.qubits()); + resetOp.getLoc(), TypeRange(typeVec), resetOp.getQubits()); measureOp->setAttr(getNoReportRuntimeAttrName(), rewriter.getUnitAttr()); size_t i = 0; - for (auto qubit : resetOp.qubits()) { + for (auto qubit : resetOp.getQubits()) { auto ifOp = rewriter.create(resetOp.getLoc(), measureOp.getResult(i), false); auto savedInsertionPoint = rewriter.saveInsertionPoint(); diff --git a/lib/Dialect/QUIR/Transforms/CMakeLists.txt b/lib/Dialect/QUIR/Transforms/CMakeLists.txt index 891a0cc59..5a809ad58 100644 --- a/lib/Dialect/QUIR/Transforms/CMakeLists.txt +++ b/lib/Dialect/QUIR/Transforms/CMakeLists.txt @@ -30,7 +30,6 @@ add_mlir_dialect_library(MLIRQUIRTransforms SubroutineCloning.cpp UnusedVariable.cpp VariableElimination.cpp - AffineScalRepCopy.cpp ADDITIONAL_HEADER_DIRS ${PROJECT_SOURCE_DIR}/include/QUIR diff --git a/lib/Dialect/QUIR/Transforms/ConvertDurationUnits.cpp b/lib/Dialect/QUIR/Transforms/ConvertDurationUnits.cpp index 54cbe0799..91162cd47 100644 --- a/lib/Dialect/QUIR/Transforms/ConvertDurationUnits.cpp +++ b/lib/Dialect/QUIR/Transforms/ConvertDurationUnits.cpp @@ -21,13 +21,26 @@ #include "Dialect/QUIR/Transforms/ConvertDurationUnits.h" +#include "Dialect/QUIR/IR/QUIRAttributes.h" +#include "Dialect/QUIR/IR/QUIREnums.h" #include "Dialect/QUIR/IR/QUIROps.h" +#include "Dialect/QUIR/IR/QUIRTypes.h" #include "Dialect/QUIR/Utils/Utils.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" -#include "mlir/IR/BuiltinOps.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/IR/BuiltinTypes.h" +#include "mlir/IR/Location.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" #include "mlir/Transforms/DialectConversion.h" -#include "mlir/Transforms/GreedyPatternRewriteDriver.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" + +#include +#include +#include using namespace mlir; using namespace mlir::quir; @@ -43,7 +56,7 @@ class DurationTypeConverter : public TypeConverter { DurationTypeConverter(const TimeUnits convertUnits) : convertUnits_(convertUnits) { // Convert durations to the appropriate type - addConversion([&](mlir::Type t) -> Optional { + addConversion([&](mlir::Type t) -> std::optional { // All non-durations are legal in the conversion. if (!t.isa()) return t; @@ -63,8 +76,8 @@ class DurationTypeConverter : public TypeConverter { convertFunctionSignature(FunctionType funcTy, DurationTypeConverter::SignatureConversion &result) { // Convert argument types one by one and check for errors. - for (auto &en : llvm::enumerate(funcTy.getInputs())) { - Type type = en.value(); + for (const auto &en : llvm::enumerate(funcTy.getInputs())) { + Type const type = en.value(); SmallVector converted; auto convertedType = convertType(type); if (!convertedType) @@ -107,7 +120,7 @@ struct DurationUnitsConstantOpConversionPattern matchAndRewrite(quir::ConstantOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override { - auto duration = op.value().dyn_cast(); + auto duration = op.getValue().dyn_cast(); if (!duration) return failure(); @@ -118,7 +131,7 @@ struct DurationUnitsConstantOpConversionPattern auto units = dstType.cast().getUnits(); - DurationAttr newDuration = + DurationAttr const newDuration = duration.getConvertedDurationAttr(units, dtTimestep); rewriter.replaceOpWithNewOp(op, newDuration); @@ -199,7 +212,7 @@ struct DurationUnitsFunctionOpConversionPattern typename FunctionType::Adaptor adaptor, ConversionPatternRewriter &rewriter) const override { - auto funcLikeType = funcLikeOp.getType(); + auto funcLikeType = funcLikeOp.getFunctionType(); // Create a signature converter for our interface DurationTypeConverter::SignatureConversion signatureConverter( funcLikeType.getNumInputs()); @@ -208,13 +221,13 @@ struct DurationUnitsFunctionOpConversionPattern // The signatureConverter is built up which will then be // used below to map region types in the rewriter. auto newFuncLikeType = typeConverter.convertFunctionSignature( - funcLikeOp.getType(), signatureConverter); + funcLikeOp.getFunctionType(), signatureConverter); if (!newFuncLikeType) return failure(); // Create a new function operation with the update signature type. - Location loc = funcLikeOp.getLoc(); - StringRef name = funcLikeOp.getName(); + Location const loc = funcLikeOp.getLoc(); + StringRef const name = funcLikeOp.getName(); auto newFuncLikeOp = rewriter.create(loc, name, newFuncLikeType); @@ -256,7 +269,7 @@ void ConvertDurationUnitsPass::runOnOperation() { // Extract conversion units auto targetConvertUnits = getTargetConvertUnits(); - double dtConversion = getDtTimestep(); + double const dtConversion = getDtTimestep(); auto &context = getContext(); ConversionTarget target(context); @@ -277,34 +290,40 @@ void ConvertDurationUnitsPass::runOnOperation() { return true; }); - target.addDynamicallyLegalOp( - [&](mlir::FunctionOpInterface op) { - for (auto type : op.getArgumentTypes()) { - if (checkTypeNeedsConversion(type, targetConvertUnits)) - return false; - } - for (auto type : op.getResultTypes()) { - if (checkTypeNeedsConversion(type, targetConvertUnits)) - return false; - } + target.addDynamicallyLegalOp([&](mlir::func::FuncOp op) { + for (auto type : op.getArgumentTypes()) + if (checkTypeNeedsConversion(type, targetConvertUnits)) + return false; + for (auto type : op.getResultTypes()) + if (checkTypeNeedsConversion(type, targetConvertUnits)) + return false; + + return true; + }); + + target.addDynamicallyLegalOp([&](quir::CircuitOp op) { + for (auto type : op.getArgumentTypes()) + if (checkTypeNeedsConversion(type, targetConvertUnits)) + return false; + for (auto type : op.getResultTypes()) + if (checkTypeNeedsConversion(type, targetConvertUnits)) + return false; - return true; - }); + return true; + }); // Only constant declared durations if their type is not // the target output duration type. target .addDynamicallyLegalOp( + mlir::func::ReturnOp, mlir::func::CallOp>( [&](mlir::Operation *op) { - for (auto type : op->getOperandTypes()) { + for (auto type : op->getOperandTypes()) if (checkTypeNeedsConversion(type, targetConvertUnits)) return false; - } - for (auto type : op->getResultTypes()) { + for (auto type : op->getResultTypes()) if (checkTypeNeedsConversion(type, targetConvertUnits)) return false; - } return true; }); @@ -316,9 +335,9 @@ void ConvertDurationUnitsPass::runOnOperation() { DurationUnitsConversionPattern, DurationUnitsReturnsTypeOpConversionPattern, DurationUnitsFunctionOpConversionPattern, - DurationUnitsConversionPattern, - DurationUnitsReturnsTypeOpConversionPattern, - DurationUnitsFunctionOpConversionPattern>( + DurationUnitsConversionPattern, + DurationUnitsReturnsTypeOpConversionPattern, + DurationUnitsFunctionOpConversionPattern>( &getContext(), typeConverter); if (failed( diff --git a/lib/Dialect/QUIR/Transforms/FunctionArgumentSpecialization.cpp b/lib/Dialect/QUIR/Transforms/FunctionArgumentSpecialization.cpp index 89217a576..7d32a4288 100644 --- a/lib/Dialect/QUIR/Transforms/FunctionArgumentSpecialization.cpp +++ b/lib/Dialect/QUIR/Transforms/FunctionArgumentSpecialization.cpp @@ -22,16 +22,25 @@ #include "Dialect/QUIR/Transforms/FunctionArgumentSpecialization.h" -#include "Dialect/QUIR/IR/QUIRDialect.h" #include "Dialect/QUIR/IR/QUIROps.h" -#include "Dialect/QUIR/IR/QUIRTypes.h" #include "Dialect/QUIR/Utils/Utils.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/IR/Block.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/BuiltinOps.h" -#include "mlir/Pass/Pass.h" +#include "mlir/IR/BuiltinTypes.h" +#include "mlir/IR/SymbolTable.h" #include "mlir/Pass/PassManager.h" +#include "mlir/Support/LLVM.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Debug.h" +#include +#include #define DEBUG_TYPE "QUIRFunctionArgumentSpecialization" @@ -50,9 +59,9 @@ void FunctionArgumentSpecializationPass::processCallOp( Operation *moduleOp = callOp->template getParentOfType().getOperation(); // look for func def match - Operation *findOp = SymbolTable::lookupSymbolIn(moduleOp, callOp.callee()); + Operation *findOp = SymbolTable::lookupSymbolIn(moduleOp, callOp.getCallee()); if (findOp) { - FuncOp funcOp = dyn_cast(findOp); + mlir::func::FuncOp funcOp = dyn_cast(findOp); if (!funcOp) return; // check arguments for width match @@ -60,7 +69,7 @@ void FunctionArgumentSpecializationPass::processCallOp( // no callable region found (just a prototype) } else { FunctionType callType = callOp.getCalleeType(); - FunctionType funcType = funcOp.getType(); + FunctionType funcType = funcOp.getFunctionType(); if (callType == funcType) { // add calls inside this func def to the work list findOp->walk([&](Operation *op) { @@ -73,13 +82,13 @@ void FunctionArgumentSpecializationPass::processCallOp( copyFuncAndSpecialize(funcOp, callOp, callWorkList); } else { llvm::errs() << "Fundamental type mismatch between call to " - << callOp.callee() << " and func def " << funcOp.getName() - << "\n"; + << callOp.getCallee() << " and func def " + << funcOp.getName() << "\n"; } } // else callable region found - } else { // callee not matched by FuncOp + } else { // callee not matched by mlir::func::FuncOp LLVM_DEBUG(llvm::dbgs() - << "Found call to " << callOp.callee() + << "Found call to " << callOp.getCallee() << " with no matching function definition or prototype\n"); } } // processCallOp @@ -95,7 +104,8 @@ void FunctionArgumentSpecializationPass::processCallOp( template void FunctionArgumentSpecializationPass::copyFuncAndSpecialize( - FuncOp inFunc, CallOpTy callOp, std::deque &callWorkList) { + mlir::func::FuncOp inFunc, CallOpTy callOp, + std::deque &callWorkList) { OpBuilder b(inFunc); std::string newName = SymbolRefAttr::get(inFunc).getLeafReference().str(); @@ -113,7 +123,7 @@ void FunctionArgumentSpecializationPass::copyFuncAndSpecialize( return; } - FuncOp newFunc = cast(b.clone(*inFunc)); + mlir::func::FuncOp newFunc = cast(b.clone(*inFunc)); newFunc->moveBefore(inFunc); newFunc->setAttr(SymbolTable::getSymbolAttrName(), StringAttr::get(newFunc.getContext(), newName)); diff --git a/lib/Dialect/QUIR/Transforms/LoadElimination.cpp b/lib/Dialect/QUIR/Transforms/LoadElimination.cpp index 81b6347a6..9aede0d40 100644 --- a/lib/Dialect/QUIR/Transforms/LoadElimination.cpp +++ b/lib/Dialect/QUIR/Transforms/LoadElimination.cpp @@ -21,10 +21,16 @@ #include "Dialect/QUIR/Transforms/LoadElimination.h" #include "Dialect/OQ3/IR/OQ3Ops.h" -#include "Dialect/QUIR/IR/QUIROps.h" +#include "Dialect/QUIR/IR/QUIRAttributes.h" #include "mlir/IR/Dominance.h" #include "mlir/IR/SymbolTable.h" +#include "mlir/IR/Visitors.h" +#include "mlir/Support/LLVM.h" + +#include "llvm/ADT/StringRef.h" + +#include namespace mlir::quir { @@ -83,7 +89,7 @@ void LoadEliminationPass::runOnOperation() { // constants). For now and for angle constants, this approach is good-enough // while not satisfying. if (decl.isInputVariable()) - varAssignmentOp.assigned_value().getDefiningOp()->setAttr( + varAssignmentOp.getAssignedValue().getDefiningOp()->setAttr( mlir::quir::getInputParameterAttrName(), decl.getNameAttr()); for (auto *userOp : symbolUses) { @@ -101,7 +107,7 @@ void LoadEliminationPass::runOnOperation() { if (!domInfo.dominates(assignment, variableUse)) // that is not the case continue; - variableUse.replaceAllUsesWith(varAssignmentOp.assigned_value()); + variableUse.replaceAllUsesWith(varAssignmentOp.getAssignedValue()); varUsesToErase.push_back(variableUse); } diff --git a/lib/Dialect/QUIR/Transforms/MergeCircuits.cpp b/lib/Dialect/QUIR/Transforms/MergeCircuits.cpp index c1485b824..f801aed90 100644 --- a/lib/Dialect/QUIR/Transforms/MergeCircuits.cpp +++ b/lib/Dialect/QUIR/Transforms/MergeCircuits.cpp @@ -20,20 +20,40 @@ //===----------------------------------------------------------------------===// #include "Dialect/QUIR/Transforms/MergeCircuits.h" + +#include "Dialect/QUIR/IR/QUIRAttributes.h" +#include "Dialect/QUIR/IR/QUIRInterfaces.h" #include "Dialect/QUIR/IR/QUIROps.h" #include "Dialect/QUIR/Utils/Utils.h" -#include "mlir/IR/BlockAndValueMapping.h" +#include "mlir/IR/Attributes.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/IRMapping.h" +#include "mlir/IR/MLIRContext.h" #include "mlir/IR/Operation.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/IR/SymbolTable.h" +#include "mlir/IR/TypeRange.h" +#include "mlir/IR/Types.h" +#include "mlir/IR/Value.h" +#include "mlir/IR/ValueRange.h" +#include "mlir/Support/LLVM.h" #include "mlir/Support/LogicalResult.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" -#include "llvm/ADT/None.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include +#include +#include +#include +#include +#include #include +#include #include using namespace mlir; @@ -65,7 +85,7 @@ struct CircuitAndCircuitPattern : public OpRewritePattern { // find next CallCircuitOp or fail Operation *searchOp = callCircuitOp.getOperation(); - llvm::Optional secondOp; + std::optional secondOp; CallCircuitOp nextCallCircuitOp; while (true) { secondOp = nextQuantumOpOrNull(searchOp); @@ -151,14 +171,14 @@ struct CircuitAndCircuitPattern : public OpRewritePattern { }; // struct CircuitAndCircuitPattern template -Optional getNextOpAndCompareOverlap(FirstOp firstOp) { - llvm::Optional secondOp = nextQuantumOpOrNull(firstOp); +std::optional getNextOpAndCompareOverlap(FirstOp firstOp) { + std::optional secondOp = nextQuantumOpOrNull(firstOp); if (!secondOp) - return llvm::None; + return std::nullopt; auto secondOpByClass = dyn_cast(*secondOp); if (!secondOpByClass) - return llvm::None; + return std::nullopt; // Check for overlap between currQubits and what's operated on by nextOp std::set firstQubits = QubitOpInterface::getOperatedQubits(firstOp); @@ -166,7 +186,7 @@ Optional getNextOpAndCompareOverlap(FirstOp firstOp) { QubitOpInterface::getOperatedQubits(secondOpByClass); if (QubitOpInterface::qubitSetsOverlap(firstQubits, secondQubits)) - return llvm::None; + return std::nullopt; return secondOpByClass; } @@ -187,10 +207,10 @@ struct BarrierAndCircuitPattern : public OpRewritePattern { auto callCircuitOp = getNextOpAndCompareOverlap(barrierOp); - if (!callCircuitOp.hasValue()) + if (!callCircuitOp.has_value()) return failure(); - barrierOp->moveAfter(callCircuitOp.getValue().getOperation()); + barrierOp->moveAfter(callCircuitOp.value().getOperation()); return success(); } // matchAndRewrite @@ -207,10 +227,10 @@ struct CircuitAndBarrierPattern : public OpRewritePattern { auto barrierOp = getNextOpAndCompareOverlap(callCircuitOp); - if (!barrierOp.hasValue()) + if (!barrierOp.has_value()) return failure(); - auto *barrierOperation = barrierOp.getValue().getOperation(); + auto *barrierOperation = barrierOp.value().getOperation(); // check for circuit op to merge with auto nextCallCircuitOp = nextQuantumOpOrNullOfType(barrierOperation); @@ -230,7 +250,7 @@ MergeCircuitsPass::getCircuitOp(CallCircuitOp callCircuitOp, llvm::StringMap *symbolMap) { // look for func def match assert(symbolMap && "a valid symbolMap pointer must be provided"); - auto search = symbolMap->find(callCircuitOp.callee()); + auto search = symbolMap->find(callCircuitOp.getCallee()); assert(search != symbolMap->end() && "matching circuit not found"); @@ -265,15 +285,15 @@ LogicalResult MergeCircuitsPass::mergeCallCircuits( callInputValues.push_back(inputValue); insertedArguments.push_back(index); } else { - int originalIndex = search - callInputValues.begin(); + int const originalIndex = search - callInputValues.begin(); reusedArguments[index] = originalIndex; } index++; } // merge circuit names - std::string newName = - (circuitOp.sym_name() + "_" + nextCircuitOp.sym_name()).str(); + std::string const newName = + (circuitOp.getSymName() + "_" + nextCircuitOp.getSymName()).str(); // create new circuit operation by cloning first circuit CircuitOp newCircuitOp = cast(rewriter.clone(*circuitOp)); @@ -289,7 +309,7 @@ LogicalResult MergeCircuitsPass::mergeCallCircuits( // map original arguments for new circuit based on original circuit // argument numbers - BlockAndValueMapping mapper; + IRMapping mapper; auto baseArgNum = newCircuitOp.getNumArguments(); int insertedCount = 0; for (uint cnt = 0; cnt < nextCircuitOp.getNumArguments(); cnt++) { @@ -331,7 +351,7 @@ LogicalResult MergeCircuitsPass::mergeCallCircuits( rewriter.create(nextReturnOp->getLoc(), outputValues); // change the input / output types for the quir.circuit - auto opType = newCircuitOp.getType(); + auto opType = newCircuitOp.getFunctionType(); newCircuitOp.setType(rewriter.getFunctionType( /*inputs=*/opType.getInputs(), /*results=*/ArrayRef(outputTypes))); @@ -345,13 +365,13 @@ LogicalResult MergeCircuitsPass::mergeCallCircuits( // collect all of the first circuit's ids std::vector allIds; - for (Attribute valAttr : theseIdsAttr) { + for (Attribute const valAttr : theseIdsAttr) { auto intAttr = valAttr.dyn_cast(); allIds.push_back(intAttr.getInt()); } // add IDs from the second circuit if not from the first - for (Attribute valAttr : newIdsAttr) { + for (Attribute const valAttr : newIdsAttr) { auto intAttr = valAttr.dyn_cast(); auto result = std::find(begin(allIds), end(allIds), intAttr.getInt()); if (result == end(allIds)) @@ -386,7 +406,7 @@ void MergeCircuitsPass::runOnOperation() { llvm::StringMap circuitOpsMap; moduleOperation->walk([&](CircuitOp circuitOp) { - circuitOpsMap[circuitOp.sym_name()] = circuitOp.getOperation(); + circuitOpsMap[circuitOp.getSymName()] = circuitOp.getOperation(); }); RewritePatternSet patterns(&getContext()); diff --git a/lib/Dialect/QUIR/Transforms/MergeMeasures.cpp b/lib/Dialect/QUIR/Transforms/MergeMeasures.cpp index 38c8708d0..febe0225c 100644 --- a/lib/Dialect/QUIR/Transforms/MergeMeasures.cpp +++ b/lib/Dialect/QUIR/Transforms/MergeMeasures.cpp @@ -21,15 +21,28 @@ #include "Dialect/QUIR/Transforms/MergeMeasures.h" +#include "Dialect/QUIR/IR/QUIRInterfaces.h" #include "Dialect/QUIR/IR/QUIROps.h" #include "Dialect/QUIR/Utils/Utils.h" -#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/IR/TypeRange.h" +#include "mlir/IR/ValueRange.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" #include "mlir/Transforms/DialectConversion.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" +#include "llvm/ADT/StringRef.h" + #include +#include +#include +#include +#include #include +#include +#include using namespace mlir; using namespace mlir::quir; @@ -50,19 +63,20 @@ static void mergeMeasurements(PatternRewriter &rewriter, MeasureOp measureOp, measureOp.result_type_end()); typeVec.insert(typeVec.end(), nextMeasureOp.result_type_begin(), nextMeasureOp.result_type_end()); - valVec.insert(valVec.end(), measureOp.qubits().begin(), - measureOp.qubits().end()); - valVec.insert(valVec.end(), nextMeasureOp.qubits().begin(), - nextMeasureOp.qubits().end()); + valVec.insert(valVec.end(), measureOp.getQubits().begin(), + measureOp.getQubits().end()); + valVec.insert(valVec.end(), nextMeasureOp.getQubits().begin(), + nextMeasureOp.getQubits().end()); auto mergedOp = rewriter.create( measureOp.getLoc(), TypeRange(typeVec), ValueRange(valVec)); // dice the output so we can specify which results to replace - auto iterSep = mergedOp.outs().begin() + measureOp.getNumResults(); - rewriter.replaceOp(measureOp, ResultRange(mergedOp.outs().begin(), iterSep)); + auto iterSep = mergedOp.getOuts().begin() + measureOp.getNumResults(); + rewriter.replaceOp(measureOp, + ResultRange(mergedOp.getOuts().begin(), iterSep)); rewriter.replaceOp(nextMeasureOp, - ResultRange(iterSep, mergedOp.outs().end())); + ResultRange(iterSep, mergedOp.getOuts().end())); } struct MeasureAndMeasureLexographicalPattern @@ -72,7 +86,7 @@ struct MeasureAndMeasureLexographicalPattern LogicalResult matchAndRewrite(MeasureOp measureOp, PatternRewriter &rewriter) const override { - llvm::Optional nextQuantumOp = nextQuantumOpOrNull(measureOp); + std::optional nextQuantumOp = nextQuantumOpOrNull(measureOp); if (!nextQuantumOp) return failure(); @@ -83,14 +97,14 @@ struct MeasureAndMeasureLexographicalPattern // found a measure and a measure, now make sure they aren't working on the // same qubit and that we can resolve them both std::unordered_set measureIds; - for (auto qubit : measureOp.qubits()) { - llvm::Optional id = lookupQubitId(qubit); + for (auto qubit : measureOp.getQubits()) { + std::optional id = lookupQubitId(qubit); if (!id) return failure(); measureIds.emplace(*id); } - for (auto qubit : nextMeasureOp.qubits()) { - llvm::Optional id = lookupQubitId(qubit); + for (auto qubit : nextMeasureOp.getQubits()) { + std::optional id = lookupQubitId(qubit); if (!id || measureIds.count(*id)) return failure(); } @@ -143,7 +157,7 @@ struct MeasureAndMeasureTopologicalPattern // topological path if it exists auto [nextMeasureOpt, observedQubits] = QubitOpInterface::getNextQubitOpOfTypeWithQubits(measureOp); - if (!nextMeasureOpt.hasValue()) + if (!nextMeasureOpt.has_value()) return failure(); // If any qubit along path touches the same qubits we cannot merge the next @@ -152,7 +166,7 @@ struct MeasureAndMeasureTopologicalPattern // found a measure and a measure, now make sure they aren't working on the // same qubit and that we can resolve them both - MeasureOp nextMeasureOp = nextMeasureOpt.getValue(); + MeasureOp nextMeasureOp = nextMeasureOpt.value(); auto nextMeasureQubits = nextMeasureOp.getOperatedQubits(); // If there is an intersection we cannot merge diff --git a/lib/Dialect/QUIR/Transforms/MergeParallelResets.cpp b/lib/Dialect/QUIR/Transforms/MergeParallelResets.cpp index 9a324ed1d..8e20432cf 100644 --- a/lib/Dialect/QUIR/Transforms/MergeParallelResets.cpp +++ b/lib/Dialect/QUIR/Transforms/MergeParallelResets.cpp @@ -21,14 +21,26 @@ #include "Dialect/QUIR/Transforms/MergeParallelResets.h" +#include "Dialect/QUIR/IR/QUIRInterfaces.h" #include "Dialect/QUIR/IR/QUIROps.h" #include "Dialect/QUIR/Utils/Utils.h" -#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" #include "mlir/Transforms/DialectConversion.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" +#include "llvm/ADT/StringRef.h" + +#include +#include +#include +#include +#include #include +#include +#include using namespace mlir; using namespace mlir::quir; @@ -45,9 +57,9 @@ struct MergeResetsLexicographicPattern : public OpRewritePattern { LogicalResult matchAndRewrite(ResetQubitOp resetOp, PatternRewriter &rewriter) const override { std::unordered_set qubitIds; - qubitIds.reserve(resetOp.qubits().size()); + qubitIds.reserve(resetOp.getQubits().size()); - for (auto qubit : resetOp.qubits()) { + for (auto qubit : resetOp.getQubits()) { auto id = lookupQubitId(qubit); if (!id) return failure(); @@ -56,9 +68,9 @@ struct MergeResetsLexicographicPattern : public OpRewritePattern { // identify additional reset operations that may happen in parallel and can // be merged - auto resetQubitOperands = resetOp.qubitsMutable(); + auto resetQubitOperands = resetOp.getQubitsMutable(); - llvm::Optional nextQuantumOp = nextQuantumOpOrNull(resetOp); + std::optional nextQuantumOp = nextQuantumOpOrNull(resetOp); if (!nextQuantumOp) return failure(); @@ -67,8 +79,8 @@ struct MergeResetsLexicographicPattern : public OpRewritePattern { return failure(); // check if we can add this reset - if (!std::all_of(nextResetOp.qubits().begin(), nextResetOp.qubits().end(), - [&](auto qubit) { + if (!std::all_of(nextResetOp.getQubits().begin(), + nextResetOp.getQubits().end(), [&](auto qubit) { // can merge this adjacent qubit reset op when we can // lookup all of its qubits' ids and these are not // overlapping with the qubit ids in resetOp or other @@ -79,7 +91,7 @@ struct MergeResetsLexicographicPattern : public OpRewritePattern { return failure(); // good to merge - for (auto qubit : nextResetOp.qubits()) + for (auto qubit : nextResetOp.getQubits()) resetQubitOperands.append(qubit); rewriter.eraseOp(nextResetOp); return success(); @@ -127,10 +139,10 @@ struct MergeResetsTopologicalPattern : public OpRewritePattern { // topological path if it exists auto [nextResetOpt, observedQubits] = QubitOpInterface::getNextQubitOpOfTypeWithQubits(resetOp); - if (!nextResetOpt.hasValue()) + if (!nextResetOpt.has_value()) return failure(); - ResetQubitOp nextResetOp = nextResetOpt.getValue(); + ResetQubitOp nextResetOp = nextResetOpt.value(); // There are 2 possible merge directions; we can hoist the next reset // to merge with this one (if nothing uses the future qubit between here @@ -172,8 +184,8 @@ struct MergeResetsTopologicalPattern : public OpRewritePattern { // good to merge one way or the other. Prefer hoisting the next reset. if (mergeFwdIntersection.empty()) { // Hoist the next reset into this one - auto resetQubitOperands = resetOp.qubitsMutable(); - for (auto qubit : nextResetOp.qubits()) + auto resetQubitOperands = resetOp.getQubitsMutable(); + for (auto qubit : nextResetOp.getQubits()) resetQubitOperands.append(qubit); rewriter.eraseOp(nextResetOp); } else { diff --git a/lib/Dialect/QUIR/Transforms/Passes.cpp b/lib/Dialect/QUIR/Transforms/Passes.cpp index fe860e1c5..9b7daf38e 100644 --- a/lib/Dialect/QUIR/Transforms/Passes.cpp +++ b/lib/Dialect/QUIR/Transforms/Passes.cpp @@ -14,26 +14,49 @@ // //===----------------------------------------------------------------------===// -#include -#include -#include -#include -#include - +#include "Dialect/QUIR/Transforms/Passes.h" #include "Dialect/OQ3/IR/OQ3Ops.h" -#include "Dialect/QUIR/IR/QUIRDialect.h" #include "Dialect/QUIR/IR/QUIROps.h" #include "Dialect/QUIR/IR/QUIRTestInterfaces.h" #include "Dialect/QUIR/IR/QUIRTypes.h" -#include "Dialect/QUIR/Transforms/Passes.h" +#include "Dialect/QUIR/Transforms/AddShotLoop.h" +#include "Dialect/QUIR/Transforms/AngleConversion.h" +#include "Dialect/QUIR/Transforms/BreakReset.h" +#include "Dialect/QUIR/Transforms/ConvertDurationUnits.h" +#include "Dialect/QUIR/Transforms/FunctionArgumentSpecialization.h" +#include "Dialect/QUIR/Transforms/LoadElimination.h" +#include "Dialect/QUIR/Transforms/MergeCircuits.h" +#include "Dialect/QUIR/Transforms/MergeMeasures.h" +#include "Dialect/QUIR/Transforms/MergeParallelResets.h" +#include "Dialect/QUIR/Transforms/QuantumDecoration.h" +#include "Dialect/QUIR/Transforms/RemoveQubitOperands.h" +#include "Dialect/QUIR/Transforms/ReorderCircuits.h" +#include "Dialect/QUIR/Transforms/ReorderMeasurements.h" +#include "Dialect/QUIR/Transforms/SubroutineCloning.h" +#include "Dialect/QUIR/Transforms/UnusedVariable.h" +#include "Dialect/QUIR/Transforms/VariableElimination.h" #include "Dialect/QUIR/Utils/Utils.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" -#include "mlir/IR/BuiltinOps.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/Dialect/SCF/IR/SCF.h" +#include "mlir/IR/Attributes.h" +#include "mlir/IR/Block.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/Dominance.h" +#include "mlir/IR/Region.h" #include "mlir/IR/SymbolTable.h" +#include "mlir/IR/Visitors.h" #include "mlir/Pass/Pass.h" #include "mlir/Pass/PassManager.h" +#include "mlir/Pass/PassRegistry.h" +#include "mlir/Support/LLVM.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" + +#include using namespace mlir; using namespace mlir::quir; @@ -65,7 +88,7 @@ struct TestPrintNestingPass // Print the operation attributes if (!op->getAttrs().empty()) { printIndent() << op->getAttrs().size() << " attributes:\n"; - for (NamedAttribute attr : op->getAttrs()) + for (NamedAttribute const attr : op->getAttrs()) printIndent() << " - '" << attr.getName() << "' : '" << attr.getValue() << "'\n"; } @@ -155,10 +178,11 @@ void ClassicalOnlyDetectionPass::runOnOperation() { dyn_cast(op)) op->setAttr(llvm::StringRef("quir.classicalOnly"), b.getBoolAttr(hasQuantumSubOps(op))); - if (auto funcOp = dyn_cast(op)) { + if (auto funcOp = dyn_cast(op)) { // just check the arguments for qubitType values - FunctionType fType = funcOp.getType(); - bool isMain = SymbolRefAttr::get(funcOp).getLeafReference() == "main"; + FunctionType const fType = funcOp.getFunctionType(); + bool const isMain = + SymbolRefAttr::get(funcOp).getLeafReference() == "main"; bool quantumOperands = false; for (auto argType : fType.getInputs()) { if (argType.isa()) { @@ -217,7 +241,7 @@ struct DumpVariableDominanceInfoPass assignment->dump(); for (Operation *use : varUses) { - bool dominates = domInfo.dominates(assignment, use); + bool const dominates = domInfo.dominates(assignment, use); llvm::errs() << " " << (dominates ? "dominates" : "no dominance over") << " "; @@ -276,8 +300,8 @@ void registerQuirPasses() { } void registerQuirPassPipeline() { - PassPipelineRegistration<> pipeline("quirOpt", - "Enable QUIR-specific optimizations", - quir::quirPassPipelineBuilder); + PassPipelineRegistration<> const pipeline( + "quirOpt", "Enable QUIR-specific optimizations", + quir::quirPassPipelineBuilder); } } // end namespace mlir::quir diff --git a/lib/Dialect/QUIR/Transforms/QUIRCircuitAnalysis.cpp b/lib/Dialect/QUIR/Transforms/QUIRCircuitAnalysis.cpp index 1c722212e..ab6f50d21 100644 --- a/lib/Dialect/QUIR/Transforms/QUIRCircuitAnalysis.cpp +++ b/lib/Dialect/QUIR/Transforms/QUIRCircuitAnalysis.cpp @@ -17,11 +17,28 @@ #include "Dialect/OQ3/IR/OQ3Ops.h" #include "Dialect/QCS/IR/QCSOps.h" +#include "Dialect/QCS/Utils/ParameterInitialValueAnalysis.h" +#include "Dialect/QUIR/IR/QUIRAttributes.h" #include "Dialect/QUIR/IR/QUIROps.h" +#include "Dialect/QUIR/IR/QUIRTypes.h" #include "Dialect/QUIR/Utils/Utils.h" -#include "mlir/Pass/AnalysisManager.h" +#include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/Value.h" +#include "mlir/Pass/AnalysisManager.h" +#include "mlir/Pass/Pass.h" +#include "mlir/Support/LLVM.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" + +#include +#include +#include +#include +#include using namespace mlir; @@ -66,10 +83,11 @@ angleValToDouble(mlir::Value inVal, } if (auto castOp = inVal.getDefiningOp()) { - auto defOp = castOp.arg().getDefiningOp(); + auto defOp = castOp.getArg().getDefiningOp(); if (defOp) return parameterValToDouble(defOp, nameAnalysis); - if (auto constOp = castOp.arg().getDefiningOp()) { + if (auto constOp = + castOp.getArg().getDefiningOp()) { if (auto angleAttr = constOp.getValue().dyn_cast()) return angleAttr.getValue().convertToDouble(); if (auto floatAttr = constOp.getValue().dyn_cast()) @@ -105,7 +123,7 @@ llvm::StringRef QUIRCircuitAnalysis::getParameterName(mlir::Value operand) { auto castOp = dyn_cast(operand.getDefiningOp()); if (castOp) parameterLoad = - dyn_cast(castOp.arg().getDefiningOp()); + dyn_cast(castOp.getArg().getDefiningOp()); } if (parameterLoad && @@ -121,7 +139,7 @@ quir::DurationAttr QUIRCircuitAnalysis::getDuration(mlir::Value operand) { auto constantOp = dyn_cast(operand.getDefiningOp()); if (constantOp) - return constantOp.value().dyn_cast(); + return constantOp.getValue().dyn_cast(); return duration; } @@ -139,8 +157,8 @@ QUIRCircuitAnalysis::QUIRCircuitAnalysis(mlir::Operation *moduleOp, auto nameAnalysisOptional = am.getCachedParentAnalysis( moduleOp->getParentOfType()); - if (nameAnalysisOptional.hasValue()) { - nameAnalysis = &nameAnalysisOptional.getValue().get(); + if (nameAnalysisOptional.has_value()) { + nameAnalysis = &nameAnalysisOptional.value().get(); runGetAnalysis = false; } } @@ -152,13 +170,13 @@ QUIRCircuitAnalysis::QUIRCircuitAnalysis(mlir::Operation *moduleOp, circuitOps; moduleOp->walk([&](CircuitOp circuitOp) { - circuitOps[circuitOp->getParentOfType()][circuitOp.sym_name()] = + circuitOps[circuitOp->getParentOfType()][circuitOp.getSymName()] = circuitOp.getOperation(); }); moduleOp->walk([&](CallCircuitOp callCircuitOp) { auto search = circuitOps[callCircuitOp->getParentOfType()].find( - callCircuitOp.calleeAttr().getValue()); + callCircuitOp.getCalleeAttr().getValue()); if (search == circuitOps[callCircuitOp->getParentOfType()].end()) { @@ -169,13 +187,13 @@ QUIRCircuitAnalysis::QUIRCircuitAnalysis(mlir::Operation *moduleOp, auto circuitOp = dyn_cast(search->second); auto parentModuleOp = circuitOp->getParentOfType(); - for (uint ii = 0; ii < callCircuitOp.operands().size(); ++ii) { + for (uint ii = 0; ii < callCircuitOp.getOperands().size(); ++ii) { double value = 0; llvm::StringRef parameterName = {}; quir::DurationAttr duration; - auto operand = callCircuitOp.operands()[ii]; + auto operand = callCircuitOp.getOperands()[ii]; // cache angle values and parameter names if (auto angType = operand.getType().dyn_cast()) { diff --git a/lib/Dialect/QUIR/Transforms/QuantumDecoration.cpp b/lib/Dialect/QUIR/Transforms/QuantumDecoration.cpp index 612296799..3cdf4a150 100644 --- a/lib/Dialect/QUIR/Transforms/QuantumDecoration.cpp +++ b/lib/Dialect/QUIR/Transforms/QuantumDecoration.cpp @@ -20,13 +20,21 @@ //===----------------------------------------------------------------------===// #include "Dialect/QUIR/Transforms/QuantumDecoration.h" + +#include "Dialect/QUIR/IR/QUIRAttributes.h" #include "Dialect/QUIR/IR/QUIROps.h" #include "Dialect/QUIR/Utils/Utils.h" -#include "mlir/Dialect/SCF/SCF.h" +#include "mlir/Dialect/SCF/IR/SCF.h" +#include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/Value.h" +#include "mlir/Support/LLVM.h" + +#include "llvm/ADT/StringRef.h" #include +#include #include using namespace mlir; @@ -67,18 +75,18 @@ void QuantumDecorationPass::processOp(Operation *op, void QuantumDecorationPass::processOp(Builtin_UOp builtinUOp, std::unordered_set &retSet) { - retSet.emplace(lookupOrMinus1(builtinUOp.target())); + retSet.emplace(lookupOrMinus1(builtinUOp.getTarget())); } // processOp Builtin_UOp void QuantumDecorationPass::processOp(BuiltinCXOp builtinCXOp, std::unordered_set &retSet) { - retSet.emplace(lookupOrMinus1(builtinCXOp.control())); - retSet.emplace(lookupOrMinus1(builtinCXOp.target())); + retSet.emplace(lookupOrMinus1(builtinCXOp.getControl())); + retSet.emplace(lookupOrMinus1(builtinCXOp.getTarget())); } // processOp BuiltinCXOp void QuantumDecorationPass::processOp(MeasureOp measureOp, std::unordered_set &retSet) { - for (auto qubit : measureOp.qubits()) + for (auto qubit : measureOp.getQubits()) retSet.emplace(lookupOrMinus1(qubit)); } // processOp MeasureOp @@ -87,19 +95,19 @@ void QuantumDecorationPass::processOp(CallDefcalMeasureOp measureOp, std::vector qubitOperands; qubitCallOperands(measureOp, qubitOperands); - for (Value &val : qubitOperands) + for (Value const &val : qubitOperands) retSet.emplace(lookupOrMinus1(val)); } // processOp MeasureOp void QuantumDecorationPass::processOp(DelayOp delayOp, std::unordered_set &retSet) { - for (auto qubit_operand : delayOp.qubits()) + for (auto qubit_operand : delayOp.getQubits()) retSet.emplace(lookupOrMinus1(qubit_operand)); } // processOp MeasureOp void QuantumDecorationPass::processOp(ResetQubitOp resetOp, std::unordered_set &retSet) { - for (auto qubit : resetOp.qubits()) + for (auto qubit : resetOp.getQubits()) retSet.emplace(lookupOrMinus1(qubit)); } // processOp MeasureOp @@ -108,7 +116,7 @@ void QuantumDecorationPass::processOp(CallDefCalGateOp callOp, std::vector qubitOperands; qubitCallOperands(callOp, qubitOperands); - for (Value &val : qubitOperands) + for (Value const &val : qubitOperands) retSet.emplace(lookupOrMinus1(val)); } // processOp CallGateOp @@ -117,7 +125,7 @@ void QuantumDecorationPass::processOp(CallGateOp callOp, std::vector qubitOperands; qubitCallOperands(callOp, qubitOperands); - for (Value &val : qubitOperands) + for (Value const &val : qubitOperands) retSet.emplace(lookupOrMinus1(val)); } // processOp CallGateOp @@ -126,7 +134,7 @@ void QuantumDecorationPass::processOp(BarrierOp barrierOp, std::vector qubitOperands; qubitCallOperands(barrierOp, qubitOperands); - for (Value &val : qubitOperands) + for (Value const &val : qubitOperands) retSet.emplace(lookupOrMinus1(val)); } // processOp BarrierOp @@ -135,12 +143,12 @@ void QuantumDecorationPass::processOp(CallCircuitOp callOp, std::vector qubitOperands; qubitCallOperands(callOp, qubitOperands); - for (Value &val : qubitOperands) + for (Value const &val : qubitOperands) retSet.emplace(lookupOrMinus1(val)); } // processOp CallGateOp void QuantumDecorationPass::runOnOperation() { - ModuleOp moduleOp = getOperation(); + ModuleOp const moduleOp = getOperation(); OpBuilder build(moduleOp); moduleOp->walk([&](Operation *op) { diff --git a/lib/Dialect/QUIR/Transforms/RemoveQubitOperands.cpp b/lib/Dialect/QUIR/Transforms/RemoveQubitOperands.cpp index 8fd9f0c79..c03503674 100644 --- a/lib/Dialect/QUIR/Transforms/RemoveQubitOperands.cpp +++ b/lib/Dialect/QUIR/Transforms/RemoveQubitOperands.cpp @@ -21,23 +21,43 @@ //===----------------------------------------------------------------------===// #include "Dialect/QUIR/Transforms/RemoveQubitOperands.h" + +#include "Dialect/QUIR/IR/QUIRAttributes.h" +#include "Dialect/QUIR/IR/QUIROps.h" +#include "Dialect/QUIR/IR/QUIRTypes.h" #include "Dialect/QUIR/Utils/Utils.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/SymbolTable.h" +#include "mlir/IR/Value.h" +#include "mlir/Support/LLVM.h" + #include "llvm/ADT/BitVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" using namespace mlir; using namespace mlir::quir; auto RemoveQubitOperandsPass::lookupQubitId(const Value val) -> int { auto declOp = val.getDefiningOp(); - if (declOp) - return declOp.id().getValue(); - + if (declOp) { + auto id = declOp.getId(); + if (!id.has_value()) { + declOp->emitOpError() << "Qubit declaration does not have id"; + signalPassFailure(); + return -1; + } + return id.value(); + } // Must be an argument to a function // see if we can find an attribute with the info if (auto blockArg = val.dyn_cast()) { - unsigned argIdx = blockArg.getArgNumber(); - auto funcOp = dyn_cast(blockArg.getOwner()->getParentOp()); + unsigned const argIdx = blockArg.getArgNumber(); + auto funcOp = + dyn_cast(blockArg.getOwner()->getParentOp()); if (funcOp) { auto argAttr = funcOp.getArgAttrOfType( argIdx, quir::getPhysicalIdAttrName()); @@ -59,13 +79,13 @@ auto RemoveQubitOperandsPass::lookupQubitId(const Value val) -> int { return -1; } // lookupQubitId -void RemoveQubitOperandsPass::addQubitDeclarations(FuncOp funcOp) { +void RemoveQubitOperandsPass::addQubitDeclarations(mlir::func::FuncOp funcOp) { // build inside the func def body - OpBuilder build(funcOp.getBody()); + OpBuilder build = OpBuilder::atBlockBegin(&funcOp.getBody().front()); for (auto arg : funcOp.getArguments()) { if (arg.getType().isa()) { - int qId = lookupQubitId(arg); + int const qId = lookupQubitId(arg); if (qId < 0) { funcOp->emitOpError() << "Subroutine function argument does not specify physicalId, run " @@ -75,7 +95,7 @@ void RemoveQubitOperandsPass::addQubitDeclarations(FuncOp funcOp) { auto newDeclOp = build.create( funcOp->getLoc(), build.getType(1), build.getI32IntegerAttr(qId)); - arg.replaceAllUsesWith(newDeclOp.res()); + arg.replaceAllUsesWith(newDeclOp.getRes()); } } } // addQubitDeclarations @@ -88,8 +108,8 @@ void RemoveQubitOperandsPass::processCallOp(Operation *op) { // look for func def match Operation *findOp = - SymbolTable::lookupSymbolIn(moduleOperation, callOp.callee()); - auto funcOp = dyn_cast(findOp); + SymbolTable::lookupSymbolIn(moduleOperation, callOp.getCallee()); + auto funcOp = dyn_cast(findOp); if (!qIndicesBV.empty()) // some qubit args callOp->eraseOperands(qIndicesBV); diff --git a/lib/Dialect/QUIR/Transforms/ReorderCircuits.cpp b/lib/Dialect/QUIR/Transforms/ReorderCircuits.cpp index 5303a9864..caa49f966 100644 --- a/lib/Dialect/QUIR/Transforms/ReorderCircuits.cpp +++ b/lib/Dialect/QUIR/Transforms/ReorderCircuits.cpp @@ -24,11 +24,20 @@ #include "Dialect/QUIR/Utils/Utils.h" #include "mlir/Dialect/Affine/IR/AffineOps.h" -#include "mlir/IR/BuiltinOps.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" #include "mlir/Transforms/DialectConversion.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include +#include #define DEBUG_TYPE "QUIRReorderMeasurements" @@ -49,13 +58,13 @@ struct ReorderCircuitsAndNonCircuitPat PatternRewriter &rewriter) const override { // Accumulate qubits in measurement set - std::set currQubits = callCircuitOp.getOperatedQubits(); + std::set const currQubits = callCircuitOp.getOperatedQubits(); LLVM_DEBUG(llvm::dbgs() << "Matching on call_circuit for qubits:\t"); - LLVM_DEBUG(for (uint id : currQubits) llvm::dbgs() << id << " "); + LLVM_DEBUG(for (const uint id : currQubits) llvm::dbgs() << id << " "); LLVM_DEBUG(llvm::dbgs() << "\n"); auto nextAffineStoreOpp = - dyn_cast(callCircuitOp->getNextNode()); + dyn_cast(callCircuitOp->getNextNode()); if (nextAffineStoreOpp) { bool moveAffine = true; for (auto operand : nextAffineStoreOpp->getOperands()) @@ -78,7 +87,8 @@ void ReorderCircuitsPass::runOnOperation() { RewritePatternSet patterns(&getContext()); patterns.add(&getContext()); - FuncOp mainFunc = dyn_cast(getMainFunction(moduleOperation)); + mlir::func::FuncOp mainFunc = + dyn_cast(getMainFunction(moduleOperation)); if (!mainFunc) { signalPassFailure(); diff --git a/lib/Dialect/QUIR/Transforms/ReorderMeasurements.cpp b/lib/Dialect/QUIR/Transforms/ReorderMeasurements.cpp index e2d1ffa53..9ba91d50c 100644 --- a/lib/Dialect/QUIR/Transforms/ReorderMeasurements.cpp +++ b/lib/Dialect/QUIR/Transforms/ReorderMeasurements.cpp @@ -21,20 +21,25 @@ #include "Dialect/QUIR/Transforms/ReorderMeasurements.h" #include "Dialect/OQ3/IR/OQ3Ops.h" +#include "Dialect/QUIR/IR/QUIRInterfaces.h" #include "Dialect/QUIR/IR/QUIROps.h" +#include "Dialect/QUIR/IR/QUIRTraits.h" #include "Dialect/QUIR/Utils/Utils.h" -#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/IR/Visitors.h" +#include "mlir/Interfaces/ControlFlowInterfaces.h" #include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" #include "mlir/Transforms/DialectConversion.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" -#include -#include -#include +#include "llvm/Support/Debug.h" -#include #include +#include +#include +#include #include #define DEBUG_TYPE "QUIRReorderMeasurements" @@ -60,11 +65,11 @@ bool mayMoveVariableLoadOp(MeasureOp measureOp, bool moveVariableLoadOp = true; auto *currentBlock = variableLoadOp->getBlock(); currentBlock->walk([&](oq3::VariableAssignOp assignOp) { - if (assignOp.variable_name() == variableLoadOp.variable_name()) { + if (assignOp.getVariableName() == variableLoadOp.getVariableName()) { moveVariableLoadOp = assignOp->isBeforeInBlock(measureOp); if (!moveVariableLoadOp) { auto assignCastOp = - dyn_cast(assignOp.assigned_value().getDefiningOp()); + dyn_cast(assignOp.getAssignedValue().getDefiningOp()); if (assignCastOp) moveVariableLoadOp = mayMoveCastOp(measureOp, assignCastOp, moveList); } @@ -81,10 +86,10 @@ bool mayMoveCastOp(MeasureOp measureOp, oq3::CastOp castOp, MoveListVec &moveList) { bool moveCastOp = false; auto variableLoadOp = - dyn_cast(castOp.arg().getDefiningOp()); + dyn_cast(castOp.getArg().getDefiningOp()); if (variableLoadOp) moveCastOp = mayMoveVariableLoadOp(measureOp, variableLoadOp, moveList); - auto castMeasureOp = dyn_cast(castOp.arg().getDefiningOp()); + auto castMeasureOp = dyn_cast(castOp.getArg().getDefiningOp()); if (castMeasureOp) moveCastOp = ((castMeasureOp != measureOp) && (castMeasureOp->isBeforeInBlock(measureOp) || @@ -113,14 +118,14 @@ struct ReorderMeasureAndNonMeasurePat : public OpRewritePattern { // Accumulate qubits in measurement set std::set currQubits = measureOp.getOperatedQubits(); LLVM_DEBUG(llvm::dbgs() << "Matching on measurement for qubits:\t"); - LLVM_DEBUG(for (uint id : currQubits) llvm::dbgs() << id << " "); + LLVM_DEBUG(for (const uint id : currQubits) llvm::dbgs() << id << " "); LLVM_DEBUG(llvm::dbgs() << "\n"); auto nextOpt = nextQuantumOrControlFlowOrNull(measureOp); - if (!nextOpt.hasValue()) + if (!nextOpt.has_value()) break; - Operation *nextOp = nextOpt.getValue(); + Operation *nextOp = nextOpt.value(); // for control flow ops, continue, but add the operated qubits of the // control flow block to the currQubits set while (nextOp->hasTrait<::mlir::RegionBranchOpInterface::Trait>()) { @@ -128,10 +133,10 @@ struct ReorderMeasureAndNonMeasurePat : public OpRewritePattern { // now find the next next op auto nextNextOpt = nextQuantumOrControlFlowOrNull(nextOp); - if (!nextNextOpt.hasValue()) // only move non-control-flow ops + if (!nextNextOpt.has_value()) // only move non-control-flow ops break; - nextOp = nextNextOpt.getValue(); + nextOp = nextNextOpt.value(); } // don't reorder past the next measurement or reset or control flow @@ -188,7 +193,7 @@ struct ReorderMeasureAndNonMeasurePat : public OpRewritePattern { LLVM_DEBUG(llvm::dbgs() << "Succeeded match with operation:\n"); LLVM_DEBUG(nextOp->dump()); LLVM_DEBUG(llvm::dbgs() << "on qubits:\t"); - LLVM_DEBUG(for (uint id // this is ugly but clang-format insists + LLVM_DEBUG(for (const uint id // this is ugly but clang-format insists : QubitOpInterface::getOperatedQubits(nextOp)) { llvm::dbgs() << id << " "; }); diff --git a/lib/Dialect/QUIR/Transforms/SubroutineCloning.cpp b/lib/Dialect/QUIR/Transforms/SubroutineCloning.cpp index 83882825e..cfc944048 100644 --- a/lib/Dialect/QUIR/Transforms/SubroutineCloning.cpp +++ b/lib/Dialect/QUIR/Transforms/SubroutineCloning.cpp @@ -23,22 +23,48 @@ //===----------------------------------------------------------------------===// #include "Dialect/QUIR/Transforms/SubroutineCloning.h" + +#include "Dialect/QUIR/IR/QUIRAttributes.h" #include "Dialect/QUIR/IR/QUIROps.h" +#include "Dialect/QUIR/IR/QUIRTypes.h" #include "Dialect/QUIR/Utils/Utils.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/IR/Attributes.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/SymbolTable.h" +#include "mlir/IR/Value.h" +#include "mlir/Support/LLVM.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include +#include + using namespace mlir; using namespace mlir::quir; auto SubroutineCloningPass::lookupQubitId(const Value val) -> int { auto declOp = val.getDefiningOp(); - if (declOp) - return declOp.id().getValue(); + if (declOp) { + auto id = declOp.getId(); + if (!id.has_value()) { + declOp->emitOpError() << "Qubit declaration does not have id"; + signalPassFailure(); + return -1; + } + return id.value(); + } // Must be an argument to a function // see if we can find an attribute with the info if (auto blockArg = val.dyn_cast()) { - unsigned argIdx = blockArg.getArgNumber(); - auto funcOp = dyn_cast(blockArg.getOwner()->getParentOp()); + unsigned const argIdx = blockArg.getArgNumber(); + auto funcOp = + dyn_cast(blockArg.getOwner()->getParentOp()); if (funcOp) { auto argAttr = funcOp.getArgAttrOfType( argIdx, mlir::quir::getPhysicalIdAttrName()); @@ -63,13 +89,13 @@ auto SubroutineCloningPass::lookupQubitId(const Value val) -> int { template auto SubroutineCloningPass::getMangledName(Operation *op) -> std::string { auto callOp = dyn_cast(op); - std::string mangledName = callOp.callee().str(); + std::string mangledName = callOp.getCallee().str(); std::vector qOperands; qubitCallOperands(callOp, qOperands); - for (Value qArg : qOperands) { - int qId = SubroutineCloningPass::lookupQubitId(qArg); + for (Value const qArg : qOperands) { + int const qId = SubroutineCloningPass::lookupQubitId(qArg); if (qId < 0) { callOp->emitOpError() << "Unable to resolve qubit ID for call\n"; callOp->print(llvm::errs()); @@ -88,11 +114,11 @@ void SubroutineCloningPass::processCallOp(Operation *op, OpBuilder build(moduleOperation->getRegion(0)); // look for func def match - auto search = symbolOps.find(callOp.callee()); + auto search = symbolOps.find(callOp.getCallee()); if (search == symbolOps.end()) { callOp->emitOpError() << "No matching function def found for " - << callOp.callee() << "\n"; + << callOp.getCallee() << "\n"; return signalPassFailure(); } @@ -102,7 +128,7 @@ void SubroutineCloningPass::processCallOp(Operation *op, qubitCallOperands(callOp, qOperands); // first get the mangled name - std::string mangledName = getMangledName(callOp); + std::string const mangledName = getMangledName(callOp); callOp->setAttr("callee", FlatSymbolRefAttr::get(&getContext(), mangledName)); @@ -118,10 +144,10 @@ void SubroutineCloningPass::processCallOp(Operation *op, StringAttr::get(&getContext(), mangledName)); // add qubit ID attributes to all the arguments - for (uint ii = 0; ii < callOp.operands().size(); ++ii) { - if (callOp.operands()[ii].getType().template isa()) { - int qId = - lookupQubitId(callOp.operands()[ii]); // copy qubitId from call + for (uint ii = 0; ii < callOp.getOperands().size(); ++ii) { + if (callOp.getOperands()[ii].getType().template isa()) { + int const qId = + lookupQubitId(callOp.getOperands()[ii]); // copy qubitId from call newFunc.setArgAttrs( ii, ArrayRef({NamedAttribute( StringAttr::get(&getContext(), @@ -137,7 +163,7 @@ void SubroutineCloningPass::processCallOp(Operation *op, } else { // matching function not found callOp->emitOpError() << "No matching function def found for " - << callOp.callee() << "\n"; + << callOp.getCallee() << "\n"; return signalPassFailure(); } @@ -159,15 +185,15 @@ void SubroutineCloningPass::runOnOperation() { SymbolOpMap symbolOps; if (!callWorkList.empty()) { - moduleOperation->walk([&](FuncOp functionOp) { - symbolOps[functionOp.sym_name()] = functionOp.getOperation(); + moduleOperation->walk([&](mlir::func::FuncOp functionOp) { + symbolOps[functionOp.getSymName()] = functionOp.getOperation(); }); } while (!callWorkList.empty()) { Operation *op = callWorkList.front(); callWorkList.pop_front(); - processCallOp(op, symbolOps); + processCallOp(op, symbolOps); } mainFunc->walk([&](CallCircuitOp op) { callWorkList.push_back(op); }); @@ -175,7 +201,7 @@ void SubroutineCloningPass::runOnOperation() { if (!callWorkList.empty()) { symbolOps.clear(); moduleOperation->walk([&](CircuitOp circuitOp) { - symbolOps[circuitOp.sym_name()] = circuitOp.getOperation(); + symbolOps[circuitOp.getSymName()] = circuitOp.getOperation(); }); } diff --git a/lib/Dialect/QUIR/Transforms/UnusedVariable.cpp b/lib/Dialect/QUIR/Transforms/UnusedVariable.cpp index e32a4489f..88c486a7f 100644 --- a/lib/Dialect/QUIR/Transforms/UnusedVariable.cpp +++ b/lib/Dialect/QUIR/Transforms/UnusedVariable.cpp @@ -22,16 +22,18 @@ #include "Dialect/QUIR/Transforms/UnusedVariable.h" #include "Dialect/OQ3/IR/OQ3Ops.h" -#include "Dialect/QUIR/IR/QUIRDialect.h" -#include "Dialect/QUIR/IR/QUIROps.h" -#include "Dialect/QUIR/IR/QUIRTypes.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" #include "mlir/IR/PatternMatch.h" #include "mlir/IR/SymbolTable.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" #include "mlir/Transforms/DialectConversion.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" +#include "llvm/ADT/StringRef.h" + +#include + using namespace mlir; using namespace quir; using namespace oq3; diff --git a/lib/Dialect/QUIR/Transforms/VariableElimination.cpp b/lib/Dialect/QUIR/Transforms/VariableElimination.cpp index fef7e79a5..8320d96bf 100644 --- a/lib/Dialect/QUIR/Transforms/VariableElimination.cpp +++ b/lib/Dialect/QUIR/Transforms/VariableElimination.cpp @@ -21,43 +21,56 @@ #include "Dialect/QUIR/Transforms/VariableElimination.h" -#include "Dialect/OQ3/IR/OQ3Ops.h" -#include "Dialect/QUIR/IR/QUIRDialect.h" -#include "Dialect/QUIR/IR/QUIROps.h" - #include "Conversion/OQ3ToStandard/OQ3ToStandard.h" #include "Conversion/QUIRToStandard/VariablesToGlobalMemRefConversion.h" +#include "Dialect/OQ3/IR/OQ3Ops.h" +#include "Dialect/QUIR/IR/QUIRTypes.h" #include "mlir/Dialect/Affine/IR/AffineOps.h" #include "mlir/Dialect/Affine/Passes.h" #include "mlir/Dialect/Affine/Utils.h" +#include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" -#include "mlir/Dialect/SCF/SCF.h" +#include "mlir/Dialect/SCF/IR/SCF.h" +#include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/Dominance.h" +#include "mlir/IR/MLIRContext.h" +#include "mlir/IR/PatternMatch.h" #include "mlir/IR/SymbolTable.h" +#include "mlir/IR/Types.h" +#include "mlir/IR/Visitors.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" +#include "mlir/Transforms/DialectConversion.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" -#include +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +#include +#include +#include namespace mlir { -void affineScalarReplaceCopy(FuncOp f, DominanceInfo &domInfo, +void affineScalarReplaceCopy(mlir::func::FuncOp f, DominanceInfo &domInfo, PostDominanceInfo &postDomInfo); } // namespace mlir namespace mlir::quir { namespace { -Optional convertCBitType(quir::CBitType t) { +std::optional convertCBitType(quir::CBitType t) { if (t.getWidth() <= 64) return IntegerType::get(t.getContext(), t.getWidth()); - return llvm::None; + return std::nullopt; } template -Optional legalizeType(T t) { +std::optional legalizeType(T t) { return t; } @@ -96,12 +109,12 @@ struct MaterializeIntToAngleCastPattern matchAndRewrite(oq3::CastOp castOp, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override { - if (!adaptor.arg().getType().isIntOrIndexOrFloat() || - !castOp.out().getType().isa()) + if (!adaptor.getArg().getType().isIntOrIndexOrFloat() || + !castOp.getOut().getType().isa()) return failure(); - rewriter.replaceOpWithNewOp(castOp, castOp.out().getType(), - adaptor.arg()); + rewriter.replaceOpWithNewOp(castOp, castOp.getOut().getType(), + adaptor.getArg()); return success(); } // matchAndRewrite @@ -128,11 +141,9 @@ struct MaterializeBitOpForInt : public OpConversionPattern { } }; -} // namespace - -static mlir::LogicalResult -convertQuirVariables(mlir::MLIRContext &context, mlir::Operation *top, - bool externalizeOutputVariables) { +mlir::LogicalResult convertQuirVariables(mlir::MLIRContext &context, + mlir::Operation *top, + bool externalizeOutputVariables) { // This conversion step gets rid of QUIR variables and classical bit // registers. These two concepts should be in the OpenQASM 3 dialect. @@ -144,9 +155,9 @@ convertQuirVariables(mlir::MLIRContext &context, mlir::Operation *top, CBitTypeConverter typeConverter; // Only convert QUIR variable operations - target.addLegalDialect(); + mlir::func::FuncDialect, affine::AffineDialect>(); target.addIllegalOp(); // TODO add additional QUIR variable operations here @@ -172,7 +183,7 @@ convertQuirVariables(mlir::MLIRContext &context, mlir::Operation *top, // clang-format on target.addDynamicallyLegalOp([](oq3::CastOp op) { if (op.getType().isa() || - op.arg().getType().isa()) + op.getArg().getType().isa()) return false; return true; }); @@ -185,7 +196,7 @@ convertQuirVariables(mlir::MLIRContext &context, mlir::Operation *top, target.addDynamicallyLegalOp( [](mlir::oq3::CBitExtractBitOp op) { if (op.getType().isa() || - op.operand().getType().isa()) + op.getOperand().getType().isa()) return false; return true; @@ -193,7 +204,7 @@ convertQuirVariables(mlir::MLIRContext &context, mlir::Operation *top, target.addDynamicallyLegalOp( [](mlir::oq3::CBitInsertBitOp op) { if (op.getType().isa() || - op.operand().getType().isa()) + op.getOperand().getType().isa()) return false; return true; @@ -206,14 +217,13 @@ convertQuirVariables(mlir::MLIRContext &context, mlir::Operation *top, return applyPartialConversion(top, target, std::move(patterns)); } -namespace { LogicalResult MemrefGlobalToAllocaPattern::matchAndRewrite( mlir::memref::GetGlobalOp op, mlir::PatternRewriter &rewriter) const { // Check that the global memref is only used by this GetGlobalOp auto global = mlir::SymbolTable::lookupNearestSymbolFrom( - op, op.nameAttr()); + op, op.getNameAttr()); if (!global) return failure(); @@ -225,26 +235,25 @@ LogicalResult MemrefGlobalToAllocaPattern::matchAndRewrite( if (!uses) return failure(); - for (auto &use : uses.getValue()) { - assert(use.getSymbolRef() == op.nameAttr() && "found wrong symbol"); + for (auto &use : uses.value()) { + assert(use.getSymbolRef() == op.getNameAttr() && "found wrong symbol"); if (use.getUser() != op) // other reference to the global memref return failure(); } - auto mrt = op.result().getType().dyn_cast(); + auto mrt = op.getResult().getType().dyn_cast(); assert(mrt && "expect result of a GetGlobalOp to be of MemRefType"); if (!mrt) return failure(); - rewriter.replaceOpWithNewOp(op, mrt, - global.alignmentAttr()); + rewriter.replaceOpWithNewOp( + op, mrt, global.getAlignmentAttr()); rewriter.eraseOp(global); return success(); } -} // namespace -static mlir::LogicalResult +mlir::LogicalResult convertIsolatedMemrefGlobalToAlloca(mlir::MLIRContext &context, mlir::Operation *top) { @@ -260,7 +269,6 @@ convertIsolatedMemrefGlobalToAlloca(mlir::MLIRContext &context, return applyPatternsAndFoldGreedily(top, std::move(patterns), config); } -namespace { struct RemoveAllocaWithIsolatedStoresPattern : public OpRewritePattern { RemoveAllocaWithIsolatedStoresPattern(MLIRContext *context, @@ -283,7 +291,7 @@ LogicalResult RemoveAllocaWithIsolatedStoresPattern::matchAndRewrite( // push to small vector for erasing for (auto *user : op.getResult().getUsers()) { usersToErase.push_back(user); - if (!mlir::isa(user)) + if (!mlir::isa(user)) return failure(); } @@ -295,10 +303,9 @@ LogicalResult RemoveAllocaWithIsolatedStoresPattern::matchAndRewrite( rewriter.eraseOp(op); return success(); } -} // namespace -static mlir::LogicalResult -dropAllocaWithIsolatedStores(mlir::MLIRContext &context, mlir::Operation *top) { +mlir::LogicalResult dropAllocaWithIsolatedStores(mlir::MLIRContext &context, + mlir::Operation *top) { RewritePatternSet patterns(&context); @@ -312,6 +319,8 @@ dropAllocaWithIsolatedStores(mlir::MLIRContext &context, mlir::Operation *top) { return applyPatternsAndFoldGreedily(top, std::move(patterns), config); } +} // anonymous namespace + void VariableEliminationPass::runOnOperation() { if (failed(convertQuirVariables(getContext(), getOperation(), @@ -324,10 +333,8 @@ void VariableEliminationPass::runOnOperation() { auto &domInfo = getAnalysis(); auto &postDomInfo = getAnalysis(); - WalkResult result = getOperation()->walk([&](mlir::FuncOp func) { - // TODO LLVM 15+: Use MLIR's builtin affineScalarReplace, which is fixed - // there - mlir::affineScalarReplaceCopy(func, domInfo, postDomInfo); + WalkResult const result = getOperation()->walk([&](mlir::func::FuncOp func) { + mlir::affine::affineScalarReplace(func, domInfo, postDomInfo); return WalkResult::advance(); }); diff --git a/lib/Dialect/QUIR/Utils/Utils.cpp b/lib/Dialect/QUIR/Utils/Utils.cpp index c5668a9e9..a0dfb2564 100644 --- a/lib/Dialect/QUIR/Utils/Utils.cpp +++ b/lib/Dialect/QUIR/Utils/Utils.cpp @@ -19,22 +19,36 @@ //===----------------------------------------------------------------------===// #include "Dialect/QUIR/Utils/Utils.h" + +#include "Dialect/QUIR/IR/QUIRAttributes.h" #include "Dialect/QUIR/IR/QUIROps.h" #include "Dialect/QUIR/IR/QUIRTraits.h" #include "Dialect/QUIR/IR/QUIRTypes.h" -#include "mlir/Dialect/SCF/SCF.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/IR/Attributes.h" #include "mlir/IR/Builders.h" -#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/FunctionInterfaces.h" #include "mlir/IR/SymbolTable.h" +#include "mlir/IR/Value.h" +#include "mlir/IR/Visitors.h" +#include "mlir/Interfaces/ControlFlowInterfaces.h" +#include "mlir/Support/LLVM.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Error.h" - +#include "llvm/Support/raw_ostream.h" + +#include +#include +#include +#include +#include +#include #include -#include +#include namespace mlir::quir { @@ -58,15 +72,15 @@ auto quirFunctionTypeMatch(FunctionType &ft1, FunctionType &ft2) -> bool { return false; for (uint ii = 0; ii < ft1.getNumInputs(); ++ii) { - Type t1 = ft1.getInput(ii); - Type t2 = ft2.getInput(ii); + Type const t1 = ft1.getInput(ii); + Type const t2 = ft2.getInput(ii); if (!quirTypeMatch(t1, t2) && t1 != t2) return false; } for (uint ii = 0; ii < ft1.getNumResults(); ++ii) { - Type t1 = ft1.getResult(ii); - Type t2 = ft2.getResult(ii); + Type const t1 = ft1.getResult(ii); + Type const t2 = ft2.getResult(ii); if (!quirTypeMatch(t1, t2) && t1 != t2) return false; } @@ -76,9 +90,9 @@ auto quirFunctionTypeMatch(FunctionType &ft1, FunctionType &ft2) -> bool { // walks the module operation and searches for a func def labeled "main" auto getMainFunction(Operation *moduleOperation) -> Operation * { - OpBuilder b(moduleOperation); + OpBuilder const b(moduleOperation); Operation *mainFunc = nullptr; - moduleOperation->walk([&](FuncOp funcOp) { + moduleOperation->walk([&](mlir::func::FuncOp funcOp) { if (SymbolRefAttr::get(funcOp).getLeafReference() == "main") { mainFunc = funcOp.getOperation(); return WalkResult::interrupt(); @@ -119,7 +133,7 @@ void addQubitIdsFromAttr(Operation *operation, std::vector &theseIds) { if (thisIdAttr) theseIds.push_back(thisIdAttr.getInt()); if (theseIdsAttr) { - for (Attribute valAttr : theseIdsAttr) { + for (Attribute const valAttr : theseIdsAttr) { auto intAttr = valAttr.dyn_cast(); theseIds.push_back(intAttr.getInt()); } @@ -135,7 +149,7 @@ void addQubitIdsFromAttr(Operation *operation, std::set &theseIds) { if (thisIdAttr) theseIds.emplace(thisIdAttr.getInt()); if (theseIdsAttr) { - for (Attribute valAttr : theseIdsAttr) { + for (Attribute const valAttr : theseIdsAttr) { auto intAttr = valAttr.dyn_cast(); theseIds.emplace(intAttr.getInt()); } @@ -145,7 +159,7 @@ void addQubitIdsFromAttr(Operation *operation, std::set &theseIds) { // returns a vector of all of the classical arguments for a callOp template void classicalCallOperands(CallOpTy &callOp, std::vector &vec) { - for (auto arg : callOp.operands()) + for (auto arg : callOp.getOperands()) if (!arg.getType().template isa()) vec.emplace_back(arg); } // classicalCallOperands @@ -194,7 +208,7 @@ template void qubitArgIndices(CallOpTy &callOp, llvm::BitVector &bv) { uint ii = 0; - for (auto arg : callOp.operands()) { + for (auto arg : callOp.getOperands()) { if (arg.getType().template isa()) { if (bv.size() <= ii) bv.resize(ii + 1); @@ -215,12 +229,12 @@ template void qubitArgIndices(CallSubroutineOp &, // TODO: Determine a better way of tracing qubit identities // other than decorating blocks and functions. -llvm::Optional lookupQubitId(const Value &val) { +std::optional lookupQubitId(const Value &val) { auto declOp = val.getDefiningOp(); if (!declOp) { // Must be an argument to a function // see if we can find an attribute with the info if (auto blockArg = val.dyn_cast()) { - unsigned argIdx = blockArg.getArgNumber(); + unsigned const argIdx = blockArg.getArgNumber(); auto *parentOp = blockArg.getOwner()->getParentOp(); if (FunctionOpInterface functionOpInterface = dyn_cast(parentOp)) { @@ -233,42 +247,49 @@ llvm::Optional lookupQubitId(const Value &val) { } } // if parentOp is funcOp } // if val is blockArg - return llvm::None; + return std::nullopt; } // if !declOp - int id = declOp.id().getValue(); + auto idOpt = declOp.getId(); + + int id; + if (idOpt.has_value()) + id = idOpt.value(); + else + id = -1; + assert(id >= 0 && "Declared ID of qubit is < 0"); return static_cast(id); } // lookupQubitId -llvm::Optional nextQuantumOpOrNull(Operation *op) { +std::optional nextQuantumOpOrNull(Operation *op) { Operation *curOp = op; while (Operation *nextOp = curOp->getNextNode()) { if (isQuantumOp(nextOp)) return nextOp; if (nextOp->hasTrait<::mlir::RegionBranchOpInterface::Trait>()) { // control flow found, no next quantum op - return llvm::None; + return std::nullopt; } curOp = nextOp; } - return llvm::None; + return std::nullopt; } // nextQuantumOpOrNull -llvm::Optional prevQuantumOpOrNull(Operation *op) { +std::optional prevQuantumOpOrNull(Operation *op) { Operation *curOp = op; while (Operation *prevOp = curOp->getPrevNode()) { if (isQuantumOp(prevOp)) return prevOp; if (prevOp->hasTrait<::mlir::RegionBranchOpInterface::Trait>()) { // control flow found, no prev quantum op - return llvm::None; + return std::nullopt; } curOp = prevOp; } - return llvm::None; + return std::nullopt; } // prevQuantumOpOrNull -llvm::Optional nextQuantumOrControlFlowOrNull(Operation *op) { +std::optional nextQuantumOrControlFlowOrNull(Operation *op) { Operation *curOp = op; while (Operation *nextOp = curOp->getNextNode()) { if (isQuantumOp(nextOp)) @@ -279,10 +300,10 @@ llvm::Optional nextQuantumOrControlFlowOrNull(Operation *op) { } curOp = nextOp; } - return llvm::None; + return std::nullopt; } // nextQuantumOrControlFlowOrNull -llvm::Optional prevQuantumOrControlFlowOrNull(Operation *op) { +std::optional prevQuantumOrControlFlowOrNull(Operation *op) { Operation *curOp = op; while (Operation *prevOp = curOp->getPrevNode()) { if (isQuantumOp(prevOp)) @@ -293,7 +314,7 @@ llvm::Optional prevQuantumOrControlFlowOrNull(Operation *op) { } curOp = prevOp; } - return llvm::None; + return std::nullopt; } // prevQuantumOrControlFlowOrNull bool isQuantumOp(Operation *op) { @@ -305,13 +326,13 @@ bool isQuantumOp(Operation *op) { llvm::Expected getDuration(mlir::quir::DelayOp &delayOp) { - std::string durationStr; - auto durationDeclare = delayOp.time().getDefiningOp(); + std::string const durationStr; + auto durationDeclare = delayOp.getTime().getDefiningOp(); if (durationDeclare) - return durationDeclare.value().dyn_cast(); - auto argNum = delayOp.time().cast().getArgNumber(); + return durationDeclare.getValue().dyn_cast(); + auto argNum = delayOp.getTime().cast().getArgNumber(); auto circuitOp = mlir::dyn_cast( - delayOp.time().getParentBlock()->getParentOp()); + delayOp.getTime().getParentBlock()->getParentOp()); assert(circuitOp && "can only handle circuit arguments"); auto argAttr = circuitOp.getArgAttrOfType( argNum, mlir::quir::getDurationAttrName()); @@ -320,7 +341,7 @@ getDuration(mlir::quir::DelayOp &delayOp) { llvm::Expected getDuration(mlir::quir::ConstantOp &duration) { - auto durAttr = duration.value().dyn_cast(); + auto durAttr = duration.getValue().dyn_cast(); if (!durAttr) return llvm::createStringError(llvm::inconvertibleErrorCode(), "Expected a ConstantOp with a DurationAttr"); @@ -330,25 +351,25 @@ getDuration(mlir::quir::ConstantOp &duration) { std::tuple qubitFromMeasResult(MeasureOp measureOp, Value result) { auto opRes = result.cast(); - uint resNum = opRes.getResultNumber(); - return std::make_tuple(measureOp.qubits()[resNum], measureOp); + uint const resNum = opRes.getResultNumber(); + return std::make_tuple(measureOp.getQubits()[resNum], measureOp); } std::tuple qubitFromMeasResult(CallCircuitOp callCircuitOp, Value result) { auto opRes = result.cast(); - uint resNum = opRes.getResultNumber(); + uint const resNum = opRes.getResultNumber(); Operation *findOp = SymbolTable::lookupNearestSymbolFrom( - callCircuitOp, callCircuitOp.calleeAttr()); + callCircuitOp, callCircuitOp.getCalleeAttr()); auto circuitOp = dyn_cast(findOp); auto returnOp = dyn_cast(circuitOp.back().getTerminator()); auto circuitResult = returnOp->getOperand(resNum).cast(); auto measureOp = dyn_cast(circuitResult.getDefiningOp()); - return std::make_tuple(measureOp.qubits()[circuitResult.getResultNumber()], + return std::make_tuple(measureOp.getQubits()[circuitResult.getResultNumber()], measureOp); } diff --git a/lib/Frontend/OpenQASM3/BaseQASM3Visitor.cpp b/lib/Frontend/OpenQASM3/BaseQASM3Visitor.cpp index 9e82f8373..98bd15ebf 100644 --- a/lib/Frontend/OpenQASM3/BaseQASM3Visitor.cpp +++ b/lib/Frontend/OpenQASM3/BaseQASM3Visitor.cpp @@ -56,7 +56,40 @@ #include "Frontend/OpenQASM3/BaseQASM3Visitor.h" -#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace QASM; @@ -85,7 +118,7 @@ void BaseQASM3Visitor::visit(const ASTStatementList *list) { void BaseQASM3Visitor::visit(const ASTSymbolTableEntry *symTableEntry) { assert(symTableEntry); - switch (ASTType astType = symTableEntry->GetValueType()) { + switch (ASTType const astType = symTableEntry->GetValueType()) { case ASTTypeQubitContainer: dispatchSymbolTableEntryVisit(symTableEntry); break; @@ -145,7 +178,7 @@ void BaseQASM3Visitor::visit(const ASTSymbolTableEntry *symTableEntry) { void BaseQASM3Visitor::visit(const ASTStatementNode *node) { // evaluate statements by type - switch (ASTType astType = node->GetASTType()) { + switch (ASTType const astType = node->GetASTType()) { case ASTTypeOpenQASMStatement: dispatchVisit(node); break; @@ -240,7 +273,7 @@ void BaseQASM3Visitor::visit(const ASTBinaryOpStatementNode *node) { void BaseQASM3Visitor::visit(const ASTOpenQASMStatementNode *node) {} void BaseQASM3Visitor::visit(const ASTExpressionNode *node) { - switch (ASTType astType = node->GetASTType()) { + switch (ASTType const astType = node->GetASTType()) { case ASTTypeIdentifier: { const ASTIdentifierNode *identifierNode = nullptr; if (node->IsIdentifier()) { diff --git a/lib/Frontend/OpenQASM3/OpenQASM3Frontend.cpp b/lib/Frontend/OpenQASM3/OpenQASM3Frontend.cpp index 48278d142..85e03d378 100644 --- a/lib/Frontend/OpenQASM3/OpenQASM3Frontend.cpp +++ b/lib/Frontend/OpenQASM3/OpenQASM3Frontend.cpp @@ -20,55 +20,74 @@ #include "Frontend/OpenQASM3/OpenQASM3Frontend.h" -#include "Frontend/OpenQASM3/PrintQASM3Visitor.h" -#include "Frontend/OpenQASM3/QUIRGenQASM3Visitor.h" - +#include "API/errors.h" #include "Dialect/QUIR/IR/QUIRDialect.h" #include "Dialect/QUIR/IR/QUIREnums.h" +#include "Frontend/OpenQASM3/PrintQASM3Visitor.h" +#include "Frontend/OpenQASM3/QUIRGenQASM3Visitor.h" -#include "qasm/Frontend/QasmDiagnosticEmitter.h" -#include "qasm/Frontend/QasmParser.h" - +#include "mlir/Dialect/Complex/IR/Complex.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/Verifier.h" #include "mlir/Support/FileUtilities.h" +#include "mlir/Support/LogicalResult.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SMLoc.h" #include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include + +namespace { -static llvm::cl::OptionCategory openqasm3Cat( +llvm::cl::OptionCategory openqasm3Cat( " OpenQASM 3 Frontend Options", "Options that control the OpenQASM 3 frontend of QSS Compiler"); -static llvm::cl::opt +llvm::cl::opt numShots("num-shots", llvm::cl::desc("The number of shots to execute on the quantum " "circuit, default is 1000"), llvm::cl::init(1000), llvm::cl::cat(openqasm3Cat)); -static llvm::cl::opt shotDelay( +llvm::cl::opt shotDelay( "shot-delay", llvm::cl::desc("Repetition delay between shots. Defaults to 1ms."), llvm::cl::init("1ms"), llvm::cl::cat(openqasm3Cat)); -static llvm::cl::list +llvm::cl::list includeDirs("I", llvm::cl::desc("Add to the include path"), llvm::cl::value_desc("dir"), llvm::cl::cat(openqasm3Cat)); -static qssc::DiagnosticCallback *diagnosticCallback_; -static llvm::SourceMgr *sourceMgr_; +qssc::DiagnosticCallback *diagnosticCallback_; +llvm::SourceMgr *sourceMgr_; -static std::mutex qasmParserLock; +std::mutex qasmParserLock; -namespace { -static std::regex durationRe("^([0-9]*[.]?[0-9]+)([a-zA-Z]*)"); +std::regex durationRe("^([0-9]*[.]?[0-9]+)([a-zA-Z]*)"); llvm::Expected> parseDurationStr(const std::string &durationStr) { @@ -79,7 +98,7 @@ parseDurationStr(const std::string &durationStr) { llvm::inconvertibleErrorCode(), llvm::Twine("Unable to parse duration from ") + durationStr); - double parsedDuration = std::stod(m[1]); + double const parsedDuration = std::stod(m[1]); // Convert all units to lower case. auto unitStr = m[2].str(); auto lowerUnitStr = llvm::StringRef(unitStr).lower(); @@ -88,7 +107,7 @@ parseDurationStr(const std::string &durationStr) { lowerUnitStr = "s"; if (auto parsedUnits = mlir::quir::symbolizeTimeUnits(lowerUnitStr)) - return std::make_pair(parsedDuration, parsedUnits.getValue()); + return std::make_pair(parsedDuration, parsedUnits.value()); return llvm::createStringError(llvm::inconvertibleErrorCode(), llvm::Twine("Unknown duration unit ") + @@ -103,7 +122,7 @@ llvm::Error qssc::frontend::openqasm3::parse( std::optional diagnosticCallback) { // The QASM parser can only be called from a single thread. - std::lock_guard qasmParserLockGuard(qasmParserLock); + std::lock_guard const qasmParserLockGuard(qasmParserLock); for (const auto &dirStr : includeDirs) QASM::QasmPreprocessor::Instance().AddIncludePath(dirStr); @@ -177,7 +196,7 @@ llvm::Error qssc::frontend::openqasm3::parse( << sourceString << "\n"; if (diagnosticCallback_) { - qssc::Diagnostic diag{ + qssc::Diagnostic const diag{ diagLevel, qssc::ErrorCategory::OpenQASM3ParseFailure, fileLoc.str() + "\n" + Msg + "\n" + sourceString}; (*diagnosticCallback_)(diag); @@ -239,9 +258,9 @@ llvm::Error qssc::frontend::openqasm3::parse( context->loadDialect(); context->loadDialect(); - context->loadDialect(); + context->loadDialect(); - mlir::OpBuilder builder(newModule.getBodyRegion()); + mlir::OpBuilder const builder(newModule.getBodyRegion()); QASM::ASTStatementList *statementList = QASM::ASTStatementBuilder::Instance().List(); diff --git a/lib/Frontend/OpenQASM3/PrintQASM3Visitor.cpp b/lib/Frontend/OpenQASM3/PrintQASM3Visitor.cpp index 0935d0a7b..541b85a79 100644 --- a/lib/Frontend/OpenQASM3/PrintQASM3Visitor.cpp +++ b/lib/Frontend/OpenQASM3/PrintQASM3Visitor.cpp @@ -28,10 +28,44 @@ #include "Frontend/OpenQASM3/PrintQASM3Visitor.h" -#include "qasm/AST/ASTIdentifier.h" +#include "Frontend/OpenQASM3/BaseQASM3Visitor.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + using namespace QASM; namespace qssc::frontend::openqasm3 { @@ -56,7 +90,7 @@ void PrintQASM3Visitor::visit(const ASTForLoopNode *node) { } } else { vStream << "i=["; - for (int I : intList) + for (int const I : intList) vStream << I << " "; vStream << "], stepping=" << node->GetStepping(); } @@ -95,7 +129,7 @@ void PrintQASM3Visitor::visit(const ASTElseStatementNode *node) { } void PrintQASM3Visitor::visit(const ASTSwitchStatementNode *node) { - ASTType quantityType = node->GetQuantityType(); + ASTType const quantityType = node->GetQuantityType(); vStream << "SwitchStatementNode(" << "SwitchQuantity("; @@ -342,7 +376,7 @@ void PrintQASM3Visitor::visit(const ASTDelayStatementNode *node) { void PrintQASM3Visitor::visit(const ASTDelayNode *node) { vStream << "DelayNode("; - switch (ASTType delayType = node->GetDelayType()) { + switch (ASTType const delayType = node->GetDelayType()) { case ASTTypeDuration: { vStream << "duration="; const ASTDurationNode *durationNode = node->GetDurationNode(); @@ -396,7 +430,7 @@ void PrintQASM3Visitor::visit(const ASTBarrierNode *node) { } void PrintQASM3Visitor::visit(const ASTDeclarationNode *node) { - ASTType declType = node->GetASTType(); + ASTType const declType = node->GetASTType(); vStream << "DeclarationNode(type=" << PrintTypeEnum(declType) << ", "; // if it's a function, process it directly if (const auto *funcDecl = @@ -504,7 +538,7 @@ void PrintQASM3Visitor::visit(const ASTIdentifierNode *node) { } void PrintQASM3Visitor::visit(const ASTBinaryOpNode *node) { - ASTOpType opType = node->GetOpType(); + ASTOpType const opType = node->GetOpType(); const ASTExpressionNode *left = node->GetLeft(); const ASTExpressionNode *right = node->GetRight(); vStream << "BinaryOpNode(type=" << PrintOpTypeEnum(opType) << ", left="; @@ -515,7 +549,7 @@ void PrintQASM3Visitor::visit(const ASTBinaryOpNode *node) { } void PrintQASM3Visitor::visit(const ASTUnaryOpNode *node) { - ASTOpType opType = node->GetOpType(); + ASTOpType const opType = node->GetOpType(); const auto *operand = node->GetExpression(); vStream << "UnaryOpNode(type=" << PrintOpTypeEnum(opType) << ", operand="; @@ -558,7 +592,7 @@ void PrintQASM3Visitor::visit(const ASTFloatNode *node) { void PrintQASM3Visitor::visit(const ASTMPDecimalNode *node) { const unsigned bits = node->GetIdentifier()->GetBits(); - std::string val = node->GetValue(); + std::string const val = node->GetValue(); vStream << "MPDecimalNode(name=" << node->GetName(); if (!node->IsNan()) vStream << ", value=" << val; @@ -569,9 +603,10 @@ void PrintQASM3Visitor::visit(const ASTMPComplexNode *node) { const std::string &name = node->GetName(); const std::string val = node->GetValue(); const unsigned bits = node->GetIdentifier()->GetBits(); - int position = val.find(' '); - std::string real = val.substr(1, position - 1); - std::string imag = val.substr(position + 1, val.length() - position - 2); + int const position = val.find(' '); + std::string const real = val.substr(1, position - 1); + std::string const imag = + val.substr(position + 1, val.length() - position - 2); vStream << "MPComplexNode(name=" << name; if (!node->IsNan()) { diff --git a/lib/Frontend/OpenQASM3/QUIRGenQASM3Visitor.cpp b/lib/Frontend/OpenQASM3/QUIRGenQASM3Visitor.cpp index a7c0bc36b..14c7188d4 100644 --- a/lib/Frontend/OpenQASM3/QUIRGenQASM3Visitor.cpp +++ b/lib/Frontend/OpenQASM3/QUIRGenQASM3Visitor.cpp @@ -37,38 +37,85 @@ /// //===----------------------------------------------------------------------===// +#include "Frontend/OpenQASM3/QUIRGenQASM3Visitor.h" + #include "Dialect/OQ3/IR/OQ3Ops.h" #include "Dialect/QCS/IR/QCSAttributes.h" #include "Dialect/QCS/IR/QCSOps.h" +#include "Dialect/QUIR/IR/QUIRAttributes.h" #include "Dialect/QUIR/IR/QUIREnums.h" #include "Dialect/QUIR/IR/QUIROps.h" #include "Dialect/QUIR/IR/QUIRTypes.h" - #include "Frontend/OpenQASM3/BaseQASM3Visitor.h" -#include "Frontend/OpenQASM3/QUIRGenQASM3Visitor.h" #include "Frontend/OpenQASM3/QUIRVariableBuilder.h" -#include "qasm/AST/ASTDelay.h" -#include "qasm/AST/ASTTypeEnums.h" - -#include "mlir/Dialect/Arithmetic/IR/Arithmetic.h" +#include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/Dialect/Complex/IR/Complex.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" +#include "mlir/Dialect/SCF/IR/SCF.h" +#include "mlir/IR/Attributes.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/BuiltinTypes.h" - +#include "mlir/IR/Diagnostics.h" +#include "mlir/IR/Operation.h" +#include "mlir/IR/Region.h" +#include "mlir/IR/SymbolTable.h" +#include "mlir/IR/Value.h" +#include "mlir/IR/ValueRange.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" + +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include #include +#include #define DEBUG_TYPE "QUIRGen" @@ -82,19 +129,22 @@ namespace qssc::frontend::openqasm3 { using ExpressionValueType = llvm::Expected; +namespace { // temporary feature flags to be used during development of parameters support -static llvm::cl::opt +llvm::cl::opt enableParameters("enable-parameters", llvm::cl::desc("enable qasm3 input parameters"), llvm::cl::init(false)); -static llvm::cl::opt - enableCircuits("enable-circuits", llvm::cl::desc("enable quir circuits"), - llvm::cl::init(false)); +llvm::cl::opt enableCircuits("enable-circuits", + llvm::cl::desc("enable quir circuits"), + llvm::cl::init(false)); + +llvm::cl::opt debugCircuits("debug-circuits", + llvm::cl::desc("debug quir circuits"), + llvm::cl::init(false)); -static llvm::cl::opt debugCircuits("debug-circuits", - llvm::cl::desc("debug quir circuits"), - llvm::cl::init(false)); +} // anonymous namespace auto QUIRGenQASM3Visitor::getLocation(const ASTBase *node) -> Location { return mlir::FileLineColLoc::get(builder.getContext(), filename, @@ -128,9 +178,9 @@ QUIRGenQASM3Visitor::getExpressionName(const ASTExpressionNode *node) { dynamic_cast(node->GetExpression())) return refNode->GetName(); if (const auto *intNode = dynamic_cast(node)) { - unsigned bits = intNode->GetBits(); - int64_t value = intNode->IsSigned() ? intNode->GetSignedValue() - : intNode->GetUnsignedValue(); + unsigned const bits = intNode->GetBits(); + int64_t const value = intNode->IsSigned() ? intNode->GetSignedValue() + : intNode->GetUnsignedValue(); return intNode->GetName() + std::to_string(value) + "_i" + std::to_string(bits); } @@ -167,7 +217,30 @@ getDurationTimeUnits(const QASM::LengthUnit &durationUnit) { llvm_unreachable("unhandled time unit"); } } -}; // anonymous namespace + +mlir::arith::CmpIPredicate getComparisonPredicate(QASM::ASTOpType opType) { + switch (opType) { + case ASTOpTypeCompEq: + return mlir::arith::CmpIPredicate::eq; + case ASTOpTypeCompNeq: + return mlir::arith::CmpIPredicate::ne; + case ASTOpTypeLT: + return mlir::arith::CmpIPredicate::slt; + case ASTOpTypeLE: + return mlir::arith::CmpIPredicate::sle; + case ASTOpTypeGT: + return mlir::arith::CmpIPredicate::sgt; + case ASTOpTypeGE: + return mlir::arith::CmpIPredicate::sge; + + default: + llvm::errs() << "Cannot derive comparison predicate for opType " + << QASM::PrintOpTypeEnum(opType) << "\n"; + llvm_unreachable("Unimplemented."); + } +} + +} // anonymous namespace auto QUIRGenQASM3Visitor::createDurationRef(const Location &location, uint64_t durationValue, @@ -188,7 +261,7 @@ auto QUIRGenQASM3Visitor::createDurationRef(const Location &location, void QUIRGenQASM3Visitor::initialize( uint numShots, const double &shotDelay, const mlir::quir::TimeUnits &shotDelayUnits) { - Location initialLocation = + Location const initialLocation = mlir::FileLineColLoc::get(topLevelBuilder.getContext(), filename, 0, 0); // validate command line options @@ -201,7 +274,7 @@ void QUIRGenQASM3Visitor::initialize( } // create the "main" function - auto func = topLevelBuilder.create( + auto func = topLevelBuilder.create( initialLocation, "main", topLevelBuilder.getFunctionType( /*inputs=*/ArrayRef(), @@ -209,7 +282,7 @@ void QUIRGenQASM3Visitor::initialize( // set up the builders to point to the proper places func.addEntryBlock(); - OpBuilder b(func.getBody()); + OpBuilder const b = OpBuilder::atBlockBegin(&func.getBody().front()); builder = b; topLevelBuilder.setInsertionPointToStart(topLevelBuilder.getBlock()); @@ -249,10 +322,10 @@ void QUIRGenQASM3Visitor::initialize( builder.create(initialLocation); // return 0 - Value intRef = builder.create( + Value const intRef = builder.create( initialLocation, builder.getIntegerAttr(builder.getIntegerType(32), 0)); auto returnValueRange = ValueRange(intRef); - builder.create(initialLocation, returnValueRange); + builder.create(initialLocation, returnValueRange); // Set the builder to add circuit operations inside the for loop builder.setInsertionPointAfter(shotInit); @@ -301,7 +374,7 @@ void QUIRGenQASM3Visitor::visit(const ASTForStatementNode *node) { } const ASTIntegerList &intList = loop->GetIntegerList(); - Location loc = getLocation(node); + Location const loc = getLocation(node); // Lower bound auto startOp = builder.create( @@ -322,7 +395,7 @@ void QUIRGenQASM3Visitor::visit(const ASTForStatementNode *node) { // Adding induction variable to SSA values map const ASTIntNode *indVar = loop->GetIndVar(); - Value forOpIndVar = forOp.getInductionVar(); + Value const forOpIndVar = forOp.getInductionVar(); ssaValues[indVar->GetName()] = forOpIndVar; // Dictionary of SSA values used inside "for" @@ -331,7 +404,7 @@ void QUIRGenQASM3Visitor::visit(const ASTForStatementNode *node) { std::swap(ssaValues, forSsaValues); // set up the builders to point to the proper places - OpBuilder b(&forOp.getRegion()); + OpBuilder const b(&forOp.getRegion()); builder = b; circuitParentBuilder = b; @@ -357,7 +430,7 @@ void QUIRGenQASM3Visitor::visit(const ASTIfStatementNode *node) { switchCircuit(false, getLocation(node)); // Checking to see if the IfStatementNode has an else part or not - bool hasElse = node->HasElse(); + bool const hasElse = node->HasElse(); // Create an SSA Value from the if statement condition const ASTExpressionNode *exprNode = node->GetExpression(); @@ -367,7 +440,7 @@ void QUIRGenQASM3Visitor::visit(const ASTIfStatementNode *node) { "set state to failed."); return; } - Value condition = conditionOrError.get(); + Value const condition = conditionOrError.get(); Value conditionBool; if (condition.getType() == builder.getI1Type()) { @@ -382,7 +455,7 @@ void QUIRGenQASM3Visitor::visit(const ASTIfStatementNode *node) { /*withElseRegion=*/hasElse); // Save current level OpBuilder - OpBuilder prevBuilder = builder; + OpBuilder const prevBuilder = builder; // Dictionary of SSA values used inside "if" std::unordered_map ifSsaValues = ssaValues; @@ -390,7 +463,7 @@ void QUIRGenQASM3Visitor::visit(const ASTIfStatementNode *node) { std::swap(ssaValues, ifSsaValues); // New OpBuilder for the if statement Region - OpBuilder ifRegionBuilder(ifOp.getThenRegion()); + OpBuilder const ifRegionBuilder(ifOp.getThenRegion()); builder = ifRegionBuilder; circuitParentBuilder = ifRegionBuilder; @@ -419,9 +492,9 @@ void QUIRGenQASM3Visitor::visit(const ASTIfStatementNode *node) { std::swap(ssaValues, elseSsaValues); // Save current level OpBuilder - OpBuilder elseBuilder = builder; + OpBuilder const elseBuilder = builder; - OpBuilder ElseRegionBuilder(ifOp.getElseRegion()); + OpBuilder const ElseRegionBuilder(ifOp.getElseRegion()); builder = ElseRegionBuilder; circuitParentBuilder = builder; @@ -451,8 +524,8 @@ void QUIRGenQASM3Visitor::visit(const ASTSwitchStatementNode *node) { switchCircuit(false, getLocation(node)); // Getting the number of cases we have - unsigned caseSize = node->GetNumCaseStatements(); - Location loc = getLocation(node); + unsigned const caseSize = node->GetNumCaseStatements(); + Location const loc = getLocation(node); // Getting all the case values DenseIntElementsAttr caseValuesAttr; @@ -467,7 +540,7 @@ void QUIRGenQASM3Visitor::visit(const ASTSwitchStatementNode *node) { auto caseOperands = node->GetCaseStatementsMap(); - ASTType quantityType = node->GetQuantityType(); + ASTType const quantityType = node->GetQuantityType(); llvm::Expected flagOrError(llvm::createStringError( llvm::inconvertibleErrorCode(), "Initializing error flag")); @@ -511,12 +584,12 @@ void QUIRGenQASM3Visitor::visit(const ASTSwitchStatementNode *node) { /*caseRegionsCount=*/caseSize); // Save current level OpBuilder - OpBuilder prevBuilder = builder; + OpBuilder const prevBuilder = builder; // Parse the default region. - Region &defaultRegion = switchOp.defaultRegion(); + Region &defaultRegion = switchOp.getDefaultRegion(); defaultRegion.emplaceBlock(); - OpBuilder defaultRegionBuilder(defaultRegion); + OpBuilder const defaultRegionBuilder(defaultRegion); builder = defaultRegionBuilder; circuitParentBuilder = defaultRegionBuilder; if (const ASTDefaultStatementNode *defaultStatementNode = @@ -533,9 +606,9 @@ void QUIRGenQASM3Visitor::visit(const ASTSwitchStatementNode *node) { // adding case regions int i = 0; for (auto const &[key, caseValue] : node->GetCaseStatementsMap()) { - Region &caseRegion = switchOp.caseRegions()[i]; + Region &caseRegion = switchOp.getCaseRegions()[i]; caseRegion.emplaceBlock(); - OpBuilder caseRegionBuilder(caseRegion); + OpBuilder const caseRegionBuilder(caseRegion); i++; builder = caseRegionBuilder; circuitParentBuilder = caseRegionBuilder; @@ -555,7 +628,7 @@ void QUIRGenQASM3Visitor::visit(const ASTWhileStatementNode *node) { switchCircuit(false, getLocation(node)); const ASTWhileLoopNode *loop = node->GetLoop(); - Location loc = getLocation(node); + Location const loc = getLocation(node); auto whileOp = builder.create(loc, TypeRange({}), ValueRange({})); @@ -569,7 +642,7 @@ void QUIRGenQASM3Visitor::visit(const ASTWhileStatementNode *node) { "set state to failed."); return; } - Value condition = conditionOrError.get(); + Value const condition = conditionOrError.get(); builder.create(loc, condition, ValueRange({})); @@ -626,16 +699,16 @@ void QUIRGenQASM3Visitor::visit(const ASTFunctionCallNode *node) { } operands.push_back(expressionOrError.get()); } - ValueRange operandRange(operands.data(), operands.size()); + ValueRange const operandRange(operands.data(), operands.size()); llvm::SmallVector resultTypes; if (node->ReturnsResult()) resultTypes.emplace_back( varHandler.resolveQUIRVariableType(node->GetResult())); - TypeRange resultRange(resultTypes.data(), resultTypes.size()); + TypeRange const resultRange(resultTypes.data(), resultTypes.size()); - auto callOp = builder.create(getLocation(node), node->GetCallName(), - resultRange, operandRange); + auto callOp = builder.create( + getLocation(node), node->GetCallName(), resultRange, operandRange); // fill the expression in case the call result is assigned to something if (node->ReturnsResult()) @@ -658,18 +731,19 @@ void QUIRGenQASM3Visitor::visit(const ASTGateDeclarationNode *node) { } auto inputsRef = ArrayRef(inputs.data(), inputs.size()); - auto func = - topLevelBuilder.create(getLocation(node), gateNode->GetName(), - builder.getFunctionType( - /*inputs=*/inputsRef, - /*results=*/ArrayRef())); + auto func = topLevelBuilder.create( + getLocation(node), gateNode->GetName(), + builder.getFunctionType( + /*inputs=*/inputsRef, + /*results=*/ArrayRef())); func.addEntryBlock(); // TODO this wants to be a symbol table that now enters a new scope // Store argument Values so we can reference them within this gate std::unordered_map gateSsaValues; unsigned i = 0; - MutableArrayRef arguments = func.getBody().getArguments(); + MutableArrayRef const arguments = + func.getBody().getArguments(); for (BlockArgument *arg = arguments.begin(); arg < arguments.end(); arg++) { if (i < numQubits) { gateSsaValues[gateNode->GetQubit(i)->GetGateQubitName()] = *arg; @@ -681,11 +755,11 @@ void QUIRGenQASM3Visitor::visit(const ASTGateDeclarationNode *node) { } // Save the current builder, temporarily swap the available Values - OpBuilder prevBuilder = builder; + OpBuilder const prevBuilder = builder; std::swap(ssaValues, gateSsaValues); // New OpBuilder for the gate declaration Region - OpBuilder gateDeclarationBuilder(func.getBody()); + OpBuilder const gateDeclarationBuilder(func.getBody()); builder = gateDeclarationBuilder; circuitParentBuilder = builder; @@ -696,7 +770,7 @@ void QUIRGenQASM3Visitor::visit(const ASTGateDeclarationNode *node) { if (buildingInCircuit) finishCircuit(); - builder.create(getLocation(node)); + builder.create(getLocation(node)); // Restore SSA Values and OpBuilder as we exit the function builder = prevBuilder; @@ -831,7 +905,7 @@ void QUIRGenQASM3Visitor::visit(const ASTUGateOpNode *node) { } auto resolveQCParam = resolveQCParamOrError.get(); - Value qubitRef = getCurrentValue(resolveQCParam); + Value const qubitRef = getCurrentValue(resolveQCParam); std::array angles; for (unsigned i = 0; i < fixedNumParams; i++) { @@ -886,7 +960,7 @@ void QUIRGenQASM3Visitor::visit(const ASTCXGateOpNode *node) { } auto resolveQCParam0 = resolveQCParam0OrError.get(); - Value controlQubit = getCurrentValue(resolveQCParam0); + Value const controlQubit = getCurrentValue(resolveQCParam0); auto resolveQCParam1OrError = resolveQCParam(gateNode, 1); if (!resolveQCParam1OrError) { @@ -896,7 +970,7 @@ void QUIRGenQASM3Visitor::visit(const ASTCXGateOpNode *node) { } auto resolveQCParam1 = resolveQCParam1OrError.get(); - Value targetQubit = getCurrentValue(resolveQCParam1); + Value const targetQubit = getCurrentValue(resolveQCParam1); builder.create(getLocation(node), controlQubit, targetQubit); } @@ -904,7 +978,7 @@ void QUIRGenQASM3Visitor::visit(const ASTCXGateOpNode *node) { void QUIRGenQASM3Visitor::visit(const ASTResetNode *node) { // do not insert reset into circuit due to BreakResetPass switchCircuit(false, getLocation(node)); - Value qubitRef = getCurrentValue(node->GetTarget()->GetName()); + Value const qubitRef = getCurrentValue(node->GetTarget()->GetName()); builder.create(getLocation(node), qubitRef); } @@ -940,12 +1014,12 @@ mlir::Value QUIRGenQASM3Visitor::createMeasurement(const ASTMeasureNode *node, } const ASTQubitContainerNode *qubitsNode = node->GetTarget(); - Value qubitRef = getCurrentValue(qubitsNode->GetName()); + Value const qubitRef = getCurrentValue(qubitsNode->GetName()); auto measureOp = builder.create(getLocation(node), builder.getI1Type(), qubitRef); if (emitAssignment) { auto *target = node->GetResult(); - unsigned resultIndex = + unsigned const resultIndex = node->GetResultSize() == 0 ? 0 : node->GetResultIndex(0); auto *identifier = target->GetIdentifier(); @@ -962,10 +1036,10 @@ mlir::Value QUIRGenQASM3Visitor::createMeasurement(const ASTMeasureNode *node, } varHandler.generateCBitSingleBitAssignment( - getLocation(node), identifier->GetName(), measureOp.outs().front(), + getLocation(node), identifier->GetName(), measureOp.getOuts().front(), resultIndex, identifier->GetBits()); } - return measureOp.outs().front(); + return measureOp.getOuts().front(); } void QUIRGenQASM3Visitor::visit(const ASTMeasureNode *node) { @@ -980,8 +1054,9 @@ void QUIRGenQASM3Visitor::visit(const ASTDelayStatementNode *node) { switch (delayNode->GetDelayType()) { case ASTTypeDuration: { // duration a = 10ns; delay[a] $q; - Value duration = getCurrentValue(delayNode->GetDurationNode()->GetName()); - Value qubitRef = + Value const duration = + getCurrentValue(delayNode->GetDurationNode()->GetName()); + Value const qubitRef = getCurrentValue(delayNode->GetDelayQubitIdentifier()->GetName()); builder.create(getLocation(delayNode), duration, qubitRef); break; @@ -1008,7 +1083,7 @@ void QUIRGenQASM3Visitor::visit(const ASTDelayStatementNode *node) { case ASTTypeStretch: { // stretch a; delay[a] $q; // stretch a; delay[a] $0, $1; - Value stretchRef = getCurrentValue( + Value const stretchRef = getCurrentValue( delayNode->GetStretchNode()->GetIdentifier()->GetName()); const ASTIdentifierList &idList = delayNode->GetOperandList(); @@ -1154,9 +1229,9 @@ void QUIRGenQASM3Visitor::visit(const ASTKernelNode *node) { attrs.emplace_back( builder.getStringAttr(SymbolTable::getVisibilityAttrName()), builder.getStringAttr("private")); - ArrayRef funcAttrs(attrs.data(), attrs.size()); + ArrayRef const funcAttrs(attrs.data(), attrs.size()); - topLevelBuilder.create( + topLevelBuilder.create( getLocation(node), node->GetName(), builder.getFunctionType(/*inputs=*/inputsRef, /*results=*/outputsRef), /*attrs=*/funcAttrs); @@ -1189,14 +1264,14 @@ ExpressionValueType QUIRGenQASM3Visitor::visit_(const ASTQubitContainerNode *node) { switchCircuit(false, getLocation(node)); const std::string &qId = node->GetName(); - int id = stoi(node->GetIdentifier()->GetQubitMnemonic()); + int const id = stoi(node->GetIdentifier()->GetQubitMnemonic()); const unsigned size = node->Size(); Value qubitRef = builder .create( getLocation(node), builder.getType(size), builder.getIntegerAttr(builder.getI32Type(), id)) - .res(); + .getRes(); ssaValues[qId] = qubitRef; return qubitRef; } @@ -1250,7 +1325,7 @@ ExpressionValueType QUIRGenQASM3Visitor::visit_(const ASTCBitNode *node) { // classical bit expression, so truncate to trailing (least-significant bits) // or take full string auto stringRepr = llvm::StringRef(node->AsString()).take_back(node->Size()); - llvm::APInt initializer(node->Size(), stringRepr, /* radix */ 2); + llvm::APInt const initializer(node->Size(), stringRepr, /* radix */ 2); // build an arbitrary-precision integer and let OQ3_CastOp take care of // initializing a classical register value from it. @@ -1302,7 +1377,7 @@ ExpressionValueType QUIRGenQASM3Visitor::visit_(const ASTStretchNode *node) { ExpressionValueType QUIRGenQASM3Visitor::visit_(const ASTIdentifierRefNode *node) { switchCircuit(false, getLocation(node)); - unsigned index = node->IsIndexed() ? node->GetIndex() : 0; + unsigned const index = node->IsIndexed() ? node->GetIndex() : 0; std::string const &variableName = node->GetIdentifier()->GetName(); if (varHandler.tracksVariable(variableName)) { @@ -1325,9 +1400,9 @@ QUIRGenQASM3Visitor::visit_(const ASTIdentifierRefNode *node) { } // TODO replace old case, incorrect handling - Value memRef = getCurrentValue(variableName); + Value const memRef = getCurrentValue(variableName); - Value indexRef = builder.create( + Value const indexRef = builder.create( getLocation(node), builder.getIndexAttr(index)); Value loadOpRef = @@ -1338,8 +1413,8 @@ QUIRGenQASM3Visitor::visit_(const ASTIdentifierRefNode *node) { ExpressionValueType QUIRGenQASM3Visitor::visit_(const ASTIdentifierNode *node) { switchCircuit(false, getLocation(node)); - llvm::StringRef variableName = node->GetName(); - mlir::Location location = getLocation(node); + llvm::StringRef const variableName = node->GetName(); + mlir::Location const location = getLocation(node); // old-style variable (i.e., still broken?!) if (!varHandler.tracksVariable(variableName)) @@ -1350,28 +1425,6 @@ ExpressionValueType QUIRGenQASM3Visitor::visit_(const ASTIdentifierNode *node) { using mlir::arith::CmpIPredicate; -static CmpIPredicate getComparisonPredicate(QASM::ASTOpType opType) { - switch (opType) { - case ASTOpTypeCompEq: - return CmpIPredicate::eq; - case ASTOpTypeCompNeq: - return CmpIPredicate::ne; - case ASTOpTypeLT: - return CmpIPredicate::slt; - case ASTOpTypeLE: - return CmpIPredicate::sle; - case ASTOpTypeGT: - return CmpIPredicate::sgt; - case ASTOpTypeGE: - return CmpIPredicate::sge; - - default: - llvm::errs() << "Cannot derive comparison predicate for opType " - << QASM::PrintOpTypeEnum(opType) << "\n"; - llvm_unreachable("Unimplemented."); - } -} - ExpressionValueType QUIRGenQASM3Visitor::handleAssign(const ASTBinaryOpNode *node) { const Location location = getLocation(node); @@ -1385,7 +1438,7 @@ QUIRGenQASM3Visitor::handleAssign(const ASTBinaryOpNode *node) { "set state to failed."); return rightRefOrError; } - Value rightRef = rightRefOrError.get(); + Value const rightRef = rightRefOrError.get(); llvm::Expected leftNameOrError = getExpressionName(left); if (!leftNameOrError) { @@ -1393,7 +1446,7 @@ QUIRGenQASM3Visitor::handleAssign(const ASTBinaryOpNode *node) { "the state to failed."); return createVoidValue(node); } - std::string leftName = leftNameOrError.get(); + std::string const leftName = leftNameOrError.get(); if (left->GetASTType() != ASTTypeIdentifier) { reportError(node, mlir::DiagnosticSeverity::Error) @@ -1425,7 +1478,7 @@ QUIRGenQASM3Visitor::handleAssign(const ASTBinaryOpNode *node) { "not set state to failed."); return leftRefOrError; } - Value leftRef = leftRefOrError.get(); + Value const leftRef = leftRefOrError.get(); Value opRef = rightRef; if (leftRef.getType() != rightRef.getType()) { @@ -1797,7 +1850,7 @@ ExpressionValueType QUIRGenQASM3Visitor::visit_(const ASTIntNode *node) { } const unsigned bits = node->GetBits(); - int64_t value = + int64_t const value = node->IsSigned() ? node->GetSignedValue() : node->GetUnsignedValue(); return builder.create( @@ -1833,11 +1886,11 @@ ExpressionValueType QUIRGenQASM3Visitor::visit_(const ASTMPIntegerNode *node) { "the state to failed."); return createVoidValue(node); } - std::string name = nameOrError.get(); + std::string const name = nameOrError.get(); const unsigned bits = node->GetBits(); - bool isSigned = node->IsSigned(); - int64_t value = isSigned ? node->ToSignedInt() : node->ToUnsignedInt(); + bool const isSigned = node->IsSigned(); + int64_t const value = isSigned ? node->ToSignedInt() : node->ToUnsignedInt(); return builder.create( getLocation(node), @@ -1856,7 +1909,7 @@ ExpressionValueType QUIRGenQASM3Visitor::visit_(const ASTFloatNode *node) { } const unsigned bits = node->GetBits(); - double value = node->GetValue(); + double const value = node->GetValue(); // MLIR does not support arbitrary precision float types mlir::Type type; @@ -1943,7 +1996,7 @@ ExpressionValueType QUIRGenQASM3Visitor::visit_(const ASTMPComplexNode *node) { "the state to failed."); return createVoidValue(node); } - std::string name = nameOrError.get(); + std::string const name = nameOrError.get(); if (ssaValues.find(name) != ssaValues.end()) { reportError(node, mlir::DiagnosticSeverity::Error) @@ -1959,13 +2012,13 @@ ExpressionValueType QUIRGenQASM3Visitor::visit_(const ASTMPComplexNode *node) { assert(hasFailed && "Error in real value"); return realOrError; } - Value real = realOrError.get(); + Value const real = realOrError.get(); if (!imagOrError) { assert(hasFailed && "Error in imag value"); return imagOrError; } - Value imag = imagOrError.get(); + Value const imag = imagOrError.get(); return builder.create( getLocation(node), ComplexType::get(real.getType()), real, imag); @@ -2055,7 +2108,7 @@ QUIRGenQASM3Visitor::visit_(const ASTCastExpressionNode *node) { assert(hasFailed && "Expected visit functions to signal error state"); return std::move(expression); } - mlir::Value operandRef = expression.get(); + mlir::Value const operandRef = expression.get(); Value opRef = builder.create( getLocation(node), getCastDestinationType(node, builder), operandRef); @@ -2064,7 +2117,8 @@ QUIRGenQASM3Visitor::visit_(const ASTCastExpressionNode *node) { } mlir::Value QUIRGenQASM3Visitor::createVoidValue(mlir::Location location) { - return builder.create(location, builder.getUnitAttr()); + return builder.create( + location, builder.getZeroAttr(builder.getI1Type())); } mlir::Value QUIRGenQASM3Visitor::createVoidValue(QASM::ASTBase const *node) { @@ -2084,9 +2138,11 @@ void QUIRGenQASM3Visitor::startCircuit(mlir::Location location) { auto *block = currentCircuitOp.addEntryBlock(); if (debugCircuits) - llvm::errs() << "Start Circuit " << currentCircuitOp.sym_name() << "\n"; + llvm::errs() << "Start Circuit " << currentCircuitOp.getSymName() << "\n"; + + OpBuilder circuitBuilder = + OpBuilder::atBlockBegin(¤tCircuitOp.getBody().front()); - OpBuilder circuitBuilder(currentCircuitOp.getBody()); circuitBuilder.create(location, ValueRange({})); circuitBuilder.setInsertionPointToStart(block); @@ -2105,7 +2161,7 @@ void QUIRGenQASM3Visitor::finishCircuit() { return; if (debugCircuits) - llvm::errs() << "Finish Circuit " << currentCircuitOp.sym_name() << "\n"; + llvm::errs() << "Finish Circuit " << currentCircuitOp.getSymName() << "\n"; // check if the first Op in the circuit is a ReturnOp // if so - no ops were added - erase circuit and return @@ -2145,8 +2201,8 @@ void QUIRGenQASM3Visitor::finishCircuit() { return; for (auto *user : value.getUsers()) { if (currentCircuitOp->isAncestor(user)) { - auto arg = currentCircuitOp.body().front().addArgument(value.getType(), - value.getLoc()); + auto arg = currentCircuitOp.getBody().front().addArgument( + value.getType(), value.getLoc()); value.replaceUsesWithIf(arg, [&](OpOperand &operand) { return (operand.getOwner()->getParentOp() == currentCircuitOp); }); diff --git a/lib/Frontend/OpenQASM3/QUIRVariableBuilder.cpp b/lib/Frontend/OpenQASM3/QUIRVariableBuilder.cpp index 65090cbb9..293a3bda8 100644 --- a/lib/Frontend/OpenQASM3/QUIRVariableBuilder.cpp +++ b/lib/Frontend/OpenQASM3/QUIRVariableBuilder.cpp @@ -24,21 +24,28 @@ #include "Dialect/OQ3/IR/OQ3Ops.h" #include "Dialect/QCS/IR/QCSOps.h" #include "Dialect/QUIR/IR/QUIROps.h" - #include "Dialect/QUIR/IR/QUIRTypes.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" + +#include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/BuiltinTypes.h" +#include "mlir/IR/Location.h" #include "mlir/IR/SymbolTable.h" - -#include "qasm/AST/ASTTypeEnums.h" +#include "mlir/IR/Value.h" +#include "mlir/Support/LLVM.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" +#include +#include #include -#include -#include +#include +#include +#include +#include namespace qssc::frontend::openqasm3 { @@ -48,7 +55,7 @@ void QUIRVariableBuilder::generateVariableDeclaration( // variables are symbols and thus need to be placed directly in a surrounding // Op that contains a symbol table. - mlir::OpBuilder::InsertionGuard g(builder); + mlir::OpBuilder::InsertionGuard const g(builder); auto *symbolTableOp = mlir::SymbolTable::getNearestSymbolTable( builder.getInsertionBlock()->getParentOp()); assert(symbolTableOp && @@ -66,9 +73,9 @@ void QUIRVariableBuilder::generateVariableDeclaration( lastDeclaration[surroundingModuleOp] = declareOp; // save this to insert after if (isInputVariable) - declareOp.inputAttr(builder.getUnitAttr()); + declareOp.setInputAttr(builder.getUnitAttr()); if (isOutputVariable) - declareOp.outputAttr(builder.getUnitAttr()); + declareOp.setOutputAttr(builder.getUnitAttr()); variables.emplace(variableName.str(), type); } @@ -76,7 +83,7 @@ void QUIRVariableBuilder::generateParameterDeclaration( mlir::Location location, llvm::StringRef variableName, mlir::Type type, mlir::Value assignedValue) { - mlir::OpBuilder::InsertionGuard g(builder); + mlir::OpBuilder::InsertionGuard const g(builder); auto *symbolTableOp = mlir::SymbolTable::getNearestSymbolTable( builder.getInsertionBlock()->getParentOp()); assert(symbolTableOp && @@ -93,7 +100,7 @@ void QUIRVariableBuilder::generateParameterDeclaration( declareParameterOp = getClassicalBuilder().create( location, variableName.str(), - builder.getType(64), constantOp.value()); + builder.getType(64), constantOp.getValue()); } // if the source is a arith::ConstantOp cast to angle diff --git a/lib/HAL/Compile/TargetCompilationManager.cpp b/lib/HAL/Compile/TargetCompilationManager.cpp index 1438c38f1..556283b56 100644 --- a/lib/HAL/Compile/TargetCompilationManager.cpp +++ b/lib/HAL/Compile/TargetCompilationManager.cpp @@ -14,10 +14,20 @@ // //===----------------------------------------------------------------------===// +#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/MLIRContext.h" +#include "mlir/IR/Operation.h" +#include "mlir/IR/OperationSupport.h" +#include "mlir/Support/LogicalResult.h" + +#include "llvm/ADT/StringRef.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" #include "HAL/Compile/TargetCompilationManager.h" +#include "HAL/TargetSystem.h" using namespace qssc::hal::compile; @@ -44,9 +54,10 @@ struct TargetCompilationManagerOptions { llvm::cl::desc("Print IR after failure of applying target compilation"), llvm::cl::init(false)}; }; -} // namespace -static llvm::ManagedStatic options; +llvm::ManagedStatic options; + +} // anonymous namespace void qssc::hal::compile::registerTargetCompilationManagerCLOptions() { // Make sure that the options struct has been constructed. @@ -71,10 +82,10 @@ TargetCompilationManager::TargetCompilationManager( qssc::hal::TargetSystem &target, mlir::MLIRContext *context) : target(target), context(context) {} -llvm::Error TargetCompilationManager::walkTarget( +llvm::Error TargetCompilationManager::walkTargetModules( Target *target, mlir::ModuleOp targetModuleOp, - const WalkTargetFunction &walkFunc, - const WalkTargetFunction &postChildrenCallbackFunc) { + const WalkTargetModulesFunction &walkFunc, + const WalkTargetModulesFunction &postChildrenCallbackFunc) { // Call the input function for the walk on the target if (auto err = walkFunc(target, targetModuleOp)) return err; @@ -84,8 +95,8 @@ llvm::Error TargetCompilationManager::walkTarget( auto childModuleOp = child->getModule(targetModuleOp); if (auto err = childModuleOp.takeError()) return err; - if (auto err = walkTarget(child, *childModuleOp, walkFunc, - postChildrenCallbackFunc)) + if (auto err = walkTargetModules(child, *childModuleOp, walkFunc, + postChildrenCallbackFunc)) return err; } @@ -95,6 +106,22 @@ llvm::Error TargetCompilationManager::walkTarget( return llvm::Error::success(); } +llvm::Error +TargetCompilationManager::walkTarget(Target *target, + const WalkTargetFunction &walkFunc) { + // Call the input function for the walk on the target + if (auto err = walkFunc(target)) + return err; + + for (auto *child : target->getChildren()) { + // Recurse on the target + if (auto err = walkTarget(child, walkFunc)) + return err; + } + + return llvm::Error::success(); +} + void TargetCompilationManager::enableIRPrinting( bool printBeforeAllTargetPasses, bool printAfterAllTargetPasses, bool printBeforeAllTargetPayload, bool printAfterTargetCompileFailure) { @@ -110,6 +137,7 @@ void TargetCompilationManager::printIR(llvm::StringRef msg, mlir::Operation *op, out << msg; out << " //----- //"; out << "\n"; - op->print(out); + mlir::OpPrintingFlags flags = mlir::OpPrintingFlags(); + op->print(out, flags.useLocalScope()); out << "\n"; } diff --git a/lib/HAL/Compile/ThreadedCompilationManager.cpp b/lib/HAL/Compile/ThreadedCompilationManager.cpp index 229911617..8a26233df 100644 --- a/lib/HAL/Compile/ThreadedCompilationManager.cpp +++ b/lib/HAL/Compile/ThreadedCompilationManager.cpp @@ -16,7 +16,27 @@ #include "HAL/Compile/ThreadedCompilationManager.h" +#include "HAL/Compile/TargetCompilationManager.h" +#include "HAL/TargetSystem.h" +#include "Payload/Payload.h" + +#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/DialectRegistry.h" +#include "mlir/IR/MLIRContext.h" +#include "mlir/IR/Operation.h" #include "mlir/IR/Threading.h" +#include "mlir/Pass/PassManager.h" +#include "mlir/Support/LogicalResult.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include +#include +#include +#include using namespace qssc; using namespace qssc::hal::compile; @@ -31,10 +51,10 @@ const std::string ThreadedCompilationManager::getName() const { return "ThreadedCompilationManager"; } -llvm::Error ThreadedCompilationManager::walkTargetThreaded( +llvm::Error ThreadedCompilationManager::walkTargetModulesThreaded( Target *target, mlir::ModuleOp targetModuleOp, - const WalkTargetFunction &walkFunc, - const WalkTargetFunction &postChildrenCallbackFunc) { + const WalkTargetModulesFunction &walkFunc, + const WalkTargetModulesFunction &postChildrenCallbackFunc) { if (auto err = walkFunc(target, targetModuleOp)) return err; @@ -53,7 +73,8 @@ llvm::Error ThreadedCompilationManager::walkTargetThreaded( auto parallelWalkFunc = [&](Target *childTarget) { // Recurse on this target's children in a depth first fashion. - if (auto err = walkTargetThreaded(childTarget, childrenModules[childTarget], + if (auto err = + walkTargetModulesThreaded(childTarget, childrenModules[childTarget], walkFunc, postChildrenCallbackFunc)) { llvm::errs() << err << "\n"; return mlir::failure(); @@ -77,16 +98,102 @@ llvm::Error ThreadedCompilationManager::walkTargetThreaded( return llvm::Error::success(); } +llvm::Error ThreadedCompilationManager::walkTargetThreaded( + Target *target, const WalkTargetFunction &walkFunc) { + + if (auto err = walkFunc(target)) + return err; + + auto parallelWalkFunc = [&](Target *childTarget) { + // Recurse on this target's children in a depth first fashion. + + if (auto err = walkTargetThreaded(childTarget, walkFunc)) { + llvm::errs() << err << "\n"; + return mlir::failure(); + } + + return mlir::success(); + }; + + // By utilizing the MLIR parallelism methods, we automatically inherit the + // multiprocessing settings from the context. + if (mlir::failed(mlir::failableParallelForEach( + getContext(), target->getChildren(), parallelWalkFunc))) + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Problems encountered while walking children of target " + + target->getName()); + + return llvm::Error::success(); +} + llvm::Error -ThreadedCompilationManager::buildTargetPassManager(mlir::PassManager &pm) { - return pmBuilder(pm); +ThreadedCompilationManager::buildTargetPassManagers_(Target &target) { + + auto threadedBuildTargetPassManager = + [&](hal::Target *target) -> llvm::Error { + auto &pm = createTargetPassManager_(target); + + if (auto err = pmBuilder(pm)) + return err; + + if (auto err = target->addPasses(pm)) + return err; + + registerPassManagerWithContext_(pm); + + return llvm::Error::success(); + }; + + auto err = + walkTargetThreaded(&getTargetSystem(), threadedBuildTargetPassManager); + return err; +} + +// Mirroring mlir::PassManager::run() we register all of the pass's dependent +// dialects with the context in a thread-safe way to prevent issues with the +// default non-threadsafe modification of the dialect registry performed by the +// pass manager. See: +// https://github.com/llvm/llvm-project/blob/9423e459875b0dcdf24975976838d651a92f1bdb/mlir/lib/Pass/Pass.cpp#L840-L845 +void ThreadedCompilationManager::registerPassManagerWithContext_( + mlir::PassManager &pm) { + mlir::DialectRegistry dependentDialects; + pm.getDependentDialects(dependentDialects); + auto *context = getContext(); + + // NOLINTNEXTLINE(clang-diagnostic-ctad-maybe-unsupported) + std::unique_lock const lock(contextMutex_); + context->appendDialectRegistry(dependentDialects); + for (llvm::StringRef const name : dependentDialects.getDialectNames()) + context->getOrLoadDialect(name); +} + +mlir::PassManager & +ThreadedCompilationManager::getTargetPassManager_(Target *target) { + // NOLINTNEXTLINE(clang-diagnostic-ctad-maybe-unsupported) + std::shared_lock const lock(targetPassManagersMutex_); + return targetPassManagers_.at(target); +} + +mlir::PassManager & +ThreadedCompilationManager::createTargetPassManager_(Target *target) { + // NOLINTNEXTLINE(clang-diagnostic-ctad-maybe-unsupported) + std::unique_lock const lock(targetPassManagersMutex_); + return targetPassManagers_.emplace(target, getContext()).first->second; } llvm::Error ThreadedCompilationManager::compileMLIR(mlir::ModuleOp moduleOp) { + auto &target = getTargetSystem(); + + /// Build target pass managers prior to compilation + /// to ensure thread safety + if (auto err = buildTargetPassManagers_(target)) + return err; + auto threadedCompileMLIRTarget = [&](hal::Target *target, mlir::ModuleOp targetModuleOp) -> llvm::Error { - if (auto err = compileMLIRTarget(*target, targetModuleOp)) + if (auto err = compileMLIRTarget_(*target, targetModuleOp)) return err; return llvm::Error::success(); }; @@ -97,25 +204,20 @@ llvm::Error ThreadedCompilationManager::compileMLIR(mlir::ModuleOp moduleOp) { return llvm::Error::success(); }; - return walkTargetThreaded(&getTargetSystem(), moduleOp, - threadedCompileMLIRTarget, - postChildrenEmitToPayload); + auto err = walkTargetModulesThreaded( + &target, moduleOp, threadedCompileMLIRTarget, postChildrenEmitToPayload); + return err; } llvm::Error -ThreadedCompilationManager::compileMLIRTarget(Target &target, - mlir::ModuleOp targetModuleOp) { - mlir::PassManager pm(getContext()); - if (auto err = buildTargetPassManager(pm)) - return err; - - if (auto err = target.addPasses(pm)) - return err; - +ThreadedCompilationManager::compileMLIRTarget_(Target &target, + mlir::ModuleOp targetModuleOp) { if (getPrintBeforeAllTargetPasses()) printIR("IR dump before running passes for target " + target.getName(), targetModuleOp, llvm::outs()); + mlir::PassManager &pm = getTargetPassManager_(&target); + if (mlir::failed(pm.run(targetModuleOp))) { if (getPrintAfterTargetCompileFailure()) printIR("IR dump after failure emitting payload for target " + @@ -137,10 +239,17 @@ llvm::Error ThreadedCompilationManager::compilePayload(mlir::ModuleOp moduleOp, qssc::payload::Payload &payload, bool doCompileMLIR) { + auto &target = getTargetSystem(); + + /// Build target pass managers prior to compilation + /// to ensure thread safety + if (auto err = buildTargetPassManagers_(target)) + return err; + auto threadedCompilePayloadTarget = [&](hal::Target *target, mlir::ModuleOp targetModuleOp) -> llvm::Error { - if (auto err = compilePayloadTarget(*target, targetModuleOp, payload, - doCompileMLIR)) + if (auto err = compilePayloadTarget_(*target, targetModuleOp, payload, + doCompileMLIR)) return err; return llvm::Error::success(); }; @@ -152,17 +261,18 @@ ThreadedCompilationManager::compilePayload(mlir::ModuleOp moduleOp, return llvm::Error::success(); }; - return walkTargetThreaded(&getTargetSystem(), moduleOp, - threadedCompilePayloadTarget, - postChildrenEmitToPayload); + auto err = + walkTargetModulesThreaded(&target, moduleOp, threadedCompilePayloadTarget, + postChildrenEmitToPayload); + return err; } -llvm::Error ThreadedCompilationManager::compilePayloadTarget( +llvm::Error ThreadedCompilationManager::compilePayloadTarget_( Target &target, mlir::ModuleOp targetModuleOp, qssc::payload::Payload &payload, bool doCompileMLIR) { if (doCompileMLIR) - if (auto err = compileMLIRTarget(target, targetModuleOp)) + if (auto err = compileMLIRTarget_(target, targetModuleOp)) return err; if (getPrintBeforeAllTargetPayload()) @@ -178,3 +288,10 @@ llvm::Error ThreadedCompilationManager::compilePayloadTarget( } return llvm::Error::success(); } + +void ThreadedCompilationManager::printIR(llvm::StringRef msg, + mlir::Operation *op, + llvm::raw_ostream &out) { + const std::lock_guard lock(printIRMutex_); + TargetCompilationManager::printIR(msg, op, out); +} diff --git a/lib/HAL/PassRegistration.cpp b/lib/HAL/PassRegistration.cpp index 5c6c9ed4e..558cb1efe 100644 --- a/lib/HAL/PassRegistration.cpp +++ b/lib/HAL/PassRegistration.cpp @@ -17,6 +17,10 @@ #include "HAL/PassRegistration.h" #include "HAL/TargetSystemRegistry.h" +#include "llvm/Support/Error.h" + +#include + using namespace qssc; using namespace qssc::hal; diff --git a/lib/HAL/TargetSystem.cpp b/lib/HAL/TargetSystem.cpp index ace196eed..acda39483 100644 --- a/lib/HAL/TargetSystem.cpp +++ b/lib/HAL/TargetSystem.cpp @@ -14,10 +14,18 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/SmallString.h" +#include "HAL/TargetSystem.h" #include "Dialect/QUIR/Utils/Utils.h" -#include "HAL/TargetSystem.h" + +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/BuiltinOps.h" + +#include "llvm/Support/Error.h" + +#include +#include +#include using namespace qssc::hal; using namespace qssc::payload; diff --git a/lib/HAL/TargetSystemInfo.cpp b/lib/HAL/TargetSystemInfo.cpp index c9342e37b..b3d1ad5e3 100644 --- a/lib/HAL/TargetSystemInfo.cpp +++ b/lib/HAL/TargetSystemInfo.cpp @@ -14,10 +14,21 @@ #include "HAL/TargetSystemInfo.h" +#include "HAL/TargetSystem.h" + +#include "mlir/IR/MLIRContext.h" + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" + #include +#include +#include // Inject static initialization headers from targets. We need to include them in // a translation unit that is not being optimized (removed) by the compiler. +// NOLINTNEXTLINE: Required for target initializations even if not used #include "Targets.inc" using namespace qssc::hal::registry; @@ -43,7 +54,7 @@ TargetSystemInfo::~TargetSystemInfo() = default; llvm::Expected TargetSystemInfo::createTarget( mlir::MLIRContext *context, - llvm::Optional configuration) { + std::optional configuration) { auto target = PluginInfo::createPluginInstance(configuration); if (!target) return target.takeError(); diff --git a/lib/HAL/TargetSystemRegistry.cpp b/lib/HAL/TargetSystemRegistry.cpp index 6d8b14ffc..fc5c437cf 100644 --- a/lib/HAL/TargetSystemRegistry.cpp +++ b/lib/HAL/TargetSystemRegistry.cpp @@ -14,6 +14,19 @@ #include "HAL/TargetSystemRegistry.h" +#include "HAL/TargetSystem.h" +#include "HAL/TargetSystemInfo.h" +#include "Payload/Payload.h" + +#include "mlir/IR/BuiltinOps.h" +#include "mlir/Pass/PassManager.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" + +#include +#include + using namespace qssc::hal::registry; namespace { @@ -38,7 +51,7 @@ TargetSystemInfo *TargetSystemRegistry::nullTargetSystemInfo() { static auto nullTarget = std::make_unique( "NullTarget", "A no-op target used by default unless a real target is specified.", - [](llvm::Optional config) { + [](std::optional config) { return std::make_unique(); }, []() { return llvm::Error::success(); }, diff --git a/lib/Payload/Payload.cpp b/lib/Payload/Payload.cpp index d429a2b4d..6c81472f1 100644 --- a/lib/Payload/Payload.cpp +++ b/lib/Payload/Payload.cpp @@ -18,17 +18,17 @@ // //===----------------------------------------------------------------------===// -#include -#include -#include -#include - -#include "nlohmann/json.hpp" - #include "Payload/Payload.h" +#include +#include +#include +#include +#include + // Inject static initialization headers from payloads. We need to include them // in a translation unit that is not being optimized (removed) by the compiler. +// NOLINTNEXTLINE: Required for payload initializations even if not used #include "Payloads.inc" using namespace qssc::payload; @@ -51,6 +51,7 @@ auto Payload::getFile(const char *fName) -> std::string * { auto Payload::orderedFileNames() -> std::vector { const std::lock_guard lock(_mtx); std::vector ret; + ret.reserve(files.size()); for (auto &filePair : files) ret.emplace_back(filePair.first); std::sort(ret.begin(), ret.end()); diff --git a/lib/Payload/ZipPayload/PatchableZipPayload.cpp b/lib/Payload/ZipPayload/PatchableZipPayload.cpp index ecd6f2a19..f5d1d6d54 100644 --- a/lib/Payload/ZipPayload/PatchableZipPayload.cpp +++ b/lib/Payload/ZipPayload/PatchableZipPayload.cpp @@ -20,14 +20,25 @@ //===----------------------------------------------------------------------===// #include "Payload/PatchableZipPayload.h" + #include "ZipUtil.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include #include -#include +#include +#include +#include +#include +#include +#include #include +#include namespace qssc::payload { @@ -86,22 +97,24 @@ llvm::Error PatchableZipPayload::ensureOpen() { zip_error_init(&zipError); if (enableInMemory) { - zip_source_t *zs; - if ((zs = zip_source_buffer_create(path.data(), path.length(), 0, - &zipError)) == nullptr) { + zip_source_t *zs = + zip_source_buffer_create(path.data(), path.length(), 0, &zipError); + if (zs == nullptr) { zip_error_set(&zipError, errorCode, errno); retVal = extractLibZipError( "Failure while opening in memory circuit module (zip) ", zipError); } - if ((zip = zip_open_from_source(zs, 0, &zipError)) == nullptr) { + zip = zip_open_from_source(zs, 0, &zipError); + if (zip == nullptr) { zip_error_set(&zipError, errorCode, errno); retVal = extractLibZipError( "Failure while opening in memory circuit module (zip) ", zipError); } inMemoryZipSource = zs; } else { - if ((zip = zip_open(path.c_str(), 0, &errorCode)) == nullptr) { + zip = zip_open(path.c_str(), 0, &errorCode); + if (zip == nullptr) { zip_error_set(&zipError, errorCode, errno); retVal = extractLibZipError( "Failure while opening circuit module (zip) file ", zipError); @@ -131,7 +144,8 @@ llvm::Error PatchableZipPayload::addFileToZip(zip_t *zip, if (src == nullptr) return extractLibZipError("Creating zip source from data buffer", err); - if (int idx = zip_file_add(zip, path.c_str(), src, ZIP_FL_OVERWRITE) < 0) { + if (int const idx = + zip_file_add(zip, path.c_str(), src, ZIP_FL_OVERWRITE) < 0) { if (idx < 0) { auto *archiveErr = zip_get_error(zip); return extractLibZipError("Adding or replacing file to zip", *archiveErr); @@ -180,9 +194,10 @@ llvm::Error PatchableZipPayload::writeString(std::string *outputString) { return llvm::make_error("outputString buffer is null", llvm::inconvertibleErrorCode()); - llvm::Optional outStringStream; + std::optional outStringStream; outStringStream.emplace(*outputString); - llvm::raw_ostream *ostream = outStringStream.getPointer(); + llvm::raw_ostream *ostream = std::addressof(outStringStream.value()); + ; if (inMemoryZipSource) { // read from in memory source @@ -198,7 +213,7 @@ llvm::Error PatchableZipPayload::writeString(std::string *outputString) { } else { // re-read file from disk std::ostringstream buf; - std::ifstream input(path.c_str()); + std::ifstream const input(path.c_str()); buf << input.rdbuf(); ostream->write(buf.str().c_str(), buf.str().length()); } @@ -209,7 +224,7 @@ llvm::Error PatchableZipPayload::writeString(std::string *outputString) { llvm::Expected PatchableZipPayload::readMember(llvm::StringRef path, bool markForWriteBack) { - auto pathStr = path.operator std::string(); + std::string pathStr = path.str(); auto pos = files.find(pathStr); if (pos != files.end()) @@ -220,7 +235,7 @@ PatchableZipPayload::readMember(llvm::StringRef path, bool markForWriteBack) { // in memory payload does not have leading directory so attempt to remove auto index = path.find("/") + 1; path = path.substr(index); - pathStr = path.operator std::string(); + pathStr = path.str(); } zip_stat_t zs; @@ -258,8 +273,8 @@ PatchableZipPayload::readMember(llvm::StringRef path, bool markForWriteBack) { return extractLibZipError("Closing file in zip", err); } - auto ins = files.emplace(std::make_pair( - pathStr, TrackedFile{markForWriteBack, std::move(fileBuf)})); + auto ins = + files.emplace(pathStr, TrackedFile{markForWriteBack, std::move(fileBuf)}); assert(ins.second && "expect insertion, i.e., had not been present before."); diff --git a/lib/Payload/ZipPayload/ZipPayload.cpp b/lib/Payload/ZipPayload/ZipPayload.cpp index a30036792..6836ff98f 100644 --- a/lib/Payload/ZipPayload/ZipPayload.cpp +++ b/lib/Payload/ZipPayload/ZipPayload.cpp @@ -18,33 +18,46 @@ /// //===----------------------------------------------------------------------===// -#include +#include "ZipPayload.h" + +#include "Payload/Payload.h" +#include "ZipUtil.h" + +#include "Config.h" +#include "Payload/PayloadRegistry.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_os_ostream.h" +#include "llvm/Support/raw_ostream.h" + #include +#include +#include #include +#include +#include +#include +#include +#include #include +#include +// NOLINTNEXTLINE(misc-include-cleaner) #include -#include - -#include "nlohmann/json.hpp" +#include #include - -#include "Config.h" -#include "ZipPayload.h" -#include "ZipUtil.h" - -#include "Payload/PayloadRegistry.h" +#include using namespace qssc::payload; namespace fs = std::filesystem; int qssc::payload::init() { const char *name = "ZIP"; - bool registered = registry::PayloadRegistry::registerPlugin( + bool const registered = registry::PayloadRegistry::registerPlugin( name, name, "Payload that generates zip file with .qem extension.", - [](llvm::Optional config) + [](std::optional config) -> llvm::Expected> { - if (config.hasValue()) - return std::make_unique(config.getValue()); + if (config.has_value()) + return std::make_unique(config.value()); return std::make_unique(); }); return registered ? 0 : -1; @@ -52,8 +65,8 @@ int qssc::payload::init() { // creates a manifest json file and adds it to the file map void ZipPayload::addManifest() { - std::lock_guard lock(_mtx); - std::string manifest_fname = "manifest/manifest.json"; + std::lock_guard const lock(_mtx); + std::string const manifest_fname = "manifest/manifest.json"; nlohmann::json manifest; manifest["version"] = QSSC_VERSION; manifest["contents_path"] = prefix; @@ -61,12 +74,12 @@ void ZipPayload::addManifest() { } void ZipPayload::addFile(llvm::StringRef filename, llvm::StringRef str) { - std::lock_guard lock(_mtx); + std::lock_guard const lock(_mtx); files[filename.str()] = str; } void ZipPayload::writePlain(const std::string &dirName) { - std::lock_guard lock(_mtx); + std::lock_guard const lock(_mtx); for (const auto &filePair : files) { fs::path fName(dirName); fName /= filePair.first; @@ -83,7 +96,7 @@ void ZipPayload::writePlain(const std::string &dirName) { } void ZipPayload::writePlain(llvm::raw_ostream &stream) { - std::vector orderedNames = orderedFileNames(); + std::vector const orderedNames = orderedFileNames(); stream << "------------------------------------------\n"; stream << "Plaintext payload: " << prefix << "\n"; stream << "------------------------------------------\n"; @@ -114,14 +127,17 @@ void setFilePermissions(zip_int64_t fileIndex, fs::path &fName, &attributes); if (opsys == ZIP_OPSYS_UNIX) { zip_uint32_t mask = UINT32_MAX; // all 1s for negative mask - mask ^= (S_IWGRP << 16); // turn off write for the group - mask ^= (S_IWOTH << 16); // turn off write for others + // NOLINTNEXTLINE(misc-include-cleaner) + mask ^= (S_IWGRP << 16); // turn off write for the group + // NOLINTNEXTLINE(misc-include-cleaner) + mask ^= (S_IWOTH << 16); // turn off write for others // apply negative write mask attributes &= mask; // if executable turn on S_IXUSR if (fName.has_extension() && fName.extension() == ".sh") + // NOLINTNEXTLINE(misc-include-cleaner) attributes |= (S_IXUSR << 16); // turn on execute for user // set new attributes @@ -146,8 +162,8 @@ void ZipPayload::writeZip(llvm::raw_ostream &stream) { zip_error_init(&error); // open a zip source, buffer is allocated internally to libzip - if ((new_archive_src = zip_source_buffer_create(nullptr, 0, 0, &error)) == - nullptr) { + new_archive_src = zip_source_buffer_create(nullptr, 0, 0, &error); + if (new_archive_src == nullptr) { llvm::errs() << "Can't create zip source for new archive: " << zip_error_strerror(&error) << "\n"; zip_error_fini(&error); @@ -158,8 +174,8 @@ void ZipPayload::writeZip(llvm::raw_ostream &stream) { zip_source_keep(new_archive_src); // create and open an archive from the new archive source - if ((new_archive = zip_open_from_source(new_archive_src, ZIP_TRUNCATE, - &error)) == nullptr) { + new_archive = zip_open_from_source(new_archive_src, ZIP_TRUNCATE, &error); + if (new_archive == nullptr) { llvm::errs() << "Can't create/open an archive from the new archive source: " << zip_error_strerror(&error) << "\n"; zip_source_free(new_archive_src); @@ -180,9 +196,9 @@ void ZipPayload::writeZip(llvm::raw_ostream &stream) { zip_error_init(&error); // first create a zip source from the file data - if ((file_src = zip_source_buffer_create(files[fName].c_str(), - files[fName].size(), 0, &error)) == - nullptr) { + file_src = zip_source_buffer_create(files[fName].c_str(), + files[fName].size(), 0, &error); + if (file_src == nullptr) { llvm::errs() << "Can't create zip source for " << fName << " : " << zip_error_strerror(&error) << "\n"; zip_error_fini(&error); @@ -191,9 +207,9 @@ void ZipPayload::writeZip(llvm::raw_ostream &stream) { zip_error_fini(&error); // now add it to the archive - zip_int64_t fileIndex = -1; - if ((fileIndex = zip_file_add(new_archive, fName.c_str(), file_src, - ZIP_FL_OVERWRITE)) < 0) { + zip_int64_t const fileIndex = + zip_file_add(new_archive, fName.c_str(), file_src, ZIP_FL_OVERWRITE); + if (fileIndex < 0) { llvm::errs() << "Problem adding file " << fName << " to archive: " << zip_strerror(new_archive) << "\n"; continue; diff --git a/lib/Payload/ZipPayload/ZipUtil.cpp b/lib/Payload/ZipPayload/ZipUtil.cpp index 0bd8d7c72..247380e8e 100644 --- a/lib/Payload/ZipPayload/ZipUtil.cpp +++ b/lib/Payload/ZipPayload/ZipUtil.cpp @@ -22,6 +22,11 @@ #include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include + char *qssc::payload::read_zip_src_to_buffer(zip_source_t *zip_src, zip_int64_t &sz) { //===---- Reopen for copying ----===// diff --git a/lib/QSSC.cpp b/lib/QSSC.cpp index 5739a3d5d..3f245abd6 100644 --- a/lib/QSSC.cpp +++ b/lib/QSSC.cpp @@ -21,15 +21,13 @@ #include "QSSC.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/Path.h" - #include "Config.h" #include "HAL/TargetSystem.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Path.h" + #include #include @@ -53,7 +51,7 @@ namespace { llvm::StringRef _getResourcesDir() { if (char *env = getenv("QSSC_RESOURCES")) { /* strings returned by getenv may be invalidated, so keep a copy */ - static std::string resourcesDir{env}; + static std::string const resourcesDir{env}; return resourcesDir; } @@ -64,7 +62,7 @@ llvm::StringRef _getResourcesDir() { }; // namespace llvm::StringRef qssc::getResourcesDir() { - static llvm::StringRef resourcesDir = _getResourcesDir(); + static llvm::StringRef const resourcesDir = _getResourcesDir(); return resourcesDir; } diff --git a/lib/Utils/CMakeLists.txt b/lib/Utils/CMakeLists.txt index 755b1615a..df935041f 100644 --- a/lib/Utils/CMakeLists.txt +++ b/lib/Utils/CMakeLists.txt @@ -12,5 +12,5 @@ set(SOURCES DebugIndent.cpp) -add_library(Utils ${SOURCES}) -target_link_libraries(Utils ${BOOST_LIBRARIES}) +add_library(QSSCUtils ${SOURCES}) +target_link_libraries(QSSCUtils ${BOOST_LIBRARIES}) diff --git a/python_lib/qss_compiler/lib.cpp b/python_lib/qss_compiler/lib.cpp index ce03dc87d..37664550a 100644 --- a/python_lib/qss_compiler/lib.cpp +++ b/python_lib/qss_compiler/lib.cpp @@ -51,20 +51,20 @@ // https://pybind11.readthedocs.io/en/stable/ //===----------------------------------------------------------------------===// -#include "API/api.h" +#include "errors.h" #include "lib_enums.h" -#include -#include -#include -#include - -#include "llvm/ADT/Optional.h" -#include +#include "API/api.h" #include +#include +#include +#include +#include +#include #include #include +#include #include namespace py = pybind11; @@ -79,7 +79,7 @@ py::tuple py_compile_by_args(const std::vector &args, #ifndef NDEBUG std::cout << "params passed from python to C++:\n"; for (auto &str : args) - std::cout << str << std::endl; + std::cout << str << '\n'; #endif // TODO: need a C++ interface into the compiler with fewer detours. the python @@ -90,13 +90,13 @@ py::tuple py_compile_by_args(const std::vector &args, argv.push_back(str.c_str()); argv.push_back(nullptr); - int status = qssc::compile(args.size(), argv.data(), + int const status = qssc::compile(args.size(), argv.data(), outputAsStr ? &outputStr : nullptr, std::move(onDiagnostic)); - bool success = status == 0; + bool const success = status == 0; #ifndef NDEBUG - std::cerr << "Compile " << (success ? "successful" : "failed") << std::endl; + std::cerr << "Compile " << (success ? "successful" : "failed") << '\n'; #endif return py::make_tuple(success, py::bytes(outputStr)); @@ -112,14 +112,14 @@ py_link_file(const std::string &input, const bool enableInMemoryInput, std::string inMemoryOutput(""); - int status = qssc::bindArguments(target, configPath, input, outputPath, arguments, + int const status = qssc::bindArguments(target, configPath, input, outputPath, arguments, treatWarningsAsErrors, enableInMemoryInput, &inMemoryOutput, std::move(onDiagnostic)); - bool success = status == 0; + bool const success = status == 0; #ifndef NDEBUG - std::cerr << "Link " << (success ? "successful" : "failed") << std::endl; + std::cerr << "Link " << (success ? "successful" : "failed") << '\n'; #endif return py::make_tuple(success, py::bytes(inMemoryOutput)); } diff --git a/python_lib/qss_compiler/lib_enums.cpp b/python_lib/qss_compiler/lib_enums.cpp index 96ad6d82e..70e02e97d 100644 --- a/python_lib/qss_compiler/lib_enums.cpp +++ b/python_lib/qss_compiler/lib_enums.cpp @@ -1,5 +1,13 @@ -#include "API/api.h" #include "lib_enums.h" +#include "errors.h" + +#include +#include +#include +#include +#include +#include +#include namespace py = pybind11; diff --git a/targets/systems/mock/CMakeLists.txt b/targets/systems/mock/CMakeLists.txt index 43fa336d5..fe25c2ca5 100644 --- a/targets/systems/mock/CMakeLists.txt +++ b/targets/systems/mock/CMakeLists.txt @@ -51,9 +51,9 @@ ${qssc_api_libs} QSSCHAL MLIRExecutionEngine MLIROptLib -MLIRLLVMIR +MLIRLLVMDialect MLIRLLVMToLLVMIRTranslation -MLIRStandardOpsTransforms +MLIRFuncTransforms ${llvm_code_gen_libraries} PLUGIN_REGISTRATION_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/Target.inc diff --git a/targets/systems/mock/Conversion/QUIRToStandard/QUIRToStandard.cpp b/targets/systems/mock/Conversion/QUIRToStandard/QUIRToStandard.cpp index 612be5a3b..caac970af 100644 --- a/targets/systems/mock/Conversion/QUIRToStandard/QUIRToStandard.cpp +++ b/targets/systems/mock/Conversion/QUIRToStandard/QUIRToStandard.cpp @@ -18,41 +18,58 @@ // //===----------------------------------------------------------------------===// #include "Conversion/QUIRToStandard/QUIRToStandard.h" + +#include "MockTarget.h" +#include "MockUtils.h" + #include "Conversion/QUIRToStandard/TypeConversion.h" #include "Conversion/QUIRToStandard/VariablesToGlobalMemRefConversion.h" - +#include "Dialect/OQ3/IR/OQ3Dialect.h" #include "Dialect/OQ3/IR/OQ3Ops.h" #include "Dialect/Pulse/IR/PulseDialect.h" +#include "Dialect/QCS/IR/QCSDialect.h" #include "Dialect/QCS/IR/QCSOps.h" +#include "Dialect/QUIR/IR/QUIRAttributes.h" #include "Dialect/QUIR/IR/QUIRDialect.h" #include "Dialect/QUIR/IR/QUIROps.h" - -#include "MockUtils.h" +#include "Dialect/QUIR/IR/QUIRTypes.h" #include "mlir/Dialect/Affine/IR/AffineOps.h" -#include "mlir/Dialect/Arithmetic/IR/Arithmetic.h" +#include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/Dialect/Func/Transforms/FuncConversions.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" -#include "mlir/Dialect/SCF/SCF.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" -#include "mlir/Dialect/StandardOps/Transforms/FuncConversions.h" +#include "mlir/Dialect/SCF/IR/SCF.h" +#include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/BuiltinOps.h" -#include "mlir/Pass/Pass.h" +#include "mlir/IR/BuiltinTypes.h" +#include "mlir/IR/DialectRegistry.h" +#include "mlir/IR/ValueRange.h" +#include "mlir/Support/LogicalResult.h" #include "mlir/Transforms/DialectConversion.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include + using namespace mlir; namespace qssc::targets::systems::mock::conversion { -struct ReturnConversionPat : public OpConversionPattern { +struct ReturnConversionPat : public OpConversionPattern { explicit ReturnConversionPat(MLIRContext *ctx, TypeConverter &typeConverter) : OpConversionPattern(typeConverter, ctx, /*benefit=*/1) {} LogicalResult - matchAndRewrite(mlir::ReturnOp retOp, OpAdaptor adaptor, + matchAndRewrite(mlir::func::ReturnOp retOp, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override { - rewriter.create(retOp->getLoc(), adaptor.getOperands()); - rewriter.replaceOp(retOp, {}); + rewriter.create(retOp->getLoc(), + adaptor.getOperands()); + rewriter.eraseOp(retOp); return success(); } // matchAndRewrite }; // struct ReturnConversionPat @@ -68,26 +85,26 @@ struct ConstantOpConversionPat : public OpConversionPattern { LogicalResult matchAndRewrite(quir::ConstantOp constOp, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override { - if (auto angleAttr = constOp.value().dyn_cast()) { + if (auto angleAttr = constOp.getValue().dyn_cast()) { auto angleWidth = constOp.getType().cast().getWidth(); // cannot handle non-parameterized angle types - if (!angleWidth.hasValue()) + if (!angleWidth.has_value()) return failure(); - int64_t multiplier = (int64_t)1 << (int64_t)angleWidth.getValue(); + int64_t const multiplier = (int64_t)1 << (int64_t)angleWidth.value(); // shift the floating point value up by the desired precision - double fVal = angleAttr.getValue().convertToDouble() * multiplier; + double const fVal = angleAttr.getValue().convertToDouble() * multiplier; IntegerType iType; - if (angleWidth.getValue() > 31) + if (angleWidth.value() > 31) iType = rewriter.getI64Type(); else iType = rewriter.getI32Type(); - IntegerAttr iAttr = rewriter.getIntegerAttr(iType, (int64_t)fVal); + IntegerAttr const iAttr = rewriter.getIntegerAttr(iType, (int64_t)fVal); auto arithConstOp = rewriter.create( constOp->getLoc(), iType, iAttr); - rewriter.replaceOp(constOp, {arithConstOp}); + rewriter.replaceOp(constOp, arithConstOp); return success(); } // attribute type is not handled (for now) @@ -106,16 +123,18 @@ struct AngleBinOpConversionPat : public OpConversionPattern { matchAndRewrite(QuirOp binOp, typename QuirOp::Adaptor adaptor, ConversionPatternRewriter &rewriter) const override { auto operands = adaptor.getOperands(); - auto angleWidth = - binOp.lhs().getType().template dyn_cast().getWidth(); + auto angleWidth = binOp.getLhs() + .getType() + .template dyn_cast() + .getWidth(); // cannot handle non-parameterized angle types - if (!angleWidth.hasValue()) + if (!angleWidth.has_value()) return failure(); - int64_t maskVal = ((int64_t)1 << (int64_t)angleWidth.getValue()) - 1; + int64_t const maskVal = ((int64_t)1 << (int64_t)angleWidth.value()) - 1; auto iType = operands[0].getType().template dyn_cast(); - IntegerAttr iAttr = rewriter.getIntegerAttr(iType, maskVal); + IntegerAttr const iAttr = rewriter.getIntegerAttr(iType, maskVal); auto stdOp = rewriter.create(binOp.getLoc(), iType, operands[0], operands[1]); @@ -143,15 +162,15 @@ struct CommOpConversionPat : public OpConversionPattern { switch (numResults) { case 0: - rewriter.replaceOp(commOp.getOperation(), {}); + rewriter.eraseOp(commOp.getOperation()); return success(); case 1: { // shift the floating point value up by the desired precision - int64_t iVal = 1; - IntegerType i1Type = rewriter.getI1Type(); + int64_t const iVal = 1; + IntegerType const i1Type = rewriter.getI1Type(); - IntegerAttr iAttr = rewriter.getIntegerAttr(i1Type, iVal); + IntegerAttr const iAttr = rewriter.getIntegerAttr(i1Type, iVal); auto constOp = rewriter.create(commOp->getLoc(), i1Type, iAttr); rewriter.replaceOp(commOp.getOperation(), {constOp.getODSResults(0)}); @@ -170,7 +189,7 @@ struct CommOpConversionPat : public OpConversionPattern { void conversion::MockQUIRToStdPass::getDependentDialects( DialectRegistry ®istry) const { registry.insert(); + mlir::affine::AffineDialect, arith::ArithDialect>(); } void MockQUIRToStdPass::runOnOperation(MockSystem &system) { @@ -178,16 +197,16 @@ void MockQUIRToStdPass::runOnOperation(MockSystem &system) { // First remove all arguments from synchronization ops moduleOp->walk([](qcs::SynchronizeOp synchOp) { - synchOp.qubitsMutable().assign(ValueRange({})); + synchOp.getQubitsMutable().assign(ValueRange({})); }); QuirTypeConverter typeConverter; auto *context = &getContext(); ConversionTarget target(*context); - target.addLegalDialect(); // Since we are converting QUIR -> STD/LLVM, make QUIR illegal. // Further, because OQ3 and QCS ops are migrated from QUIR, make them also @@ -195,14 +214,16 @@ void MockQUIRToStdPass::runOnOperation(MockSystem &system) { target .addIllegalDialect(); target.addIllegalOp(); - target.addDynamicallyLegalOp( - [&](FuncOp op) { return typeConverter.isSignatureLegal(op.getType()); }); - target.addDynamicallyLegalOp([&](CallOp op) { - return typeConverter.isSignatureLegal(op.getCalleeType()); + target.addDynamicallyLegalOp([&](mlir::func::FuncOp op) { + return typeConverter.isSignatureLegal(op.getFunctionType()); }); - target.addDynamicallyLegalOp([&](mlir::ReturnOp op) { - return typeConverter.isLegal(op.getOperandTypes()); + target.addDynamicallyLegalOp([&](func::CallOp op) { + return typeConverter.isSignatureLegal(op.getCalleeType()); }); + target.addDynamicallyLegalOp( + [&](mlir::func::ReturnOp op) { + return typeConverter.isLegal(op.getOperandTypes()); + }); // We mark `ConstantOp` legal so we don't err when attempting to convert a // constant `DurationType`. (Only `AngleType` is currently handled by the // conversion pattern, `ConstantOpConversionPat`.) @@ -219,8 +240,8 @@ void MockQUIRToStdPass::runOnOperation(MockSystem &system) { target.addLegalOp(); RewritePatternSet patterns(context); - populateFunctionOpInterfaceTypeConversionPattern(patterns, - typeConverter); + populateFunctionOpInterfaceTypeConversionPattern( + patterns, typeConverter); populateCallOpTypeConversionPattern(patterns, typeConverter); // clang-format off patterns.add #include -#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace mlir; using namespace mlir::quir; @@ -57,26 +76,29 @@ using namespace mlir::quir; using namespace qssc::hal; using namespace qssc::targets::systems::mock; +namespace { // The space below at the front of the string causes this category to be printed // first -static llvm::cl::OptionCategory +llvm::cl::OptionCategory mockCat(" QSS Compiler Options for the Mock target", "Options that control Mock-specific behavior of the Mock QSS " "Compiler target"); +} // anonymous namespace int qssc::targets::systems::mock::init() { - bool registered = registry::TargetSystemRegistry::registerPlugin( - "mock", "Mock system for testing the targeting infrastructure.", - [](llvm::Optional configurationPath) - -> llvm::Expected> { - if (!configurationPath) - return llvm::createStringError( - llvm::inconvertibleErrorCode(), - "Configuration file must be specified.\n"); - - auto config = std::make_unique(*configurationPath); - return std::make_unique(std::move(config)); - }); + bool const registered = + registry::TargetSystemRegistry::registerPlugin( + "mock", "Mock system for testing the targeting infrastructure.", + [](std::optional configurationPath) + -> llvm::Expected> { + if (!configurationPath) + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Configuration file must be specified.\n"); + + auto config = std::make_unique(*configurationPath); + return std::make_unique(std::move(config)); + }); return registered ? 0 : -1; } @@ -145,16 +167,16 @@ MockSystem::MockSystem(std::unique_ptr config) // Create drive targets for (const auto &result : llvm::enumerate(mockConfig->getDriveNodes())) { - uint32_t qubitIdx = result.index(); - uint32_t nodeId = result.value(); + uint32_t const qubitIdx = result.index(); + uint32_t const nodeId = result.value(); addChild(std::make_unique( "MockDrive_" + std::to_string(qubitIdx), this, *mockConfig, nodeId)); } // Create acquire targets for (const auto &result : llvm::enumerate(mockConfig->getAcquireNodes())) { - uint32_t acquireIdx = result.index(); - uint32_t nodeId = result.value(); + uint32_t const acquireIdx = result.index(); + uint32_t const nodeId = result.value(); addChild(std::make_unique("MockAcquire_" + std::to_string(acquireIdx), this, *mockConfig, nodeId)); @@ -190,7 +212,7 @@ void mockPipelineBuilder(mlir::OpPassManager &pm) { } // anonymous namespace llvm::Error MockSystem::registerTargetPipelines() { - mlir::PassPipelineRegistration<> pipeline( + mlir::PassPipelineRegistration<> const pipeline( "mock-conversion", "Run Mock-specific conversions", mockPipelineBuilder); MockController::registerTargetPipelines(); MockAcquire::registerTargetPipelines(); @@ -223,13 +245,8 @@ void MockController::registerTargetPipelines() { } // MockController::registerTargetPipelines llvm::Error MockController::addPasses(mlir::PassManager &pm) { - // Register LLVM dialect and all infrastructure required for translation to - // LLVM IR - mlir::registerLLVMDialectTranslation(*pm.getContext()); - pm.addPass(std::make_unique(false)); pm.addPass(mlir::createCanonicalizerPass()); - pm.addPass(mlir::createLowerToLLVMPass()); pm.addPass(mlir::LLVM::createLegalizeForExportPass()); return llvm::Error::success(); @@ -251,6 +268,12 @@ llvm::Error MockController::emitToPayload(mlir::ModuleOp moduleOp, llvm::Error MockController::buildLLVMPayload(mlir::ModuleOp controllerModule, qssc::payload::Payload &payload) { + // Register LLVM dialect and all infrastructure required for translation to + // LLVM IR + auto *context = controllerModule.getContext(); + mlir::registerBuiltinDialectTranslation(*context); + mlir::registerLLVMDialectTranslation(*context); + // Initialize native LLVM target llvm::InitializeNativeTarget(); llvm::InitializeNativeTargetAsmParser(); @@ -258,7 +281,7 @@ llvm::Error MockController::buildLLVMPayload(mlir::ModuleOp controllerModule, llvm::InitializeAllTargetMCs(); // Setup the machine properties for the target architecture. - std::string targetTriple = llvm::sys::getDefaultTargetTriple(); + std::string const targetTriple = llvm::sys::getDefaultTargetTriple(); std::string errorMessage; const auto *target = llvm::TargetRegistry::lookupTarget(targetTriple, errorMessage); @@ -267,8 +290,8 @@ llvm::Error MockController::buildLLVMPayload(mlir::ModuleOp controllerModule, "Unable to find target: " + errorMessage); } - std::string cpu("generic"); - llvm::SubtargetFeatures features; + std::string const cpu("generic"); + llvm::SubtargetFeatures const features; std::unique_ptr machine(target->createTargetMachine( targetTriple, cpu, features.getString(), {}, {})); auto dataLayout = machine->createDataLayout(); diff --git a/targets/systems/mock/MockUtils.cpp b/targets/systems/mock/MockUtils.cpp index c65b403c9..f28d137c1 100644 --- a/targets/systems/mock/MockUtils.cpp +++ b/targets/systems/mock/MockUtils.cpp @@ -20,7 +20,11 @@ #include "MockUtils.h" -#include +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/Visitors.h" + +#include using namespace qssc::targets::systems::mock; using namespace mlir; diff --git a/targets/systems/mock/Transforms/FunctionLocalization.cpp b/targets/systems/mock/Transforms/FunctionLocalization.cpp index 8ab73ea78..e9a8db28c 100644 --- a/targets/systems/mock/Transforms/FunctionLocalization.cpp +++ b/targets/systems/mock/Transforms/FunctionLocalization.cpp @@ -20,19 +20,31 @@ #include "FunctionLocalization.h" -#include "Dialect/QUIR/IR/QUIRDialect.h" #include "Dialect/QUIR/IR/QUIROps.h" #include "Dialect/QUIR/IR/QUIRTypes.h" #include "Dialect/QUIR/Utils/Utils.h" -#include "mlir/Dialect/SCF/SCF.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/IR/Attributes.h" +#include "mlir/IR/Block.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/BuiltinOps.h" -#include "mlir/Pass/Pass.h" +#include "mlir/IR/BuiltinTypes.h" +#include "mlir/IR/Region.h" +#include "mlir/IR/SymbolTable.h" +#include "mlir/IR/Value.h" #include "mlir/Pass/PassManager.h" +#include "mlir/Support/LLVM.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include #include #include @@ -54,14 +66,14 @@ void SymbolTableBuildPass::runOnOperation() { LLVM_DEBUG(llvm::dbgs() << "\nRunning symbol table build on " << moduleOp.getName() << "\n"); - OpBuilder b(moduleOp); + OpBuilder const b(moduleOp); // very specifically do not `walk` the region, we only want top-level FuncOps for (Region ®ion : moduleOp.getOperation()->getRegions()) { for (Block &block : region.getBlocks()) { for (Operation &op : block.getOperations()) { - if (auto funcOp = dyn_cast(op)) { - std::string fName = + if (auto funcOp = dyn_cast(op)) { + std::string const fName = SymbolRefAttr::get(funcOp).getLeafReference().str(); auto origNameAttr = op.getAttrOfType("quir.orig_func_name"); @@ -81,7 +93,7 @@ void SymbolTableBuildPass::runOnOperation() { : funcMap) { llvm::dbgs() << myPair.first << " " << myPair.second.size() << " :\t"; for (auto *op : myPair.second) { - auto funcOp = dyn_cast(op); + auto funcOp = dyn_cast(op); llvm::dbgs() << funcOp.getName() << " "; } llvm::dbgs() << "\n"; @@ -91,14 +103,22 @@ void SymbolTableBuildPass::runOnOperation() { auto MockFunctionLocalizationPass::lookupQubitId(const Value val) -> int { auto declOp = val.getDefiningOp(); - if (declOp) - return declOp.id().getValue(); + if (declOp) { + auto id = declOp.getId(); + if (!id.has_value()) { + declOp->emitOpError() << "Qubit declaration does not have id"; + signalPassFailure(); + return -1; + } + return id.value(); + } // Must be an argument to a function // see if we can find an attribute with the info if (auto blockArg = val.dyn_cast()) { - unsigned argIdx = blockArg.getArgNumber(); - auto funcOp = dyn_cast(blockArg.getOwner()->getParentOp()); + unsigned const argIdx = blockArg.getArgNumber(); + auto funcOp = + dyn_cast(blockArg.getOwner()->getParentOp()); if (funcOp) { auto argAttr = funcOp.getArgAttrOfType(argIdx, "quir.physicalId"); @@ -123,9 +143,9 @@ auto MockFunctionLocalizationPass::lookupQubitId(const Value val) -> int { template auto MockFunctionLocalizationPass::getCallArgIndex(CallOpTy &callOp) -> int { int callArgIndex = -1; - for (uint ii = 0; ii < callOp.operands().size(); ++ii) { - if (callOp.operands()[ii].getType().template isa()) { - int qId = lookupQubitId(callOp.operands()[ii]); + for (uint ii = 0; ii < callOp.getOperands().size(); ++ii) { + if (callOp.getOperands()[ii].getType().template isa()) { + int const qId = lookupQubitId(callOp.getOperands()[ii]); if (qId == theseIds[0]) { callArgIndex = ii; break; @@ -140,7 +160,7 @@ auto MockFunctionLocalizationPass::getMatchedOp(CallOpTy &callOp, int callArgIndex, int thisIdIndex) -> Operation * { - std::string calleeName = callOp.callee().str(); + std::string const calleeName = callOp.getCallee().str(); FunctionType cType = callOp.getCalleeType(); Operation *matchedOp = nullptr; @@ -151,8 +171,8 @@ auto MockFunctionLocalizationPass::getMatchedOp(CallOpTy &callOp, // list, however, we should probably do something more intelligent here // with some sort of ranking system for (auto *op : funcMap[calleeName]) { - auto funcOp = dyn_cast(op); - FunctionType fType = funcOp.getType(); + auto funcOp = dyn_cast(op); + FunctionType fType = funcOp.getFunctionType(); if (quirFunctionTypeMatch(fType, cType)) { // types match auto argIdAttr = funcOp.getArgAttrOfType(callArgIndex, "quir.physicalId"); @@ -169,10 +189,10 @@ auto MockFunctionLocalizationPass::getMatchedOp(CallOpTy &callOp, template auto MockFunctionLocalizationPass::getMangledName(CallOpTy &callOp) -> std::string { - std::string newName = callOp.callee().str(); - for (uint ii = 0; ii < callOp.operands().size(); ++ii) { - if (callOp.operands()[ii].getType().template isa()) { - int qId = lookupQubitId(callOp.operands()[ii]); + std::string newName = callOp.getCallee().str(); + for (uint ii = 0; ii < callOp.getOperands().size(); ++ii) { + if (callOp.getOperands()[ii].getType().template isa()) { + int const qId = lookupQubitId(callOp.getOperands()[ii]); newName += "_q" + std::to_string(qId); } } @@ -185,21 +205,21 @@ void MockFunctionLocalizationPass::cloneMatchedOp(CallOpTy &callOp, Operation *&clonedOp, Operation *matchedOp) { // first check if the op has already been copied into this module! - auto matchedFuncOp = dyn_cast(matchedOp); - std::string matchedFuncName = + auto matchedFuncOp = dyn_cast(matchedOp); + std::string const matchedFuncName = SymbolRefAttr::get(matchedFuncOp).getLeafReference().str(); if (auto *lookedUpOp = SymbolTable::lookupSymbolIn( moduleOperation, llvm::StringRef(newName))) { clonedOp = lookedUpOp; } else { // copy the func def to this module clonedOp = builder->clone(*matchedOp); - auto newFuncOp = dyn_cast(clonedOp); + auto newFuncOp = dyn_cast(clonedOp); newFuncOp->setAttr(SymbolTable::getSymbolAttrName(), StringAttr::get(newFuncOp.getContext(), newName)); - for (uint ii = 0; ii < callOp.operands().size(); ++ii) { - if (callOp.operands()[ii].getType().template isa()) { - int qId = - lookupQubitId(callOp.operands()[ii]); // copy qubitId from call + for (uint ii = 0; ii < callOp.getOperands().size(); ++ii) { + if (callOp.getOperands()[ii].getType().template isa()) { + int const qId = + lookupQubitId(callOp.getOperands()[ii]); // copy qubitId from call newFuncOp.setArgAttrs( ii, ArrayRef({NamedAttribute( StringAttr::get(newFuncOp.getContext(), "quir.physicalId"), @@ -225,7 +245,7 @@ void MockFunctionLocalizationPass::runOnOperation() { // insert just before main func def builder = std::make_shared(mainFunc); - llvm::StringRef nodeType = + llvm::StringRef const nodeType = moduleOp->getAttrOfType("quir.nodeType").getValue(); if (nodeType == "controller") return; @@ -238,7 +258,7 @@ void MockFunctionLocalizationPass::runOnOperation() { if (thisIdAttr) theseIds.push_back(thisIdAttr.getInt()); if (theseIdsAttr) { - for (Attribute valAttr : theseIdsAttr) { + for (Attribute const valAttr : theseIdsAttr) { auto intAttr = valAttr.dyn_cast(); theseIds.push_back(intAttr.getInt()); } @@ -256,7 +276,7 @@ void MockFunctionLocalizationPass::runOnOperation() { toWalk.push_back(mainFunc); auto walkSubroutineCalls = [&](CallSubroutineOp callOp) { - std::string calleeName = callOp.callee().str(); + std::string const calleeName = callOp.getCallee().str(); FunctionType cType = callOp.getCalleeType(); Operation *matchedOp = @@ -266,8 +286,8 @@ void MockFunctionLocalizationPass::runOnOperation() { << "Unable to find func def for " << calleeName << "\n"); return; } - auto matchedFuncOp = dyn_cast(matchedOp); - FunctionType fType = matchedFuncOp.getType(); + auto matchedFuncOp = dyn_cast(matchedOp); + FunctionType fType = matchedFuncOp.getFunctionType(); if (!quirFunctionTypeMatch(fType, cType)) { LLVM_DEBUG(llvm::dbgs() << "The signatures for " << calleeName << " and it's func def don't match!\n"); @@ -276,18 +296,18 @@ void MockFunctionLocalizationPass::runOnOperation() { // specialize the function name for this application of the call Operation *clonedOp = nullptr; - std::string newName = getMangledName(callOp); + std::string const newName = getMangledName(callOp); cloneMatchedOp(callOp, newName, clonedOp, matchedOp); // now update the callee of the callop - auto clonedFuncOp = dyn_cast(clonedOp); - callOp.calleeAttr(SymbolRefAttr::get(clonedFuncOp)); + auto clonedFuncOp = dyn_cast(clonedOp); + callOp.setCalleeAttr(SymbolRefAttr::get(clonedFuncOp)); }; // walkSubroutineCalls auto walkGateCalls = [&](CallGateOp callOp) { - std::string calleeName = callOp.callee().str(); + std::string const calleeName = callOp.getCallee().str(); - int callArgIndex = getCallArgIndex(callOp); + int const callArgIndex = getCallArgIndex(callOp); if (callArgIndex == -1) { // This call does not interface with this qubit module callOp.getOperation()->erase(); @@ -303,18 +323,18 @@ void MockFunctionLocalizationPass::runOnOperation() { // specialize the function name for this application of the call Operation *clonedOp = nullptr; - std::string newName = getMangledName(callOp); + std::string const newName = getMangledName(callOp); cloneMatchedOp(callOp, newName, clonedOp, matchedOp); // now update the callee of the callop - auto clonedFuncOp = dyn_cast(clonedOp); - callOp.calleeAttr(SymbolRefAttr::get(clonedFuncOp)); + auto clonedFuncOp = dyn_cast(clonedOp); + callOp.setCalleeAttr(SymbolRefAttr::get(clonedFuncOp)); }; // walkGateCalls auto walkDefcalGateCalls = [&](CallDefCalGateOp callOp) { - std::string calleeName = callOp.callee().str(); + std::string const calleeName = callOp.getCallee().str(); - int callArgIndex = getCallArgIndex(callOp); + int const callArgIndex = getCallArgIndex(callOp); if (callArgIndex == -1) { // This call does not interface with this qubit module callOp.getOperation()->erase(); @@ -331,18 +351,18 @@ void MockFunctionLocalizationPass::runOnOperation() { // specialize the function name for this application of the call Operation *clonedOp = nullptr; - std::string newName = getMangledName(callOp); + std::string const newName = getMangledName(callOp); cloneMatchedOp(callOp, newName, clonedOp, matchedOp); // now update the callee of the callop - auto clonedFuncOp = dyn_cast(clonedOp); - callOp.calleeAttr(SymbolRefAttr::get(clonedFuncOp)); + auto clonedFuncOp = dyn_cast(clonedOp); + callOp.setCalleeAttr(SymbolRefAttr::get(clonedFuncOp)); }; // walkDefcalGateCalls auto walkDefcalMeasureCalls = [&](CallDefcalMeasureOp callOp) { - std::string calleeName = callOp.callee().str(); + std::string const calleeName = callOp.getCallee().str(); - int qId = lookupQubitId(callOp.operands()[0]); + int const qId = lookupQubitId(callOp.getOperands()[0]); int thisIdIndex = -1; for (uint ii = 0; ii < theseIds.size(); ++ii) { if (qId == theseIds[ii]) { @@ -365,19 +385,19 @@ void MockFunctionLocalizationPass::runOnOperation() { // found a match // specialize the function name for this application of the call - std::string newName = calleeName + "_q" + std::to_string(qId); + std::string const newName = calleeName + "_q" + std::to_string(qId); // first check if the op has already been copied into this module! - auto matchedFuncOp = dyn_cast(matchedOp); + auto matchedFuncOp = dyn_cast(matchedOp); Operation *clonedOp = nullptr; - std::string matchedFuncName = + std::string const matchedFuncName = SymbolRefAttr::get(matchedFuncOp).getLeafReference().str(); if (auto *lookedUpOp = SymbolTable::lookupSymbolIn(moduleOp, llvm::StringRef(newName))) { clonedOp = lookedUpOp; } else { // copy the func def to this module clonedOp = builder->clone(*matchedOp); - auto newFuncOp = dyn_cast(clonedOp); + auto newFuncOp = dyn_cast(clonedOp); newFuncOp->setAttr(SymbolTable::getSymbolAttrName(), StringAttr::get(newFuncOp.getContext(), newName)); newFuncOp.setArgAttrs( @@ -389,8 +409,8 @@ void MockFunctionLocalizationPass::runOnOperation() { } // else copy the func def to this module // now update the callee of the callop - auto clonedFuncOp = dyn_cast(clonedOp); - callOp.calleeAttr(SymbolRefAttr::get(clonedFuncOp)); + auto clonedFuncOp = dyn_cast(clonedOp); + callOp.setCalleeAttr(SymbolRefAttr::get(clonedFuncOp)); }; // walkDefcalMeasureCalls // first walk all subroutine calls @@ -407,11 +427,11 @@ void MockFunctionLocalizationPass::runOnOperation() { std::unordered_set subroutineCalls; // Find all subroutine calls moduleOp->walk([&](CallSubroutineOp callOp) { - subroutineCalls.emplace(callOp.callee().str()); + subroutineCalls.emplace(callOp.getCallee().str()); }); - moduleOp->walk([&](FuncOp funcOp) { - llvm::StringRef funcName = + moduleOp->walk([&](mlir::func::FuncOp funcOp) { + llvm::StringRef const funcName = SymbolRefAttr::get(funcOp.getOperation()).getLeafReference(); if (subroutineCalls.count(funcName.str()) == 0 && funcName != "main") { funcOp.getOperation()->erase(); diff --git a/targets/systems/mock/Transforms/FunctionLocalization.h b/targets/systems/mock/Transforms/FunctionLocalization.h index 48a4d132f..718a9c111 100644 --- a/targets/systems/mock/Transforms/FunctionLocalization.h +++ b/targets/systems/mock/Transforms/FunctionLocalization.h @@ -23,8 +23,8 @@ #include "Dialect/QUIR/IR/QUIROps.h" -#include "mlir/Dialect/SCF/SCF.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" +#include "mlir/Dialect/SCF/IR/SCF.h" +#include "mlir/IR/BuiltinOps.h" #include "mlir/Pass/Pass.h" #include diff --git a/targets/systems/mock/Transforms/QubitLocalization.cpp b/targets/systems/mock/Transforms/QubitLocalization.cpp index 61998f008..6302ccafc 100644 --- a/targets/systems/mock/Transforms/QubitLocalization.cpp +++ b/targets/systems/mock/Transforms/QubitLocalization.cpp @@ -20,20 +20,45 @@ #include "QubitLocalization.h" +#include "MockTarget.h" + #include "Dialect/OQ3/IR/OQ3Ops.h" #include "Dialect/QCS/IR/QCSOps.h" -#include "Dialect/QUIR/IR/QUIRDialect.h" #include "Dialect/QUIR/IR/QUIROps.h" #include "Dialect/QUIR/IR/QUIRTypes.h" #include "Dialect/QUIR/Utils/Utils.h" -#include "mlir/Dialect/Arithmetic/IR/Arithmetic.h" -#include "mlir/Dialect/SCF/SCF.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" -#include "mlir/IR/BlockAndValueMapping.h" +#include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/Dialect/SCF/IR/SCF.h" +#include "mlir/IR/Block.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/BuiltinOps.h" -#include "mlir/Pass/Pass.h" +#include "mlir/IR/IRMapping.h" +#include "mlir/IR/Location.h" +#include "mlir/IR/Region.h" +#include "mlir/IR/SymbolTable.h" +#include "mlir/IR/TypeRange.h" +#include "mlir/IR/Types.h" +#include "mlir/IR/Value.h" #include "mlir/Pass/PassManager.h" +#include "mlir/Support/LLVM.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace mlir; using namespace mlir::quir; @@ -60,8 +85,9 @@ auto mock::MockQubitLocalizationPass::lookupQubitId(const Value &val) -> int { if (!declOp) { // Must be an argument to a function // see if we can find an attribute with the info if (auto blockArg = val.dyn_cast()) { - unsigned argIdx = blockArg.getArgNumber(); - auto funcOp = dyn_cast(blockArg.getOwner()->getParentOp()); + unsigned const argIdx = blockArg.getArgNumber(); + auto funcOp = + dyn_cast(blockArg.getOwner()->getParentOp()); if (funcOp) { auto argAttr = funcOp.getArgAttrOfType(argIdx, "quir.physicalId"); @@ -71,7 +97,12 @@ auto mock::MockQubitLocalizationPass::lookupQubitId(const Value &val) -> int { } // if val is blockArg return -1; } // if !declOp - return declOp.id().getValue(); + + auto id = declOp.getId(); + if (id.has_value()) + return id.value(); + + return -1; } // lookupQubitId /// Creates a broadcast op on Controller and recvOp on all other mocks @@ -85,16 +116,16 @@ void mock::MockQubitLocalizationPass::broadcastAndReceiveValue( if (dyn_cast(parentOp) || dyn_cast(parentOp)) { // Just clone this op to the mocks - for (uint id : toNodeIds) + for (uint const id : toNodeIds) (*mockBuilders)[id]->clone(*parentOp, mockMapping[id]); } else { controllerBuilder->create( loc, controllerMapping.lookupOrNull(val)); - for (uint id : toNodeIds) { + for (uint const id : toNodeIds) { auto recvOp = (*mockBuilders)[id]->create( loc, TypeRange(val.getType()), controllerBuilder->getIndexArrayAttr(config->controllerNode())); - mockMapping[id].map(val, recvOp.vals().front()); + mockMapping[id].map(val, recvOp.getVals().front()); } } alreadyBroadcastValues.insert(val); @@ -104,16 +135,16 @@ void mock::MockQubitLocalizationPass::broadcastAndReceiveValue( } // if alreadyBroadcastValues.count(val) == 0 } // broadcastValue -void mock::MockQubitLocalizationPass::cloneRegionWithoutOps( - Region *from, Region *dest, BlockAndValueMapping &mapper) { +void mock::MockQubitLocalizationPass::cloneRegionWithoutOps(Region *from, + Region *dest, + IRMapping &mapper) { assert(dest && "expected valid region to clone into"); cloneRegionWithoutOps(from, dest, dest->end(), mapper); } // cloneRegionWithoutOps // clone region (from) into region (dest) before the given position void mock::MockQubitLocalizationPass::cloneRegionWithoutOps( - Region *from, Region *dest, Region::iterator destPos, - BlockAndValueMapping &mapper) { + Region *from, Region *dest, Region::iterator destPos, IRMapping &mapper) { assert(dest && "expected valid region to clone into"); assert(from != dest && "cannot clone region into itself"); @@ -151,13 +182,13 @@ void mock::MockQubitLocalizationPass::cloneRegionWithoutOps( } // cloneRegionWithoutOps auto mock::MockQubitLocalizationPass::addMainFunction( - Operation *moduleOperation, const Location &loc) -> FuncOp { + Operation *moduleOperation, const Location &loc) -> mlir::func::FuncOp { OpBuilder b(moduleOperation->getRegion(0)); - auto funcOp = - b.create(loc, "main", - b.getFunctionType( - /*inputs=*/ArrayRef(), - /*results=*/ArrayRef(b.getI32Type()))); + auto funcOp = b.create( + loc, "main", + b.getFunctionType( + /*inputs=*/ArrayRef(), + /*results=*/ArrayRef(b.getI32Type()))); funcOp.getOperation()->setAttr(llvm::StringRef("quir.classicalOnly"), b.getBoolAttr(false)); funcOp.addEntryBlock(); @@ -171,20 +202,20 @@ void mock::MockQubitLocalizationPass::processOp(DeclareQubitOp &qubitOp) { // declare every qubit on each mock for multi-qubit gates purposes for (auto nodeId : seenNodeIds) { auto *clonedOp = (*mockBuilders)[nodeId]->clone(*op); - mockMapping[nodeId].map(qubitOp.res(), - dyn_cast(clonedOp).res()); + mockMapping[nodeId].map(qubitOp.getRes(), + dyn_cast(clonedOp).getRes()); } } // processOp DeclareQubitOp void mock::MockQubitLocalizationPass::processOp(ResetQubitOp &resetOp) { - if (resetOp.qubits().size() != 1) { + if (resetOp.getQubits().size() != 1) { signalPassFailure(); // only support single-qubit resets" return; } Operation *op = resetOp.getOperation(); llvm::outs() << "Localizing a " << op->getName() << "\n"; - int qubitId = lookupQubitId(resetOp.qubits().front()); + int const qubitId = lookupQubitId(resetOp.getQubits().front()); if (qubitId < 0) { resetOp->emitOpError() << "Can't resolve qubit ID for resetOp\n"; return signalPassFailure(); @@ -195,9 +226,9 @@ void mock::MockQubitLocalizationPass::processOp(ResetQubitOp &resetOp) { *op, mockMapping[config->acquireNode(qubitId)]); } // processOp ResetQubitOp -void mock::MockQubitLocalizationPass::processOp(FuncOp &funcOp) { +void mock::MockQubitLocalizationPass::processOp(mlir::func::FuncOp &funcOp) { Operation *op = funcOp.getOperation(); - OpBuilder fBuild(funcOp); + OpBuilder const fBuild(funcOp); llvm::outs() << "Cloning FuncOp " << SymbolRefAttr::get(funcOp) << " to Controller\n"; controllerBuilder->clone(*op, controllerMapping); @@ -206,13 +237,13 @@ void mock::MockQubitLocalizationPass::processOp(FuncOp &funcOp) { void mock::MockQubitLocalizationPass::processOp(Builtin_UOp &uOp) { Operation *op = uOp.getOperation(); llvm::outs() << "Localizing a " << op->getName() << "\n"; - int qubitId = lookupQubitId(uOp.target()); + int const qubitId = lookupQubitId(uOp.getTarget()); // broadcast all classical values from Controller to all Mockss // recv all classical values on all Mockss - broadcastAndReceiveValue(uOp.theta(), op->getLoc(), seenNodeIds); - broadcastAndReceiveValue(uOp.phi(), op->getLoc(), seenNodeIds); - broadcastAndReceiveValue(uOp.lambda(), op->getLoc(), seenNodeIds); + broadcastAndReceiveValue(uOp.getTheta(), op->getLoc(), seenNodeIds); + broadcastAndReceiveValue(uOp.getPhi(), op->getLoc(), seenNodeIds); + broadcastAndReceiveValue(uOp.getLambda(), op->getLoc(), seenNodeIds); if (qubitId < 0) { uOp->emitOpError() << "Can't resolve qubit ID for uOp\n"; @@ -226,8 +257,8 @@ void mock::MockQubitLocalizationPass::processOp(Builtin_UOp &uOp) { void mock::MockQubitLocalizationPass::processOp(BuiltinCXOp &cxOp) { Operation *op = cxOp.getOperation(); llvm::outs() << "Localizing a " << op->getName() << "\n"; - int qubitId1 = lookupQubitId(cxOp.control()); - int qubitId2 = lookupQubitId(cxOp.target()); + int const qubitId1 = lookupQubitId(cxOp.getControl()); + int const qubitId2 = lookupQubitId(cxOp.getTarget()); if (qubitId1 < 0 || qubitId2 < 0) { cxOp->emitOpError() << "Can't resolve qubit ID for cxOp\n"; @@ -244,7 +275,7 @@ void mock::MockQubitLocalizationPass::processOp(MeasureOp &measureOp) { Operation *op = measureOp.getOperation(); llvm::outs() << "Localizing a " << op->getName() << "\n"; // figure out which qubit this gate operates on - int qubitId = lookupQubitId(measureOp.qubits().front()); + int const qubitId = lookupQubitId(measureOp.getQubits().front()); // clone the measure call to the drive and acquire mocks (*mockBuilders)[config->driveNode(qubitId)]->clone( *op, mockMapping[config->driveNode(qubitId)]); @@ -254,13 +285,13 @@ void mock::MockQubitLocalizationPass::processOp(MeasureOp &measureOp) { // send the results from the acquire mock and recv on Controller (*mockBuilders)[config->acquireNode(qubitId)]->create( - op->getLoc(), clonedMeasureOp.outs().front(), + op->getLoc(), clonedMeasureOp.getOuts().front(), controllerBuilder->getIndexAttr(config->controllerNode())); auto recvOp = controllerBuilder->create( - op->getLoc(), TypeRange(clonedMeasureOp.outs().front().getType()), + op->getLoc(), TypeRange(clonedMeasureOp.getOuts().front().getType()), controllerBuilder->getIndexArrayAttr(qubitId)); // map the result on Controller - controllerMapping.map(measureOp.outs().front(), recvOp.vals().front()); + controllerMapping.map(measureOp.getOuts().front(), recvOp.getVals().front()); } // processOp MeasureOp void mock::MockQubitLocalizationPass::processOp( @@ -276,15 +307,15 @@ void mock::MockQubitLocalizationPass::processOp( *op, controllerMapping); // cloning the callOp to controller // first look up the func def in the parent Module Operation *funcOperation = SymbolTable::lookupSymbolIn( - controllerModule->getParentOp(), callOp.callee()); + controllerModule->getParentOp(), callOp.getCallee()); if (!funcOperation) { callOp->emitOpError() << "Unable to find func def to match " - << callOp.callee() << "\n"; + << callOp.getCallee() << "\n"; return; } - auto funcOp = dyn_cast(funcOperation); + auto funcOp = dyn_cast(funcOperation); - bool onlyToController = classicalOnlyCheck(funcOperation); + bool const onlyToController = classicalOnlyCheck(funcOperation); if (!onlyToController) { // broadcast all classical values from Controller to all Mockss @@ -296,7 +327,7 @@ void mock::MockQubitLocalizationPass::processOp( } // for operands // Clone the subroutine call to all drive and acquire mocks - for (uint nodeId : seenNodeIds) { + for (uint const nodeId : seenNodeIds) { (*mockBuilders)[nodeId]->clone(*op, mockMapping[nodeId]); } // for nodeId in seenNodeIds } // if !onlyToController @@ -304,8 +335,8 @@ void mock::MockQubitLocalizationPass::processOp( // Now clone the corresponding funcOp and recurse on it // First check if it's already been cloned! if (SymbolTable::lookupSymbolIn(controllerModule.getOperation(), - callOp.callee())) { - llvm::outs() << callOp.callee() << " has already been cloned!\n"; + callOp.getCallee())) { + llvm::outs() << callOp.getCallee() << " has already been cloned!\n"; return; } OpBuilder::InsertPoint savedPoint = controllerBuilder->saveInsertionPoint(); @@ -313,21 +344,21 @@ void mock::MockQubitLocalizationPass::processOp( controllerBuilder->setInsertionPointToStart(controllerModule.getBody()); Operation *clonedFuncOperation = controllerBuilder->cloneWithoutRegions(*funcOperation, controllerMapping); - auto clonedFuncOp = dyn_cast(clonedFuncOperation); + auto clonedFuncOp = dyn_cast(clonedFuncOperation); if (funcOp.getCallableRegion()) { cloneRegionWithoutOps(&funcOp.getBody(), &clonedFuncOp.getBody(), controllerMapping); } controllerBuilder->restoreInsertionPoint(savedPoint); if (!onlyToController) { - for (uint nodeId : seenNodeIds) { + for (uint const nodeId : seenNodeIds) { savedPoint = (*mockBuilders)[nodeId]->saveInsertionPoint(); (*mockBuilders)[nodeId]->setInsertionPointToStart( dyn_cast(mockModules[nodeId]).getBody()); Operation *clonedFuncOperation = (*mockBuilders)[nodeId]->cloneWithoutRegions(*funcOperation, mockMapping[nodeId]); - auto clonedFuncOp = dyn_cast(clonedFuncOperation); + auto clonedFuncOp = dyn_cast(clonedFuncOperation); if (funcOp.getCallableRegion()) { cloneRegionWithoutOps(&funcOp.getBody(), &clonedFuncOp.getBody(), mockMapping[nodeId]); @@ -366,12 +397,12 @@ void mock::MockQubitLocalizationPass::processOp(CallGateOp &callOp) { // broadcast all classical values from Controller to all Mockss // recv all classical values on all Mockss - for (Value val : classicalVals) { + for (Value const val : classicalVals) { broadcastAndReceiveValue(val, op->getLoc(), seenNodeIds); } // for val in classicalVals // Clone the gate call to all relevant drive mocks - for (uint qubitId : qInd) { + for (uint const qubitId : qInd) { (*mockBuilders)[config->driveNode(qubitId)]->clone( *op, mockMapping[config->driveNode(qubitId)]); } // for qubitId in qInd @@ -400,7 +431,7 @@ void mock::MockQubitLocalizationPass::processOp(BarrierOp &barrierOp) { } // Clone the gate call to all relevant drive - for (uint qubitId : qubits) { + for (uint const qubitId : qubits) { (*mockBuilders)[config->driveNode(qubitId)]->clone( *op, mockMapping[config->driveNode(qubitId)]); } // for qubitId in qInd @@ -432,11 +463,11 @@ void mock::MockQubitLocalizationPass::processOp(CallDefCalGateOp &callOp) { // send all classical values from Controller to all Mockss // recv all classical values on all drive Mockss - for (Value val : classicalVals) + for (Value const val : classicalVals) broadcastAndReceiveValue(val, op->getLoc(), seenNodeIds); // Clone the gate call to all relevant drive mocks - for (uint qubitId : qInd) { + for (uint const qubitId : qInd) { (*mockBuilders)[config->driveNode(qubitId)]->clone( *op, mockMapping[config->driveNode(qubitId)]); } // for qubitId in qInd @@ -468,10 +499,10 @@ void mock::MockQubitLocalizationPass::processOp(CallDefcalMeasureOp &callOp) { // send all classical values from Controller to all Mockss // recv all classical values on all drive Mockss - for (Value val : classicalVals) + for (Value const val : classicalVals) broadcastAndReceiveValue(val, op->getLoc(), seenNodeIds); - for (uint qubitId : qInd) { + for (uint const qubitId : qInd) { // Clone the measure call to all drive and acquire mocks (*mockBuilders)[config->driveNode(qubitId)]->clone( *op, mockMapping[config->driveNode(qubitId)]); @@ -482,12 +513,12 @@ void mock::MockQubitLocalizationPass::processOp(CallDefcalMeasureOp &callOp) { // Send the measured value back to Controller and receive it on Controller (*mockBuilders)[config->acquireNode(qubitId)]->create( - op->getLoc(), acquireOp.res(), + op->getLoc(), acquireOp.getRes(), controllerBuilder->getIndexAttr(config->controllerNode())); auto recvOp = controllerBuilder->create( - op->getLoc(), TypeRange(acquireOp.res().getType()), + op->getLoc(), TypeRange(acquireOp.getRes().getType()), controllerBuilder->getIndexArrayAttr(qubitId)); - controllerMapping.map(callOp.res(), recvOp.vals().front()); + controllerMapping.map(callOp.getRes(), recvOp.getVals().front()); } } // processOp CallDefcalMeasureOp @@ -496,7 +527,7 @@ void mock::MockQubitLocalizationPass::processOp(DelayOpType &delayOp) { Operation *op = delayOp.getOperation(); std::vector qInd; bool qubitIdsResolved = true; - for (auto operand : delayOp.qubits()) { + for (auto operand : delayOp.getQubits()) { qInd.emplace_back(lookupQubitId(operand)); if (qInd.back() < 0) qubitIdsResolved = false; @@ -505,39 +536,40 @@ void mock::MockQubitLocalizationPass::processOp(DelayOpType &delayOp) { delayOp->emitOpError() << "Unable to resolve all qubit IDs for delay\n"; return signalPassFailure(); } - if (delayOp.qubits().empty()) // no qubit args means all qubits - for (uint qId : seenQubitIds) + if (delayOp.getQubits().empty()) // no qubit args means all qubits + for (uint const qId : seenQubitIds) qInd.emplace_back((int)qId); // turn the vector of qubitIds into a set of node Ids std::unordered_set involvedNodes; - for (int qubitId : qInd) { + for (int const qubitId : qInd) { involvedNodes.emplace(config->driveNode(qubitId)); involvedNodes.emplace(config->acquireNode(qubitId)); } if (auto dOp = dyn_cast(op)) { - auto *durationDeclare = dOp.time().getDefiningOp(); - for (uint id : involvedNodes) + auto *durationDeclare = dOp.getTime().getDefiningOp(); + for (uint const id : involvedNodes) (*mockBuilders)[id]->clone(*durationDeclare, mockMapping[id]); } - if (delayOp.qubits().empty()) + if (delayOp.getQubits().empty()) controllerBuilder->clone(*op, controllerMapping); // clone the delay op to the involved nodes - for (uint nodeId : involvedNodes) + for (uint const nodeId : involvedNodes) (*mockBuilders)[nodeId]->clone(*op, mockMapping[nodeId]); } // processOp DelayOp -void mock::MockQubitLocalizationPass::processOp(mlir::ReturnOp &returnOp) { +void mock::MockQubitLocalizationPass::processOp( + mlir::func::ReturnOp &returnOp) { Operation *op = returnOp.getOperation(); controllerBuilder->clone(*op, controllerMapping); - FlatSymbolRefAttr symbolRef = SymbolRefAttr::get(op->getParentOp()); + FlatSymbolRefAttr const symbolRef = SymbolRefAttr::get(op->getParentOp()); if (symbolRef && symbolRef.getLeafReference() == "main") - for (auto arg : returnOp.operands()) + for (auto arg : returnOp.getOperands()) broadcastAndReceiveValue(arg, op->getLoc(), seenNodeIds); if (!classicalOnlyCheck(op->getParentOp())) - for (uint nodeId : seenNodeIds) + for (uint const nodeId : seenNodeIds) (*mockBuilders)[nodeId]->clone(*op, mockMapping[nodeId]); } // processOp ReturnOp @@ -581,7 +613,7 @@ void mock::MockQubitLocalizationPass::processOp( int savedQubitId = -1; if (measureOp) { // remove the drive node from seenNodeIds temporarily // only if it can be resolved - savedQubitId = lookupQubitId(measureOp.qubits().front()); + savedQubitId = lookupQubitId(measureOp.getQubits().front()); if (savedQubitId >= 0) { seenNodeIds.erase(config->driveNode(savedQubitId)); @@ -592,8 +624,8 @@ void mock::MockQubitLocalizationPass::processOp( controllerBuilder->getIndexArrayAttr( config->acquireNode(savedQubitId))); // map the result on the drive node - mockMapping[config->driveNode(savedQubitId)].map(ifOp.getCondition(), - recvOp.vals().front()); + mockMapping[config->driveNode(savedQubitId)].map( + ifOp.getCondition(), recvOp.getVals().front()); } } @@ -614,7 +646,7 @@ void mock::MockQubitLocalizationPass::processOp( cloneRegionWithoutOps(&ifOp.getElseRegion(), &clonedIfOp.getElseRegion(), controllerMapping); } - for (uint nodeId : seenNodeIds) { + for (uint const nodeId : seenNodeIds) { Operation *clonedOp = (*mockBuilders)[nodeId]->cloneWithoutRegions(*op, mockMapping[nodeId]); auto clonedIfOp = dyn_cast(clonedOp); @@ -676,7 +708,7 @@ void mock::MockQubitLocalizationPass::processOp( auto clonedForOp = dyn_cast(clonedOp); cloneRegionWithoutOps(&forOp.getLoopBody(), &clonedForOp.getLoopBody(), controllerMapping); - for (uint nodeId : seenNodeIds) { + for (uint const nodeId : seenNodeIds) { Operation *clonedOp = (*mockBuilders)[nodeId]->cloneWithoutRegions( *op, mockMapping[nodeId]); auto clonedFor = dyn_cast(clonedOp); @@ -714,7 +746,7 @@ void mock::MockQubitLocalizationPass::runOnOperation(MockSystem &target) { controllerModule = dyn_cast( b.create(b.getUnknownLoc(), llvm::StringRef("controller")) .getOperation()); - FuncOp controllerMainOp = + mlir::func::FuncOp controllerMainOp = addMainFunction(controllerModule.getOperation(), mainFunc->getLoc()); controllerBuilder = new OpBuilder(controllerMainOp.getBody()); controllerModule->setAttr( @@ -729,8 +761,8 @@ void mock::MockQubitLocalizationPass::runOnOperation(MockSystem &target) { auto newBuilders = std::make_unique>(); for (const auto &result : llvm::enumerate(config->getDriveNodes())) { - uint qubitIdx = result.index(); - uint nodeId = result.value(); + uint const qubitIdx = result.index(); + uint const nodeId = result.value(); llvm::outs() << "Creating module for drive Mocks " << qubitIdx << "\n"; auto driveMod = b.create( b.getUnknownLoc(), @@ -745,14 +777,14 @@ void mock::MockQubitLocalizationPass::runOnOperation(MockSystem &target) { llvm::StringRef("quir.physicalId"), controllerBuilder->getI32IntegerAttr(qubitIdx)); mockModules[nodeId] = driveMod.getOperation(); - FuncOp mockMainOp = + mlir::func::FuncOp mockMainOp = addMainFunction(driveMod.getOperation(), mainFunc->getLoc()); newBuilders->emplace(nodeId, new OpBuilder(mockMainOp.getBody())); } for (const auto &result : llvm::enumerate(config->getAcquireNodes())) { - uint acquireIdx = result.index(); - uint nodeId = result.value(); + uint const acquireIdx = result.index(); + uint const nodeId = result.value(); llvm::outs() << "Creating module for acquire Mocks " << acquireIdx << "\n"; auto acquireMod = b.create( b.getUnknownLoc(), @@ -768,16 +800,16 @@ void mock::MockQubitLocalizationPass::runOnOperation(MockSystem &target) { controllerBuilder->getI32ArrayAttr( ArrayRef(config->acquireQubits(nodeId)))); mockModules[nodeId] = acquireMod.getOperation(); - FuncOp mockMainOp = + mlir::func::FuncOp mockMainOp = addMainFunction(acquireMod.getOperation(), mainFunc->getLoc()); newBuilders->emplace(nodeId, new OpBuilder(mockMainOp.getBody())); } mainFunc->walk([&](DeclareQubitOp qubitOp) { - llvm::outs() << qubitOp.getOperation()->getName() << " id: " << qubitOp.id() - << "\n"; - if (!qubitOp.id().hasValue() || - qubitOp.id().getValue() > config->getNumQubits()) { + llvm::outs() << qubitOp.getOperation()->getName() + << " id: " << qubitOp.getId() << "\n"; + if (!qubitOp.getId().has_value() || + qubitOp.getId().value() > config->getNumQubits()) { qubitOp->emitOpError() << "Error! Found a qubit without an ID or with ID > " << std::to_string(config->getNumQubits()) @@ -785,7 +817,7 @@ void mock::MockQubitLocalizationPass::runOnOperation(MockSystem &target) { << " during qubit localization!\n"; signalPassFailure(); } - uint qId = qubitOp.id().getValue(); + uint const qId = qubitOp.getId().value(); seenQubitIds.emplace(qId); driveNodeIds.emplace(config->driveNode(qId)); acquireNodeIds.emplace(config->acquireNode(qId)); @@ -835,7 +867,7 @@ void mock::MockQubitLocalizationPass::runOnOperation(MockSystem &target) { processOp(delayOp); } else if (auto delayOp = dyn_cast(op)) { processOp(delayOp); - } else if (auto returnOp = dyn_cast(op)) { + } else if (auto returnOp = dyn_cast(op)) { processOp(returnOp); } else if (auto yieldOp = dyn_cast(op)) { processOp(yieldOp); @@ -843,7 +875,7 @@ void mock::MockQubitLocalizationPass::runOnOperation(MockSystem &target) { processOp(ifOp, blockAndBuilderWorkList); } else if (auto forOp = dyn_cast(op)) { processOp(forOp, blockAndBuilderWorkList); - } else if (dyn_cast(op) || dyn_cast(op)) { + } else if (dyn_cast(op) || dyn_cast(op)) { // do nothing } // moduleOp else { // some classical op, should go to Controller @@ -858,7 +890,7 @@ void mock::MockQubitLocalizationPass::runOnOperation(MockSystem &target) { } // for Operations // delete the allocated opbuilders delete controllerBuilder; - for (uint nodeId : seenNodeIds) + for (uint const nodeId : seenNodeIds) delete (*mockBuilders)[nodeId]; delete mockBuilders; } // while !blockAndBuilderWorklist.empty() diff --git a/targets/systems/mock/Transforms/QubitLocalization.h b/targets/systems/mock/Transforms/QubitLocalization.h index 7adc8a3f2..b4616606b 100644 --- a/targets/systems/mock/Transforms/QubitLocalization.h +++ b/targets/systems/mock/Transforms/QubitLocalization.h @@ -27,9 +27,9 @@ #include "Dialect/QUIR/IR/QUIROps.h" #include "HAL/TargetOperationPass.h" -#include "mlir/Dialect/SCF/SCF.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" -#include "mlir/IR/BlockAndValueMapping.h" +#include "mlir/Dialect/SCF/IR/SCF.h" +#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/IRMapping.h" #include "mlir/Pass/Pass.h" #include @@ -45,7 +45,7 @@ struct MockQubitLocalizationPass void processOp(mlir::quir::DeclareQubitOp &qubitOp); void processOp(mlir::quir::ResetQubitOp &resetOp); - void processOp(mlir::FuncOp &funcOp); + void processOp(mlir::func::FuncOp &funcOp); void processOp(mlir::quir::Builtin_UOp &uOp); void processOp(mlir::quir::BuiltinCXOp &cxOp); void processOp(mlir::quir::MeasureOp &measureOp); @@ -61,7 +61,7 @@ struct MockQubitLocalizationPass void processOp(mlir::quir::CallDefcalMeasureOp &callOp); template void processOp(DelayOpType &delayOp); - void processOp(mlir::ReturnOp &returnOp); + void processOp(mlir::func::ReturnOp &returnOp); void processOp(mlir::scf::YieldOp &yieldOp); void processOp(mlir::scf::IfOp &ifOp, @@ -82,17 +82,17 @@ struct MockQubitLocalizationPass const mlir::Location &loc, const std::unordered_set &toNodeIds); void cloneRegionWithoutOps(mlir::Region *from, mlir::Region *dest, - mlir::BlockAndValueMapping &mapper); + mlir::IRMapping &mapper); void cloneRegionWithoutOps(mlir::Region *from, mlir::Region *dest, mlir::Region::iterator destPos, - mlir::BlockAndValueMapping &mapper); + mlir::IRMapping &mapper); auto addMainFunction(mlir::Operation *moduleOperation, - const mlir::Location &loc) -> mlir::FuncOp; + const mlir::Location &loc) -> mlir::func::FuncOp; void cloneVariableDeclarations(mlir::ModuleOp topModuleOp); MockConfig *config; mlir::ModuleOp controllerModule; - mlir::BlockAndValueMapping controllerMapping; + mlir::IRMapping controllerMapping; mlir::OpBuilder *controllerBuilder; std::unordered_set seenNodeIds; std::unordered_set seenQubitIds; @@ -102,8 +102,7 @@ struct MockQubitLocalizationPass mlir::DenseSet alreadyBroadcastValues; std::unordered_map mockModules; // one per nodeId std::unordered_map *mockBuilders; // one per nodeId - std::unordered_map - mockMapping; // one per nodeId + std::unordered_map mockMapping; // one per nodeId llvm::StringRef getArgument() const override; llvm::StringRef getDescription() const override; diff --git a/targets/systems/mock/test/python_lib/test_compile.py b/targets/systems/mock/test/python_lib/test_compile.py index 3f6da8562..5c9c2615e 100644 --- a/targets/systems/mock/test/python_lib/test_compile.py +++ b/targets/systems/mock/test/python_lib/test_compile.py @@ -180,7 +180,7 @@ def test_compile_options(mock_config_file, example_qasm3_str): config_path=mock_config_file, shot_delay=100, num_shots=10000, - extra_args=compiler_extra_args + ["--pass-statistics"], + extra_args=compiler_extra_args + ["--mlir-pass-statistics"], ) mlir = compile_str(example_qasm3_str, compile_options=compile_options) diff --git a/targets/systems/mock/test/static/Conversion/QUIRToStd/llvmgen.mlir b/targets/systems/mock/test/static/Conversion/QUIRToStd/llvmgen.mlir index 272ff43e6..6f31cbfc3 100644 --- a/targets/systems/mock/test/static/Conversion/QUIRToStd/llvmgen.mlir +++ b/targets/systems/mock/test/static/Conversion/QUIRToStd/llvmgen.mlir @@ -12,12 +12,12 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -// CHECK: define i32 @main() !dbg !3 { -// CHECK: ret i32 0, !dbg !7 +// CHECK: define i32 @main() { +// CHECK: ret i32 0 // CHECK: } module @controller attributes {quir.nodeId = 1000 : i32, quir.nodeType = "controller"} { - func @main() -> i32 attributes {quir.classicalOnly = false} { - %0 = quir.constant #quir.duration<1000.0 : !quir.duration
> + func.func @main() -> i32 attributes {quir.classicalOnly = false} { + %0 = quir.constant #quir.duration<1000.0> : !quir.duration
%1 = qcs.recv {fromId = 0 : index} : i1 qcs.broadcast %1 : i1 scf.if %1 { @@ -30,9 +30,9 @@ module @controller attributes {quir.nodeId = 1000 : i32, quir.nodeType = "contro qcs.broadcast %3 : i1 scf.if %3 { } {quir.classicalOnly = false} - %4 = llvm.mlir.constant(1.0) : i32 - %5 = llvm.mlir.constant(2.0) : i32 - %6 = "llvm.intr.pow"(%4, %5) : (i32, i32) -> i32 + %4 = llvm.mlir.constant(1.0) : f32 + %5 = llvm.mlir.constant(2.0) : f32 + %6 = "llvm.intr.pow"(%4, %5) : (f32, f32) -> f32 %c0_i32 = arith.constant 0 : i32 return %c0_i32 : i32 } diff --git a/targets/systems/mock/test/static/Transforms/qubit-localization.mlir b/targets/systems/mock/test/static/Transforms/qubit-localization.mlir index 441fcc8a1..e790e5659 100644 --- a/targets/systems/mock/test/static/Transforms/qubit-localization.mlir +++ b/targets/systems/mock/test/static/Transforms/qubit-localization.mlir @@ -12,13 +12,13 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -func @gateH_qq(%qArg : !quir.qubit<1>) attributes {quir.orig_func_name = "gateH"} { - %ang = quir.constant #quir.angle<0.1 : !quir.angle<20>> +func.func @gateH_qq(%qArg : !quir.qubit<1>) attributes {quir.orig_func_name = "gateH"} { + %ang = quir.constant #quir.angle<0.1> : !quir.angle<20> quir.builtin_U %qArg, %ang, %ang, %ang : !quir.qubit<1>, !quir.angle<20>, !quir.angle<20>, !quir.angle<20> return } -func @subroutine1(%qq1 : !quir.qubit<1>, %phi : !quir.angle, %ub : index) { +func.func @subroutine1(%qq1 : !quir.qubit<1>, %phi : !quir.angle, %ub : index) { %lb = arith.constant 0 : index %step = arith.constant 1 : index scf.for %iv = %lb to %ub step %step { @@ -32,8 +32,8 @@ func @subroutine1(%qq1 : !quir.qubit<1>, %phi : !quir.angle, %ub : index) { return } -func @subroutine2(%qq1 : !quir.qubit<1>, %qq2 : !quir.qubit<1>) { - %zero = quir.constant #quir.angle<0.0 : !quir.angle<20>> +func.func @subroutine2(%qq1 : !quir.qubit<1>, %qq2 : !quir.qubit<1>) { + %zero = quir.constant #quir.angle<0.0> : !quir.angle<20> quir.call_gate @defcalPhase_qq(%zero, %qq1) : (!quir.angle<20>, !quir.qubit<1>) -> () quir.call_gate @defcalPhase_qq(%zero, %qq2) : (!quir.angle<20>, !quir.qubit<1>) -> () %ub = arith.constant 5 : index @@ -41,14 +41,14 @@ func @subroutine2(%qq1 : !quir.qubit<1>, %qq2 : !quir.qubit<1>) { return } -func @main () -> i32 { +func.func @main () -> i32 { %q0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %q1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> quir.reset %q0 : !quir.qubit<1> quir.barrier %q0, %q1 : (!quir.qubit<1>, !quir.qubit<1>) -> () quir.call_gate @gateH(%q0) : (!quir.qubit<1>) -> () - %ang1 = quir.constant #quir.angle<0.5 : !quir.angle<20>> + %ang1 = quir.constant #quir.angle<0.5> : !quir.angle<20> %ub = arith.constant 10 : index quir.call_subroutine @subroutine1(%q1, %ang1, %ub) : (!quir.qubit<1>, !quir.angle<20>, index) -> () quir.call_subroutine @subroutine1(%q0, %ang1, %ub) : (!quir.qubit<1>, !quir.angle<20>, index) -> () @@ -61,40 +61,40 @@ func @main () -> i32 { } // CHECK: module @controller attributes {quir.nodeId = 1000 : i32, quir.nodeType = "controller"} { -// CHECK: func @subroutine2_q1_q0() attributes {quir.classicalOnly = false} { +// CHECK: func.func @subroutine2_q1_q0() attributes {quir.classicalOnly = false} { // CHECK: quir.call_subroutine @"subroutine1_q1_!quir.angle<20>_index"(%angle, %c5) : (!quir.angle<20>, index) -> () -// CHECK: func @subroutine2_q0_q1() attributes {quir.classicalOnly = false} { +// CHECK: func.func @subroutine2_q0_q1() attributes {quir.classicalOnly = false} { // CHECK: quir.call_subroutine @"subroutine1_q0_!quir.angle<20>_index"(%angle, %c5) : (!quir.angle<20>, index) -> () -// CHECK: func @"subroutine1_q0_!quir.angle<20>_index"(%arg0: !quir.angle<20>, %arg1: index) attributes {quir.classicalOnly = false} { -// CHECK: func @subroutine1_q0(%arg0: !quir.angle, %arg1: index) attributes {quir.classicalOnly = false} { -// CHECK: func @"subroutine1_q1_!quir.angle<20>_index"(%arg0: !quir.angle<20>, %arg1: index) attributes {quir.classicalOnly = false} { -// CHECK: func @subroutine1_q1(%arg0: !quir.angle, %arg1: index) attributes {quir.classicalOnly = false} { -// CHECK: func @main() -> i32 attributes {quir.classicalOnly = false} { +// CHECK: func.func @"subroutine1_q0_!quir.angle<20>_index"(%arg0: !quir.angle<20>, %arg1: index) attributes {quir.classicalOnly = false} { +// CHECK: func.func @subroutine1_q0(%arg0: !quir.angle, %arg1: index) attributes {quir.classicalOnly = false} { +// CHECK: func.func @"subroutine1_q1_!quir.angle<20>_index"(%arg0: !quir.angle<20>, %arg1: index) attributes {quir.classicalOnly = false} { +// CHECK: func.func @subroutine1_q1(%arg0: !quir.angle, %arg1: index) attributes {quir.classicalOnly = false} { +// CHECK: func.func @main() -> i32 attributes {quir.classicalOnly = false} { // CHECK: quir.call_subroutine @"subroutine1_q1_!quir.angle<20>_index"(%angle, %c10) : (!quir.angle<20>, index) -> () // CHECK: quir.call_subroutine @"subroutine1_q0_!quir.angle<20>_index"(%angle, %c10) : (!quir.angle<20>, index) -> () // CHECK: quir.call_subroutine @subroutine2_q0_q1() : () -> () // CHECK: quir.call_subroutine @subroutine2_q1_q0() : () -> () // CHECK: module @mock_drive_0 attributes {quir.nodeId = 1 : i32, quir.nodeType = "drive", quir.physicalId = 0 : i32} { -// CHECK: func @gateH_q0(%arg0: !quir.qubit<1> {quir.physicalId = 0 : i32}) attributes {quir.classicalOnly = false, quir.orig_func_name = "gateH"} { -// CHECK: func @subroutine2_q1_q0() attributes {quir.classicalOnly = false} { +// CHECK: func.func @gateH_q0(%arg0: !quir.qubit<1> {quir.physicalId = 0 : i32}) attributes {quir.classicalOnly = false, quir.orig_func_name = "gateH"} { +// CHECK: func.func @subroutine2_q1_q0() attributes {quir.classicalOnly = false} { // CHECK: quir.call_gate @defcalPhase_qq(%angle, %1) : (!quir.angle<20>, !quir.qubit<1>) -> () // CHECK: quir.call_subroutine @"subroutine1_q1_!quir.angle<20>_index"(%angle, %c5) : (!quir.angle<20>, index) -> () -// CHECK: func @subroutine2_q0_q1() attributes {quir.classicalOnly = false} { +// CHECK: func.func @subroutine2_q0_q1() attributes {quir.classicalOnly = false} { // CHECK: quir.call_gate @defcalPhase_qq(%angle, %0) : (!quir.angle<20>, !quir.qubit<1>) -> () // CHECK: quir.call_subroutine @"subroutine1_q0_!quir.angle<20>_index"(%angle, %c5) : (!quir.angle<20>, index) -> () -// CHECK: func @"subroutine1_q0_!quir.angle<20>_index"(%arg0: !quir.angle<20>, %arg1: index) attributes {quir.classicalOnly = false} { +// CHECK: func.func @"subroutine1_q0_!quir.angle<20>_index"(%arg0: !quir.angle<20>, %arg1: index) attributes {quir.classicalOnly = false} { // CHECK: quir.call_gate @defcalPhase_q0(%arg0, %0) : (!quir.angle<20>, !quir.qubit<1>) -> () // CHECK: quir.call_defcal_gate @defcalPhase_q0(%arg0, %0) : (!quir.angle<20>, !quir.qubit<1>) -> () // CHECK: %1 = quir.call_defcal_measure @defcalMeasure_q0(%0, %arg0) : (!quir.qubit<1>, !quir.angle<20>) -> i1 // CHECK: quir.call_gate @defcalPhase_q0(%arg0, %0) : (!quir.angle<20>, !quir.qubit<1>) -> () -// CHECK: func @subroutine1_q0(%arg0: !quir.angle, %arg1: index) attributes {quir.classicalOnly = false} { +// CHECK: func.func @subroutine1_q0(%arg0: !quir.angle, %arg1: index) attributes {quir.classicalOnly = false} { // CHECK: quir.call_gate @defcalPhase_q0(%arg0, %0) : (!quir.angle, !quir.qubit<1>) -> () // CHECK: quir.call_defcal_gate @defcalPhase_q0(%arg0, %0) : (!quir.angle, !quir.qubit<1>) -> () // CHECK: %1 = quir.call_defcal_measure @defcalMeasure_q0(%0, %arg0) : (!quir.qubit<1>, !quir.angle) -> i1 // CHECK: quir.call_gate @defcalPhase_q0(%arg0, %0) : (!quir.angle, !quir.qubit<1>) -> () -// CHECK: func @"subroutine1_q1_!quir.angle<20>_index"(%arg0: !quir.angle<20>, %arg1: index) attributes {quir.classicalOnly = false} { -// CHECK: func @subroutine1_q1(%arg0: !quir.angle, %arg1: index) attributes {quir.classicalOnly = false} { -// CHECK: func @main() -> i32 attributes {quir.classicalOnly = false} { +// CHECK: func.func @"subroutine1_q1_!quir.angle<20>_index"(%arg0: !quir.angle<20>, %arg1: index) attributes {quir.classicalOnly = false} { +// CHECK: func.func @subroutine1_q1(%arg0: !quir.angle, %arg1: index) attributes {quir.classicalOnly = false} { +// CHECK: func.func @main() -> i32 attributes {quir.classicalOnly = false} { // CHECK: quir.barrier %0, %1 : (!quir.qubit<1>, !quir.qubit<1>) -> () // CHECK: quir.call_gate @gateH_q0(%0) : (!quir.qubit<1>) -> () // CHECK: quir.call_subroutine @"subroutine1_q1_!quir.angle<20>_index"(%angle, %c10) : (!quir.angle<20>, index) -> () diff --git a/targets/systems/mock/test/static/integration/mlir/bell-v0.mlir b/targets/systems/mock/test/static/integration/mlir/bell-v0.mlir index e69538547..2ef4c5e5e 100644 --- a/targets/systems/mock/test/static/integration/mlir/bell-v0.mlir +++ b/targets/systems/mock/test/static/integration/mlir/bell-v0.mlir @@ -13,13 +13,13 @@ // that they have been altered from the originals. // CHECK: Manifest -func @main () -> i32 { +func.func @main () -> i32 { %q0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %q1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> - %a0 = quir.constant #quir.angle<1.57079632679 : !quir.angle<20>> - %a1 = quir.constant #quir.angle<0.0 : !quir.angle<20>> - %a2 = quir.constant #quir.angle<3.14159265359 : !quir.angle<20>> + %a0 = quir.constant #quir.angle<1.57079632679> : !quir.angle<20> + %a1 = quir.constant #quir.angle<0.0> : !quir.angle<20> + %a2 = quir.constant #quir.angle<3.14159265359> : !quir.angle<20> quir.builtin_U %q0, %a0, %a1, %a2 : !quir.qubit<1>, !quir.angle<20>, !quir.angle<20>, !quir.angle<20> quir.builtin_CX %q0, %q1 : !quir.qubit<1>, !quir.qubit<1> %zero = arith.constant 0 : i32 diff --git a/targets/systems/mock/test/static/integration/mlir/scf-iterative-phase-estimation.mlir b/targets/systems/mock/test/static/integration/mlir/scf-iterative-phase-estimation.mlir index 4797ad0ca..3f0872cbe 100644 --- a/targets/systems/mock/test/static/integration/mlir/scf-iterative-phase-estimation.mlir +++ b/targets/systems/mock/test/static/integration/mlir/scf-iterative-phase-estimation.mlir @@ -16,8 +16,8 @@ // defcal y90p %0 { // play drive(%0), drag(...); // } -// func @defcalRX_q0(%qa1 : !quir.qubit<1> {quir.physicalId = 0 : i32}, %theta : !quir.angle<20>) -> () attributes {quir.orig_func_name = "defcalRX"} { -func @defcalY90P_q0(%q0 : !quir.qubit<1> {quir.physicalId = 0 : i32}) -> () attributes {quir.orig_func_name = "defcalY90P"} { +// func.func @defcalRX_q0(%qa1 : !quir.qubit<1> {quir.physicalId = 0 : i32}, %theta : !quir.angle<20>) -> () attributes {quir.orig_func_name = "defcalRX"} { +func.func @defcalY90P_q0(%q0 : !quir.qubit<1> {quir.physicalId = 0 : i32}) -> () attributes {quir.orig_func_name = "defcalY90P"} { // PULSE IR Ops // CHECK: return return @@ -25,21 +25,21 @@ func @defcalY90P_q0(%q0 : !quir.qubit<1> {quir.physicalId = 0 : i32}) -> () attr // defcal y90p %1 { // play drive(%1), drag(...); // } -func @defcalY90P_q1(%q0 : !quir.qubit<1> {quir.physicalId = 1 : i32}) -> () attributes {quir.orig_func_name = "defcalY90P"} { +func.func @defcalY90P_q1(%q0 : !quir.qubit<1> {quir.physicalId = 1 : i32}) -> () attributes {quir.orig_func_name = "defcalY90P"} { // PULSE IR Ops return } // defcal cr90p %0, %1 { // play flat_top_gaussian(...), drive(%0), frame(drive(%1)); // } -func @defcalCR90P_q0_q1(%q0 : !quir.qubit<1> {quir.physicalId = 0 : i32}, %q1 : !quir.qubit<1> {quir.physicalId = 1 : i32}) -> () attributes {quir.orig_func_name = "defcalCR90P"} { +func.func @defcalCR90P_q0_q1(%q0 : !quir.qubit<1> {quir.physicalId = 0 : i32}, %q1 : !quir.qubit<1> {quir.physicalId = 1 : i32}) -> () attributes {quir.orig_func_name = "defcalCR90P"} { // PULSE IR Ops return } // defcal phase(angle[20]: theta) %q { // shift_phase drive(%q), -theta; // } -func @defcalPhase_qq(%angle : !quir.angle, %qq : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "defcalPhase"} { +func.func @defcalPhase_qq(%angle : !quir.angle, %qq : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "defcalPhase"} { // PULSE IR Ops return } @@ -48,9 +48,9 @@ func @defcalPhase_qq(%angle : !quir.angle, %qq : !quir.qubit<1>) -> () attribute // cr90p %0, %1; // phase(pi) %1; // } -func @defcalCR90M_q0_q1(%q0 : !quir.qubit<1> {quir.physicalId = 0 : i32}, %q1 : !quir.qubit<1> {quir.physicalId = 1 : i32}) -> () attributes {quir.orig_func_name = "defcalCR90M"} { - %npi = quir.constant #quir.angle<-1.0 : !quir.angle<20>> - %pi = quir.constant #quir.angle<1.0 : !quir.angle<20>> +func.func @defcalCR90M_q0_q1(%q0 : !quir.qubit<1> {quir.physicalId = 0 : i32}, %q1 : !quir.qubit<1> {quir.physicalId = 1 : i32}) -> () attributes {quir.orig_func_name = "defcalCR90M"} { + %npi = quir.constant #quir.angle<-1.0> : !quir.angle<20> + %pi = quir.constant #quir.angle<1.0> : !quir.angle<20> "quir.call_gate"(%npi, %q1) {callee = @defcalPhase} : (!quir.angle<20>, !quir.qubit<1>) -> () "quir.call_gate"(%q0, %q1) {callee = @defcalCR90P} : (!quir.qubit<1>, !quir.qubit<1>) -> () "quir.call_gate"(%pi, %q1) {callee = @defcalPhase} : (!quir.angle<20>, !quir.qubit<1>) -> () @@ -61,9 +61,9 @@ func @defcalCR90M_q0_q1(%q0 : !quir.qubit<1> {quir.physicalId = 0 : i32}, %q1 : // y90p %q; // phase(-pi) %q; // } -func @gateX90P_qq(%qq_1 : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "gateX90P"} { - %npi = quir.constant #quir.angle<-1.0 : !quir.angle<20>> - %pi = quir.constant #quir.angle<1.0 : !quir.angle<20>> +func.func @gateX90P_qq(%qq_1 : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "gateX90P"} { + %npi = quir.constant #quir.angle<-1.0> : !quir.angle<20> + %pi = quir.constant #quir.angle<1.0> : !quir.angle<20> "quir.call_gate"(%pi, %qq_1) {callee = @defcalPhase} : (!quir.angle<20>, !quir.qubit<1>) -> () "quir.call_gate"(%qq_1) {callee = @defcalY90P} : (!quir.qubit<1>) -> () "quir.call_gate"(%npi, %qq_1) {callee = @defcalPhase} : (!quir.angle<20>, !quir.qubit<1>) -> () @@ -73,7 +73,7 @@ func @gateX90P_qq(%qq_1 : !quir.qubit<1>) -> () attributes {quir.orig_func_name // x90p %q; // x90p %q; // } -func @gateXP_qq(%qq_1 : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "gateXP"} { +func.func @gateXP_qq(%qq_1 : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "gateXP"} { "quir.call_gate"(%qq_1) {callee = @gateX90P} : (!quir.qubit<1>) -> () "quir.call_gate"(%qq_1) {callee = @gateX90P} : (!quir.qubit<1>) -> () return @@ -82,8 +82,8 @@ func @gateXP_qq(%qq_1 : !quir.qubit<1>) -> () attributes {quir.orig_func_name = // phase(pi) %q; // y90p %q; // } -func @gateH_qq(%qq_1 : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "gateH"} { - %pi = quir.constant #quir.angle<1.0 : !quir.angle<20>> +func.func @gateH_qq(%qq_1 : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "gateH"} { + %pi = quir.constant #quir.angle<1.0> : !quir.angle<20> "quir.call_gate"(%pi, %qq_1) {callee = @defcalPhase} : (!quir.angle<20>, !quir.qubit<1>) -> () "quir.call_gate"(%qq_1) {callee = @defcalY90P} : (!quir.qubit<1>) -> () return @@ -99,8 +99,8 @@ func @gateH_qq(%qq_1 : !quir.qubit<1>) -> () attributes {quir.orig_func_name = " // barrier %control, %target; // cr90m %control, %target; // } -func @gateCX_qq_qq(%ctrl : !quir.qubit<1>, %targ : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "gateCX"} { - %npi2 = quir.constant #quir.angle<-0.5 : !quir.angle<20>> +func.func @gateCX_qq_qq(%ctrl : !quir.qubit<1>, %targ : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "gateCX"} { + %npi2 = quir.constant #quir.angle<-0.5> : !quir.angle<20> "quir.call_gate"(%ctrl) {callee = @gateXP} : (!quir.qubit<1>) -> () "quir.call_gate"(%targ) {callee = @gateX90P} : (!quir.qubit<1>) -> () "quir.call_gate"(%ctrl, %targ) {callee = @defcalCR90P} : (!quir.qubit<1>, !quir.qubit<1>) -> () @@ -116,7 +116,7 @@ func @gateCX_qq_qq(%ctrl : !quir.qubit<1>, %targ : !quir.qubit<1>) -> () attribu // iq = capture acquire(%0), 2048, kernel(k0); // return threshold(iq, 1234); // } -func @defcalMeasure_q0(%q0_1 : !quir.qubit<1> {quir.physicalId = 0 : i32}) -> i1 attributes {quir.orig_func_name = "defcalMeasure"} { +func.func @defcalMeasure_q0(%q0_1 : !quir.qubit<1> {quir.physicalId = 0 : i32}) -> i1 attributes {quir.orig_func_name = "defcalMeasure"} { // Pulse IR Ops %res = arith.constant false return %res : i1 @@ -125,7 +125,7 @@ func @defcalMeasure_q0(%q0_1 : !quir.qubit<1> {quir.physicalId = 0 : i32}) -> i1 // angle[3] c = 0; oq3.declare_variable @c : !quir.cbit<3> -func @main() -> i32 { +func.func @main() -> i32 { // qubit q; // qubit r; %q0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> @@ -155,11 +155,11 @@ quir.call_gate @gateH(%q1) : (!quir.qubit<1>) -> () quir.call_gate @gateH (%q0) : (!quir.qubit<1>) -> () // cphase(power*3*pi/8) q, r; %pow_extended = "oq3.cast"(%pow_iter) : (i3) -> !quir.angle<20> - %ang_tpo8 = quir.constant #quir.angle<0.1875 : !quir.angle<20>> + %ang_tpo8 = quir.constant #quir.angle<0.1875> : !quir.angle<20> %phase_ang = oq3.angle_mul %pow_extended, %ang_tpo8 : !quir.angle<20> quir.call_gate @cphase(%q0, %q1, %phase_ang) : (!quir.qubit<1>, !quir.qubit<1>, !quir.angle<20>) -> () // phase(-c) q; - %neg_ang = quir.constant #quir.angle<-1.0 : !quir.angle<20>> + %neg_ang = quir.constant #quir.angle<-1.0> : !quir.angle<20> %ang_c = oq3.variable_load @c : !quir.cbit<3> %ang_iter_extended = "oq3.cast"(%ang_c) : (!quir.cbit<3>) -> !quir.angle<20> %neg_ang_mul = oq3.angle_mul %neg_ang, %ang_iter_extended : !quir.angle<20> diff --git a/test/Dialect/OQ3/IR/fold-cbit-extractbit.mlir b/test/Dialect/OQ3/IR/fold-cbit-extractbit.mlir index eac1115dc..77ba08b21 100644 --- a/test/Dialect/OQ3/IR/fold-cbit-extractbit.mlir +++ b/test/Dialect/OQ3/IR/fold-cbit-extractbit.mlir @@ -1,15 +1,15 @@ // RUN: qss-opt %s --canonicalize | qss-opt | FileCheck %s --implicit-check-not cbit_extractbit // Verify that all oq3.cbit_extractbit operations are eliminated -// CHECK: func @single_bit(%[[ARG0:.*]]: i1) -> i1 { -func @single_bit(%bit: i1) -> i1 { +// CHECK: func.func @single_bit(%[[ARG0:.*]]: i1) -> i1 { +func.func @single_bit(%bit: i1) -> i1 { %2 = oq3.cbit_extractbit(%bit : i1) [0] : i1 // CHECK: return %[[ARG0]] : i1 return %2 : i1 } -// CHECK: func @two_bits(%[[ARG0:.*]]: !quir.cbit<2>, %[[ARG1:.*]]: i1, %[[ARG2:.*]]: i1) -func @two_bits(%cbit: !quir.cbit<2>, %bit1: i1, %bit2: i1) -> i1 { +// CHECK: func.func @two_bits(%[[ARG0:.*]]: !quir.cbit<2>, %[[ARG1:.*]]: i1, %[[ARG2:.*]]: i1) +func.func @two_bits(%cbit: !quir.cbit<2>, %bit1: i1, %bit2: i1) -> i1 { %0 = oq3.cbit_insertbit(%cbit : !quir.cbit<2>)[0] = %bit1 : !quir.cbit<2> %1 = oq3.cbit_insertbit(%cbit : !quir.cbit<2>)[1] = %bit2 : !quir.cbit<2> diff --git a/test/Dialect/OQ3/IR/math.mlir b/test/Dialect/OQ3/IR/math.mlir index 05a7974b2..e4cfb1e4f 100644 --- a/test/Dialect/OQ3/IR/math.mlir +++ b/test/Dialect/OQ3/IR/math.mlir @@ -23,9 +23,9 @@ module { // CHECK: oq3.cbit_lshift %{{.*}}, %{{.*}} : (!quir.cbit<10>, i32) -> !quir.cbit<10> %lshift_res = oq3.cbit_lshift %xor_res, %const2 : (!quir.cbit<10>, i32) -> !quir.cbit<10> - // CHECK: %{{.*}} = quir.constant #quir.angle<1.000000e-01 : !quir.angle<20>> - %theta = quir.constant #quir.angle<0.1 : !quir.angle<20>> - %phi = quir.constant #quir.angle<0.2 : !quir.angle<20>> + // CHECK: %{{.*}} = quir.constant #quir.angle<1.000000e-01> : !quir.angle<20> + %theta = quir.constant #quir.angle<0.1> : !quir.angle<20> + %phi = quir.constant #quir.angle<0.2> : !quir.angle<20> // CHECK: %{{.*}} = oq3.angle_add %{{.*}}, %{{.*}} : !quir.angle<20> %add_res = oq3.angle_add %theta, %phi : !quir.angle<20> // CHECK: %{{.*}} = oq3.angle_sub %{{.*}}, %{{.*}} : !quir.angle<20> diff --git a/test/Dialect/OQ3/IR/ops.mlir b/test/Dialect/OQ3/IR/ops.mlir index e5aff2708..d8dd51929 100644 --- a/test/Dialect/OQ3/IR/ops.mlir +++ b/test/Dialect/OQ3/IR/ops.mlir @@ -2,14 +2,14 @@ // Verify the printed output can be parsed. // RUN: qss-opt %s --mlir-print-op-generic | qss-opt | FileCheck %s -func @extract(%in: !quir.cbit<2>) -> i1 { +func.func @extract(%in: !quir.cbit<2>) -> i1 { // CHECK: oq3.cbit_extractbit(%arg0 : !quir.cbit<2>) [1] : i1 %1 = oq3.cbit_extractbit(%in : !quir.cbit<2>) [1] : i1 // CHECK: return %0 : i1 return %1 : i1 } -func @insert(%cbit: !quir.cbit<2>, %bit :i1) -> !quir.cbit<2> { +func.func @insert(%cbit: !quir.cbit<2>, %bit :i1) -> !quir.cbit<2> { // CHECK: oq3.cbit_insertbit(%arg0 : !quir.cbit<2>) [0] = %arg1 : !quir.cbit<2> %1 = oq3.cbit_insertbit(%cbit : !quir.cbit<2>)[0] = %bit : !quir.cbit<2> // CHECK: return %0 : !quir.cbit<2> diff --git a/test/Dialect/OQ3/integration/openqasm3/cbit-width.qasm b/test/Dialect/OQ3/integration/openqasm3/cbit-width.qasm index 5cc7c1078..a6240a0d0 100644 --- a/test/Dialect/OQ3/integration/openqasm3/cbit-width.qasm +++ b/test/Dialect/OQ3/integration/openqasm3/cbit-width.qasm @@ -13,7 +13,7 @@ cbit[48] wide; cbit[2] wide_0; // CHECK: oq3.declare_variable @wide_0 : !quir.cbit<2> -// CHECK: func @main() -> i32 +// CHECK: func.func @main() -> i32 // CHECK-DAG: %c-8_i4 = arith.constant -8 : i4 diff --git a/test/Dialect/Pulse/IR/ops-error-testing.mlir b/test/Dialect/Pulse/IR/ops-error-testing.mlir index dc06351d3..5e7248740 100644 --- a/test/Dialect/Pulse/IR/ops-error-testing.mlir +++ b/test/Dialect/Pulse/IR/ops-error-testing.mlir @@ -53,8 +53,8 @@ pulse.sequence @sequence3 () { // ----- pulse.sequence @sequence4 () -> i1 { - %ub = constant 10 : index - %cmpval = constant 9 : index + %ub = arith.constant 10 : index + %cmpval = arith.constant 9 : index // expected-error@+1 {{'arith.cmpi' op is not valid within a real-time pulse sequence.}} %cond = arith.cmpi "eq", %ub, %cmpval : index pulse.return @@ -91,7 +91,7 @@ pulse.sequence @sequence7 (%port : !pulse.port, %waveform: !pulse.waveform) { // ----- // verify MLIR sequence required error is reported when a pulse.play is not contained in a sequence -func @invalid_sequence_required1(%mf0: !pulse.mixed_frame,%waveform: !pulse.waveform) { +func.func @invalid_sequence_required1(%mf0: !pulse.mixed_frame,%waveform: !pulse.waveform) { // expected-error@+1 {{'pulse.play' op expects parent op 'pulse.sequence'}} pulse.play(%mf0, %waveform) : (!pulse.mixed_frame, !pulse.waveform) } @@ -100,7 +100,7 @@ func @invalid_sequence_required1(%mf0: !pulse.mixed_frame,%waveform: !pulse.wave // verify MLIR sequence required error is reported when a pulse.capture is not contained in a // sequence -func @invalid_sequence_required2(%mf0: !pulse.mixed_frame) { +func.func @invalid_sequence_required2(%mf0: !pulse.mixed_frame) { // expected-error@+1 {{'pulse.capture' op expects parent op 'pulse.sequence'}} %res0 = pulse.capture(%mf0) : (!pulse.mixed_frame) -> i1 } @@ -109,7 +109,7 @@ func @invalid_sequence_required2(%mf0: !pulse.mixed_frame) { // verify MLIR sequence required error is reported when a pulse.return is not contained in a // sequence -func @invalid_sequence_required3() { +func.func @invalid_sequence_required3() { %false = arith.constant 0 : i1 // expected-error@+1 {{'pulse.return' op expects parent op 'pulse.sequence'}} pulse.return %false : i1 @@ -119,7 +119,7 @@ func @invalid_sequence_required3() { // verify MLIR sequence required error is reported when a pulse.set_frequency is not contained in a // sequence -func @invalid_sequence_required4(%frame: !pulse.frame, %frequency : f64) { +func.func @invalid_sequence_required4(%frame: !pulse.frame, %frequency : f64) { // expected-error@+1 {{'pulse.set_frequency' op expects parent op 'pulse.sequence'}} pulse.set_frequency(%frame, %frequency) : (!pulse.frame, f64) } @@ -128,7 +128,7 @@ func @invalid_sequence_required4(%frame: !pulse.frame, %frequency : f64) { // verify MLIR sequence required error is reported when a pulse.shift_frequency is not contained in a // sequence -func @invalid_sequence_required5(%frame: !pulse.frame, %frequency : f64) { +func.func @invalid_sequence_required5(%frame: !pulse.frame, %frequency : f64) { // expected-error@+1 {{'pulse.shift_frequency' op expects parent op 'pulse.sequence'}} pulse.shift_frequency(%frame, %frequency) : (!pulse.frame, f64) } @@ -137,7 +137,7 @@ func @invalid_sequence_required5(%frame: !pulse.frame, %frequency : f64) { // verify MLIR sequence required error is reported when a pulse.set_phase is not contained in a // sequence -func @invalid_sequence_required4(%frame: !pulse.frame, %phase : f64) { +func.func @invalid_sequence_required4(%frame: !pulse.frame, %phase : f64) { // expected-error@+1 {{'pulse.set_phase' op expects parent op 'pulse.sequence'}} pulse.set_phase(%frame, %phase) : (!pulse.frame, f64) } @@ -146,7 +146,7 @@ func @invalid_sequence_required4(%frame: !pulse.frame, %phase : f64) { // verify MLIR sequence required error is reported when a pulse.shift_phase is not contained in a // sequence -func @invalid_sequence_required5(%frame: !pulse.frame, %phase : f64) { +func.func @invalid_sequence_required5(%frame: !pulse.frame, %phase : f64) { // expected-error@+1 {{'pulse.shift_phase' op expects parent op 'pulse.sequence'}} pulse.shift_phase(%frame, %phase) : (!pulse.frame, f64) } diff --git a/test/Dialect/Pulse/IR/ops.mlir b/test/Dialect/Pulse/IR/ops.mlir index 3cb0500f2..d73972d59 100644 --- a/test/Dialect/Pulse/IR/ops.mlir +++ b/test/Dialect/Pulse/IR/ops.mlir @@ -15,7 +15,7 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -func @main () { +func.func @main () { %p0 = "pulse.create_port"() {uid = "p0"} : () -> !pulse.port // CHECK: %[[P0:.*]] = "pulse.create_port"() {uid = "p0"} : () -> !pulse.port %p1 = "pulse.create_port"() {uid = "p1"} : () -> !pulse.port diff --git a/test/Dialect/Pulse/Transforms/classical-only-detection.mlir b/test/Dialect/Pulse/Transforms/classical-only-detection.mlir index 6b1ef82f2..f236766da 100644 --- a/test/Dialect/Pulse/Transforms/classical-only-detection.mlir +++ b/test/Dialect/Pulse/Transforms/classical-only-detection.mlir @@ -18,15 +18,15 @@ // first validate that the pulse classical-only-detection does not harm the quir pass // determinations -func private @kernel1(memref<1xi1>, memref<1xi1>, memref<1xi1>) -> memref<1xi1> attributes {quir.classicalOnly = true} -// CHECK: func private @kernel1(memref<1xi1>, memref<1xi1>, memref<1xi1>) -> memref<1xi1> +func.func private @kernel1(memref<1xi1>, memref<1xi1>, memref<1xi1>) -> memref<1xi1> attributes {quir.classicalOnly = true} +// CHECK: func.func private @kernel1(memref<1xi1>, memref<1xi1>, memref<1xi1>) -> memref<1xi1> // CHECK-SAME: attributes {quir.classicalOnly = true} -func @subroutine1 (%ang1 : !quir.angle<20>, %ang2 : !quir.angle<20>, %q1 : !quir.qubit<1>, %q2 : !quir.qubit<1>) -> (!quir.cbit<1>) attributes {quir.classicalOnly = false} { - // CHECK: func @subroutine1 +func.func @subroutine1 (%ang1 : !quir.angle<20>, %ang2 : !quir.angle<20>, %q1 : !quir.qubit<1>, %q2 : !quir.qubit<1>) -> (!quir.cbit<1>) attributes {quir.classicalOnly = false} { + // CHECK: func.func @subroutine1 // CHECK: attributes {quir.classicalOnly = false} { %zero = arith.constant 0 : index %ang3 = oq3.angle_add %ang1, %ang2 : !quir.angle<20> - %ang4 = quir.constant #quir.angle<0.9 : !quir.angle<20>> + %ang4 = quir.constant #quir.angle<0.9> : !quir.angle<20> %f1 = "oq3.cast"(%ang3) : (!quir.angle<20>) -> f64 %f2 = "oq3.cast"(%ang4) : (!quir.angle<20>) -> f64 %cond1 = arith.cmpf "ogt", %f1, %f2 : f64 @@ -54,11 +54,11 @@ func @subroutine1 (%ang1 : !quir.angle<20>, %ang2 : !quir.angle<20>, %q1 : !quir // next add pulse.sequence and validate that the pulse classical-only-detection // labels the sequence as quir.classicalOnly = false -func private @kernel2(memref<1xi1>, memref<1xi1>, memref<1xi1>) -> memref<1xi1> -// CHECK: func private @kernel2(memref<1xi1>, memref<1xi1>, memref<1xi1>) -> memref<1xi1> +func.func private @kernel2(memref<1xi1>, memref<1xi1>, memref<1xi1>) -> memref<1xi1> +// CHECK: func.func private @kernel2(memref<1xi1>, memref<1xi1>, memref<1xi1>) -> memref<1xi1> // CHECK-SAME: attributes {quir.classicalOnly = true} -func @subroutine2 () { - // CHECK: func @subroutine2() +func.func @subroutine2 () { + // CHECK: func.func @subroutine2() // CHECK-SAME: attributes {quir.classicalOnly = false} { %c0_i32 = arith.constant 0 : i32 diff --git a/test/Dialect/Pulse/Transforms/merge-delay.mlir b/test/Dialect/Pulse/Transforms/merge-delay.mlir index a9e060bb2..429eb3b3a 100644 --- a/test/Dialect/Pulse/Transforms/merge-delay.mlir +++ b/test/Dialect/Pulse/Transforms/merge-delay.mlir @@ -1,4 +1,4 @@ -// RUN: qss-compiler -X=mlir -pass-pipeline='pulse.sequence(pulse-merge-delay)' %s | FileCheck %s +// RUN: qss-compiler -X=mlir -pass-pipeline='any(pulse.sequence(pulse-merge-delay))' %s | FileCheck %s // // This code is part of Qiskit. @@ -13,7 +13,7 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -func @main() -> i32 { +func.func @main() -> i32 { %1 = "pulse.create_port"() {uid = "p0"} : () -> !pulse.port %3 = "pulse.mix_frame"(%1) {uid = "mf0-p0"} : (!pulse.port) -> !pulse.mixed_frame %5 = "pulse.mix_frame"(%1) {uid = "mf1-p0"} : (!pulse.port) -> !pulse.mixed_frame @@ -29,10 +29,10 @@ func @main() -> i32 { } pulse.sequence @seq_0(%arg0: !pulse.mixed_frame, %arg1: !pulse.mixed_frame) -> i1 { - // CHECK: %c6_i32 = arith.constant 6 : i32 - // CHECK-NOT: %c12_i32 = arith.constant 12 : i32 // CHECK: %c18_i32 = arith.constant 18 : i32 // CHECK: %c36_i32 = arith.constant 36 : i32 + // CHECK: %c6_i32 = arith.constant 6 : i32 + // CHECK-NOT: %c12_i32 = arith.constant 12 : i32 %c6_i32 = arith.constant 6 : i32 %c12_i32 = arith.constant 12 : i32 %c18_i32 = arith.constant 18 : i32 diff --git a/test/Dialect/Pulse/Transforms/pulse-inline.mlir b/test/Dialect/Pulse/Transforms/pulse-inline.mlir index 3899b6c87..614f7052c 100644 --- a/test/Dialect/Pulse/Transforms/pulse-inline.mlir +++ b/test/Dialect/Pulse/Transforms/pulse-inline.mlir @@ -14,18 +14,18 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -// CHECK-NOT: func @x0(%arg0: !pulse.port_group) -// CHECK-NOT: func @x0(%arg0: !pulse.port_group) -// CHECK-NOT: func @x0(%arg0: !pulse.port_group) -// CHECK-NOT: func @x0(%arg0: !pulse.port_group) -// CHECK-NOT: func @cx01(%arg0: !pulse.port_group, %arg1: !pulse.port_group) -// CHECK-NOT: func @cx10(%arg0: !pulse.port_group, %arg1: !pulse.port_group) -// CHECK-NOT: func @cx12(%arg0: !pulse.port_group, %arg1: !pulse.port_group) -// CHECK-NOT: func @rz0(%arg0: !pulse.port_group, %arg1: !quir.angle<10>) -// CHECK-NOT: func @rz1(%arg0: !pulse.port_group, %arg1: !quir.angle<10>) -// CHECK-NOT: func @sx1(%arg0: !pulse.port_group) -// CHECK-NOT: func @sx2(%arg0: !pulse.port_group) -// CHECK-NOT: func @sx3(%arg0: !pulse.port_group) +// CHECK-NOT: func.func @x0(%arg0: !pulse.port_group) +// CHECK-NOT: func.func @x0(%arg0: !pulse.port_group) +// CHECK-NOT: func.func @x0(%arg0: !pulse.port_group) +// CHECK-NOT: func.func @x0(%arg0: !pulse.port_group) +// CHECK-NOT: func.func @cx01(%arg0: !pulse.port_group, %arg1: !pulse.port_group) +// CHECK-NOT: func.func @cx10(%arg0: !pulse.port_group, %arg1: !pulse.port_group) +// CHECK-NOT: func.func @cx12(%arg0: !pulse.port_group, %arg1: !pulse.port_group) +// CHECK-NOT: func.func @rz0(%arg0: !pulse.port_group, %arg1: !quir.angle<10>) +// CHECK-NOT: func.func @rz1(%arg0: !pulse.port_group, %arg1: !quir.angle<10>) +// CHECK-NOT: func.func @sx1(%arg0: !pulse.port_group) +// CHECK-NOT: func.func @sx2(%arg0: !pulse.port_group) +// CHECK-NOT: func.func @sx3(%arg0: !pulse.port_group) // CHECK "pulse.select_port"(%arg0) {id = "d0"} : (!pulse.port_group) -> !pulse.port // CHECK "pulse.select_port"(%arg0) {id = "d0"} : (!pulse.port_group) -> !pulse.port @@ -39,7 +39,7 @@ module { -func @x0(%arg0: !pulse.port_group) { +func.func @x0(%arg0: !pulse.port_group) { %0 = "pulse.select_port"(%arg0) {id = "d0"} : (!pulse.port_group) -> !pulse.port %cst = arith.constant 0.17980737117787168 : f64 %cst_0 = arith.constant 0.000000e+00 : f64 @@ -51,7 +51,7 @@ func @x0(%arg0: !pulse.port_group) { pulse.play(%0, %2) : (!pulse.port, !pulse.waveform) return } -func @x1(%arg0: !pulse.port_group) { +func.func @x1(%arg0: !pulse.port_group) { %0 = "pulse.select_port"(%arg0) {id = "d1"} : (!pulse.port_group) -> !pulse.port %cst = arith.constant 0.16946846376475716 : f64 %cst_0 = arith.constant 0.000000e+00 : f64 @@ -63,7 +63,7 @@ func @x1(%arg0: !pulse.port_group) { pulse.play(%0, %2) : (!pulse.port, !pulse.waveform) return } -func @x2(%arg0: !pulse.port_group) { +func.func @x2(%arg0: !pulse.port_group) { %0 = "pulse.select_port"(%arg0) {id = "d2"} : (!pulse.port_group) -> !pulse.port %cst = arith.constant 0.18917049559967117 : f64 %cst_0 = arith.constant 0.000000e+00 : f64 @@ -75,7 +75,7 @@ func @x2(%arg0: !pulse.port_group) { pulse.play(%0, %2) : (!pulse.port, !pulse.waveform) return } -func @x3(%arg0: !pulse.port_group) { +func.func @x3(%arg0: !pulse.port_group) { %0 = "pulse.select_port"(%arg0) {id = "d3"} : (!pulse.port_group) -> !pulse.port %cst = arith.constant 0.19038039184667085 : f64 %cst_0 = arith.constant 0.000000e+00 : f64 @@ -87,7 +87,7 @@ func @x3(%arg0: !pulse.port_group) { pulse.play(%0, %2) : (!pulse.port, !pulse.waveform) return } -func @cx01(%arg0: !pulse.port_group, %arg1: !pulse.port_group) { +func.func @cx01(%arg0: !pulse.port_group, %arg1: !pulse.port_group) { %0 = "pulse.select_port"(%arg0) {id = "d0"} : (!pulse.port_group) -> !pulse.port %cst = arith.constant 1.5707963267948966 : f64 pulse.shift_phase(%0, %cst) : (!pulse.port, f64) @@ -174,7 +174,7 @@ pulse.play(%24, %26) : (!pulse.port, !pulse.waveform) pulse.shift_phase(%27, %cst_33) : (!pulse.port, f64) return } -func @cx10(%arg0: !pulse.port_group, %arg1: !pulse.port_group) { +func.func @cx10(%arg0: !pulse.port_group, %arg1: !pulse.port_group) { %0 = "pulse.select_port"(%arg0) {id = "d0"} : (!pulse.port_group) -> !pulse.port %cst = arith.constant -1.5707963267948966 : f64 pulse.shift_phase(%0, %cst) : (!pulse.port, f64) @@ -321,7 +321,7 @@ pulse.delay(%c1344_i32_55, %46) : (i32, !pulse.port) pulse.shift_phase(%47, %cst_56) : (!pulse.port, f64) return } -func @cx12(%arg0: !pulse.port_group, %arg1: !pulse.port_group) { +func.func @cx12(%arg0: !pulse.port_group, %arg1: !pulse.port_group) { %0 = "pulse.select_port"(%arg0) {id = "d1"} : (!pulse.port_group) -> !pulse.port %cst = arith.constant 1.5707963267948966 : f64 pulse.shift_phase(%0, %cst) : (!pulse.port, f64) @@ -414,7 +414,7 @@ pulse.shift_phase(%28, %cst_34) : (!pulse.port, f64) pulse.shift_phase(%29, %cst_35) : (!pulse.port, f64) return } -func @rz0(%arg0: !pulse.port_group, %arg1: !quir.angle<10>) { +func.func @rz0(%arg0: !pulse.port_group, %arg1: !quir.angle<10>) { %0 = "pulse.select_port"(%arg0) {id = "d0"} : (!pulse.port_group) -> !pulse.port %cst = arith.constant 0.000000e+00 : f64 pulse.shift_phase(%0, %cst) : (!pulse.port, f64) @@ -423,7 +423,7 @@ pulse.shift_phase(%0, %cst) : (!pulse.port, f64) pulse.shift_phase(%1, %cst_0) : (!pulse.port, f64) return } -func @rz1(%arg0: !pulse.port_group, %arg1: !quir.angle<10>) { +func.func @rz1(%arg0: !pulse.port_group, %arg1: !quir.angle<10>) { %0 = "pulse.select_port"(%arg0) {id = "d1"} : (!pulse.port_group) -> !pulse.port %cst = arith.constant 0.000000e+00 : f64 pulse.shift_phase(%0, %cst) : (!pulse.port, f64) @@ -438,7 +438,7 @@ pulse.shift_phase(%2, %cst_1) : (!pulse.port, f64) pulse.shift_phase(%3, %cst_2) : (!pulse.port, f64) return } -func @sx0(%arg0: !pulse.port_group) { +func.func @sx0(%arg0: !pulse.port_group) { %0 = "pulse.select_port"(%arg0) {id = "d0"} : (!pulse.port_group) -> !pulse.port %cst = arith.constant 0.089776566073944741 : f64 %cst_0 = arith.constant -3.3436108695185151E-4 : f64 @@ -450,7 +450,7 @@ func @sx0(%arg0: !pulse.port_group) { pulse.play(%0, %2) : (!pulse.port, !pulse.waveform) return } -func @sx1(%arg0: !pulse.port_group) { +func.func @sx1(%arg0: !pulse.port_group) { %0 = "pulse.select_port"(%arg0) {id = "d1"} : (!pulse.port_group) -> !pulse.port %cst = arith.constant 0.084483000576426853 : f64 %cst_0 = arith.constant 5.1781053983668951E-4 : f64 @@ -462,7 +462,7 @@ func @sx1(%arg0: !pulse.port_group) { pulse.play(%0, %2) : (!pulse.port, !pulse.waveform) return } -func @sx2(%arg0: !pulse.port_group) { +func.func @sx2(%arg0: !pulse.port_group) { %0 = "pulse.select_port"(%arg0) {id = "d2"} : (!pulse.port_group) -> !pulse.port %cst = arith.constant 0.094540487800318596 : f64 %cst_0 = arith.constant -3.9710888891587696E-4 : f64 @@ -474,7 +474,7 @@ func @sx2(%arg0: !pulse.port_group) { pulse.play(%0, %2) : (!pulse.port, !pulse.waveform) return } -func @sx3(%arg0: !pulse.port_group) { +func.func @sx3(%arg0: !pulse.port_group) { %0 = "pulse.select_port"(%arg0) {id = "d3"} : (!pulse.port_group) -> !pulse.port %cst = arith.constant 0.095293610036729287 : f64 %cst_0 = arith.constant 0.0010061143295647052 : f64 @@ -486,7 +486,7 @@ func @sx3(%arg0: !pulse.port_group) { pulse.play(%0, %2) : (!pulse.port, !pulse.waveform) return } -func @main() -> i32 { +func.func @main() -> i32 { %0 = "pulse.create_port"() {uid = "d0"} : () -> !pulse.port %1 = "pulse.create_port"() {uid = "d1"} : () -> !pulse.port %2 = "pulse.create_port"() {uid = "u0"} : () -> !pulse.port @@ -537,22 +537,22 @@ func @main() -> i32 { %47 = "pulse.create_port"() {uid = "u16"} : () -> !pulse.port %48 = "pulse.create_port"() {uid = "u7"} : () -> !pulse.port %49 = "pulse.create_port_group"(%35, %42, %36, %43, %40, %44, %46, %47, %48, %6, %8, %9, %10, %11, %12, %13, %14, %15, %16, %17, %18, %19, %20, %21, %22, %23, %24, %25, %26, %27, %28, %29, %30, %31, %32, %33, %7, %7) : (!pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port, !pulse.port) -> !pulse.port_group -call @x0(%34) : (!pulse.port_group) -> () -call @x1(%41) : (!pulse.port_group) -> () -call @x2(%45) : (!pulse.port_group) -> () -call @x3(%49) : (!pulse.port_group) -> () -call @cx01(%34, %41) : (!pulse.port_group, !pulse.port_group) -> () -call @cx10(%41, %34) : (!pulse.port_group, !pulse.port_group) -> () -call @cx12(%41, %45) : (!pulse.port_group, !pulse.port_group) -> () -%50 = quir.constant #quir.angle<3.140000e+00 : !quir.angle<10>> -%51 = quir.constant #quir.angle<1.070000e+00 : !quir.angle<10>> -%52 = quir.constant #quir.angle<5.350000e-01 : !quir.angle<10>> -call @rz0(%34, %50) : (!pulse.port_group, !quir.angle<10>) -> () -call @rz1(%41, %51) : (!pulse.port_group, !quir.angle<10>) -> () -call @sx0(%34) : (!pulse.port_group) -> () -call @sx1(%41) : (!pulse.port_group) -> () -call @sx2(%45) : (!pulse.port_group) -> () -call @sx3(%49) : (!pulse.port_group) -> () +func.call @x0(%34) : (!pulse.port_group) -> () +func.call @x1(%41) : (!pulse.port_group) -> () +func.call @x2(%45) : (!pulse.port_group) -> () +func.call @x3(%49) : (!pulse.port_group) -> () +func.call @cx01(%34, %41) : (!pulse.port_group, !pulse.port_group) -> () +func.call @cx10(%41, %34) : (!pulse.port_group, !pulse.port_group) -> () +func.call @cx12(%41, %45) : (!pulse.port_group, !pulse.port_group) -> () +%50 = quir.constant #quir.angle<3.140000e+00> : !quir.angle<10> +%51 = quir.constant #quir.angle<1.070000e+00> : !quir.angle<10> +%52 = quir.constant #quir.angle<5.350000e-01> : !quir.angle<10> +func.call @rz0(%34, %50) : (!pulse.port_group, !quir.angle<10>) -> () +func.call @rz1(%41, %51) : (!pulse.port_group, !quir.angle<10>) -> () +func.call @sx0(%34) : (!pulse.port_group) -> () +func.call @sx1(%41) : (!pulse.port_group) -> () +func.call @sx2(%45) : (!pulse.port_group) -> () +func.call @sx3(%49) : (!pulse.port_group) -> () %c0_i32 = arith.constant 0 : i32 return %c0_i32 : i32 } diff --git a/test/Dialect/Pulse/Transforms/pulse-prune.mlir b/test/Dialect/Pulse/Transforms/pulse-prune.mlir index 671c9b62f..8365d352b 100644 --- a/test/Dialect/Pulse/Transforms/pulse-prune.mlir +++ b/test/Dialect/Pulse/Transforms/pulse-prune.mlir @@ -17,7 +17,7 @@ // CHECK-NOT: "pulse.create_port_group" // CHECK-NOT: "pulse.select_port" -func @main() -> i32 { +func.func @main() -> i32 { %0 = "pulse.create_port"() {uid = "d0"} : () -> !pulse.port %1 = "pulse.create_port"() {uid = "d1"} : () -> !pulse.port %2 = "pulse.create_port"() {uid = "u0"} : () -> !pulse.port @@ -422,9 +422,9 @@ pulse.shift_phase(%166, %cst_157) : (!pulse.port, f64) %167 = "pulse.select_port"(%41) {id = "u8"} : (!pulse.port_group) -> !pulse.port %cst_158 = arith.constant 1.5707963267948966 : f64 pulse.shift_phase(%167, %cst_158) : (!pulse.port, f64) -%168 = quir.constant #quir.angle<3.140000e+00 : !quir.angle<10>> -%169 = quir.constant #quir.angle<1.070000e+00 : !quir.angle<10>> -%170 = quir.constant #quir.angle<5.350000e-01 : !quir.angle<10>> +%168 = quir.constant #quir.angle<3.140000e+00> : !quir.angle<10> +%169 = quir.constant #quir.angle<1.070000e+00> : !quir.angle<10> +%170 = quir.constant #quir.angle<5.350000e-01> : !quir.angle<10> %171 = "pulse.select_port"(%34) {id = "d0"} : (!pulse.port_group) -> !pulse.port %cst_159 = arith.constant 0.000000e+00 : f64 pulse.shift_phase(%171, %cst_159) : (!pulse.port, f64) diff --git a/test/Dialect/Pulse/Transforms/pulse-slice.mlir b/test/Dialect/Pulse/Transforms/pulse-slice.mlir index 2477444bd..8ef89423e 100644 --- a/test/Dialect/Pulse/Transforms/pulse-slice.mlir +++ b/test/Dialect/Pulse/Transforms/pulse-slice.mlir @@ -14,17 +14,17 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -// CHECK: func @d0 -// CHECK: func @d1 -// CHECK: func @u0 -// CHECK: func @u1 -// CHECK: func @u4 -// CHECK: func @u8 -// CHECK: func @d2 -// CHECK: func @d3 -// CHECK: func @main +// CHECK: func.func @d0 +// CHECK: func.func @d1 +// CHECK: func.func @u0 +// CHECK: func.func @u1 +// CHECK: func.func @u4 +// CHECK: func.func @u8 +// CHECK: func.func @d2 +// CHECK: func.func @d3 +// CHECK: func.func @main -func @main() -> i32 { +func.func @main() -> i32 { %0 = "pulse.create_port"() {uid = "d0"} : () -> !pulse.port %1 = "pulse.create_port"() {uid = "d1"} : () -> !pulse.port %2 = "pulse.create_port"() {uid = "u0"} : () -> !pulse.port @@ -361,9 +361,9 @@ pulse.play(%35, %99) : (!pulse.port, !pulse.waveform) pulse.shift_phase(%4, %cst_157) : (!pulse.port, f64) %cst_158 = arith.constant 1.5707963267948966 : f64 pulse.shift_phase(%5, %cst_158) : (!pulse.port, f64) -%100 = quir.constant #quir.angle<3.140000e+00 : !quir.angle<10>> -%101 = quir.constant #quir.angle<1.070000e+00 : !quir.angle<10>> -%102 = quir.constant #quir.angle<5.350000e-01 : !quir.angle<10>> +%100 = quir.constant #quir.angle<3.140000e+00> : !quir.angle<10> +%101 = quir.constant #quir.angle<1.070000e+00> : !quir.angle<10> +%102 = quir.constant #quir.angle<5.350000e-01> : !quir.angle<10> %cst_159 = arith.constant 0.000000e+00 : f64 pulse.shift_phase(%0, %cst_159) : (!pulse.port, f64) %cst_160 = arith.constant 0.000000e+00 : f64 diff --git a/test/Dialect/Pulse/Transforms/remove-unused-arguments.mlir b/test/Dialect/Pulse/Transforms/remove-unused-arguments.mlir index 859980ac2..d2492a9fb 100644 --- a/test/Dialect/Pulse/Transforms/remove-unused-arguments.mlir +++ b/test/Dialect/Pulse/Transforms/remove-unused-arguments.mlir @@ -13,7 +13,7 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -func @main() -> i32 { +func.func @main() -> i32 { %1 = "pulse.create_port"() {uid = "p0"} : () -> !pulse.port %3 = "pulse.mix_frame"(%1) {uid = "mf0-p0"} : (!pulse.port) -> !pulse.mixed_frame %5 = "pulse.mix_frame"(%1) {uid = "mf1-p0"} : (!pulse.port) -> !pulse.mixed_frame diff --git a/test/Dialect/Pulse/Transforms/schedule-port-acquire.mlir b/test/Dialect/Pulse/Transforms/schedule-port-acquire.mlir index c29a84e66..a1fb53ba8 100644 --- a/test/Dialect/Pulse/Transforms/schedule-port-acquire.mlir +++ b/test/Dialect/Pulse/Transforms/schedule-port-acquire.mlir @@ -60,12 +60,12 @@ module @acquire_0 attributes {quir.nodeId = 7 : i32, quir.nodeType = "acquire", pulse.delay(%arg0, %c1000_i32) : (!pulse.mixed_frame, i32) // CHECK-NOT: pulse.delay(%[[ARG1]], %c1000_i32) : (!pulse.mixed_frame, i32) %1 = pulse.call_sequence @seq_0(%arg0, %arg1, %arg2, %arg3, %arg4) : (!pulse.mixed_frame, !pulse.mixed_frame, !pulse.mixed_frame, !pulse.mixed_frame, !pulse.mixed_frame) -> i1 - // CHECK: %1 = pulse.call_sequence @seq_0(%arg0, %arg1, %arg2, %arg3, %arg4) {pulse.duration = 18096 : i64, pulse.timepoint = 20096 : i64} + // CHECK: %1 = pulse.call_sequence @seq_0(%arg0, %arg1, %arg2, %arg3, %arg4) {pulse.duration = 18096 : i64, pulse.timepoint = 20096 : i64} pulse.delay(%arg0, %c1000_i32) : (!pulse.mixed_frame, i32) // CHECK-NOT: pulse.delay(%[[ARG1]], %c1000_i32) : (!pulse.mixed_frame, i32) pulse.return %0, %1 : i1, i1 } - func @main() -> i32 attributes {quir.classicalOnly = false} { + func.func @main() -> i32 attributes {quir.classicalOnly = false} { %c0_i32 = arith.constant 0 : i32 %2 = "pulse.create_port"() {uid = "p0"} : () -> !pulse.port %4 = "pulse.mix_frame"(%2) {uid = "mf0-p0"} : (!pulse.port) -> !pulse.mixed_frame diff --git a/test/Dialect/Pulse/Transforms/schedule-port-drive.mlir b/test/Dialect/Pulse/Transforms/schedule-port-drive.mlir index cd96e3dbd..500d3f620 100644 --- a/test/Dialect/Pulse/Transforms/schedule-port-drive.mlir +++ b/test/Dialect/Pulse/Transforms/schedule-port-drive.mlir @@ -43,7 +43,7 @@ module @drive_0 attributes {quir.nodeId = 0 : i32, quir.nodeType = "drive", quir // CHECK: pulse.return {pulse.timepoint = 15 : i64} %false : i1 pulse.return %false : i1 } - func @main() -> i32 attributes {quir.classicalOnly = false} { + func.func @main() -> i32 attributes {quir.classicalOnly = false} { %c0_i32 = arith.constant 0 : i32 %2 = "pulse.create_port"() {uid = "p0"} : () -> !pulse.port %4 = "pulse.mix_frame"(%2) {uid = "mf0-p0"} : (!pulse.port) -> !pulse.mixed_frame diff --git a/test/Dialect/QUIR/IR/angle-cmp-ops.mlir b/test/Dialect/QUIR/IR/angle-cmp-ops.mlir index e4c703dc1..a92d86b93 100644 --- a/test/Dialect/QUIR/IR/angle-cmp-ops.mlir +++ b/test/Dialect/QUIR/IR/angle-cmp-ops.mlir @@ -13,10 +13,10 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -// CHECK: [[a0:%angle[_0-9]*]] = quir.constant #quir.angle<0.000000e+00 : !quir.angle<20>> -%a0 = quir.constant #quir.angle<0.0 : !quir.angle<20>> -// CHECK: [[a1:%angle[_0-9]*]] = quir.constant #quir.angle<0.000000e+00 : !quir.angle<20>> -%a1 = quir.constant #quir.angle<0.0 : !quir.angle<20>> +// CHECK: [[a0:%angle[_0-9]*]] = quir.constant #quir.angle<0.000000e+00> : !quir.angle<20> +%a0 = quir.constant #quir.angle<0.0> : !quir.angle<20> +// CHECK: [[a1:%angle[_0-9]*]] = quir.constant #quir.angle<0.000000e+00> : !quir.angle<20> +%a1 = quir.constant #quir.angle<0.0> : !quir.angle<20> // CHECK-COUNT-10: %{{.*}} = oq3.angle_cmp {predicate = "{{.*}}"} [[a0]], [[a1]] : !quir.angle<20> -> i1 %b0 = oq3.angle_cmp {predicate = "eq"} %a0, %a1 : !quir.angle<20> -> i1 %b1 = oq3.angle_cmp {predicate = "ne"} %a0, %a1 : !quir.angle<20> -> i1 diff --git a/test/Dialect/QUIR/IR/canonicalization.mlir b/test/Dialect/QUIR/IR/canonicalization.mlir index cbc1005ad..8415de9e3 100644 --- a/test/Dialect/QUIR/IR/canonicalization.mlir +++ b/test/Dialect/QUIR/IR/canonicalization.mlir @@ -13,8 +13,8 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -// CHECK: func @t1 -func @t1 (%arg1 : !quir.cbit<1>) -> (!quir.cbit<1>) { +// CHECK: func.func @t1 +func.func @t1 (%arg1 : !quir.cbit<1>) -> (!quir.cbit<1>) { // CHECK: oq3.cbit_not %{{.*}} : !quir.cbit<1> // CHECK-NOT: oq3.cbit_not %{{.*}} : !quir.cbit<1> %c2 = oq3.cbit_not %arg1 : !quir.cbit<1> @@ -23,8 +23,8 @@ func @t1 (%arg1 : !quir.cbit<1>) -> (!quir.cbit<1>) { return %c4 : !quir.cbit<1> } -// CHECK: func @t2 -func @t2 (%arg1 : !quir.cbit<1>) -> (!quir.cbit<1>) { +// CHECK: func.func @t2 +func.func @t2 (%arg1 : !quir.cbit<1>) -> (!quir.cbit<1>) { // CHECK-NOT: oq3.cbit_not %{{.*}} : !quir.cbit<1> // CHECK-NOT: oq3.cbit_not %{{.*}} : !quir.cbit<1> %c2 = oq3.cbit_not %arg1 : !quir.cbit<1> @@ -32,8 +32,8 @@ func @t2 (%arg1 : !quir.cbit<1>) -> (!quir.cbit<1>) { return %c3 : !quir.cbit<1> } -// CHECK: func @t7 -func @t7 (%arg0 : i32, %arg1 : f32) -> (i32, f32) { +// CHECK: func.func @t7 +func.func @t7 (%arg0 : i32, %arg1 : f32) -> (i32, f32) { %r1 = "oq3.cast"(%arg0) : (i32) -> i32 %r2 = "oq3.cast"(%arg1) : (f32) -> f32 // CHECK: return %arg0, %arg1 : i32, f32 diff --git a/test/Dialect/QUIR/IR/control-flow.mlir b/test/Dialect/QUIR/IR/control-flow.mlir index 7b1ecfea8..02c16020f 100644 --- a/test/Dialect/QUIR/IR/control-flow.mlir +++ b/test/Dialect/QUIR/IR/control-flow.mlir @@ -32,7 +32,7 @@ // angle[3] c = 0; %qq1 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %qr1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> -%angleC = quir.constant #quir.angle<0.0 : !quir.angle<3>> +%angleC = quir.constant #quir.angle<0.0> : !quir.angle<3> // reset q; // reset r; quir.reset %qq1 : !quir.qubit<1> @@ -57,17 +57,17 @@ quir.reset %qr1 : !quir.qubit<1> "quir.call_gate"(%qq1) {callee = @H} : (!quir.qubit<1>) -> () // cphase(power*3*pi/8) q, r; %power1_angle = "oq3.cast"(%power1_iter) : (i3) -> !quir.angle<3> - %angle_multiplicand = quir.constant #quir.angle<0.375 : !quir.angle<3>> + %angle_multiplicand = quir.constant #quir.angle<0.375> : !quir.angle<3> %angleP = oq3.angle_mul %power1_angle, %angle_multiplicand : !quir.angle<3> "quir.call_gate"(%qq1, %qr1, %angleP) {callee = @cphase} : (!quir.qubit<1>, !quir.qubit<1>, !quir.angle<3>) -> () - %angle_zero = quir.constant #quir.angle<0.0 : !quir.angle<3>> + %angle_zero = quir.constant #quir.angle<0.0> : !quir.angle<3> %negC = oq3.angle_sub %angle_zero, %angleC_iter : !quir.angle<3> // phase(-c) q; // h q; // measure q -> c[0]; // c <<= 1; // power <<= 1; - %angleC_shift = quir.constant #quir.angle<0.0 : !quir.angle<3>> + %angleC_shift = quir.constant #quir.angle<0.0> : !quir.angle<3> %power_shift = arith.constant 1 : i3 // } // CHECK: scf.yield %{{.*}}, %{{.*}} : !quir.angle<3>, i3 diff --git a/test/Dialect/QUIR/IR/declarations.mlir b/test/Dialect/QUIR/IR/declarations.mlir index 21b2dc26d..5cce64264 100644 --- a/test/Dialect/QUIR/IR/declarations.mlir +++ b/test/Dialect/QUIR/IR/declarations.mlir @@ -16,19 +16,19 @@ // This test case checks that QUIR declarations can be parsed from // textual/assembly input. module { - func @bar() { + func.func @bar() { // CHECK: %{{.*}} = quir.declare_qubit : !quir.qubit<1> %qa1 = quir.declare_qubit : !quir.qubit<1> %qb1 = quir.declare_qubit : !quir.qubit<1> %qc1 = quir.declare_qubit : !quir.qubit<1> // CHECK: %{{.*}} = quir.declare_qubit : !quir.qubit<1> %qd1 = quir.declare_qubit : !quir.qubit<1> - // CHECK: %{{.*}} = quir.constant #quir.angle<1.000000e-01 : !quir.angle<1>> - %theta = quir.constant #quir.angle<0.1 : !quir.angle<1>> - // CHECK: %{{.*}} = quir.constant #quir.angle<2.000000e-01 : !quir.angle> - %mu = quir.constant #quir.angle<0.2 : !quir.angle> - // CHECK %{{.*}} = quir.constant #quir.duration<1.000000e+00 : !quir.duration> - %len1 = quir.constant #quir.duration<10.0 : !quir.duration> + // CHECK: %{{.*}} = quir.constant #quir.angle<1.000000e-01> : !quir.angle<1> + %theta = quir.constant #quir.angle<0.1> : !quir.angle<1> + // CHECK: %{{.*}} = quir.constant #quir.angle<2.000000e-01> : !quir.angle + %mu = quir.constant #quir.angle<0.2> : !quir.angle + // CHECK %{{.*}} = quir.constant #quir.angle<1.000000e+00> : !quir.angle + %len1 = quir.constant #quir.duration<10.0> : !quir.duration // CHECK %{{.*}} = oq3.declare_stretch : !quir.stretch %s1 = "oq3.declare_stretch"() : () -> !quir.stretch // CHECK %{{.*}} = oq3.declare_stretch : !quir.stretch diff --git a/test/Dialect/QUIR/IR/error-testing.mlir b/test/Dialect/QUIR/IR/error-testing.mlir index 1ca934cce..ce0190ae3 100644 --- a/test/Dialect/QUIR/IR/error-testing.mlir +++ b/test/Dialect/QUIR/IR/error-testing.mlir @@ -15,7 +15,7 @@ // ----- -func @qubit_type_parse_error() { +func.func @qubit_type_parse_error() { // expected-error@+1 {{width must be > 0}} %q1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<0> return @@ -23,18 +23,17 @@ func @qubit_type_parse_error() { // ----- -func @angle_type_parse_error() { - // expected-error@+2 {{failed to parse QUIR_AngleAttr parameter 'type' which is to be a `::mlir::Type`}} +func.func @angle_type_parse_error() { // expected-error@+1 {{width must be > 0}} - %a1 = quir.constant #quir.angle<1.0 : !quir.angle<0>> + %a1 = quir.constant #quir.angle<1.0> : !quir.angle<0> return } // ----- -func @angle_type_cmp_error() { - %a1 = quir.constant #quir.angle<0.0 : !quir.angle<20>> - %a2 = quir.constant #quir.angle<0.0 : !quir.angle<20>> +func.func @angle_type_cmp_error() { + %a1 = quir.constant #quir.angle<0.0> : !quir.angle<20> + %a2 = quir.constant #quir.angle<0.0> : !quir.angle<20> // expected-error@+1 {{'oq3.angle_cmp' op requires predicate "eq", "ne", "slt", "sle", "sgt", "sge", "ult", "ule", "ugt", "uge"}} %b = oq3.angle_cmp {predicate = "test"} %a1, %a2 : !quir.angle<20> -> i1 return @@ -42,8 +41,8 @@ func @angle_type_cmp_error() { // ----- -func @call_defcal_measure_no_qubit_args() { - %c1 = quir.constant #quir.angle<1.0 : !quir.angle<20>> +func.func @call_defcal_measure_no_qubit_args() { + %c1 = quir.constant #quir.angle<1.0> : !quir.angle<20> // expected-error@+1 {{'quir.call_defcal_measure' op requires exactly one qubit}} %a1 = quir.call_defcal_measure @proto1(%c1) : (!quir.angle<20>) -> i1 return @@ -51,7 +50,7 @@ func @call_defcal_measure_no_qubit_args() { // ----- -func @call_defcal_measure_too_many_qubit_args() { +func.func @call_defcal_measure_too_many_qubit_args() { %q0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %q1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> // expected-error@+1 {{'quir.call_defcal_measure' op requires exactly one qubit argument}} @@ -61,11 +60,11 @@ func @call_defcal_measure_too_many_qubit_args() { // ----- -func @quir_switch (%flag: i32) -> (i32) { +func.func @quir_switch (%flag: i32) -> (i32) { // expected-error@+1 {{expected '{' to begin a region}} %y = quir.switch %flag -> (i32) [ 4: { - %y_1 = constant 1 : i32 + %y_1 = arith.constant 1 : i32 quir.yield %y_1 : i32 } ] @@ -74,7 +73,7 @@ func @quir_switch (%flag: i32) -> (i32) { // ----- -func @quir_switch (%flag: i32) -> (i32) { +func.func @quir_switch (%flag: i32) -> (i32) { %y = quir.switch %flag -> (i32) { %y_default = arith.constant 0 : i32 @@ -82,7 +81,7 @@ func @quir_switch (%flag: i32) -> (i32) { quir.yield } [ 1: { - %y_1 = constant 1 : i32 + %y_1 = arith.constant 1 : i32 quir.yield %y_1 : i32 } ] diff --git a/test/Dialect/QUIR/IR/gate-tests.mlir b/test/Dialect/QUIR/IR/gate-tests.mlir index 863089121..a4b05c772 100644 --- a/test/Dialect/QUIR/IR/gate-tests.mlir +++ b/test/Dialect/QUIR/IR/gate-tests.mlir @@ -14,22 +14,22 @@ // that they have been altered from the originals. module { - func private @kernel1 (%ca1 : memref<1xi1>, %ca2 : memref<1xi1>, %ca3 : memref<1xi1>) -> memref<1xi1> - func private @proto (%qa1 : !quir.qubit<1>) -> !quir.qubit<1> - func @gateCall1(%q1 : !quir.qubit<1>, %lambda : !quir.angle<1>) -> () { - %zero = quir.constant #quir.angle<0.0 : !quir.angle<1>> + func.func private @kernel1 (%ca1 : memref<1xi1>, %ca2 : memref<1xi1>, %ca3 : memref<1xi1>) -> memref<1xi1> + func.func private @proto (%qa1 : !quir.qubit<1>) -> !quir.qubit<1> + func.func @gateCall1(%q1 : !quir.qubit<1>, %lambda : !quir.angle<1>) -> () { + %zero = quir.constant #quir.angle<0.0> : !quir.angle<1> quir.builtin_U %q1, %zero, %zero, %lambda : !quir.qubit<1>, !quir.angle<1>, !quir.angle<1>, !quir.angle<1> return } - // CHECK-LABEL: func @bar() - func @bar() { + // CHECK-LABEL: func.func @bar() + func.func @bar() { %qa1 = quir.declare_qubit : !quir.qubit<1> %qb1 = quir.declare_qubit : !quir.qubit<1> %qc1 = quir.declare_qubit : !quir.qubit<1> // CHECK: quir.builtin_CX %{{.*}}, %{{.*}} : !quir.qubit<1>, !quir.qubit<1> quir.builtin_CX %qa1, %qb1 : !quir.qubit<1>, !quir.qubit<1> - // CHECK: %{{.*}} = quir.constant #quir.angle<1.000000e-01 : !quir.angle<1>> - %theta = quir.constant #quir.angle<0.1 : !quir.angle<1>> + // CHECK: %{{.*}} = quir.constant #quir.angle<1.000000e-01> : !quir.angle<1> + %theta = quir.constant #quir.angle<0.1> : !quir.angle<1> // CHECK: quir.builtin_U %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : !quir.qubit<1>, !quir.angle<1>, !quir.angle<1>, !quir.angle<1> quir.builtin_U %qb1, %theta, %theta, %theta : !quir.qubit<1>, !quir.angle<1>, !quir.angle<1>, !quir.angle<1> return diff --git a/test/Dialect/QUIR/IR/invalid.mlir b/test/Dialect/QUIR/IR/invalid.mlir index 050a5102a..a31e59dd7 100644 --- a/test/Dialect/QUIR/IR/invalid.mlir +++ b/test/Dialect/QUIR/IR/invalid.mlir @@ -15,7 +15,7 @@ // ----- -func @call_circuit_no_matching_cicuit(){ +func.func @call_circuit_no_matching_cicuit(){ quir.circuit @circuit_1() { quir.return } @@ -31,7 +31,7 @@ quir.circuit @circuit_1(%arg1: !quir.angle<32>) { quir.return } -func @call_circuit_call_does_not_match_operands(){ +func.func @call_circuit_call_does_not_match_getOperands(){ // expected-error@+1 {{'quir.call_circuit' op incorrect number of operands for the callee circuit}} quir.call_circuit @circuit_1 () : () -> () return @@ -39,12 +39,13 @@ func @call_circuit_call_does_not_match_operands(){ // ----- +// expected-note@below {{return type declared here}} quir.circuit @circuit_1() -> i1 { + // expected-error@below {{expected 1 result operands}} quir.return } -func @call_circuit_call_does_not_match_results(){ - // expected-error@+1 {{'quir.call_circuit' op incorrect number of results for the callee circuit}} +func.func @call_circuit_call_does_not_match_results(){ quir.call_circuit @circuit_1 () : () -> () return } @@ -55,7 +56,7 @@ quir.circuit @circuit_1(%arg1: !quir.angle<16>) { quir.return } -func @call_circuit_call_operand_types_do_not_match(%arg1: i1){ +func.func @call_circuit_call_operand_types_do_not_match(%arg1: i1){ // expected-error@below {{'quir.call_circuit' op operand type mismatch at index 0}} // expected-note@below {{op input types: 'i1'}} // expected-note@below {{function operand types: '!quir.angle<16>'}} @@ -65,14 +66,14 @@ func @call_circuit_call_operand_types_do_not_match(%arg1: i1){ // ----- +// expected-note@below {{return type declared here}} quir.circuit @circuit_1() -> i32 { + // expected-error@below {{expected 1 result operands}} quir.return } -func @call_circuit_call_result_types_do_not_match() { - // expected-error@below {{'quir.call_circuit' op result type mismatch at index 0}} - // expected-note@below {{op result types: 'i1'}} - // expected-note@below {{function result types: 'i32'}} +func.func @call_circuit_call_result_types_do_not_match() { quir.call_circuit @circuit_1 () : () -> (i1) return } + diff --git a/test/Dialect/QUIR/IR/ops.mlir b/test/Dialect/QUIR/IR/ops.mlir index a5905b1e4..4d0e3fa04 100644 --- a/test/Dialect/QUIR/IR/ops.mlir +++ b/test/Dialect/QUIR/IR/ops.mlir @@ -19,9 +19,9 @@ // CHECK-LABEL: quir.circuit @circuit1(%{{.*}}: !quir.qubit<1>, %{{.*}}: !quir.qubit<1>, %{{.*}}: !quir.angle<32>) -> i1 { quir.circuit @circuit1 (%q0 : !quir.qubit<1>, %q1 : !quir.qubit<1>, %theta: !quir.angle<32>) -> i1 { - %a0 = quir.constant #quir.angle<1.57079632679 : !quir.angle<20>> - %a1 = quir.constant #quir.angle<0.0 : !quir.angle<20>> - %a2 = quir.constant #quir.angle<3.14159265359 : !quir.angle<20>> + %a0 = quir.constant #quir.angle<1.57079632679> : !quir.angle<20> + %a1 = quir.constant #quir.angle<0.0> : !quir.angle<20> + %a2 = quir.constant #quir.angle<3.14159265359> : !quir.angle<20> quir.builtin_U %q0, %a0, %a1, %a2 : !quir.qubit<1>, !quir.angle<20>, !quir.angle<20>, !quir.angle<20> quir.builtin_CX %q0, %q1 : !quir.qubit<1>, !quir.qubit<1> @@ -47,8 +47,8 @@ quir.circuit @circuit2 (%q0: !quir.qubit<1>, %omega: !quir.angle<32>) -> (i1, i1 quir.return %res0, %res0 : i1, i1 } -// CHECK-LABEL: func @quir_switch(%arg0: i32) -> i32 -func @quir_switch (%flag: i32) -> (i32) { +// CHECK-LABEL: func.func @quir_switch(%arg0: i32) -> i32 +func.func @quir_switch (%flag: i32) -> (i32) { // CHECK: %[[y:.*]] = quir.switch %arg0 -> (i32) %y = quir.switch %flag -> (i32) { // CHECK: %[[y_def:.*]] = arith.constant 0 : i32 @@ -66,10 +66,10 @@ func @quir_switch (%flag: i32) -> (i32) { // CHECK: %[[qb1:.*]] = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %qb1 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> - // CHECK: %[[theta:.*]] = quir.constant #quir.angle<1.000000e-01 : !quir.angle<1>> - %theta = quir.constant #quir.angle<0.1 : !quir.angle<1>> - // CHECK: %[[twotheta:.*]] = quir.constant #quir.angle<2.000000e-01 : !quir.angle<1>> - %twotheta = quir.constant #quir.angle<0.2 : !quir.angle<1>> + // CHECK: %[[theta:.*]] = quir.constant #quir.angle<1.000000e-01> : !quir.angle<1> + %theta = quir.constant #quir.angle<0.1> : !quir.angle<1> + // CHECK: %[[twotheta:.*]] = quir.constant #quir.angle<2.000000e-01> : !quir.angle<1> + %twotheta = quir.constant #quir.angle<0.2> : !quir.angle<1> // CHECK: quir.switch %arg0 quir.switch %flag { @@ -90,23 +90,23 @@ func @quir_switch (%flag: i32) -> (i32) { return %y : i32 } -// CHECK-LABEL: func @quir_durations() -func @quir_durations () { - %duration_dt0 = quir.constant #quir.duration<10.0 :
> - // CHECK: {{.*}} = quir.constant #quir.duration<1.000000e+01 :
> - %duration_dt1 = quir.constant #quir.duration<10.0 : !quir.duration
> - // CHECK: {{.*}} = quir.constant #quir.duration<1.000000e+01 :
> - %duration_s = quir.constant #quir.duration<10.0 : !quir.duration> - // CHECK: {{.*}} = quir.constant #quir.duration<1.000000e+01 : > - %duration_ms = quir.constant #quir.duration<10.0 : !quir.duration> - // CHECK: {{.*}} = quir.constant #quir.duration<1.000000e+01 : > - %duration_us = quir.constant #quir.duration<10.0 : !quir.duration> - // CHECK: {{.*}} = quir.constant #quir.duration<1.000000e+01 : > - %duration_ns = quir.constant #quir.duration<10.0 : !quir.duration> - // CHECK: {{.*}} = quir.constant #quir.duration<1.000000e+01 : > - %duration_ps = quir.constant #quir.duration<10.0 : !quir.duration> - // CHECK: {{.*}} = quir.constant #quir.duration<1.000000e+01 : > - %duration_fs = quir.constant #quir.duration<10.0 : !quir.duration> - // CHECK: {{.*}} = quir.constant #quir.duration<1.000000e+01 : > +// CHECK-LABEL: func.func @quir_durations() +func.func @quir_durations () { + %duration_dt0 = quir.constant #quir.duration<10.0> : !quir.duration
+ // CHECK: {{.*}} = quir.constant #quir.duration<1.000000e+01> : !quir.duration
+ %duration_dt1 = quir.constant #quir.duration<10.0> : !quir.duration
+ // CHECK: {{.*}} = quir.constant #quir.duration<1.000000e+01> : !quir.duration
+ %duration_s = quir.constant #quir.duration<10.0> : !quir.duration + // CHECK: {{.*}} = quir.constant #quir.duration<1.000000e+01> : !quir.duration + %duration_ms = quir.constant #quir.duration<10.0> : !quir.duration + // CHECK: {{.*}} = quir.constant #quir.duration<1.000000e+01> : !quir.duration + %duration_us = quir.constant #quir.duration<10.0> : !quir.duration + // CHECK: {{.*}} = quir.constant #quir.duration<1.000000e+01> : !quir.duration + %duration_ns = quir.constant #quir.duration<10.0> : !quir.duration + // CHECK: {{.*}} = quir.constant #quir.duration<1.000000e+01> : !quir.duration + %duration_ps = quir.constant #quir.duration<10.0> : !quir.duration + // CHECK: {{.*}} = quir.constant #quir.duration<1.000000e+01> : !quir.duration + %duration_fs = quir.constant #quir.duration<10.0> : !quir.duration + // CHECK: {{.*}} = quir.constant #quir.duration<1.000000e+01> : !quir.duration return } diff --git a/test/Dialect/QUIR/IR/qubit-op-interface.mlir b/test/Dialect/QUIR/IR/qubit-op-interface.mlir index 017bd2d15..f4a2a9c93 100644 --- a/test/Dialect/QUIR/IR/qubit-op-interface.mlir +++ b/test/Dialect/QUIR/IR/qubit-op-interface.mlir @@ -23,7 +23,7 @@ quir.circuit @circuit0 (%q0: !quir.qubit<1> {quir.physicalId = 0 : i32}) -> (i1, quir.return %res0, %res0 : i1, i1 } -func @test_qubit_op_interface (%cond : i1) -> () { +func.func @test_qubit_op_interface (%cond : i1) -> () { %q0 = quir.declare_qubit {id = 0: i32} : !quir.qubit<1> %q1 = quir.declare_qubit {id = 1: i32} : !quir.qubit<1> %q2 = quir.declare_qubit {id = 2: i32} : !quir.qubit<1> @@ -38,16 +38,16 @@ func @test_qubit_op_interface (%cond : i1) -> () { quir.barrier %q0, %q1 : (!quir.qubit<1>, !quir.qubit<1>) -> () // CHECK: quir.barrier {{.*}}, {{.*}} {quir.operatedQubits = [0 : i32, 1 : i32]} : (!quir.qubit<1>, !quir.qubit<1>) -> () - %a0 = quir.constant #quir.angle<1.57079632679 : !quir.angle<20>> - %a1 = quir.constant #quir.angle<0.0 : !quir.angle<20>> - %a2 = quir.constant #quir.angle<3.14159265359 : !quir.angle<20>> + %a0 = quir.constant #quir.angle<1.57079632679> : !quir.angle<20> + %a1 = quir.constant #quir.angle<0.0> : !quir.angle<20> + %a2 = quir.constant #quir.angle<3.14159265359> : !quir.angle<20> quir.builtin_U %q0, %a0, %a1, %a2 : !quir.qubit<1>, !quir.angle<20>, !quir.angle<20>, !quir.angle<20> // CHECK: quir.builtin_U {quir.operatedQubits = [0 : i32]} {{.*}}, %angle, %angle_0, %angle_1 : !quir.qubit<1>, !quir.angle<20>, !quir.angle<20>, !quir.angle<20> quir.builtin_CX %q0, %q1 : !quir.qubit<1>, !quir.qubit<1> // CHECK: quir.builtin_CX {quir.operatedQubits = [0 : i32, 1 : i32]} {{.*}}, {{.*}} : !quir.qubit<1>, !quir.qubit<1> - %duration = quir.constant #quir.duration<20.0 : !quir.duration> + %duration = quir.constant #quir.duration<20.0> : !quir.duration quir.delay %duration, (%q0) : !quir.duration, (!quir.qubit<1>) -> () // CHECK: quir.delay {quir.operatedQubits = [0 : i32]} {{.*}}, ({{.*}}) : !quir.duration, (!quir.qubit<1>) -> () diff --git a/test/Dialect/QUIR/IR/test.mlir b/test/Dialect/QUIR/IR/test.mlir index 80648c19c..d8f28edf0 100644 --- a/test/Dialect/QUIR/IR/test.mlir +++ b/test/Dialect/QUIR/IR/test.mlir @@ -14,15 +14,15 @@ // that they have been altered from the originals. module { - func private @proto (%qa1 : !quir.qubit<1>) -> () - // CHECK-LABEL: func @gateCall1 - func @gateCall1(%q1 : !quir.qubit<1>, %lambda : !quir.angle<1>) -> () { - %zero = quir.constant #quir.angle<0.0 : !quir.angle<1>> + func.func private @proto (%qa1 : !quir.qubit<1>) -> () + // CHECK-LABEL: func.func @gateCall1 + func.func @gateCall1(%q1 : !quir.qubit<1>, %lambda : !quir.angle<1>) -> () { + %zero = quir.constant #quir.angle<0.0> : !quir.angle<1> // CHECK: quir.builtin_U %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : !quir.qubit<1>, !quir.angle<1>, !quir.angle<1>, !quir.angle<1> quir.builtin_U %q1, %zero, %zero, %lambda : !quir.qubit<1>, !quir.angle<1>, !quir.angle<1>, !quir.angle<1> return } - func @subroutine1(%q1 : !quir.qubit<1>, %phi : !quir.angle, %ub : index) { + func.func @subroutine1(%q1 : !quir.qubit<1>, %phi : !quir.angle, %ub : index) { %lb = arith.constant 0 : index %step = arith.constant 1 : index scf.for %iv = %lb to %ub step %step { @@ -38,8 +38,8 @@ module { } return } - // CHECK-LABEL: func @bar() - func @bar() { + // CHECK-LABEL: func.func @bar() + func.func @bar() { // CHECK: qcs.init qcs.init // CHECK: qcs.finalize @@ -49,14 +49,14 @@ module { %0 = arith.constant 1 : i32 %val = arith.constant 1 : i1 // quir.constant canonical form example with angle attribute - // CHECK: %angle{{.*}} = quir.constant #quir.angle<1.000000e+00 : !quir.angle<10>> - %angle1 = "quir.constant"() {"value" = #quir.angle<1.0 : !quir.angle<10>>} : () -> (!quir.angle<10>) - // CHECK: %angle{{.*}} = quir.constant #quir.angle<0.000000e+00 : !quir.angle<10>> - %angle2 = quir.constant #quir.angle<0.0 : !quir.angle<10>> - // CHECK: %angle{{.*}} = quir.constant #quir.angle<1.000000e+01 : !quir.angle> - %angle3 = quir.constant #quir.angle<10.0 : !quir.angle> - // CHECK: %angle{{.*}} = quir.constant #quir.angle<3.141591 : !quir.angle<20>> - %angle4 = quir.constant #quir.angle<3.141591 : !quir.angle<20>> + // CHECK: %angle{{.*}} = quir.constant #quir.angle<1.000000e+00> : !quir.angle<10> + %angle1 = "quir.constant"() {"value" = #quir.angle<1.0> : !quir.angle<10>} : () -> (!quir.angle<10>) + // CHECK: %angle{{.*}} = quir.constant #quir.angle<0.000000e+00> : !quir.angle<10> + %angle2 = quir.constant #quir.angle<0.0> : !quir.angle<10> + // CHECK: %angle{{.*}} = quir.constant #quir.angle<1.000000e+01> : !quir.angle + %angle3 = quir.constant #quir.angle<10.0> : !quir.angle + // CHECK: %angle{{.*}} = quir.constant #quir.angle<3.141591> : !quir.angle<20> + %angle4 = quir.constant #quir.angle<3.141591> : !quir.angle<20> // arbitrary constants can also be produced // CHECK: %qcst{{.*}} = quir.constant 2 : i16 %qcst = quir.constant 2 : i16 @@ -68,8 +68,8 @@ module { quir.reset %qc1 : !quir.qubit<1> // CHECK: quir.builtin_CX %{{.*}}, %{{.*}} : !quir.qubit<1>, !quir.qubit<1> quir.builtin_CX %qa1, %qb1 : !quir.qubit<1>, !quir.qubit<1> - // CHECK: %{{.*}} = quir.constant #quir.angle<1.000000e-01 : !quir.angle<1>> - %theta = quir.constant #quir.angle<0.1 : !quir.angle<1>> + // CHECK: %{{.*}} = quir.constant #quir.angle<1.000000e-01> : !quir.angle<1> + %theta = quir.constant #quir.angle<0.1> : !quir.angle<1> // CHECK: quir.builtin_U %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : !quir.qubit<1>, !quir.angle<1>, !quir.angle<1>, !quir.angle<1> quir.builtin_U %qb1, %theta, %theta, %theta : !quir.qubit<1>, !quir.angle<1>, !quir.angle<1>, !quir.angle<1> // CHECK: quir.call_gate @gateCall1(%{{.*}}, %{{.*}}) : (!quir.qubit<1>, !quir.angle<1>) -> () @@ -97,8 +97,8 @@ module { %ca3 = quir.call_defcal_measure @defcalMeas1(%qa1) : (!quir.qubit<1>) -> i1 // CHECK: %{{.*}} = "oq3.cast"(%{{.*}}) : (i1) -> !quir.angle<20> %ang = "oq3.cast"(%ca3) : (i1) -> !quir.angle<20> - // CHECK: %{{.*}} = quir.constant #quir.duration<1.000000e+01 : > - %len1 = quir.constant #quir.duration<10.0 : !quir.duration> + // CHECK: %{{.*}} = quir.constant #quir.duration<1.000000e+01> : !quir.duration + %len1 = quir.constant #quir.duration<10.0> : !quir.duration // CHECK: %{{.*}} = oq3.declare_stretch : !quir.stretch %s1 = "oq3.declare_stretch"() : () -> !quir.stretch // CHECK: %{{.*}} = oq3.declare_stretch : !quir.stretch diff --git a/test/Dialect/QUIR/Transforms/add-shot-loop.mlir b/test/Dialect/QUIR/Transforms/add-shot-loop.mlir index 015f1848f..112552f50 100644 --- a/test/Dialect/QUIR/Transforms/add-shot-loop.mlir +++ b/test/Dialect/QUIR/Transforms/add-shot-loop.mlir @@ -13,7 +13,7 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -func @main() { +func.func @main() { qcs.init // CHECK: scf.for // CHECK: qcs.shot_init diff --git a/test/Dialect/QUIR/Transforms/arg-specialization0.mlir b/test/Dialect/QUIR/Transforms/arg-specialization0.mlir index 9adfa9b57..ca57f4b79 100644 --- a/test/Dialect/QUIR/Transforms/arg-specialization0.mlir +++ b/test/Dialect/QUIR/Transforms/arg-specialization0.mlir @@ -20,51 +20,51 @@ module { oq3.declare_variable @cb1 : !quir.cbit<1> oq3.declare_variable @cb2 : !quir.cbit<1> - func private @proto (%qa1 : !quir.qubit<1>) -> () - func @gateCall1(%q1 : !quir.qubit<1>, %lambda : !quir.angle<1>) -> () { - %zero = quir.constant #quir.angle<0.0 : !quir.angle<1>> + func.func private @proto (%qa1 : !quir.qubit<1>) -> () + func.func @gateCall1(%q1 : !quir.qubit<1>, %lambda : !quir.angle<1>) -> () { + %zero = quir.constant #quir.angle<0.0> : !quir.angle<1> quir.builtin_U %q1, %zero, %zero, %lambda : !quir.qubit<1>, !quir.angle<1>, !quir.angle<1>, !quir.angle<1> "quir.call_gate"(%q1) {callee = @proto} : (!quir.qubit<1>) -> () return } - func @gateCall2(%q1 : !quir.qubit<1>, %lambda : !quir.angle) -> () { - %zero = quir.constant #quir.angle<0.0 : !quir.angle<20>> + func.func @gateCall2(%q1 : !quir.qubit<1>, %lambda : !quir.angle) -> () { + %zero = quir.constant #quir.angle<0.0> : !quir.angle<20> quir.builtin_U %q1, %zero, %zero, %lambda : !quir.qubit<1>, !quir.angle<20>, !quir.angle<20>, !quir.angle quir.builtin_U %q1, %zero, %zero, %lambda : !quir.qubit<1>, !quir.angle<20>, !quir.angle<20>, !quir.angle quir.builtin_U %q1, %zero, %zero, %lambda : !quir.qubit<1>, !quir.angle<20>, !quir.angle<20>, !quir.angle quir.builtin_U %q1, %zero, %zero, %lambda : !quir.qubit<1>, !quir.angle<20>, !quir.angle<20>, !quir.angle return } - func @multiQubitGateCall(%qa1 : !quir.qubit<1>, %qb1 : !quir.qubit<1>) -> () { + func.func @multiQubitGateCall(%qa1 : !quir.qubit<1>, %qb1 : !quir.qubit<1>) -> () { quir.builtin_CX %qa1, %qb1 : !quir.qubit<1>, !quir.qubit<1> return } - func @defcalGate2(%qa1 : !quir.qubit<1> {quir.qubit_id = 0 : i32}, %theta : !quir.angle {quir.value = 0.5 : f64}) -> () { - %zero = quir.constant #quir.angle<0.0 : !quir.angle> + func.func @defcalGate2(%qa1 : !quir.qubit<1> {quir.qubit_id = 0 : i32}, %theta : !quir.angle {quir.value = 0.5 : f64}) -> () { + %zero = quir.constant #quir.angle<0.0> : !quir.angle quir.builtin_U %qa1, %zero, %theta, %zero : !quir.qubit<1>, !quir.angle, !quir.angle, !quir.angle return } - func @defcalRX(%qa1 : !quir.qubit<1>, %theta : !quir.angle<20>) -> () { + func.func @defcalRX(%qa1 : !quir.qubit<1>, %theta : !quir.angle<20>) -> () { quir.call_gate @proto1(%qa1, %theta) : (!quir.qubit<1>, !quir.angle<20>) -> () return } - func @defcalRX_q0(%qa1 : !quir.qubit<1> {quir.qubit_id = 0 : i32}, %theta : !quir.angle<20>) -> () attributes {quir.orig_func_name = "defcalRX"} { + func.func @defcalRX_q0(%qa1 : !quir.qubit<1> {quir.qubit_id = 0 : i32}, %theta : !quir.angle<20>) -> () attributes {quir.orig_func_name = "defcalRX"} { quir.call_gate @proto2(%qa1, %theta) : (!quir.qubit<1>, !quir.angle<20>) -> () return } - func @defcalRX_q0_api2(%qa1 : !quir.qubit<1> {quir.qubit_id = 0 : i32}, %theta : !quir.angle<20> {quir.value = 0.5 : f64}) -> () + func.func @defcalRX_q0_api2(%qa1 : !quir.qubit<1> {quir.qubit_id = 0 : i32}, %theta : !quir.angle<20> {quir.value = 0.5 : f64}) -> () attributes {quir.orig_func_name = "defcalRX"} { quir.call_gate @proto3(%qa1, %theta) : (!quir.qubit<1>, !quir.angle<20>) -> () return } - func @main () -> i32 { + func.func @main () -> i32 { %qa1 = quir.declare_qubit { id = 1 : i32 } : !quir.qubit<1> %qb1 = quir.declare_qubit { id = 2 : i32 } : !quir.qubit<1> %qc1 = quir.declare_qubit { id = 3 : i32 } : !quir.qubit<1> quir.reset %qc1 : !quir.qubit<1> %cb1 = oq3.variable_load @cb1 : !quir.cbit<1> - %theta = quir.constant #quir.angle<0.1 : !quir.angle<1>> + %theta = quir.constant #quir.angle<0.1> : !quir.angle<1> // CHECK: quir.call_gate @gateCall1(%{{.*}}, %{{.*}}) : (!quir.qubit<1>, !quir.angle<1>) -> () // MLIR: quir.call_gate @gateCall1(%{{.*}}, %{{.*}}) : (!quir.qubit<1>, !quir.angle<1>) -> () diff --git a/test/Dialect/QUIR/Transforms/arg-specialization1.mlir b/test/Dialect/QUIR/Transforms/arg-specialization1.mlir index e66ecde10..3fd702c6c 100644 --- a/test/Dialect/QUIR/Transforms/arg-specialization1.mlir +++ b/test/Dialect/QUIR/Transforms/arg-specialization1.mlir @@ -17,40 +17,40 @@ module { oq3.declare_variable @cb1 : !quir.cbit<1> oq3.declare_variable @cb2 : !quir.cbit<1> - func @gateCall1(%q1 : !quir.qubit<1>, %lambda : !quir.angle<1>) { - %zero = quir.constant #quir.angle<0.0 : !quir.angle<1>> + func.func @gateCall1(%q1 : !quir.qubit<1>, %lambda : !quir.angle<1>) { + %zero = quir.constant #quir.angle<0.0> : !quir.angle<1> quir.builtin_U %q1, %zero, %zero, %lambda : !quir.qubit<1>, !quir.angle<1>, !quir.angle<1>, !quir.angle<1> "quir.call_gate"(%q1) {callee = @proto} : (!quir.qubit<1>) -> () return } - func @gateCall2(%q1 : !quir.qubit<1>, %lambda : !quir.angle) { - %zero = quir.constant #quir.angle<0.0 : !quir.angle<20>> + func.func @gateCall2(%q1 : !quir.qubit<1>, %lambda : !quir.angle) { + %zero = quir.constant #quir.angle<0.0> : !quir.angle<20> quir.builtin_U %q1, %zero, %zero, %lambda : !quir.qubit<1>, !quir.angle<20>, !quir.angle<20>, !quir.angle quir.builtin_U %q1, %zero, %zero, %lambda : !quir.qubit<1>, !quir.angle<20>, !quir.angle<20>, !quir.angle quir.builtin_U %q1, %zero, %zero, %lambda : !quir.qubit<1>, !quir.angle<20>, !quir.angle<20>, !quir.angle quir.builtin_U %q1, %zero, %zero, %lambda : !quir.qubit<1>, !quir.angle<20>, !quir.angle<20>, !quir.angle %cb2 = "quir.measure"(%q1) : (!quir.qubit<1>) -> (i1) - cond_br %cb2, ^runz, ^dontrunz + cf.cond_br %cb2, ^runz, ^dontrunz ^runz: "quir.call_gate"(%q1) {callee = @Z} : (!quir.qubit<1>) -> () - br ^afterz + cf.br ^afterz ^dontrunz: - br ^afterz + cf.br ^afterz ^afterz: // if(c1==1) { x q[2]; } // braces optional in this case - cond_br %cb2, ^runx, ^dontrunx + cf.cond_br %cb2, ^runx, ^dontrunx // this checks for both specialized and non-specialized intermediate qubit gate calls // CHECK: quir.call_gate @X(%{{.*}}) : (!quir.qubit<1>) -> () ^runx: "quir.call_gate"(%q1) {callee = @X} : (!quir.qubit<1>) -> () - br ^afterx + cf.br ^afterx ^dontrunx: - br ^afterx + cf.br ^afterx ^afterx: // post q[2]; // NOP/identity @@ -59,9 +59,9 @@ module { return } - func @gateCall3(%q1 : !quir.qubit<1>, %phi : !quir.angle) { - %zero = quir.constant #quir.angle<0.0 : !quir.angle<20>> - %cmpval = quir.constant #quir.angle<0.3 : !quir.angle<20>> + func.func @gateCall3(%q1 : !quir.qubit<1>, %phi : !quir.angle) { + %zero = quir.constant #quir.angle<0.0> : !quir.angle<20> + %cmpval = quir.constant #quir.angle<0.3> : !quir.angle<20> %farg = "oq3.cast"(%phi) : (!quir.angle) -> f64 %cval = "oq3.cast"(%cmpval) : (!quir.angle<20>) -> f64 %cond = arith.cmpf "ogt", %farg, %cval : f64 @@ -72,13 +72,13 @@ module { } return } - func @main () -> i32 { + func.func @main () -> i32 { %qa1 = quir.declare_qubit { id = 1 : i32 } : !quir.qubit<1> %qb1 = quir.declare_qubit { id = 2 : i32 } : !quir.qubit<1> %qc1 = quir.declare_qubit { id = 3 : i32 } : !quir.qubit<1> quir.reset %qc1 : !quir.qubit<1> %cb1 = oq3.variable_load @cb1 : !quir.cbit<1> - %theta = quir.constant #quir.angle<0.1 : !quir.angle<1>> + %theta = quir.constant #quir.angle<0.1> : !quir.angle<1> // CHECK: quir.call_gate @gateCall1(%{{.*}}, %{{.*}}) : (!quir.qubit<1>, !quir.angle<1>) -> () "quir.call_gate"(%qb1, %theta) {callee = @gateCall1} : (!quir.qubit<1>, !quir.angle<1>) -> () // CHECK: quir.call_gate @"gateCall2_!quir.qubit<1>_!quir.angle<1>"(%{{.*}}, %{{.*}}) : (!quir.qubit<1>, !quir.angle<1>) -> () @@ -96,7 +96,7 @@ module { quir.call_gate @gateCall3(%qb1, %theta) : (!quir.qubit<1>, !quir.angle<1>) -> () %false = arith.constant false scf.if %false { - %theta2 = quir.constant #quir.angle<0.1 : !quir.angle<3>> + %theta2 = quir.constant #quir.angle<0.1> : !quir.angle<3> // CHECK: quir.call_gate @"gateCall3_!quir.qubit<1>_!quir.angle<3>"(%{{.*}}, %{{.*}}) : (!quir.qubit<1>, !quir.angle<3>) -> () quir.call_gate @gateCall3(%qb1, %theta2) : (!quir.qubit<1>, !quir.angle<3>) -> () } diff --git a/test/Dialect/QUIR/Transforms/arg-specialization2.mlir b/test/Dialect/QUIR/Transforms/arg-specialization2.mlir index 80145a40e..6e52cf180 100644 --- a/test/Dialect/QUIR/Transforms/arg-specialization2.mlir +++ b/test/Dialect/QUIR/Transforms/arg-specialization2.mlir @@ -13,14 +13,14 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -// CHECK: func @"defcalPhase_q0_!quir.angle<20>_!quir.qubit<1>"(%arg0: !quir.angle<20>, %arg1: !quir.qubit<1> {quir.physicalId = 0 : i32}) attributes {quir.orig_func_name = "defcalPhase"} -// CHECK: func @"defcalPhase_q0_!quir.angle<10>_!quir.qubit<1>"(%arg0: !quir.angle<10>, %arg1: !quir.qubit<1> {quir.physicalId = 0 : i32}) attributes {quir.orig_func_name = "defcalPhase"} -func @defcalPhase_q0(%arg0: !quir.angle, %arg1: !quir.qubit<1> {quir.physicalId = 0 : i32}) attributes {quir.orig_func_name = "defcalPhase"} { +// CHECK: func.func @"defcalPhase_q0_!quir.angle<20>_!quir.qubit<1>"(%arg0: !quir.angle<20>, %arg1: !quir.qubit<1> {quir.physicalId = 0 : i32}) attributes {quir.orig_func_name = "defcalPhase"} +// CHECK: func.func @"defcalPhase_q0_!quir.angle<10>_!quir.qubit<1>"(%arg0: !quir.angle<10>, %arg1: !quir.qubit<1> {quir.physicalId = 0 : i32}) attributes {quir.orig_func_name = "defcalPhase"} +func.func @defcalPhase_q0(%arg0: !quir.angle, %arg1: !quir.qubit<1> {quir.physicalId = 0 : i32}) attributes {quir.orig_func_name = "defcalPhase"} { return } -// CHECK: func @"subroutine1_!quir.qubit<1>_!quir.angle<20>_index"(%arg0: !quir.qubit<1>, %arg1: !quir.angle<20>, %arg2: index) -func @subroutine1(%q1 : !quir.qubit<1>, %phi : !quir.angle, %ub : index) { +// CHECK: func.func @"subroutine1_!quir.qubit<1>_!quir.angle<20>_index"(%arg0: !quir.qubit<1>, %arg1: !quir.angle<20>, %arg2: index) +func.func @subroutine1(%q1 : !quir.qubit<1>, %phi : !quir.angle, %ub : index) { %lb = arith.constant 0 : index %step = arith.constant 1 : index scf.for %iv = %lb to %ub step %step { @@ -34,17 +34,17 @@ func @subroutine1(%q1 : !quir.qubit<1>, %phi : !quir.angle, %ub : index) { return } -// CHECK: func @"defcalMeasure_q0_!quir.qubit<1>_!quir.angle<10>"(%arg0: !quir.qubit<1> {quir.physicalId = 0 : i32}, %arg1: !quir.angle<10>) -> i1 attributes {quir.orig_func_name = "defcalMeasure"} -// CHECK: func @"defcalMeasure_q0_!quir.qubit<1>_!quir.angle<20>"(%arg0: !quir.qubit<1> {quir.physicalId = 0 : i32}, %arg1: !quir.angle<20>) -> i1 attributes {quir.orig_func_name = "defcalMeasure"} -func @defcalMeasure_q0(%q1: !quir.qubit<1> {quir.physicalId = 0 : i32}, %phi : !quir.angle) -> i1 attributes {quir.orig_func_name = "defcalMeasure"} { +// CHECK: func.func @"defcalMeasure_q0_!quir.qubit<1>_!quir.angle<10>"(%arg0: !quir.qubit<1> {quir.physicalId = 0 : i32}, %arg1: !quir.angle<10>) -> i1 attributes {quir.orig_func_name = "defcalMeasure"} +// CHECK: func.func @"defcalMeasure_q0_!quir.qubit<1>_!quir.angle<20>"(%arg0: !quir.qubit<1> {quir.physicalId = 0 : i32}, %arg1: !quir.angle<20>) -> i1 attributes {quir.orig_func_name = "defcalMeasure"} +func.func @defcalMeasure_q0(%q1: !quir.qubit<1> {quir.physicalId = 0 : i32}, %phi : !quir.angle) -> i1 attributes {quir.orig_func_name = "defcalMeasure"} { quir.call_gate @defcalPhase_q0(%phi, %q1) : (!quir.angle, !quir.qubit<1>) -> () %false = arith.constant false return %false : i1 } -func @main () -> i32 { +func.func @main () -> i32 { %q1 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> - %ang = quir.constant #quir.angle<0.1 : !quir.angle<20>> + %ang = quir.constant #quir.angle<0.1> : !quir.angle<20> %ub = arith.constant 10 : index // CHECK: quir.call_subroutine @"subroutine1_!quir.qubit<1>_!quir.angle<20>_index"(%{{.*}}, %{{.*}}, %{{.*}}) : (!quir.qubit<1>, !quir.angle<20>, index) -> () quir.call_subroutine @subroutine1(%q1, %ang, %ub) : (!quir.qubit<1>, !quir.angle<20>, index) -> () @@ -58,7 +58,7 @@ func @main () -> i32 { quir.call_subroutine @subroutine1(%q1, %ang, %ub) : (!quir.qubit<1>, !quir.angle<20>, index) -> () %true = arith.constant true scf.if %true { - %ang2 = quir.constant #quir.angle<0.2 : !quir.angle<10>> + %ang2 = quir.constant #quir.angle<0.2> : !quir.angle<10> // CHECK: quir.call_defcal_gate @"defcalPhase_q0_!quir.angle<10>_!quir.qubit<1>"(%{{.*}}, %{{.*}}) : (!quir.angle<10>, !quir.qubit<1>) -> () quir.call_defcal_gate @defcalPhase_q0(%ang2, %q1) : (!quir.angle<10>, !quir.qubit<1>) -> () // CHECK: %{{.*}} = quir.call_defcal_measure @"defcalMeasure_q0_!quir.qubit<1>_!quir.angle<10>"(%{{.*}}, %{{.*}}) : (!quir.qubit<1>, !quir.angle<10>) -> i1 diff --git a/test/Dialect/QUIR/Transforms/break-reset-multiqubit.mlir b/test/Dialect/QUIR/Transforms/break-reset-multiqubit.mlir index 3744d74a7..2d5b591e6 100644 --- a/test/Dialect/QUIR/Transforms/break-reset-multiqubit.mlir +++ b/test/Dialect/QUIR/Transforms/break-reset-multiqubit.mlir @@ -14,11 +14,11 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -func @main() { +func.func @main() { // CHECK: [[QUBIT0:%.*]] = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> // CHECK: [[QUBIT1:%.*]] = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> // CHECK: [[QUBIT2:%.*]] = quir.declare_qubit {id = 2 : i32} : !quir.qubit<1> -// DELAYITER: [[DURATION:%.*]] = quir.constant #quir.duration<5.000000e+02 :
> +// DELAYITER: [[DURATION:%.*]] = quir.constant #quir.duration<5.000000e+02> : !quir.duration
// DELAYITER: [[QUBIT0:%.*]] = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> // DELAYITER: [[QUBIT1:%.*]] = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> // DELAYITER: [[QUBIT2:%.*]] = quir.declare_qubit {id = 2 : i32} : !quir.qubit<1> diff --git a/test/Dialect/QUIR/Transforms/break-reset-nested.mlir b/test/Dialect/QUIR/Transforms/break-reset-nested.mlir index 740a93196..ed7e0d2ae 100644 --- a/test/Dialect/QUIR/Transforms/break-reset-nested.mlir +++ b/test/Dialect/QUIR/Transforms/break-reset-nested.mlir @@ -18,7 +18,7 @@ // CHECK-NEXT: %{{.*}} = quir.measure(%arg0) {quir.noReportRuntime} : (!quir.qubit<1>) -> i1 // CHECK-NEXT: scf.if %0 { // CHECK-NEXT: quir.call_gate @x(%arg0) : (!quir.qubit<1>) -> () -func @main (%inq : !quir.qubit<1>, %cond1 : i1, %cond2 : i1) { +func.func @main (%inq : !quir.qubit<1>, %cond1 : i1, %cond2 : i1) { scf.if %cond1 { scf.if %cond2 { quir.reset %inq : !quir.qubit<1> diff --git a/test/Dialect/QUIR/Transforms/break-reset.mlir b/test/Dialect/QUIR/Transforms/break-reset.mlir index 56d186419..95edefec8 100644 --- a/test/Dialect/QUIR/Transforms/break-reset.mlir +++ b/test/Dialect/QUIR/Transforms/break-reset.mlir @@ -16,20 +16,20 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -func @t1 (%inq : !quir.qubit<1>) { +func.func @t1 (%inq : !quir.qubit<1>) { // CHECK: %0 = quir.measure(%arg0) {quir.noReportRuntime} : (!quir.qubit<1>) -> i1 // CHECK: scf.if %0 { // CHECK: quir.call_gate @x(%arg0) : (!quir.qubit<1>) -> () // CHECK: } -// DELAY: [[DURATION:%.*]] = quir.constant #quir.duration<5.000000e+02 :
> +// DELAY: [[DURATION:%.*]] = quir.constant #quir.duration<5.000000e+02> : !quir.duration
// DELAY-COUNT-2: quir.delay [[DURATION]], ({{.*}}) : !quir.duration
, (!quir.qubit<1>) -> () // ITER: quir.call_gate @x(%arg0) : (!quir.qubit<1>) -> () // ITER: quir.call_gate @x(%arg0) : (!quir.qubit<1>) -> () // ITER-NOT: quir.call_gate @x(%arg0) : (!quir.qubit<1>) -> () -// DELAYITER: %dur = quir.constant #quir.duration<5.000000e+02 :
> +// DELAYITER: %dur = quir.constant #quir.duration<5.000000e+02> : !quir.duration
// DELAYITER: quir.call_gate @x(%arg0) : (!quir.qubit<1>) -> () // DELAYITER: quir.call_gate @x(%arg0) : (!quir.qubit<1>) -> () // DELAYITER-NOT: quir.call_gate @x(%arg0) : (!quir.qubit<1>) -> () diff --git a/test/Dialect/QUIR/Transforms/canonicalize-assign-cbit-bit.mlir b/test/Dialect/QUIR/Transforms/canonicalize-assign-cbit-bit.mlir index b3bce0e16..7322f577f 100644 --- a/test/Dialect/QUIR/Transforms/canonicalize-assign-cbit-bit.mlir +++ b/test/Dialect/QUIR/Transforms/canonicalize-assign-cbit-bit.mlir @@ -22,7 +22,7 @@ module { oq3.declare_variable @a : !quir.cbit<1> oq3.declare_variable @b : !quir.cbit<1> - func @main() -> i32 { + func.func @main() -> i32 { %1 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %2 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> diff --git a/test/Dialect/QUIR/Transforms/canonicalize-bit-eqeqone.mlir b/test/Dialect/QUIR/Transforms/canonicalize-bit-eqeqone.mlir index 3d7540c1b..e617c1aea 100644 --- a/test/Dialect/QUIR/Transforms/canonicalize-bit-eqeqone.mlir +++ b/test/Dialect/QUIR/Transforms/canonicalize-bit-eqeqone.mlir @@ -18,7 +18,7 @@ // CHECK: module module { - func @extract(%in : !quir.cbit<2>) -> i1 { + func.func @extract(%in : !quir.cbit<2>) -> i1 { // CHECK: [[BIT:%.]] = oq3.cbit_extractbit %1 = oq3.cbit_extractbit(%in : !quir.cbit<2>) [0] : i1 %c1_i32 = arith.constant 1 : i32 @@ -28,7 +28,7 @@ module { return %3 : i1 } - func @main() -> i1 { + func.func @main() -> i1 { %c1_i32 = arith.constant 1 : i32 %1 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> diff --git a/test/Dialect/QUIR/Transforms/classical-only-detection.mlir b/test/Dialect/QUIR/Transforms/classical-only-detection.mlir index b056d9432..aacbc5c56 100644 --- a/test/Dialect/QUIR/Transforms/classical-only-detection.mlir +++ b/test/Dialect/QUIR/Transforms/classical-only-detection.mlir @@ -13,12 +13,12 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -func private @kernel1 (%ca1 : memref<1xi1>, %ca2 : memref<1xi1>, %ca3 : memref<1xi1>) -> memref<1xi1> -func private @kernel2 (memref) -> memref<1xi1> -func @subroutine1 (%ang1 : !quir.angle<20>, %ang2 : !quir.angle<20>, %q1 : !quir.qubit<1>, %q2 : !quir.qubit<1>) -> (!quir.cbit<1>) { +func.func private @kernel1 (%ca1 : memref<1xi1>, %ca2 : memref<1xi1>, %ca3 : memref<1xi1>) -> memref<1xi1> +func.func private @kernel2 (memref) -> memref<1xi1> +func.func @subroutine1 (%ang1 : !quir.angle<20>, %ang2 : !quir.angle<20>, %q1 : !quir.qubit<1>, %q2 : !quir.qubit<1>) -> (!quir.cbit<1>) { %zero = arith.constant 0 : index %ang3 = oq3.angle_add %ang1, %ang2 : !quir.angle<20> - %ang4 = quir.constant #quir.angle<0.9 : !quir.angle<20>> + %ang4 = quir.constant #quir.angle<0.9> : !quir.angle<20> %f1 = "oq3.cast"(%ang3) : (!quir.angle<20>) -> f64 %f2 = "oq3.cast"(%ang4) : (!quir.angle<20>) -> f64 %cond1 = arith.cmpf "ogt", %f1, %f2 : f64 @@ -41,49 +41,49 @@ func @subroutine1 (%ang1 : !quir.angle<20>, %ang2 : !quir.angle<20>, %q1 : !quir %c1 = "oq3.cast"(%mres1) : (i1) -> !quir.cbit<1> return %c1 : !quir.cbit<1> } -func private @proto (%qa1 : !quir.qubit<1>) -> () -func @gateCall1(%q1 : !quir.qubit<1>, %lambda : !quir.angle<1>) -> () { - %zero = quir.constant #quir.angle<0.0 : !quir.angle<1>> +func.func private @proto (%qa1 : !quir.qubit<1>) -> () +func.func @gateCall1(%q1 : !quir.qubit<1>, %lambda : !quir.angle<1>) -> () { + %zero = quir.constant #quir.angle<0.0> : !quir.angle<1> quir.builtin_U %q1, %zero, %zero, %lambda : !quir.qubit<1>, !quir.angle<1>, !quir.angle<1>, !quir.angle<1> "quir.call_gate"(%q1) {callee = @proto} : (!quir.qubit<1>) -> () return } -func @gateCall2(%q1 : !quir.qubit<1>, %lambda : !quir.angle) -> () { - %zero = quir.constant #quir.angle<0.0 : !quir.angle> +func.func @gateCall2(%q1 : !quir.qubit<1>, %lambda : !quir.angle) -> () { + %zero = quir.constant #quir.angle<0.0> : !quir.angle quir.builtin_U %q1, %zero, %zero, %lambda : !quir.qubit<1>, !quir.angle, !quir.angle, !quir.angle return } -func @multiQubitGateCall(%qa1 : !quir.qubit<1>, %qb1 : !quir.qubit<1>) -> () { +func.func @multiQubitGateCall(%qa1 : !quir.qubit<1>, %qb1 : !quir.qubit<1>) -> () { quir.builtin_CX %qa1, %qb1 : !quir.qubit<1>, !quir.qubit<1> return } -func @defcalGate2(%qa1 : !quir.qubit<1> {quir.qubit_id = 0 : i32}, %theta : !quir.angle {quir.value = 0.5 : f64}) -> () { - %zero = quir.constant #quir.angle<0.0 : !quir.angle> +func.func @defcalGate2(%qa1 : !quir.qubit<1> {quir.qubit_id = 0 : i32}, %theta : !quir.angle {quir.value = 0.5 : f64}) -> () { + %zero = quir.constant #quir.angle<0.0> : !quir.angle quir.builtin_U %qa1, %zero, %theta, %zero : !quir.qubit<1>, !quir.angle, !quir.angle, !quir.angle return } -func @defcalRX(%qa1 : !quir.qubit<1>, %theta : !quir.angle<20>) -> () { +func.func @defcalRX(%qa1 : !quir.qubit<1>, %theta : !quir.angle<20>) -> () { quir.call_gate @proto1(%qa1, %theta) : (!quir.qubit<1>, !quir.angle<20>) -> () return } -func @defcalRX_q0(%qa1 : !quir.qubit<1> {quir.qubit_id = 0 : i32}, %theta : !quir.angle<20>) -> () attributes {quir.orig_func_name = "defcalRX"} { +func.func @defcalRX_q0(%qa1 : !quir.qubit<1> {quir.qubit_id = 0 : i32}, %theta : !quir.angle<20>) -> () attributes {quir.orig_func_name = "defcalRX"} { quir.call_gate @proto2(%qa1, %theta) : (!quir.qubit<1>, !quir.angle<20>) -> () return } -func @defcalRX_q0_api2(%qa1 : !quir.qubit<1> {quir.qubit_id = 0 : i32}, %theta : !quir.angle<20> {quir.value = 0.5 : f64}) -> () +func.func @defcalRX_q0_api2(%qa1 : !quir.qubit<1> {quir.qubit_id = 0 : i32}, %theta : !quir.angle<20> {quir.value = 0.5 : f64}) -> () attributes {quir.orig_func_name = "defcalRX"} { quir.call_gate @proto3(%qa1, %theta) : (!quir.qubit<1>, !quir.angle<20>) -> () return } -%ang1 = quir.constant #quir.angle<0.15 : !quir.angle<20>> -%ang2 = quir.constant #quir.angle<0.2 : !quir.angle<20>> +%ang1 = quir.constant #quir.angle<0.15> : !quir.angle<20> +%ang2 = quir.constant #quir.angle<0.2> : !quir.angle<20> %q1 = quir.declare_qubit {id = 4 : i32} : !quir.qubit<1> %q2 = quir.declare_qubit {id = 5 : i32} : !quir.qubit<1> %zero = arith.constant 0 : index %ang3 = oq3.angle_add %ang1, %ang2 : !quir.angle<20> -%ang4 = quir.constant #quir.angle<0.9 : !quir.angle<20>> +%ang4 = quir.constant #quir.angle<0.9> : !quir.angle<20> %f1 = "oq3.cast"(%ang3) : (!quir.angle<20>) -> f64 %f2 = "oq3.cast"(%ang4) : (!quir.angle<20>) -> f64 %cond1 = arith.cmpf "ogt", %f1, %f2 : f64 @@ -107,7 +107,7 @@ scf.if %cond2 { %cb1 = "oq3.cast"(%mres1) : (i1) -> !quir.cbit<1> oq3.declare_variable @c1 : !quir.cbit<1> oq3.variable_assign @c1 : !quir.cbit<1> = %cb1 -//%res2 = call @subroutine1(%ang1, %ang2, %q1, %q2) : (!quir.angle<20>, !quir.angle<20>, !quir.qubit<1>, !quir.qubit<1>) -> memref<1xi1> +//%res2 = func.call @subroutine1(%ang1, %ang2, %q1, %q2) : (!quir.angle<20>, !quir.angle<20>, !quir.qubit<1>, !quir.qubit<1>) -> memref<1xi1> %c11 = arith.constant 0 : i1 %c21 = arith.constant 1 : i1 @@ -129,7 +129,7 @@ oq3.variable_assign @c1 : !quir.cbit<1> = %cb1 // angle[3] c = 0; %qq1 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %qr1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> -%angleC = quir.constant #quir.angle<0.0 : !quir.angle<3>> +%angleC = quir.constant #quir.angle<0.0> : !quir.angle<3> // reset q; // reset r; quir.reset %qq1 : !quir.qubit<1> @@ -150,17 +150,17 @@ quir.reset %qr1 : !quir.qubit<1> "quir.call_gate"(%qq1) {callee = @H} : (!quir.qubit<1>) -> () // cphase(power*3*pi/8) q, r; %power1_angle = "oq3.cast"(%power1_iter) : (i3) -> !quir.angle<3> - %angle_multiplicand = quir.constant #quir.angle<0.375 : !quir.angle<3>> + %angle_multiplicand = quir.constant #quir.angle<0.375> : !quir.angle<3> %angleP = oq3.angle_mul %power1_angle, %angle_multiplicand : !quir.angle<3> "quir.call_gate"(%qq1, %qr1, %angleP) {callee = @cphase} : (!quir.qubit<1>, !quir.qubit<1>, !quir.angle<3>) -> () - %angle_zero = quir.constant #quir.angle<0.0 : !quir.angle<3>> + %angle_zero = quir.constant #quir.angle<0.0> : !quir.angle<3> %negC = oq3.angle_sub %angle_zero, %angleC_iter : !quir.angle<3> // phase(-c) q; // h q; // measure q -> c[0]; // c <<= 1; // power <<= 1; - %angleC_shift = quir.constant #quir.angle<0.0 : !quir.angle<3>> + %angleC_shift = quir.constant #quir.angle<0.0> : !quir.angle<3> %power_shift = arith.constant 1 : i3 // } scf.yield %angleC_shift, %power_shift : !quir.angle<3>, i3 diff --git a/test/Dialect/QUIR/Transforms/convert-duration-units.mlir b/test/Dialect/QUIR/Transforms/convert-duration-units.mlir index 1e2329c94..39199b10d 100644 --- a/test/Dialect/QUIR/Transforms/convert-duration-units.mlir +++ b/test/Dialect/QUIR/Transforms/convert-duration-units.mlir @@ -18,37 +18,37 @@ // This test verifies that the pass --convert-quir-duration-units // is able to globally convert duration units throughout the IR. -// CHECK-LABEL: func @quir_durations() -func @quir_durations (%arg : i32) { +// CHECK-LABEL: func.func @quir_durations() +func.func @quir_durations (%arg : i32) { %q0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> // Test a non-duration constant - %angle = quir.constant #quir.angle<3.1415926535900001 : !quir.angle<64>> - // DT: {{.*}} = quir.constant #quir.angle<3.1415926535900001 : !quir.angle<64>> + %angle = quir.constant #quir.angle<3.1415926535900001> : !quir.angle<64> + // DT: {{.*}} = quir.constant #quir.angle<3.1415926535900001> : !quir.angle<64> - %duration_dt0 = quir.constant #quir.duration<10.0 :
> - // DT: [[duration_dt0:%.*]] = quir.constant #quir.duration<1.000000e+01 :
> - // S: [[duration_dt0:%.*]] = quir.constant #quir.duration<1.000000e+00 : > - %duration_dt1 = quir.constant #quir.duration<10.0 : !quir.duration
> - // DT: {{.*}} = quir.constant #quir.duration<1.000000e+01 :
> - // S: {{.*}} = quir.constant #quir.duration<1.000000e+00 : > - %duration_s = quir.constant #quir.duration<10.0 : !quir.duration> - // DT: [[duration_s:%.*]] = quir.constant #quir.duration<1.000000e+02 :
> - // S: [[duration_s:%.*]] = quir.constant #quir.duration<1.000000e+01 : > - %duration_ms = quir.constant #quir.duration<10.0 : !quir.duration> - // DT: [[duration_ms:%.*]] = quir.constant #quir.duration<0.099999999999999992 :
> - // S: [[duration_ms:%.*]] = quir.constant #quir.duration<1.000000e-02 : > - %duration_us = quir.constant #quir.duration<10.0 : !quir.duration> - // DT: {{.*}} = quir.constant #quir.duration<9.9999999999999995E-8 :
> - // S: {{.*}} = quir.constant #quir.duration<1.000000e-05 : > - %duration_ns = quir.constant #quir.duration<10.0 : !quir.duration> + %duration_dt0 = quir.constant #quir.duration<10.0> : !quir.duration
+ // DT: [[duration_dt0:%.*]] = quir.constant #quir.duration<1.000000e+01> : !quir.duration
+ // S: [[duration_dt0:%.*]] = quir.constant #quir.duration<1.000000e+00> : !quir.duration + %duration_dt1 = quir.constant #quir.duration<10.0> : !quir.duration
+ // DT: {{.*}} = quir.constant #quir.duration<1.000000e+01> : !quir.duration
+ // S: {{.*}} = quir.constant #quir.duration<1.000000e+00> : !quir.duration + %duration_s = quir.constant #quir.duration<10.0> : !quir.duration + // DT: [[duration_s:%.*]] = quir.constant #quir.duration<1.000000e+02> : !quir.duration
+ // S: [[duration_s:%.*]] = quir.constant #quir.duration<1.000000e+01> : !quir.duration + %duration_ms = quir.constant #quir.duration<10.0> : !quir.duration + // DT: [[duration_ms:%.*]] = quir.constant #quir.duration<0.099999999999999992> : !quir.duration
+ // S: [[duration_ms:%.*]] = quir.constant #quir.duration<1.000000e-02> : !quir.duration + %duration_us = quir.constant #quir.duration<10.0> : !quir.duration + // DT: {{.*}} = quir.constant #quir.duration<9.9999999999999995E-8> : !quir.duration
+ // S: {{.*}} = quir.constant #quir.duration<1.000000e-05> : !quir.duration + %duration_ns = quir.constant #quir.duration<10.0> : !quir.duration // Floating point precision errors. If this is an issue longrun we should move to APFloat. // which is an easy change. - // S: {{.*}} = quir.constant #quir.duration<1.000000e-08 : > + // S: {{.*}} = quir.constant #quir.duration<1.000000e-08> : !quir.duration - %duration_ps = quir.constant #quir.duration<10.0 : !quir.duration> - %duration_fs = quir.constant #quir.duration<10.0 : !quir.duration> + %duration_ps = quir.constant #quir.duration<10.0> : !quir.duration + %duration_fs = quir.constant #quir.duration<10.0> : !quir.duration quir.delay %duration_s, (%q0) : !quir.duration, (!quir.qubit<1>) -> () // DT: quir.delay [[duration_s]], ({{.*}}) : !quir.duration
, (!quir.qubit<1>) -> () @@ -61,7 +61,7 @@ func @quir_durations (%arg : i32) { quir.call_circuit @circuit0(%q0, %duration_dt0, %duration_s, %duration_ms) : (!quir.qubit<1>, !quir.duration
, !quir.duration, !quir.duration) -> (!quir.duration, !quir.duration) // DT: {{.*}}:2 = quir.call_circuit @circuit0({{.*}}, [[duration_dt0]], [[duration_s]], [[duration_ms]]) : (!quir.qubit<1>, !quir.duration
, !quir.duration
, !quir.duration
) -> (!quir.duration
, !quir.duration
) // S: {{.*}}:2 = quir.call_circuit @circuit0({{.*}}, [[duration_dt0]], [[duration_s]], [[duration_ms]]) : (!quir.qubit<1>, !quir.duration, !quir.duration, !quir.duration) -> (!quir.duration, !quir.duration) - call @func0(%arg, %q0, %duration_dt0, %duration_s, %duration_ms) : (i32, !quir.qubit<1>, !quir.duration
, !quir.duration, !quir.duration) -> (i32, !quir.duration) + func.call @func0(%arg, %q0, %duration_dt0, %duration_s, %duration_ms) : (i32, !quir.qubit<1>, !quir.duration
, !quir.duration, !quir.duration) -> (i32, !quir.duration) // DT: {{.*}}:2 = call @func0({{.*}}, {{.*}}, [[duration_dt0]], [[duration_s]], [[duration_ms]]) : (i32, !quir.qubit<1>, !quir.duration
, !quir.duration
, !quir.duration
) -> (i32, !quir.duration
) // S: {{.*}}:2 = call @func0({{.*}}, {{.*}}, [[duration_dt0]], [[duration_s]], [[duration_ms]]) : (i32, !quir.qubit<1>, !quir.duration, !quir.duration, !quir.duration) -> (i32, !quir.duration) return @@ -85,9 +85,9 @@ quir.circuit @circuit0 (%q: !quir.qubit<1>, %duration_dt0: !quir.duration
, % // S: quir.return [[duration_ms]], [[duration_ms]] : !quir.duration, !quir.duration } -func @func0 (%arg: i32, %q: !quir.qubit<1>, %duration_dt0: !quir.duration
, %duration_s: !quir.duration, %duration_ms: !quir.duration) -> (i32, !quir.duration) { -// DT: func @func0(%arg0: i32, %arg1: !quir.qubit<1>, [[duration_dt0:%.*]]: !quir.duration
, [[duration_s:%.*]]: !quir.duration
, [[duration_ms:%.*]]: !quir.duration
) -> (i32, !quir.duration
) { -// S: func @func0(%arg0: i32, %arg1: !quir.qubit<1>, [[duration_dt0:%.*]]: !quir.duration, [[duration_s:%.*]]: !quir.duration, [[duration_ms:%.*]]: !quir.duration) -> (i32, !quir.duration) { +func.func @func0 (%arg: i32, %q: !quir.qubit<1>, %duration_dt0: !quir.duration
, %duration_s: !quir.duration, %duration_ms: !quir.duration) -> (i32, !quir.duration) { +// DT: func.func @func0(%arg0: i32, %arg1: !quir.qubit<1>, [[duration_dt0:%.*]]: !quir.duration
, [[duration_s:%.*]]: !quir.duration
, [[duration_ms:%.*]]: !quir.duration
) -> (i32, !quir.duration
) { +// S: func.func @func0(%arg0: i32, %arg1: !quir.qubit<1>, [[duration_dt0:%.*]]: !quir.duration, [[duration_s:%.*]]: !quir.duration, [[duration_ms:%.*]]: !quir.duration) -> (i32, !quir.duration) { quir.delay %duration_dt0, (%q) : !quir.duration
, (!quir.qubit<1>) -> () // DT: quir.delay [[duration_dt0]], ({{.*}}) : !quir.duration
, (!quir.qubit<1>) -> () // S: quir.delay [[duration_dt0]], ({{.*}}) : !quir.duration, (!quir.qubit<1>) -> () diff --git a/test/Dialect/QUIR/Transforms/convert-quir-angles.mlir b/test/Dialect/QUIR/Transforms/convert-quir-angles.mlir index 723222ae5..f44ac7e31 100644 --- a/test/Dialect/QUIR/Transforms/convert-quir-angles.mlir +++ b/test/Dialect/QUIR/Transforms/convert-quir-angles.mlir @@ -14,14 +14,14 @@ // that they have been altered from the originals. module { - func @rz(%arg0: !quir.qubit<1>, %arg1: !quir.angle<64>) { + func.func @rz(%arg0: !quir.qubit<1>, %arg1: !quir.angle<64>) { return } - func @main() -> i32 { + func.func @main() -> i32 { %c0_i32 = arith.constant 0 : i32 %0 = quir.declare_qubit {id = 2 : i32} : !quir.qubit<1> - // CHECK: {{.*}} = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> - %1 = quir.constant #quir.angle<0.000000e+00 : !quir.angle<32>> + // CHECK: {{.*}} = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> + %1 = quir.constant #quir.angle<0.000000e+00> : !quir.angle<32> quir.call_gate @rz(%0, %1) : (!quir.qubit<1>, !quir.angle<32>) -> () qcs.finalize return %c0_i32 : i32 diff --git a/test/Dialect/QUIR/Transforms/for-localization.mlir b/test/Dialect/QUIR/Transforms/for-localization.mlir index 4513bc377..9b4b65659 100644 --- a/test/Dialect/QUIR/Transforms/for-localization.mlir +++ b/test/Dialect/QUIR/Transforms/for-localization.mlir @@ -14,8 +14,8 @@ // that they have been altered from the originals. %q1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> -%ang = quir.constant #quir.angle<0.00 : !quir.angle<20>> -%ang_incr = quir.constant #quir.angle<0.1 : !quir.angle<20>> +%ang = quir.constant #quir.angle<0.00> : !quir.angle<20> +%ang_incr = quir.constant #quir.angle<0.1> : !quir.angle<20> %lb = arith.constant 0 : index %ub = arith.constant 10 : index %step = arith.constant 1 : index diff --git a/test/Dialect/QUIR/Transforms/load-elimination.mlir b/test/Dialect/QUIR/Transforms/load-elimination.mlir index acad3df78..f5661687b 100644 --- a/test/Dialect/QUIR/Transforms/load-elimination.mlir +++ b/test/Dialect/QUIR/Transforms/load-elimination.mlir @@ -25,7 +25,7 @@ module { // REMOVE-UNUSED-NOT: oq3.declare_variable @a - func @main() -> i32 { + func.func @main() -> i32 { %c1 = arith.constant 1 : index // CHECK: [[CONST17_I32:%.*]] = arith.constant 17 : i32 diff --git a/test/Dialect/QUIR/Transforms/load-elimination2.mlir b/test/Dialect/QUIR/Transforms/load-elimination2.mlir index 23377535a..6edbb904a 100644 --- a/test/Dialect/QUIR/Transforms/load-elimination2.mlir +++ b/test/Dialect/QUIR/Transforms/load-elimination2.mlir @@ -25,17 +25,17 @@ module { // REMOVE-UNUSED-NOT: oq3.declare_variable {input} @a - func @main() -> !quir.angle<64> { + func.func @main() -> !quir.angle<64> { - // CHECK: [[CONST314_ANGLE:%.*]] = quir.constant {quir.inputParameter = "a"} #quir.angle<3.140000e+00 : !quir.angle<64>> - // REMOVE-UNUSED: [[CONST314_ANGLE:%.*]] = quir.constant #quir.angle<3.140000e+00 : !quir.angle<64>> - %angle = quir.constant #quir.angle<3.140000e+00 : !quir.angle<64>> - %angle2 = quir.constant #quir.angle<3.140000e+00 : !quir.angle<64>> + // CHECK: [[CONST314_ANGLE:%.*]] = quir.constant {quir.inputParameter = "a"} #quir.angle<3.140000e+00> : !quir.angle<64> + // REMOVE-UNUSED: [[CONST314_ANGLE:%.*]] = quir.constant {quir.inputParameter = "a"} #quir.angle<3.140000e+00> : !quir.angle<64> + %angle = quir.constant #quir.angle<3.140000e+00> : !quir.angle<64> + %angle2 = quir.constant #quir.angle<3.140000e+00> : !quir.angle<64> // REMOVE-UNUSED-NOT: oq3.variable_assign @a oq3.variable_assign @a : !quir.angle<64> = %angle - %angle_0 = quir.constant #quir.angle<1.000000e+00 : !quir.angle<64>> + %angle_0 = quir.constant #quir.angle<1.000000e+00> : !quir.angle<64> oq3.variable_assign @b : !quir.angle<64> = %angle_0 // The load elimination pass should forward-propagate the initializer to the diff --git a/test/Dialect/QUIR/Transforms/merge-circuits.mlir b/test/Dialect/QUIR/Transforms/merge-circuits.mlir index 1d75e4051..28a73e12a 100644 --- a/test/Dialect/QUIR/Transforms/merge-circuits.mlir +++ b/test/Dialect/QUIR/Transforms/merge-circuits.mlir @@ -1,4 +1,4 @@ -// RUN: qss-compiler -X=mlir --subroutine-cloning --quantum-decorate --merge-circuits %s | FileCheck %s +// RUN: qss-compiler -X=mlir --subroutine-cloning --quantum-decorate --merge-circuits %s | FileCheck %s // // This code is part of Qiskit. @@ -62,7 +62,7 @@ module { // CHECK: %1 = quir.measure(%arg1) : (!quir.qubit<1>) -> i1 // CHECK: quir.return %0, %1 : i1, i1 // CHECK: } - func @main() -> i32 { + func.func @main() -> i32 { %0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> %200 = quir.declare_qubit {id = 2 : i32} : !quir.qubit<1> @@ -129,4 +129,4 @@ module { %c0_i32 = arith.constant 0 : i32 return %c0_i32 : i32 } -} \ No newline at end of file +} diff --git a/test/Dialect/QUIR/Transforms/merge-measurements-circuits.mlir b/test/Dialect/QUIR/Transforms/merge-measurements-circuits.mlir index b0d61fe77..8ded30852 100644 --- a/test/Dialect/QUIR/Transforms/merge-measurements-circuits.mlir +++ b/test/Dialect/QUIR/Transforms/merge-measurements-circuits.mlir @@ -22,7 +22,7 @@ quir.circuit @circuit_0(%arg0: !quir.qubit<1>, %arg1: !quir.qubit<1>) -> (i1, i1 // CHECK: [[MEASURE:%.*]]:2 = quir.measure(%arg0, %arg1) : (!quir.qubit<1>, !quir.qubit<1>) -> (i1, i1) // CHECK: quir.return [[MEASURE]]#0, [[MEASURE]]#1 : i1, i1 } -func @main() -> i32 { +func.func @main() -> i32 { %0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> %2:2 = quir.call_circuit @circuit_0(%0, %1) : (!quir.qubit<1>, !quir.qubit<1>) -> (i1, i1) diff --git a/test/Dialect/QUIR/Transforms/merge-measures.mlir b/test/Dialect/QUIR/Transforms/merge-measures.mlir index 6e9422275..6315c0504 100644 --- a/test/Dialect/QUIR/Transforms/merge-measures.mlir +++ b/test/Dialect/QUIR/Transforms/merge-measures.mlir @@ -14,7 +14,7 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -func @one() { +func.func @one() { %q = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> // LEX: %{{.*}} = quir.measure(%{{.*}}) : (!quir.qubit<1>) -> i1 // TOP: %{{.*}} = quir.measure(%{{.*}}) : (!quir.qubit<1>) -> i1 @@ -22,7 +22,7 @@ func @one() { return } -func @two(%c : memref<1xi1>, %ind : index) { +func.func @two(%c : memref<1xi1>, %ind : index) { %q0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %q1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> // LEX: %{{.*}}:2 = quir.measure(%{{.*}}, %{{.*}}) : (!quir.qubit<1>, !quir.qubit<1>) -> (i1, i1) @@ -33,7 +33,7 @@ func @two(%c : memref<1xi1>, %ind : index) { return } -func @three(%c : memref<1xi1>, %ind : index) { +func.func @three(%c : memref<1xi1>, %ind : index) { %q0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %q1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> %q2 = quir.declare_qubit {id = 2 : i32} : !quir.qubit<1> @@ -47,7 +47,7 @@ func @three(%c : memref<1xi1>, %ind : index) { return } -func @four(%c : memref<1xi1>, %ind : index) { +func.func @four(%c : memref<1xi1>, %ind : index) { %q0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %q1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> %q2 = quir.declare_qubit {id = 2 : i32} : !quir.qubit<1> @@ -64,7 +64,7 @@ func @four(%c : memref<1xi1>, %ind : index) { return } -func @four_interrupted(%c : memref<1xi1>, %ind : index) { +func.func @four_interrupted(%c : memref<1xi1>, %ind : index) { %q0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %q1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> %q2 = quir.declare_qubit {id = 2 : i32} : !quir.qubit<1> @@ -90,7 +90,7 @@ func @four_interrupted(%c : memref<1xi1>, %ind : index) { return } -func @inter_if(%c : memref<1xi1>, %ind : index, %cond : i1) { +func.func @inter_if(%c : memref<1xi1>, %ind : index, %cond : i1) { %q0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %q1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> %q2 = quir.declare_qubit {id = 2 : i32} : !quir.qubit<1> @@ -112,7 +112,7 @@ func @inter_if(%c : memref<1xi1>, %ind : index, %cond : i1) { return } -func @barrier(%c : memref<1xi1>, %ind : index) { +func.func @barrier(%c : memref<1xi1>, %ind : index) { %q0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %q1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> %q2 = quir.declare_qubit {id = 2 : i32} : !quir.qubit<1> @@ -136,7 +136,7 @@ func @barrier(%c : memref<1xi1>, %ind : index) { } -func @inter_switch(%flag : i32) { +func.func @inter_switch(%flag : i32) { %q0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %q1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> %q2 = quir.declare_qubit {id = 2 : i32} : !quir.qubit<1> diff --git a/test/Dialect/QUIR/Transforms/merge-resets.mlir b/test/Dialect/QUIR/Transforms/merge-resets.mlir index be12018ec..38f621805 100644 --- a/test/Dialect/QUIR/Transforms/merge-resets.mlir +++ b/test/Dialect/QUIR/Transforms/merge-resets.mlir @@ -18,15 +18,15 @@ // that they have been altered from the originals. module { - func @x(%arg0: !quir.qubit<1>) { + func.func @x(%arg0: !quir.qubit<1>) { return } - func @main() -> i32 { + func.func @main() -> i32 { %c0 = arith.constant 0 : index %c1000 = arith.constant 1000 : index %c1 = arith.constant 1 : index scf.for %arg0 = %c0 to %c1000 step %c1 { - %0 = quir.constant #quir.duration<1.0 : !quir.duration> + %0 = quir.constant #quir.duration<1.0> : !quir.duration quir.delay %0, () : !quir.duration, () -> () // qubit $0; @@ -101,7 +101,6 @@ module { quir.reset %1 : !quir.qubit<1> // CHECK: quir.reset [[QUBIT0]] : !quir.qubit<1> quir.call_gate @x(%4) : (!quir.qubit<1>) -> () - %cst = constant unit quir.reset %2 : !quir.qubit<1> // CHECK: quir.reset [[QUBIT1]] : !quir.qubit<1> // TOPO: quir.reset [[QUBIT0]], [[QUBIT1]] : !quir.qubit<1>, !quir.qubit<1> diff --git a/test/Dialect/QUIR/Transforms/merge-resets2.mlir b/test/Dialect/QUIR/Transforms/merge-resets2.mlir index 93efe33ed..01d3bfd20 100644 --- a/test/Dialect/QUIR/Transforms/merge-resets2.mlir +++ b/test/Dialect/QUIR/Transforms/merge-resets2.mlir @@ -18,12 +18,12 @@ // that they have been altered from the originals. module { - func @main() -> i32 { + func.func @main() -> i32 { %c0 = arith.constant 0 : index %c1000 = arith.constant 1000 : index %c1 = arith.constant 1 : index scf.for %arg0 = %c0 to %c1000 step %c1 { - %0 = quir.constant #quir.duration<1.0 : !quir.duration> + %0 = quir.constant #quir.duration<1.0> : !quir.duration quir.delay %0, () : !quir.duration, () -> () // qubit $0; diff --git a/test/Dialect/QUIR/Transforms/quantum-decoration.mlir b/test/Dialect/QUIR/Transforms/quantum-decoration.mlir index 16d34f050..c1e071ef8 100644 --- a/test/Dialect/QUIR/Transforms/quantum-decoration.mlir +++ b/test/Dialect/QUIR/Transforms/quantum-decoration.mlir @@ -13,7 +13,7 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -func @t1 (%cond : i1) -> () { +func.func @t1 (%cond : i1) -> () { %q0 = quir.declare_qubit {id = 0: i32} : !quir.qubit<1> %q1 = quir.declare_qubit {id = 1: i32} : !quir.qubit<1> %q2 = quir.declare_qubit {id = 2: i32} : !quir.qubit<1> diff --git a/test/Dialect/QUIR/Transforms/remove-unused-variables.mlir b/test/Dialect/QUIR/Transforms/remove-unused-variables.mlir index 81ee8aa4a..10d5bab87 100644 --- a/test/Dialect/QUIR/Transforms/remove-unused-variables.mlir +++ b/test/Dialect/QUIR/Transforms/remove-unused-variables.mlir @@ -21,8 +21,8 @@ oq3.declare_variable @isUsed : !quir.cbit<1> oq3.declare_variable {output} @isOutput : !quir.cbit<1> oq3.declare_variable @storeOnly : !quir.cbit<1> oq3.declare_variable @notUsed : !quir.cbit<1> -// UNUSED: func @variableTests -func @variableTests(%ref : memref<1xi1>, %ind : index) { +// UNUSED: func.func @variableTests +func.func @variableTests(%ref : memref<1xi1>, %ind : index) { %false = arith.constant false %false_cbit = "oq3.cast"(%false) : (i1) -> !quir.cbit<1> diff --git a/test/Dialect/QUIR/Transforms/reorder-circuits.mlir b/test/Dialect/QUIR/Transforms/reorder-circuits.mlir index e8b60abff..719dbd360 100644 --- a/test/Dialect/QUIR/Transforms/reorder-circuits.mlir +++ b/test/Dialect/QUIR/Transforms/reorder-circuits.mlir @@ -1,4 +1,4 @@ -// RUN: qss-compiler -X=mlir --enable-circuits=true --reorder-circuits %s | FileCheck %s +// RUN: qss-compiler -X=mlir --enable-circuits=true --reorder-circuits %s | FileCheck %s // // This code is part of Qiskit. @@ -20,7 +20,7 @@ module { quir.return %0: i1 } - func @main() -> i32 { + func.func @main() -> i32 { %false = arith.constant false %0 = memref.get_global @a : memref %1 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> @@ -39,4 +39,4 @@ module { %c0_i32 = arith.constant 0 : i32 return %c0_i32 : i32 } -} \ No newline at end of file +} diff --git a/test/Dialect/QUIR/Transforms/reorder-measurements-2.mlir b/test/Dialect/QUIR/Transforms/reorder-measurements-2.mlir index 066711227..cea63ce37 100644 --- a/test/Dialect/QUIR/Transforms/reorder-measurements-2.mlir +++ b/test/Dialect/QUIR/Transforms/reorder-measurements-2.mlir @@ -20,18 +20,18 @@ module { oq3.declare_variable @b : !quir.cbit<1> oq3.declare_variable @results : !quir.cbit<1> - func @x(%arg0: !quir.qubit<1>) { + func.func @x(%arg0: !quir.qubit<1>) { return } - func @sx(%arg0: !quir.qubit<1>) { + func.func @sx(%arg0: !quir.qubit<1>) { return } - func @rz(%arg0: !quir.qubit<1>, %arg1: !quir.angle<64>) { + func.func @rz(%arg0: !quir.qubit<1>, %arg1: !quir.angle<64>) { return } - func @main() -> i32 { + func.func @main() -> i32 { %c0_i32 = arith.constant 0 : i32 - %angle = quir.constant #quir.angle<1.500000e+00 : !quir.angle<64>> + %angle = quir.constant #quir.angle<1.500000e+00> : !quir.angle<64> // CHECK: [[QUBIT0:%.*]] = quir.declare_qubit {id = 0 : i32} // CHECK: [[QUBIT1:%.*]] = quir.declare_qubit {id = 1 : i32} diff --git a/test/Dialect/QUIR/Transforms/reorder-measurements-issue-1730.mlir b/test/Dialect/QUIR/Transforms/reorder-measurements-issue-1730.mlir index f61bb8b9a..2974d9e62 100644 --- a/test/Dialect/QUIR/Transforms/reorder-measurements-issue-1730.mlir +++ b/test/Dialect/QUIR/Transforms/reorder-measurements-issue-1730.mlir @@ -29,17 +29,17 @@ module { oq3.declare_variable {input} @p001 : !quir.angle<64> oq3.declare_variable {input} @p002 : !quir.angle<64> oq3.declare_variable {input} @p003 : !quir.angle<64> - func @rz(%arg0: !quir.qubit<1>, %arg1: !quir.angle<64>) attributes {quir.classicalOnly = false} { + func.func @rz(%arg0: !quir.qubit<1>, %arg1: !quir.angle<64>) attributes {quir.classicalOnly = false} { return } - func @main() -> i32 attributes {quir.classicalOnly = false} { + func.func @main() -> i32 attributes {quir.classicalOnly = false} { %c0_i32 = arith.constant 0 : i32 - %angle = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> + %angle = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> %0 = quir.declare_qubit {id = 12 : i32} : !quir.qubit<1> %1 = quir.declare_qubit {id = 16 : i32} : !quir.qubit<1> %2 = quir.declare_qubit {id = 22 : i32} : !quir.qubit<1> %3 = quir.declare_qubit {id = 23 : i32} : !quir.qubit<1> - + oq3.variable_assign @p001 : !quir.angle<64> = %angle // test do not reorder if variable_assign is between measures @@ -47,24 +47,24 @@ module { oq3.variable_assign @p002 : !quir.angle<64> = %angle %5 = oq3.variable_load @p002 : !quir.angle<64> quir.call_gate @rz(%1, %5) : (!quir.qubit<1>, !quir.angle<64>) -> () - + // CHECK: %4 = quir.measure(%0) : (!quir.qubit<1>) -> i1 // CHECK: oq3.variable_assign @p002 : !quir.angle<64> = %angle // CHECK: %5 = oq3.variable_load @p002 : !quir.angle<64> // CHECK: quir.call_gate @rz(%1, %5) : (!quir.qubit<1>, !quir.angle<64>) -> () - + // test re-order if: - // variable_assign not in block || + // variable_assign not in block || // variable_assign above measure in block %6 = quir.measure(%1) : (!quir.qubit<1>) -> i1 // CHECK-NOT: %6 = quir.measure(%1) : (!quir.qubit<1>) -> i1 - + %7 = oq3.variable_load @p003 : !quir.angle<64> quir.call_gate @rz(%2, %7) : (!quir.qubit<1>, !quir.angle<64>) -> () %8 = oq3.variable_load @p001 : !quir.angle<64> quir.call_gate @rz(%3, %8) : (!quir.qubit<1>, !quir.angle<64>) -> () - + // CHECK: %6 = oq3.variable_load @p003 : !quir.angle<64> // CHECK: quir.call_gate @rz(%2, %6) : (!quir.qubit<1>, !quir.angle<64>) -> () // CHECK: %7 = oq3.variable_load @p001 : !quir.angle<64> @@ -72,7 +72,7 @@ module { // CHECK: %8 = quir.measure(%1) : (!quir.qubit<1>) -> i1 %9 = quir.measure(%3) : (!quir.qubit<1>) -> i1 // CHECK: %9 = quir.measure(%3) : (!quir.qubit<1>) -> i1 - + return %c0_i32 : i32 } } diff --git a/test/Dialect/QUIR/Transforms/reorder-measurements-issue-910-2.mlir b/test/Dialect/QUIR/Transforms/reorder-measurements-issue-910-2.mlir index 0e90dcf3a..a450ad99b 100644 --- a/test/Dialect/QUIR/Transforms/reorder-measurements-issue-910-2.mlir +++ b/test/Dialect/QUIR/Transforms/reorder-measurements-issue-910-2.mlir @@ -16,10 +16,10 @@ // CHECK: module module { oq3.declare_variable @results : !quir.cbit<1> - func @cx(%arg0: !quir.qubit<1>, %arg1: !quir.qubit<1>) { + func.func @cx(%arg0: !quir.qubit<1>, %arg1: !quir.qubit<1>) { return } - func @main() -> i32 { + func.func @main() -> i32 { %c0_i32 = arith.constant 0 : i32 %0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> diff --git a/test/Dialect/QUIR/Transforms/reorder-measurements-issue-910.mlir b/test/Dialect/QUIR/Transforms/reorder-measurements-issue-910.mlir index da38c5dd1..5a54ed41a 100644 --- a/test/Dialect/QUIR/Transforms/reorder-measurements-issue-910.mlir +++ b/test/Dialect/QUIR/Transforms/reorder-measurements-issue-910.mlir @@ -16,10 +16,10 @@ // CHECK: module module { oq3.declare_variable @results : !quir.cbit<1> - func @cx(%arg0: !quir.qubit<1>, %arg1: !quir.qubit<1>) { + func.func @cx(%arg0: !quir.qubit<1>, %arg1: !quir.qubit<1>) { return } - func @main() -> i32 { + func.func @main() -> i32 { %c0_i32 = arith.constant 0 : i32 %0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> diff --git a/test/Dialect/QUIR/Transforms/reorder-measurements-issue-921.mlir b/test/Dialect/QUIR/Transforms/reorder-measurements-issue-921.mlir index 09eb813da..1270a1c77 100644 --- a/test/Dialect/QUIR/Transforms/reorder-measurements-issue-921.mlir +++ b/test/Dialect/QUIR/Transforms/reorder-measurements-issue-921.mlir @@ -30,7 +30,7 @@ module { oq3.declare_variable @a : !quir.cbit<1> oq3.declare_variable @b : !quir.cbit<1> - func @main() -> i32 attributes {quir.classicalOnly = false} { + func.func @main() -> i32 attributes {quir.classicalOnly = false} { %c0_i32 = arith.constant 0 : i32 %c1_i32 = arith.constant 1 : i32 qcs.shot_init {qcs.num_shots = 1000 : i32} diff --git a/test/Dialect/QUIR/Transforms/reorder-measurements.mlir b/test/Dialect/QUIR/Transforms/reorder-measurements.mlir index 2ad3ee9c0..da18a489d 100644 --- a/test/Dialect/QUIR/Transforms/reorder-measurements.mlir +++ b/test/Dialect/QUIR/Transforms/reorder-measurements.mlir @@ -13,8 +13,8 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -// CHECK: func @three -func @three(%c : memref<1xi1>, %ind : index, %angle_0 : !quir.angle<64>) { +// CHECK: func.func @three +func.func @three(%c : memref<1xi1>, %ind : index, %angle_0 : !quir.angle<64>) { %q0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %q1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> %q2 = quir.declare_qubit {id = 2 : i32} : !quir.qubit<1> @@ -54,8 +54,8 @@ func @three(%c : memref<1xi1>, %ind : index, %angle_0 : !quir.angle<64>) { // Reordering should fail when there is a usage of the same qubit in a gate // after the measurement -// CHECK: func @reorder_fail1 -func @reorder_fail1(%c : memref<1xi1>, %ind : index, %angle_0 : !quir.angle<64>) { +// CHECK: func.func @reorder_fail1 +func.func @reorder_fail1(%c : memref<1xi1>, %ind : index, %angle_0 : !quir.angle<64>) { %q0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %q1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> %q2 = quir.declare_qubit {id = 2 : i32} : !quir.qubit<1> diff --git a/test/Dialect/QUIR/Transforms/subroutine-cloning.mlir b/test/Dialect/QUIR/Transforms/subroutine-cloning.mlir index 760186591..855e78ab2 100644 --- a/test/Dialect/QUIR/Transforms/subroutine-cloning.mlir +++ b/test/Dialect/QUIR/Transforms/subroutine-cloning.mlir @@ -14,27 +14,27 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -func @classical() -> i32 { +func.func @classical() -> i32 { %ret = arith.constant 32 : i32 return %ret : i32 } -func @sub1(%q0 : !quir.qubit<1>) { +func.func @sub1(%q0 : !quir.qubit<1>) { quir.call_gate @x(%q0) : (!quir.qubit<1>) -> () return } -func @sub2(%q0 : !quir.qubit<1>, %q1 : !quir.qubit<1>, %a1 : !quir.angle<20>) { +func.func @sub2(%q0 : !quir.qubit<1>, %q1 : !quir.qubit<1>, %a1 : !quir.angle<20>) { quir.call_gate @h(%q0) : (!quir.qubit<1>) -> () quir.call_gate @x(%q1) : (!quir.qubit<1>) -> () quir.call_subroutine @sub1(%q0) : (!quir.qubit<1>) -> () return } -func @main() -> i32 { +func.func @main() -> i32 { %q0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %q1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> - %a1 = quir.constant #quir.angle<3.14159 : !quir.angle<20>> + %a1 = quir.constant #quir.angle<3.14159> : !quir.angle<20> quir.call_subroutine @sub1(%q0) : (!quir.qubit<1>) -> () quir.call_subroutine @sub1(%q1) : (!quir.qubit<1>) -> () quir.call_subroutine @sub2(%q0, %q1, %a1) : (!quir.qubit<1>, !quir.qubit<1>, !quir.angle<20>) -> () @@ -43,34 +43,34 @@ func @main() -> i32 { return %ret : i32 } -// CHECK: func @classical() -> i32 { -// CHECK: func @sub1_q0(%arg0: !quir.qubit<1> {quir.physicalId = 0 : i32}) { -// CHECK: func @sub1_q1(%arg0: !quir.qubit<1> {quir.physicalId = 1 : i32}) { -// CHECK: func @sub2_q0_q1(%arg0: !quir.qubit<1> {quir.physicalId = 0 : i32}, %arg1: !quir.qubit<1> {quir.physicalId = 1 : i32}, %arg2: !quir.angle<20>) { +// CHECK: func.func @classical() -> i32 { +// CHECK: func.func @sub1_q0(%arg0: !quir.qubit<1> {quir.physicalId = 0 : i32}) { +// CHECK: func.func @sub1_q1(%arg0: !quir.qubit<1> {quir.physicalId = 1 : i32}) { +// CHECK: func.func @sub2_q0_q1(%arg0: !quir.qubit<1> {quir.physicalId = 0 : i32}, %arg1: !quir.qubit<1> {quir.physicalId = 1 : i32}, %arg2: !quir.angle<20>) { // CHECK: quir.call_subroutine @sub1_q0(%arg0) : (!quir.qubit<1>) -> () -// CHECK: func @sub2_q1_q0(%arg0: !quir.qubit<1> {quir.physicalId = 1 : i32}, %arg1: !quir.qubit<1> {quir.physicalId = 0 : i32}, %arg2: !quir.angle<20>) { +// CHECK: func.func @sub2_q1_q0(%arg0: !quir.qubit<1> {quir.physicalId = 1 : i32}, %arg1: !quir.qubit<1> {quir.physicalId = 0 : i32}, %arg2: !quir.angle<20>) { // CHECK: quir.call_subroutine @sub1_q1(%arg0) : (!quir.qubit<1>) -> () -// CHECK: func @main() -> i32 { +// CHECK: func.func @main() -> i32 { // CHECK: quir.call_subroutine @sub1_q0(%0) : (!quir.qubit<1>) -> () // CHECK: quir.call_subroutine @sub1_q1(%1) : (!quir.qubit<1>) -> () // CHECK: quir.call_subroutine @sub2_q0_q1(%0, %1, %angle) : (!quir.qubit<1>, !quir.qubit<1>, !quir.angle<20>) -> () // CHECK: quir.call_subroutine @sub2_q1_q0(%1, %0, %angle) : (!quir.qubit<1>, !quir.qubit<1>, !quir.angle<20>) -> () // CHECK: %{{[0-9]+}} = quir.call_subroutine @classical() : () -> i32 -// NOQARG: func @classical() -> i32 { -// NOQARG: func @sub1_q0() { +// NOQARG: func.func @classical() -> i32 { +// NOQARG: func.func @sub1_q0() { // NOQARG-NEXT: %0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> -// NOQARG: func @sub1_q1() { +// NOQARG: func.func @sub1_q1() { // NOQARG-NEXT: %0 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> -// NOQARG: func @sub2_q0_q1(%arg0: !quir.angle<20>) { +// NOQARG: func.func @sub2_q0_q1(%arg0: !quir.angle<20>) { // NOQARG-NEXT: %0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> // NOQARG-NEXT: %1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> // NOQARG: quir.call_subroutine @sub1_q0() : () -> () -// NOQARG: func @sub2_q1_q0(%arg0: !quir.angle<20>) { +// NOQARG: func.func @sub2_q1_q0(%arg0: !quir.angle<20>) { // NOQARG-NEXT: %0 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> // NOQARG-NEXT: %1 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> // NOQARG: quir.call_subroutine @sub1_q1() : () -> () -// NOQARG: func @main() -> i32 { +// NOQARG: func.func @main() -> i32 { // NOQARG: quir.call_subroutine @sub1_q0() : () -> () // NOQARG: quir.call_subroutine @sub1_q1() : () -> () // NOQARG: quir.call_subroutine @sub2_q0_q1(%angle) : (!quir.angle<20>) -> () diff --git a/test/Dialect/QUIR/Transforms/variable-elimination1.mlir b/test/Dialect/QUIR/Transforms/variable-elimination1.mlir index 517c42fb5..b875b9b75 100644 --- a/test/Dialect/QUIR/Transforms/variable-elimination1.mlir +++ b/test/Dialect/QUIR/Transforms/variable-elimination1.mlir @@ -22,10 +22,10 @@ module { oq3.declare_variable @a : !quir.cbit<1> oq3.declare_variable @b : !quir.cbit<1> - func @x(%arg0: !quir.qubit<1>) { + func.func @x(%arg0: !quir.qubit<1>) { return } - func @main() -> i32 { + func.func @main() -> i32 { // CHECK: [[QUBIT0:%.*]] = quir.declare_qubit {id = 0 : i32} // CHECK: [[QUBIT1:%.*]] = quir.declare_qubit {id = 1 : i32} %1 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> @@ -55,7 +55,6 @@ module { scf.if %9 { quir.call_gate @x(%1) : (!quir.qubit<1>) -> () - %cst = constant unit } %10 = oq3.variable_load @b : !quir.cbit<1> %c1_i32_1 = arith.constant 1 : i32 @@ -66,7 +65,6 @@ module { %12 = arith.cmpi eq, %11, %c1_i32_1 : i32 scf.if %12 { quir.call_gate @x(%2) : (!quir.qubit<1>) -> () - %cst = constant unit } %c0_i32 = arith.constant 0 : i32 diff --git a/test/Dialect/QUIR/Transforms/variable-elimination2.mlir b/test/Dialect/QUIR/Transforms/variable-elimination2.mlir index b49b2ff62..b93ee5dbb 100644 --- a/test/Dialect/QUIR/Transforms/variable-elimination2.mlir +++ b/test/Dialect/QUIR/Transforms/variable-elimination2.mlir @@ -19,10 +19,10 @@ // CHECK: module module { oq3.declare_variable @b : !quir.cbit<1> - func @x(%arg0: !quir.qubit<1>) { + func.func @x(%arg0: !quir.qubit<1>) { return } - func @main() -> i32 { + func.func @main() -> i32 { // CHECK-DAG: [[MEMREF:%.*]] = memref.alloca() : memref // CHECK-DAG: [[QUBIT0:%.*]] = quir.declare_qubit {id = 0 : i32} // CHECK-DAG: [[QUBIT1:%.*]] = quir.declare_qubit {id = 1 : i32} @@ -46,7 +46,6 @@ module { scf.if %5 { quir.call_gate @x(%1) : (!quir.qubit<1>) -> () oq3.cbit_assign_bit @b<1> [0] : i1 = %5 - %cst = constant unit } // CHECK: [[LOAD:%.*]] = affine.load [[MEMREF]] @@ -58,7 +57,6 @@ module { // CHECK: scf.if [[LOAD]] scf.if %12 { quir.call_gate @x(%2) : (!quir.qubit<1>) -> () - %cst = constant unit } return %11 : i32 diff --git a/test/Dialect/QUIR/Transforms/variable-elimination3.mlir b/test/Dialect/QUIR/Transforms/variable-elimination3.mlir index 503ff658f..5947ae7a9 100644 --- a/test/Dialect/QUIR/Transforms/variable-elimination3.mlir +++ b/test/Dialect/QUIR/Transforms/variable-elimination3.mlir @@ -19,10 +19,10 @@ module { oq3.declare_variable @a : !quir.cbit<1> oq3.declare_variable @b : !quir.cbit<2> - func @x(%arg0: !quir.qubit<1>) { + func.func @x(%arg0: !quir.qubit<1>) { return } - func @main() -> i32 { + func.func @main() -> i32 { %c0_i32 = arith.constant 0 : i32 %c0_i2 = arith.constant 0 : i2 %true = arith.constant true diff --git a/test/Dialect/QUIR/integration/iterative-phase-estimation.mlir b/test/Dialect/QUIR/integration/iterative-phase-estimation.mlir index 7daee83d5..d42c6759c 100644 --- a/test/Dialect/QUIR/integration/iterative-phase-estimation.mlir +++ b/test/Dialect/QUIR/integration/iterative-phase-estimation.mlir @@ -18,8 +18,8 @@ module { // defcal y90p %0 { // play drive(%0), drag(...); // } - // func @defcalRX_q0(%qa1 : !quir.qubit<1> {quir.physicalId = 0 : i32}, %theta : !quir.angle<20>) -> () attributes {quir.orig_func_name = "defcalRX"} { - func @defcalY90P_q0(%q0 : !quir.qubit<1> {quir.physicalId = 0 : i32}) -> () attributes {quir.orig_func_name = "defcalY90P"} { + // func.func @defcalRX_q0(%qa1 : !quir.qubit<1> {quir.physicalId = 0 : i32}, %theta : !quir.angle<20>) -> () attributes {quir.orig_func_name = "defcalRX"} { + func.func @defcalY90P_q0(%q0 : !quir.qubit<1> {quir.physicalId = 0 : i32}) -> () attributes {quir.orig_func_name = "defcalY90P"} { // PULSE IR Ops // CHECK: return return @@ -27,21 +27,21 @@ module { // defcal y90p %1 { // play drive(%1), drag(...); // } - func @defcalY90P_q1(%q0 : !quir.qubit<1> {quir.physicalId = 1 : i32}) -> () attributes {quir.orig_func_name = "defcalY90P"} { + func.func @defcalY90P_q1(%q0 : !quir.qubit<1> {quir.physicalId = 1 : i32}) -> () attributes {quir.orig_func_name = "defcalY90P"} { // PULSE IR Ops return } // defcal cr90p %0, %1 { // play flat_top_gaussian(...), drive(%0), frame(drive(%1)); // } - func @defcalCR90P_q0_q1(%q0 : !quir.qubit<1> {quir.physicalId = 0 : i32}, %q1 : !quir.qubit<1> {quir.physicalId = 1 : i32}) -> () attributes {quir.orig_func_name = "defcalCR90P"} { + func.func @defcalCR90P_q0_q1(%q0 : !quir.qubit<1> {quir.physicalId = 0 : i32}, %q1 : !quir.qubit<1> {quir.physicalId = 1 : i32}) -> () attributes {quir.orig_func_name = "defcalCR90P"} { // PULSE IR Ops return } // defcal phase(angle[20]: theta) %q { // shift_phase drive(%q), -theta; // } - func @defcalPhase_qq(%angle : !quir.angle, %qq : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "defcalPhase"} { + func.func @defcalPhase_qq(%angle : !quir.angle, %qq : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "defcalPhase"} { // PULSE IR Ops return } @@ -50,9 +50,9 @@ module { // cr90p %0, %1; // phase(pi) %1; // } - func @defcalCR90M_q0_q1(%q0 : !quir.qubit<1> {quir.physicalId = 0 : i32}, %q1 : !quir.qubit<1> {quir.physicalId = 1 : i32}) -> () attributes {quir.orig_func_name = "defcalCR90M"} { - %npi = quir.constant #quir.angle<-1.0 : !quir.angle<20>> - %pi = quir.constant #quir.angle<1.0 : !quir.angle<20>> + func.func @defcalCR90M_q0_q1(%q0 : !quir.qubit<1> {quir.physicalId = 0 : i32}, %q1 : !quir.qubit<1> {quir.physicalId = 1 : i32}) -> () attributes {quir.orig_func_name = "defcalCR90M"} { + %npi = quir.constant #quir.angle<-1.0> : !quir.angle<20> + %pi = quir.constant #quir.angle<1.0> : !quir.angle<20> "quir.call_gate"(%npi, %q1) {callee = @defcalPhase} : (!quir.angle<20>, !quir.qubit<1>) -> () "quir.call_gate"(%q0, %q1) {callee = @defcalCR90P} : (!quir.qubit<1>, !quir.qubit<1>) -> () "quir.call_gate"(%pi, %q1) {callee = @defcalPhase} : (!quir.angle<20>, !quir.qubit<1>) -> () @@ -63,9 +63,9 @@ module { // y90p %q; // phase(-pi) %q; // } - func @gateX90P_qq(%qq_1 : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "gateX90P"} { - %npi = quir.constant #quir.angle<-1.0 : !quir.angle<20>> - %pi = quir.constant #quir.angle<1.0 : !quir.angle<20>> + func.func @gateX90P_qq(%qq_1 : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "gateX90P"} { + %npi = quir.constant #quir.angle<-1.0> : !quir.angle<20> + %pi = quir.constant #quir.angle<1.0> : !quir.angle<20> "quir.call_gate"(%pi, %qq_1) {callee = @defcalPhase} : (!quir.angle<20>, !quir.qubit<1>) -> () "quir.call_gate"(%qq_1) {callee = @defcalY90P} : (!quir.qubit<1>) -> () "quir.call_gate"(%npi, %qq_1) {callee = @defcalPhase} : (!quir.angle<20>, !quir.qubit<1>) -> () @@ -75,7 +75,7 @@ module { // x90p %q; // x90p %q; // } - func @gateXP_qq(%qq_1 : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "gateXP"} { + func.func @gateXP_qq(%qq_1 : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "gateXP"} { "quir.call_gate"(%qq_1) {callee = @gateX90P} : (!quir.qubit<1>) -> () "quir.call_gate"(%qq_1) {callee = @gateX90P} : (!quir.qubit<1>) -> () return @@ -84,8 +84,8 @@ module { // phase(pi) %q; // y90p %q; // } - func @gateH_qq(%qq_1 : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "gateH"} { - %pi = quir.constant #quir.angle<1.0 : !quir.angle<20>> + func.func @gateH_qq(%qq_1 : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "gateH"} { + %pi = quir.constant #quir.angle<1.0> : !quir.angle<20> "quir.call_gate"(%pi, %qq_1) {callee = @defcalPhase} : (!quir.angle<20>, !quir.qubit<1>) -> () "quir.call_gate"(%qq_1) {callee = @defcalY90P} : (!quir.qubit<1>) -> () return @@ -101,8 +101,8 @@ module { // barrier %control, %target; // cr90m %control, %target; // } - func @gateCX_qq_qq(%ctrl : !quir.qubit<1>, %targ : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "gateCX"} { - %npi2 = quir.constant #quir.angle<-0.5 : !quir.angle<20>> + func.func @gateCX_qq_qq(%ctrl : !quir.qubit<1>, %targ : !quir.qubit<1>) -> () attributes {quir.orig_func_name = "gateCX"} { + %npi2 = quir.constant #quir.angle<-0.5> : !quir.angle<20> "quir.call_gate"(%ctrl) {callee = @gateXP} : (!quir.qubit<1>) -> () "quir.call_gate"(%targ) {callee = @gateX90P} : (!quir.qubit<1>) -> () "quir.call_gate"(%ctrl, %targ) {callee = @defcalCR90P} : (!quir.qubit<1>, !quir.qubit<1>) -> () @@ -118,13 +118,13 @@ module { // iq = capture acquire(%0), 2048, kernel(k0); // return threshold(iq, 1234); // } - func @defcalMeasure_q0(%q0_1 : !quir.qubit<1> {quir.physicalId = 0 : i32}) -> i1 attributes {quir.orig_func_name = "defcalMeasure"} { + func.func @defcalMeasure_q0(%q0_1 : !quir.qubit<1> {quir.physicalId = 0 : i32}) -> i1 attributes {quir.orig_func_name = "defcalMeasure"} { // Pulse IR Ops %res = arith.constant false return %res : i1 } // angle[3] c = 0; - %npi2 = quir.constant #quir.angle<0.0 : !quir.angle<3>> + %npi2 = quir.constant #quir.angle<0.0> : !quir.angle<3> // reset %0; // reset %1; %q0_0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> @@ -136,8 +136,8 @@ module { "quir.call_gate"(%q1_0) {callee = @gateH} : (!quir.qubit<1>) -> () "quir.call_gate"(%q0_0) {callee = @gateH} : (!quir.qubit<1>) -> () // duration a, b; // should be resolved to duration by this point - %duration_a = quir.constant #quir.duration<10.0 : !quir.duration> - %duration_b = quir.constant #quir.duration<20.0 : !quir.duration> + %duration_a = quir.constant #quir.duration<10.0> : !quir.duration + %duration_b = quir.constant #quir.duration<20.0> : !quir.duration // delay(a) %0; // delay(b) %1; "quir.delay"(%duration_a, %q0_0) : (!quir.duration, !quir.qubit<1>) -> () @@ -145,13 +145,13 @@ module { // cx %0, %1; "quir.call_gate"(%q0_0, %q1_0) {callee = @gateCX} : (!quir.qubit<1>, !quir.qubit<1>) -> () // phase(1.8125*pi) %1; - %ang1 = quir.constant #quir.angle<1.1825 : !quir.angle<20>> + %ang1 = quir.constant #quir.angle<1.1825> : !quir.angle<20> "quir.call_gate"(%ang1, %q1_0) {callee = @defcalPhase} : (!quir.angle<20>, !quir.qubit<1>) -> () // cx %0, %1; "quir.call_gate"(%q0_0, %q1_0) {callee = @gateCX} : (!quir.qubit<1>, !quir.qubit<1>) -> () // phase(0.1875*pi) %1; // phase(0.1875*pi) %0; - %ang2 = quir.constant #quir.angle<0.1875 : !quir.angle<20>> + %ang2 = quir.constant #quir.angle<0.1875> : !quir.angle<20> "quir.call_gate"(%ang1, %q1_0) {callee = @defcalPhase} : (!quir.angle<20>, !quir.qubit<1>) -> () "quir.call_gate"(%ang1, %q0_0) {callee = @defcalPhase} : (!quir.angle<20>, !quir.qubit<1>) -> () // h %0; @@ -171,24 +171,24 @@ module { "quir.call_gate"(%q0_0) {callee = @gateH} : (!quir.qubit<1>) -> () // duration cs; // delay(cs) %1; - %duration_c = quir.constant #quir.duration<5.0 : !quir.duration> + %duration_c = quir.constant #quir.duration<5.0> : !quir.duration "quir.delay"(%duration_c, %q1_0) : (!quir.duration, !quir.qubit<1>) -> () // cx %0, %1; "quir.call_gate"(%q0_0, %q1_0) {callee = @gateCX} : (!quir.qubit<1>, !quir.qubit<1>) -> () // phase(1.625*pi) %1; // mod 2*pi - %ang3 = quir.constant #quir.angle<1.625 : !quir.angle<20>> + %ang3 = quir.constant #quir.angle<1.625> : !quir.angle<20> "quir.call_gate"(%ang3, %q1_0) {callee = @defcalPhase} : (!quir.angle<20>, !quir.qubit<1>) -> () // cx %0, %1; "quir.call_gate"(%q0_0, %q1_0) {callee = @gateCX} : (!quir.qubit<1>, !quir.qubit<1>) -> () // phase(0.375*pi) %1; - %ang4 = quir.constant #quir.angle<0.375 : !quir.angle<20>> + %ang4 = quir.constant #quir.angle<0.375> : !quir.angle<20> "quir.call_gate"(%ang4, %q1_0) {callee = @defcalPhase} : (!quir.angle<20>, !quir.qubit<1>) -> () // angle[32] temp_1 = 0.375*pi; // temp_1 -= c; // cast and do arithmetic mod 2 pi - %tmp_angle_1 = quir.constant #quir.angle<0.375 : !quir.angle<32>> + %tmp_angle_1 = quir.constant #quir.angle<0.375> : !quir.angle<32> %cast_c = "oq3.cast"(%creg_1) : (!quir.cbit<3>) -> !quir.angle<32> // Math Ops resulting in !quir.angle<32> - %tmp_angle_2 = quir.constant #quir.angle<0.0 : !quir.angle<32>> + %tmp_angle_2 = quir.constant #quir.angle<0.0> : !quir.angle<32> %tmp_angle_2_cast = "oq3.cast"(%tmp_angle_2) : (!quir.angle<32>) -> !quir.angle<20> // phase(temp_1) %0; "quir.call_gate"(%tmp_angle_2_cast, %q1_0) {callee = @defcalPhase} : (!quir.angle<20>, !quir.qubit<1>) -> () diff --git a/test/Dialect/QUIR/integration/measure-reset.mlir b/test/Dialect/QUIR/integration/measure-reset.mlir index 4f2a6dae9..8538bb574 100644 --- a/test/Dialect/QUIR/integration/measure-reset.mlir +++ b/test/Dialect/QUIR/integration/measure-reset.mlir @@ -14,7 +14,7 @@ // that they have been altered from the originals. module { - func @bar() { + func.func @bar() { %0 = arith.constant 1 : i32 // CHECK: %{{.*}} = quir.declare_qubit : !quir.qubit<1> %qa1 = quir.declare_qubit : !quir.qubit<1> diff --git a/test/Dialect/QUIR/integration/qasm-bell-v0.mlir b/test/Dialect/QUIR/integration/qasm-bell-v0.mlir index a8e22a5e2..e6bbf2e2e 100644 --- a/test/Dialect/QUIR/integration/qasm-bell-v0.mlir +++ b/test/Dialect/QUIR/integration/qasm-bell-v0.mlir @@ -18,7 +18,7 @@ oq3.declare_variable @c0 : !quir.cbit<1> oq3.declare_variable @c1 : !quir.cbit<1> -func @main () -> i32 { +func.func @main () -> i32 { // qubit %0; // qubit %1; @@ -26,9 +26,9 @@ func @main () -> i32 { %q0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> %q1 = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> // U(1.57079632679, 0.0, 3.14159265359) %0; - %a0 = quir.constant #quir.angle<1.57079632679 : !quir.angle<20>> - %a1 = quir.constant #quir.angle<0.0 : !quir.angle<20>> - %a2 = quir.constant #quir.angle<3.14159265359 : !quir.angle<20>> + %a0 = quir.constant #quir.angle<1.57079632679> : !quir.angle<20> + %a1 = quir.constant #quir.angle<0.0> : !quir.angle<20> + %a2 = quir.constant #quir.angle<3.14159265359> : !quir.angle<20> quir.builtin_U %q0, %a0, %a1, %a2 : !quir.qubit<1>, !quir.angle<20>, !quir.angle<20>, !quir.angle<20> // CX %0, %1; quir.builtin_CX %q0, %q1 : !quir.qubit<1>, !quir.qubit<1> diff --git a/test/Dialect/QUIR/integration/qasm-bell-v1.mlir b/test/Dialect/QUIR/integration/qasm-bell-v1.mlir index cbd7b0482..9775efb02 100644 --- a/test/Dialect/QUIR/integration/qasm-bell-v1.mlir +++ b/test/Dialect/QUIR/integration/qasm-bell-v1.mlir @@ -16,15 +16,15 @@ // gate h q { // U(1.57079632679, 0.0, 3.14159265359) q; // } -func @h (%q : !quir.qubit<1>) -> () { - %a0 = quir.constant #quir.angle<1.57079632679 : !quir.angle<20>> - %a1 = quir.constant #quir.angle<0.0 : !quir.angle<20>> - %a2 = quir.constant #quir.angle<3.14159265359 : !quir.angle<20>> +func.func @h (%q : !quir.qubit<1>) -> () { + %a0 = quir.constant #quir.angle<1.57079632679> : !quir.angle<20> + %a1 = quir.constant #quir.angle<0.0> : !quir.angle<20> + %a2 = quir.constant #quir.angle<3.14159265359> : !quir.angle<20> quir.builtin_U %q, %a0, %a1, %a2 : !quir.qubit<1>, !quir.angle<20>, !quir.angle<20>, !quir.angle<20> return } -func @main () -> i32 { +func.func @main () -> i32 { // qubit %0; // qubit %1; // CHECK: %{{.*}} = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> diff --git a/test/Dialect/QUIR/integration/qasm-bell-v2.mlir b/test/Dialect/QUIR/integration/qasm-bell-v2.mlir index 1ca6205a8..184a936d6 100644 --- a/test/Dialect/QUIR/integration/qasm-bell-v2.mlir +++ b/test/Dialect/QUIR/integration/qasm-bell-v2.mlir @@ -16,26 +16,26 @@ // gate h q { // U(1.57079632679, 0.0, 3.14159265359) q; // } -func @h (%q : !quir.qubit<1>) -> () { - %a0 = quir.constant #quir.angle<1.57079632679 : !quir.angle<20>> - %a1 = quir.constant #quir.angle<0.0 : !quir.angle<20>> - %a2 = quir.constant #quir.angle<3.14159265359 : !quir.angle<20>> +func.func @h (%q : !quir.qubit<1>) -> () { + %a0 = quir.constant #quir.angle<1.57079632679> : !quir.angle<20> + %a1 = quir.constant #quir.angle<0.0> : !quir.angle<20> + %a2 = quir.constant #quir.angle<3.14159265359> : !quir.angle<20> quir.builtin_U %q, %a0, %a1, %a2 : !quir.qubit<1>, !quir.angle<20>, !quir.angle<20>, !quir.angle<20> return } -func @cx (%ctrl : !quir.qubit<1>, %targ : !quir.qubit<1>) { +func.func @cx (%ctrl : !quir.qubit<1>, %targ : !quir.qubit<1>) { quir.builtin_CX %ctrl, %targ : !quir.qubit<1>, !quir.qubit<1> return } -func @fake_multiqubit (%ctrl : !quir.qubit<1>, %targ : !quir.qubit<1>, %p1 : !quir.angle<20>) { +func.func @fake_multiqubit (%ctrl : !quir.qubit<1>, %targ : !quir.qubit<1>, %p1 : !quir.angle<20>) { quir.builtin_U %ctrl, %p1, %p1, %p1 : !quir.qubit<1>, !quir.angle<20>, !quir.angle<20>, !quir.angle<20> quir.builtin_CX %ctrl, %targ : !quir.qubit<1>, !quir.qubit<1> return } -func @main () -> i32 { +func.func @main () -> i32 { // qubit %0; // qubit %1; // CHECK: %{{.*}} = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> diff --git a/test/Dialect/QUIR/integration/qasm-reset-v1.mlir b/test/Dialect/QUIR/integration/qasm-reset-v1.mlir index d217caefb..faca28464 100644 --- a/test/Dialect/QUIR/integration/qasm-reset-v1.mlir +++ b/test/Dialect/QUIR/integration/qasm-reset-v1.mlir @@ -13,7 +13,7 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -func @main () -> i32 { +func.func @main () -> i32 { // CHECK: %{{.*}} = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> // qubit %0; %q0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> @@ -23,8 +23,8 @@ func @main () -> i32 { // if (result) { scf.if %mres { // U(pi, 0, pi) %0; - %zero_ang = quir.constant #quir.angle<0.0 : !quir.angle<20>> - %pi_ang = quir.constant #quir.angle<3.14159 : !quir.angle<20>> + %zero_ang = quir.constant #quir.angle<0.0> : !quir.angle<20> + %pi_ang = quir.constant #quir.angle<3.14159> : !quir.angle<20> quir.builtin_U %q0, %pi_ang, %zero_ang, %pi_ang : !quir.qubit<1>, !quir.angle<20>, !quir.angle<20>, !quir.angle<20> } %bigfloat = arith.constant 1.0 : f64 diff --git a/test/Dialect/QUIR/integration/qasm-reset-v1b.mlir b/test/Dialect/QUIR/integration/qasm-reset-v1b.mlir index 270f3579c..4f98de064 100644 --- a/test/Dialect/QUIR/integration/qasm-reset-v1b.mlir +++ b/test/Dialect/QUIR/integration/qasm-reset-v1b.mlir @@ -13,7 +13,7 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -func @main () -> i32 { +func.func @main () -> i32 { // CHECK: %{{.*}} = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> // qubit %0; %q0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> @@ -25,8 +25,8 @@ func @main () -> i32 { %condition = arith.cmpi "eq", %mres, %one_i1 : i1 scf.if %condition { // U(pi, 0, pi) %0; - %zero_ang = quir.constant #quir.angle<0.0 : !quir.angle<20>> - %pi_ang = quir.constant #quir.angle<3.14159 : !quir.angle<20>> + %zero_ang = quir.constant #quir.angle<0.0> : !quir.angle<20> + %pi_ang = quir.constant #quir.angle<3.14159> : !quir.angle<20> quir.builtin_U %q0, %pi_ang, %zero_ang, %pi_ang : !quir.qubit<1>, !quir.angle<20>, !quir.angle<20>, !quir.angle<20> } %zero = arith.constant 0 : i32 diff --git a/test/Dialect/QUIR/integration/scf-teleportation.mlir b/test/Dialect/QUIR/integration/scf-teleportation.mlir index 091c73496..9c84bd580 100644 --- a/test/Dialect/QUIR/integration/scf-teleportation.mlir +++ b/test/Dialect/QUIR/integration/scf-teleportation.mlir @@ -30,10 +30,10 @@ quir.reset %qa1 : !quir.qubit<1> quir.reset %qb1 : !quir.qubit<1> quir.reset %qc1 : !quir.qubit<1> // u3(0.3, 0.2, 0.1) q[0]; -// CHECK: %{{.*}} = quir.constant #quir.angle<3.000000e-01 : !quir.angle<1>> -%theta = quir.constant #quir.angle<0.3 : !quir.angle<1>> -%phi = quir.constant #quir.angle<0.2 : !quir.angle<1>> -%lambda = quir.constant #quir.angle<0.1 : !quir.angle<1>> +// CHECK: %{{.*}} = quir.constant #quir.angle<3.000000e-01> : !quir.angle<1> +%theta = quir.constant #quir.angle<0.3> : !quir.angle<1> +%phi = quir.constant #quir.angle<0.2> : !quir.angle<1> +%lambda = quir.constant #quir.angle<0.1> : !quir.angle<1> // CHECK: quir.builtin_U %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : !quir.qubit<1>, !quir.angle<1>, !quir.angle<1>, !quir.angle<1> quir.builtin_U %qa1, %theta, %phi, %lambda : !quir.qubit<1>, !quir.angle<1>, !quir.angle<1>, !quir.angle<1> // h q[1]; diff --git a/test/Frontend/OpenQASM3/angles.qasm b/test/Frontend/OpenQASM3/angles.qasm index bc6ff4118..664eb5a0d 100644 --- a/test/Frontend/OpenQASM3/angles.qasm +++ b/test/Frontend/OpenQASM3/angles.qasm @@ -15,12 +15,12 @@ OPENQASM 3.0; // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -// MLIR: %{{.*}} = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> +// MLIR: %{{.*}} = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> // AST-PRETTY: DeclarationNode(type=ASTTypeAngle, AngleNode(value=0.0, bits=64)) angle[64] angle_a; -// MLIR: %{{.*}} = quir.constant #quir.angle<0.70699977874755859 : !quir.angle<20>> -// MLIR: %{{.*}} = quir.constant #quir.angle<0.69999980926513672 : !quir.angle<20>> +// MLIR: %{{.*}} = quir.constant #quir.angle<0.70699977874755859> : !quir.angle<20> +// MLIR: %{{.*}} = quir.constant #quir.angle<0.69999980926513672> : !quir.angle<20> // AST-PRETTY: DeclarationNode(type=ASTTypeAngle, AngleNode(value=0.70699978, bits=20)) // AST-PRETTY: DeclarationNode(type=ASTTypeAngle, AngleNode(value=0.69999981, bits=20)) angle[20] my_angle = 0.707; @@ -32,9 +32,9 @@ angle[20] second_angle = 0.7; qubit $0; // if (my_angle == second_angle) { // -// // COM: MLIR: %{{.*}} = quir.constant #quir.angle<5.000000e-01 : !quir.angle<64>> -// // COM: MLIR: %{{.*}} = quir.constant #quir.angle<0.000000e+00 : !quir.angle<32>> -// // COM: MLIR: %{{.*}} = quir.constant #quir.angle<0.32432432 : !quir.angle<64>> +// // COM: MLIR: %{{.*}} = quir.constant #quir.angle<5.000000e-01> : !quir.angle<64> +// // COM: MLIR: %{{.*}} = quir.constant #quir.angle<0.000000e+00> : !quir.angle<32> +// // COM: MLIR: %{{.*}} = quir.constant #quir.angle<0.32432432> : !quir.angle<64> // U(0.5, 0, 0.32432432) $0; // // } diff --git a/test/Frontend/OpenQASM3/assign.qasm b/test/Frontend/OpenQASM3/assign.qasm index 5c32f2faf..77b797eb9 100644 --- a/test/Frontend/OpenQASM3/assign.qasm +++ b/test/Frontend/OpenQASM3/assign.qasm @@ -19,7 +19,7 @@ OPENQASM 3.0; // MLIR-DAG: oq3.declare_variable @j : !quir.cbit<1> // Angle -// MLIR: %{{.*}} = quir.constant #quir.angle<0.000000e+00 : !quir.angle<3>> +// MLIR: %{{.*}} = quir.constant #quir.angle<0.000000e+00> : !quir.angle<3> angle[3] c = 0; // MLIR: %{{.*}} = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> qubit $0; diff --git a/test/Frontend/OpenQASM3/bell-v0.qasm b/test/Frontend/OpenQASM3/bell-v0.qasm index 35d92b467..ed8eeca3a 100644 --- a/test/Frontend/OpenQASM3/bell-v0.qasm +++ b/test/Frontend/OpenQASM3/bell-v0.qasm @@ -53,11 +53,11 @@ bit c1; // AST-PRETTY: UGateOpNode(params=[AngleNode(value=1.57079632679000003037, bits=64), AngleNode(value=0.0, bits=64), AngleNode(value=3.14159265359000006157, bits=64)], qubits=[], qcparams=[$0]) // AST-PRETTY: GateDeclarationNode(name=cx, params=[], qubits=[QubitNode(name=ast-gate-qubit-param-control-0, bits=0), QubitNode(name=ast-gate-qubit-param-target-1, bits=0)], qcparams=[control, target]) // MLIR-CIRCUITS: quir.circuit @circuit_0([[ARG0:%[A-Za-z0-9]+]]: !quir.qubit<1>) { -// MLIR: [[a0:%angle[_0-9]*]] = quir.constant #quir.angle<1.57079632679 : !quir.angle<64>> +// MLIR: [[a0:%angle[_0-9]*]] = quir.constant #quir.angle<1.57079632679> : !quir.angle<64> // MLIR-NO-CIRCUITS: quir.builtin_U [[QUBIT0]], [[a0]], {{.*}}, {{.*}} : !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> // MLIR-NO-CIRCUITS: quir.builtin_CX [[QUBIT0]], [[QUBIT1]] : !quir.qubit<1>, !quir.qubit<1> -// MLIR-CIRCUITS: [[a1:%angle[_0-9]*]] = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: [[a2:%angle[_0-9]*]] = quir.constant #quir.angle<3.1415926535900001 : !quir.angle<64>> +// MLIR-CIRCUITS: [[a1:%angle[_0-9]*]] = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: [[a2:%angle[_0-9]*]] = quir.constant #quir.angle<3.1415926535900001> : !quir.angle<64> // MLIR-CIRCUITS: quir.builtin_U [[ARG0]], [[a0]], [[a1]], [[a2]] : !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> // MLIR-CIRCUITS: quir.circuit @circuit_1([[ARG0:%[A-Za-z0-9]+]]: !quir.qubit<1>, [[ARG1:%[A-Za-z0-9]+]]: !quir.qubit<1>) -> i1 { // MLIR-CIRCUITS: quir.builtin_CX [[ARG1]], [[ARG0]] : !quir.qubit<1>, !quir.qubit<1> diff --git a/test/Frontend/OpenQASM3/bell-v1.qasm b/test/Frontend/OpenQASM3/bell-v1.qasm index 04ccf317d..b38d85ce8 100644 --- a/test/Frontend/OpenQASM3/bell-v1.qasm +++ b/test/Frontend/OpenQASM3/bell-v1.qasm @@ -31,15 +31,15 @@ OPENQASM 3.0; // AST-PRETTY: , // AST-PRETTY: ] // AST-PRETTY: ) -// MLIR: func @h(%arg0: !quir.qubit<1>) { -// MLIR-NO-CIRCUITS: [[a0:%angle[_0-9]*]] = quir.constant #quir.angle<1.57079632679 : !quir.angle<64>> +// MLIR: func.func @h(%arg0: !quir.qubit<1>) { +// MLIR-NO-CIRCUITS: [[a0:%angle[_0-9]*]] = quir.constant #quir.angle<1.57079632679> : !quir.angle<64> // MLIR-NO-CIRCUITS: quir.builtin_U %arg0, [[a0]], {{.*}}, {{.*}} : !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> // MLIR-CIRCUITS: quir.call_circuit @circuit_0(%arg0) : (!quir.qubit<1>) -> () // MLIR: return // MLIR-CIRCUITS: quir.circuit @circuit_0(%arg0: !quir.qubit<1>) { -// MLIR-CIRCUITS: [[a0:%angle[_0-9]*]] = quir.constant #quir.angle<1.57079632679 : !quir.angle<64>> -// MLIR-CIRCUITS: [[a1:%angle[_0-9]*]] = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: [[a2:%angle[_0-9]*]] = quir.constant #quir.angle<3.1415926535900001 : !quir.angle<64>> +// MLIR-CIRCUITS: [[a0:%angle[_0-9]*]] = quir.constant #quir.angle<1.57079632679> : !quir.angle<64> +// MLIR-CIRCUITS: [[a1:%angle[_0-9]*]] = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: [[a2:%angle[_0-9]*]] = quir.constant #quir.angle<3.1415926535900001> : !quir.angle<64> // MLIR-CIRCUITS: quir.builtin_U %arg0, [[a0]], [[a1]], [[a2]] : !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> // MLIR-CIRCUITS: quir.return // MLIR-CIRCUITS: quir.circuit @circuit_1(%arg0: !quir.qubit<1>, %arg1: !quir.qubit<1>) -> i1 { @@ -57,7 +57,7 @@ gate h q { gate cx control, target { } -// MLIR: func @main() -> i32 { +// MLIR: func.func @main() -> i32 { // Qiskit will provide physical qubits // MLIR: [[QUBIT0:%.*]] = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> // MLIR: [[QUBIT1:%.*]] = quir.declare_qubit {id = 1 : i32} : !quir.qubit<1> diff --git a/test/Frontend/OpenQASM3/bitindices.qasm b/test/Frontend/OpenQASM3/bitindices.qasm index d56f262c0..0a6c681ef 100644 --- a/test/Frontend/OpenQASM3/bitindices.qasm +++ b/test/Frontend/OpenQASM3/bitindices.qasm @@ -1,7 +1,7 @@ OPENQASM 3.0; // RUN: qss-compiler -X=qasm --emit=ast-pretty %s | FileCheck %s --check-prefix AST-PRETTY // RUN: qss-compiler -X=qasm --emit=mlir %s --enable-circuits=false | FileCheck %s --check-prefixes MLIR,MLIR-NO-CIRCUITS -// RUN: qss-compiler -X=qasm --emit=mlir %s --enable-circuits | FileCheck %s --check-prefixes MLIR,MLIR-CIRCUITS +// RUN: qss-compiler -X=qasm --emit=mlir %s --enable-circuits | FileCheck %s --check-prefixes MLIR,MLIR-CIRCUITS // // This code is part of Qiskit. @@ -17,7 +17,7 @@ OPENQASM 3.0; // that they have been altered from the originals. // MLIR: module -// MLIR-DAG: func @main +// MLIR-DAG: func.func @main // AST-PRETTY DeclarationNode(type=ASTTypeBitset, CBitNode(name=a, bits=1)) // DeclarationNode(type=ASTTypeBitset, CBitNode(name=b, bits=2, value=10)) diff --git a/test/Frontend/OpenQASM3/bitops-reg.qasm b/test/Frontend/OpenQASM3/bitops-reg.qasm index fd2398564..045d07b21 100644 --- a/test/Frontend/OpenQASM3/bitops-reg.qasm +++ b/test/Frontend/OpenQASM3/bitops-reg.qasm @@ -16,7 +16,7 @@ OPENQASM 3.0; // that they have been altered from the originals. // MLIR: module -// MLIR-DAG: func @main +// MLIR-DAG: func.func @main bit[6] r; diff --git a/test/Frontend/OpenQASM3/bitops.qasm b/test/Frontend/OpenQASM3/bitops.qasm index 80a754bb3..8b10a663a 100644 --- a/test/Frontend/OpenQASM3/bitops.qasm +++ b/test/Frontend/OpenQASM3/bitops.qasm @@ -16,7 +16,7 @@ OPENQASM 3.0; // that they have been altered from the originals. // MLIR: module -// MLIR-DAG: func @main +// MLIR-DAG: func.func @main bit a; diff --git a/test/Frontend/OpenQASM3/bitops2.qasm b/test/Frontend/OpenQASM3/bitops2.qasm index 7c8e893aa..2894c6b58 100644 --- a/test/Frontend/OpenQASM3/bitops2.qasm +++ b/test/Frontend/OpenQASM3/bitops2.qasm @@ -16,7 +16,7 @@ OPENQASM 3.0; // that they have been altered from the originals. // MLIR: module -// MLIR: func @main +// MLIR: func.func @main // AST-PRETTY: DeclarationNode(type=ASTTypeQubitContainer qubit $0; diff --git a/test/Frontend/OpenQASM3/conditionals.qasm b/test/Frontend/OpenQASM3/conditionals.qasm index 42f83de1d..0fc9f3a30 100644 --- a/test/Frontend/OpenQASM3/conditionals.qasm +++ b/test/Frontend/OpenQASM3/conditionals.qasm @@ -17,18 +17,18 @@ OPENQASM 3.0; // that they have been altered from the originals. // MLIR-CIRCUITS: quir.circuit @circuit_1(%arg0: !quir.qubit<1>) { -// MLIR-CIRCUITS: %angle = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: %angle_0 = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: %angle_1 = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> +// MLIR-CIRCUITS: %angle = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: %angle_0 = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: %angle_1 = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> // MLIR-CIRCUITS: quir.builtin_U %arg0, %angle, %angle_0, %angle_1 : !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> -// MLIR-CIRCUITS: quir.return +// MLIR-CIRCUITS: quir.return // MLIR-CIRCUITS: quir.circuit @circuit_2(%arg0: !quir.qubit<1>) { -// MLIR-CIRCUITS: %angle = quir.constant #quir.angle<3.1415926000000001 : !quir.angle<64>> -// MLIR-CIRCUITS: %angle_0 = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: %angle_1 = quir.constant #quir.angle<3.1415926000000001 : !quir.angle<64>> +// MLIR-CIRCUITS: %angle = quir.constant #quir.angle<3.1415926000000001> : !quir.angle<64> +// MLIR-CIRCUITS: %angle_0 = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: %angle_1 = quir.constant #quir.angle<3.1415926000000001> : !quir.angle<64> // MLIR-CIRCUITS: quir.builtin_U %arg0, %angle, %angle_0, %angle_1 : !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> -// MLIR-CIRCUITS: quir.return +// MLIR-CIRCUITS: quir.return // AST-PRETTY: DeclarationNode(type=ASTTypeQubitContainer, QubitContainerNode(QubitNode(name=$0:0, bits=1))) qubit $0; @@ -46,9 +46,9 @@ bool b = false; // MLIR: {{.*}} = arith.cmpi ne, {{.*}}, %true : i1 // MLIR: scf.if {{.*}} { if (!b) { - // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> - // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> - // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> + // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> + // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> + // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> // MLIR-CIRCUITS: quir.call_circuit @circuit_1(%0) : (!quir.qubit<1>) -> () U(0, 0, 0) $0; } @@ -58,9 +58,9 @@ if (!b) { // AST-PRETTY: ) // MLIR: } else { else { - //MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<3.1415926000000001 : !quir.angle<64>> - //MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> - //MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<3.1415926000000001 : !quir.angle<64>> + //MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<3.1415926000000001> : !quir.angle<64> + //MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> + //MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<3.1415926000000001> : !quir.angle<64> // MLIR-CIRCUITS: quir.call_circuit @circuit_2(%0) : (!quir.qubit<1>) -> () U(3.1415926, 0, 3.1415926) $0; } diff --git a/test/Frontend/OpenQASM3/delay-inside-controlflow.qasm b/test/Frontend/OpenQASM3/delay-inside-controlflow.qasm index 72c3bd727..b3ff25e04 100644 --- a/test/Frontend/OpenQASM3/delay-inside-controlflow.qasm +++ b/test/Frontend/OpenQASM3/delay-inside-controlflow.qasm @@ -9,51 +9,45 @@ bit c; // MLIR-CIRCUITS: quir.circuit @circuit_0(%{{.*}}: !quir.qubit<1>, %{{.*}}: !quir.duration
) { // MLIR-CIRCUITS: quir.delay %{{.*}}, (%{{.*}}) : !quir.duration
, (!quir.qubit<1>) -> () // MLIR-CIRCUITS: quir.call_gate @x(%{{.*}}) : (!quir.qubit<1>) -> () -// MLIR-CIRCUITS: %cst = constant unit // MLIR-CIRCUITS: quir.return // MLIR-CIRCUITS: } // MLIR-CIRCUITS: quir.circuit @circuit_1(%{{.*}}: !quir.qubit<1>, %{{.*}}: !quir.duration
) { // MLIR-CIRCUITS: quir.delay %{{.*}}, (%{{.*}}) : !quir.duration
, (!quir.qubit<1>) -> () // MLIR-CIRCUITS: quir.call_gate @x(%{{.*}}) : (!quir.qubit<1>) -> () -// MLIR-CIRCUITS: %cst = constant unit // MLIR-CIRCUITS: quir.return // MLIR-CIRCUITS: } // MLIR-CIRCUITS: quir.circuit @circuit_2(%{{.*}}: !quir.qubit<1>, %{{.*}}: !quir.duration
) { // MLIR-CIRCUITS: quir.delay %{{.*}}, (%{{.*}}) : !quir.duration
, (!quir.qubit<1>) -> () // MLIR-CIRCUITS: quir.call_gate @x(%{{.*}}) : (!quir.qubit<1>) -> () -// MLIR-CIRCUITS: %cst = constant unit // MLIR-CIRCUITS: quir.return // MLIR-CIRCUITS: } // MLIR-CIRCUITS: quir.circuit @circuit_3(%{{.*}}: !quir.qubit<1>, %{{.*}}: !quir.duration
) { // MLIR-CIRCUITS: quir.delay %{{.*}}, (%{{.*}}) : !quir.duration
, (!quir.qubit<1>) -> () // MLIR-CIRCUITS: quir.call_gate @x(%{{.*}}) : (!quir.qubit<1>) -> () -// MLIR-CIRCUITS: %cst = constant unit // MLIR-CIRCUITS: quir.return // MLIR-CIRCUITS: } // MLIR-CIRCUITS: quir.circuit @circuit_4(%{{.*}}: !quir.qubit<1>, %{{.*}}: !quir.duration
) { // MLIR-CIRCUITS: quir.delay %{{.*}}, (%{{.*}}) : !quir.duration
, (!quir.qubit<1>) -> () // MLIR-CIRCUITS: quir.call_gate @x(%{{.*}}) : (!quir.qubit<1>) -> () -// MLIR-CIRCUITS: %cst = constant unit // MLIR-CIRCUITS: quir.return // MLIR-CIRCUITS: } // MLIR-CIRCUITS: quir.circuit @circuit_5(%{{.*}}: !quir.qubit<1>, %{{.*}}: !quir.duration
) { // MLIR-CIRCUITS: quir.delay %{{.*}}, (%{{.*}}) : !quir.duration
, (!quir.qubit<1>) -> () // MLIR-CIRCUITS: quir.call_gate @x(%{{.*}}) : (!quir.qubit<1>) -> () -// MLIR-CIRCUITS: %cst = constant unit // MLIR-CIRCUITS: quir.return // MLIR-CIRCUITS: } c = 0; // MLIR: scf.if %{{.*}} { if (c == 0) { -// MLIR: %{{.*}} = quir.constant #quir.duration<1.600000e+01 :
> +// MLIR: %{{.*}} = quir.constant #quir.duration<1.600000e+01> : !quir.duration
// MLIR-NO-CIRCUITS: quir.delay %{{.*}}, (%{{.*}}) : !quir.duration
, (!quir.qubit<1>) -> () // MLIR-CIRCUITS: quir.call_circuit @circuit_0(%{{.*}}, %{{.*}}) : (!quir.qubit<1>, !quir.duration
) -> () delay[16dt] $0; x $0; // MLIR: } else { } else { -// MLIR: %{{.*}} = quir.constant #quir.duration<9.600000e+01 :
> +// MLIR: %{{.*}} = quir.constant #quir.duration<9.600000e+01> : !quir.duration
// MLIR-NO-CIRCUITS: quir.delay %{{.*}}, (%{{.*}}) : !quir.duration
, (!quir.qubit<1>) -> () // MLIR-CIRCUITS: quir.call_circuit @circuit_1(%{{.*}}, %{{.*}}) : (!quir.qubit<1>, !quir.duration
) -> () delay[96dt] $0; @@ -62,7 +56,7 @@ if (c == 0) { // MLIR: scf.for %{{.*}} = %{{.*}} to %{{.*}} step %c{{.*}}1_3 { for ii in [0 : 4] { -// MLIR: %{{.*}} = quir.constant #quir.duration<3.200000e+01 :
> +// MLIR: %{{.*}} = quir.constant #quir.duration<3.200000e+01> : !quir.duration
// MLIR-NO-CIRCUITS: quir.delay %{{.*}}, (%{{.*}}) : !quir.duration
, (!quir.qubit<1>) -> () // MLIR-CIRCUITS: quir.call_circuit @circuit_2(%{{.*}}, %{{.*}}) : (!quir.qubit<1>, !quir.duration
) -> () delay[32dt] $0; @@ -72,7 +66,7 @@ for ii in [0 : 4] { // MLIR: scf.while : () -> () { int nn = 1; while (nn != 0) { -// MLIR: %{{.*}} = quir.constant #quir.duration<4.800000e+01 :
> +// MLIR: %{{.*}} = quir.constant #quir.duration<4.800000e+01> : !quir.duration
// MLIR-NO-CIRCUITS: quir.delay %{{.*}}, (%{{.*}}) : !quir.duration
, (!quir.qubit<1>) -> () // MLIR-CIRCUITS: quir.call_circuit @circuit_3(%{{.*}}, %{{.*}}) : (!quir.qubit<1>, !quir.duration
) -> () delay[48dt] $0; @@ -85,7 +79,7 @@ int ii = 15; switch (ii) { // default case gets printed first -// MLIR: %{{.*}} = quir.constant #quir.duration<8.000000e+01 :
> +// MLIR: %{{.*}} = quir.constant #quir.duration<8.000000e+01> : !quir.duration
// MLIR-NO-CIRCUITS: quir.delay %{{.*}}, (%{{.*}}) : !quir.duration
, (!quir.qubit<1>) -> () // MLIR-CIRCUITS: quir.call_circuit @circuit_4(%{{.*}}, %{{.*}}) : (!quir.qubit<1>, !quir.duration
) -> () @@ -93,7 +87,7 @@ switch (ii) { // MLIR: }[1 : { case 1: { delay[64dt] $0; -// MLIR: %{{.*}} = quir.constant #quir.duration<6.400000e+01 :
> +// MLIR: %{{.*}} = quir.constant #quir.duration<6.400000e+01> : !quir.duration
// MLIR-NO-CIRCUITS: quir.delay %{{.*}}, (%{{.*}}) : !quir.duration
, (!quir.qubit<1>) -> () // MLIR-CIRCUITS: quir.call_circuit @circuit_5(%{{.*}}, %{{.*}}) : (!quir.qubit<1>, !quir.duration
) -> () x $0; diff --git a/test/Frontend/OpenQASM3/delay.qasm b/test/Frontend/OpenQASM3/delay.qasm index e8f8845f2..ddfe0a87c 100755 --- a/test/Frontend/OpenQASM3/delay.qasm +++ b/test/Frontend/OpenQASM3/delay.qasm @@ -24,31 +24,31 @@ qubit $0; qubit $1; // MLIR-CIRCUITS: quir.circuit @circuit_0(%arg0: !quir.duration, %arg1: !quir.qubit<1>, %arg2: !quir.qubit<1>, %arg3: !quir.duration, %arg4: !quir.duration, %arg5: !quir.duration, %arg6: !quir.duration
, %arg7: !quir.duration) { -// MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.duration<5.000000e+00 : > +// MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.duration<5.000000e+00> : !quir.duration // MLIR: quir.delay {{.*}}, ({{.*}}) : !quir.duration, (!quir.qubit<1>) -> () // AST-PRETTY: DeclarationNode(type=ASTTypeDuration, DurationNode(duration=5, unit=Nanoseconds, name=t)) // AST-PRETTY: DelayStatementNode(DelayNode(duration=t, qubit=IdentifierNode(name=$0, bits=1))) duration t = 5ns; delay[t] $0; -// MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.duration<1.000000e+01 : > +// MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.duration<1.000000e+01> : !quir.duration // MLIR: quir.delay {{.*}}, ({{.*}}) : !quir.duration, (!quir.qubit<1>) -> () // AST-PRETTY: DelayStatementNode(DelayNode(duration=10Nanoseconds, qubit=IdentifierNode(name=$1, bits=1), )) delay[10ns] $1; -// MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.duration<2.000000e+01 : > +// MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.duration<2.000000e+01> : !quir.duration // MLIR: quir.delay {{.*}}, ({{.*}}) : !quir.duration, (!quir.qubit<1>) -> () // AST-PRETTY: DelayStatementNode(DelayNode(duration=20Microseconds, qubit=IdentifierNode(name=$1, bits=1), )) delay[20us] $1; -// MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.duration<3.000000e+01 : > +// MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.duration<3.000000e+01> : !quir.duration // MLIR: quir.delay {{.*}}, ({{.*}}) : !quir.duration, (!quir.qubit<1>) -> () // AST-PRETTY: DelayStatementNode(DelayNode(duration=30Milliseconds, qubit=IdentifierNode(name=$1, bits=1), )) delay[30ms] $1; -// MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.duration<4.000000e+01 :
> +// MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.duration<4.000000e+01> : !quir.duration
// MLIR: quir.delay {{.*}}, ({{.*}}) : !quir.duration
, (!quir.qubit<1>) -> () // AST-PRETTY: DelayStatementNode(DelayNode(duration=40DT, qubit=IdentifierNode(name=$1, bits=1), )) delay[40dt] $1; -// MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.duration<1.000000e+01 : > +// MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.duration<1.000000e+01> : !quir.duration // MLIR: quir.delay {{.*}}, ({{.*}}, {{.*}}) : !quir.duration, (!quir.qubit<1>, !quir.qubit<1>) -> () // AST-PRETTY: DelayStatementNode(DelayNode(duration=10Nanoseconds, qubit=IdentifierNode(name=$0, bits=1), IdentifierNode(name=$1, bits=1), )) delay [10ns] $0, $1; @@ -67,13 +67,13 @@ delay[a] $0; delay[a] $0, $1; //MLIR-CIRCUITS: quir.return -//MLIR-CIRCUITS: func @main() -> i32 { -// MLIR-CIRCUITS: {{.*}} = quir.constant #quir.duration<5.000000e+00 : > -// MLIR-CIRCUITS: {{.*}} = quir.constant #quir.duration<1.000000e+01 : > -// MLIR-CIRCUITS: {{.*}} = quir.constant #quir.duration<2.000000e+01 : > -// MLIR-CIRCUITS: {{.*}} = quir.constant #quir.duration<3.000000e+01 : > -// MLIR-CIRCUITS: {{.*}} = quir.constant #quir.duration<4.000000e+01 :
> -// MLIR-CIRCUITS: {{.*}} = quir.constant #quir.duration<1.000000e+01 : > +//MLIR-CIRCUITS: func.func @main() -> i32 { +// MLIR-CIRCUITS: {{.*}} = quir.constant #quir.duration<5.000000e+00> : !quir.duration +// MLIR-CIRCUITS: {{.*}} = quir.constant #quir.duration<1.000000e+01> : !quir.duration +// MLIR-CIRCUITS: {{.*}} = quir.constant #quir.duration<2.000000e+01> : !quir.duration +// MLIR-CIRCUITS: {{.*}} = quir.constant #quir.duration<3.000000e+01> : !quir.duration +// MLIR-CIRCUITS: {{.*}} = quir.constant #quir.duration<4.000000e+01> : !quir.duration
+// MLIR-CIRCUITS: {{.*}} = quir.constant #quir.duration<1.000000e+01> : !quir.duration // MLIR-CIRCUITS: quir.call_circuit @circuit_0({{.*}}, {{.*}}, {{.*}}, {{.*}}, {{.*}}, {{.*}}, {{.*}}, {{.*}}) : (!quir.{{.*}}, !quir.{{.*}}, !quir.{{.*}}, !quir.{{.*}}, !quir.{{.*}}, !quir.{{.*}}, !quir.{{.*}}, !quir.{{.*}}) -> () // TODO: Two oq3.declare_stretch statements are generated independent of --enable-circuits // This does no harm but might potentially be fixed at some point diff --git a/test/Frontend/OpenQASM3/extern.qasm b/test/Frontend/OpenQASM3/extern.qasm index 810617f35..6d90f856b 100644 --- a/test/Frontend/OpenQASM3/extern.qasm +++ b/test/Frontend/OpenQASM3/extern.qasm @@ -16,32 +16,32 @@ OPENQASM 3.0; // that they have been altered from the originals. // AST-PRETTY: DeclarationNode(type=Unknown, ExternNode(name=test0, parameters=[], returns=ResultNode(void)) -// MLIR: func private @test0() +// MLIR: func.func private @test0() extern test0(); // AST-PRETTY: DeclarationNode(type=Unknown, ExternNode(name=test1, parameters=[DeclarationNode(type=ASTTypeInt, IntNode(signed=true, value=10, bits=32)) // AST-PRETTY: ], returns=ResultNode(void)) -// MLIR: func private @test1(i32) +// MLIR: func.func private @test1(i32) extern test1(int a); // AST-PRETTY: DeclarationNode(type=Unknown, ExternNode(name=test2, parameters=[], returns=ResultNode(CBitNode(name=bitset, bits=1))) -// MLIR: func private @test2() -> !quir.cbit<1> +// MLIR: func.func private @test2() -> !quir.cbit<1> extern test2() -> bit; // AST-PRETTY: DeclarationNode(type=Unknown, ExternNode(name=test3, parameters=[DeclarationNode(type=ASTTypeInt, IntNode(signed=true, value=10, bits=32)) // AST-PRETTY: ], returns=ResultNode(CBitNode(name=bitset, bits=1))) -// MLIR: func private @test3(i32) -> !quir.cbit<1> +// MLIR: func.func private @test3(i32) -> !quir.cbit<1> extern test3(int a) -> bit; // AST-PRETTY: DeclarationNode(type=Unknown, ExternNode(name=test4, parameters=[DeclarationNode(type=ASTTypeInt, IntNode(signed=true, value=10, bits=32)) // AST-PRETTY: DeclarationNode(type=ASTTypeFloat, IdentifierNode(name=b, bits=32)) // AST-PRETTY: ], returns=ResultNode(MPDecimalNode(name=ast-mpdecimal-type-param-{{.*}}, bits=32))) -// MLIR: func private @test4(i32, f32) -> f32 +// MLIR: func.func private @test4(i32, f32) -> f32 extern test4(int a, float b) -> float[32]; // AST-PRETTY: DeclarationNode(type=Unknown, ExternNode(name=test5, parameters=[DeclarationNode(type=ASTTypeMPInteger, IdentifierNode(name=a, bits=32)) // AST-PRETTY: ], returns=ResultNode(MPIntegerNode(name=ast-mpinteger-type-param-{{.*}}, value=0, bits=64, signed=1))) -// MLIR: func private @test5(i32) -> i64 +// MLIR: func.func private @test5(i32) -> i64 extern test5(int[32] a) -> int[64]; @@ -57,19 +57,19 @@ int[32] e = 10; int[64] f; // AST-PRETTY: FunctionCallNode(type=ASTTypeFunctionCallExpression, expressions=IdentifierNode(name=a, bits=32), kernelDefinition=DeclarationNode(type=ASTTypeInt, IntNode(signed=true, value=10, bits=32) -// MLIR: [[RES3:%[0-9]*]] = call @test3(%{{[0-9]+}}) : (i32) -> !quir.cbit<1> +// MLIR: [[RES3:%[0-9]*]] = func.call @test3(%{{[0-9]+}}) : (i32) -> !quir.cbit<1> // MLIR-NEXT: oq3.variable_assign @b : !quir.cbit<1> = [[RES3]] b = test3(a); // AST-PRETTY: BinaryOpNode(type=ASTOpTypeAssign, left=IdentifierNode(name=d, bits=32), right=FunctionCallNode(type=ASTTypeFunctionCallExpression, expressions=IdentifierNode(name=a, bits=32)IdentifierNode(name=c, bits=32), kernelDefinition=DeclarationNode(type=ASTTypeInt, IntNode(signed=true, value=10, bits=32)) // AST-PRETTY: DeclarationNode(type=ASTTypeFloat, IdentifierNode(name=b, bits=32)) // AST-PRETTY: ResultNode(MPDecimalNode(name=ast-mpdecimal-type-param-{{.*}}, bits=32))) -// MLIR: [[RES4:%[0-9]*]] = call @test4(%{{[0-9]+}}, %{{[0-9]+}}) : (i32, f32) -> f32 +// MLIR: [[RES4:%[0-9]*]] = func.call @test4(%{{[0-9]+}}, %{{[0-9]+}}) : (i32, f32) -> f32 // MLIR-NEXT: oq3.variable_assign @d : f32 = [[RES4]] d = test4(a, c); // AST-PRETTY: BinaryOpNode(type=ASTOpTypeAssign, left=IdentifierNode(name=f, bits=64), right=FunctionCallNode(type=ASTTypeFunctionCallExpression, expressions=IdentifierNode(name=e, bits=32), kernelDefinition=DeclarationNode(type=ASTTypeMPInteger, IdentifierNode(name=a, bits=32)) // AST-PRETTY: ResultNode(MPIntegerNode(name=ast-mpinteger-type-param-{{.*}}, value=0, bits=64, signed=1))) -// MLIR: [[RES5:%[0-9]*]] = call @test5(%{{[0-9]+}}) : (i32) -> i64 +// MLIR: [[RES5:%[0-9]*]] = func.call @test5(%{{[0-9]+}}) : (i32) -> i64 // MLIR-NEXT: oq3.variable_assign @f : i64 = [[RES5]] f = test5(e); diff --git a/test/Frontend/OpenQASM3/for-loop.qasm b/test/Frontend/OpenQASM3/for-loop.qasm index 37c0accdb..d92d33e0b 100644 --- a/test/Frontend/OpenQASM3/for-loop.qasm +++ b/test/Frontend/OpenQASM3/for-loop.qasm @@ -26,9 +26,9 @@ qubit $0; // MLIR: scf.for %arg1 = %c0_0 to %c5 step %c1_1 { // AST-PRETTY: ForStatementNode(start=0, end=4, for i in [0 : 4] { - // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<1.57079632679 : !quir.angle<64>> - // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> - // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<3.1415926535900001 : !quir.angle<64>> + // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<1.57079632679> : !quir.angle<64> + // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> + // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<3.1415926535900001> : !quir.angle<64> // MLIR-NO-CIRCUITS: quir.builtin_U {{.*}}, {{.*}}, {{.*}}, {{.*}} : !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> // MLIR-CIRCUITS: quir.call_circuit @circuit_0(%0) : (!quir.qubit<1>) -> () // AST-PRETTY: statements= @@ -43,9 +43,9 @@ for i in [0 : 4] { // MLIR: scf.for %arg1 = %c0_2 to %c5_3 step %c1_4 { // AST-PRETTY: ForStatementNode(start=0, stepping=1, end=4, for i in [0 : 1 : 4] { - // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<1.57079632679 : !quir.angle<64>> - // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> - // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<3.1415926535900001 : !quir.angle<64>> + // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<1.57079632679> : !quir.angle<64> + // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> + // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<3.1415926535900001> : !quir.angle<64> // MLIR-NO-CIRCUITS: quir.builtin_U {{.*}}, {{.*}}, {{.*}}, {{.*}} : !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> // MLIR-CIRCUITS: quir.call_circuit @circuit_1(%0) : (!quir.qubit<1>) -> () U(1.57079632679, 0.0, 3.14159265359) $0; @@ -57,9 +57,9 @@ for i in [0 : 1 : 4] { // MLIR: scf.for %arg1 = %c-1 to %c1001 step %c10 { // AST-PRETTY: ForStatementNode(start=-1, stepping=10, end=1000, for i in [-1 : 10 : 1000] { - // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<1.57079632679 : !quir.angle<64>> - // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> - // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<3.1415926535900001 : !quir.angle<64>> + // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<1.57079632679> : !quir.angle<64> + // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> + // MLIR-NO-CIRCUITS: {{.*}} = quir.constant #quir.angle<3.1415926535900001> : !quir.angle<64> // MLIR-NO-CIRCUITS: quir.builtin_U {{.*}}, {{.*}}, {{.*}}, {{.*}} : !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> // MLIR-CIRCUITS: quir.call_circuit @circuit_2(%0) : (!quir.qubit<1>) -> () U(1.57079632679, 0.0, 3.14159265359) $0; diff --git a/test/Frontend/OpenQASM3/gate.qasm b/test/Frontend/OpenQASM3/gate.qasm index c6a9b3f7f..67702a2f0 100644 --- a/test/Frontend/OpenQASM3/gate.qasm +++ b/test/Frontend/OpenQASM3/gate.qasm @@ -15,8 +15,8 @@ OPENQASM 3.0; // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -// MLIR: func @h(%arg0: !quir.qubit<1>) { -// MLIR-NO-CIRCUITS: %angle = quir.constant #quir.angle<1.57079632679 : !quir.angle<64>> +// MLIR: func.func @h(%arg0: !quir.qubit<1>) { +// MLIR-NO-CIRCUITS: %angle = quir.constant #quir.angle<1.57079632679> : !quir.angle<64> // MLIR-NO-CIRCUITS: quir.builtin_U %arg0, %angle, %angle_0, %angle_1 : !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> // MLIR-CIRCUITS: quir.call_circuit @circuit_0(%arg0) : (!quir.qubit<1>) -> () gate h q { @@ -24,20 +24,20 @@ gate h q { } // MLIR-CIRCUITS: quir.circuit @circuit_0(%arg0: !quir.qubit<1>) { -// MLIR-CIRCUITS: %angle = quir.constant #quir.angle<1.57079632679 : !quir.angle<64>> -// MLIR-CIRCUITS: %angle_0 = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: %angle_1 = quir.constant #quir.angle<3.1415926535900001 : !quir.angle<64>> +// MLIR-CIRCUITS: %angle = quir.constant #quir.angle<1.57079632679> : !quir.angle<64> +// MLIR-CIRCUITS: %angle_0 = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: %angle_1 = quir.constant #quir.angle<3.1415926535900001> : !quir.angle<64> // MLIR-CIRCUITS: quir.builtin_U %arg0, %angle, %angle_0, %angle_1 : !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> // MLIR-CIRCUITS: quir.return // MLIR-CIRCUITS: quir.circuit @circuit_1(%arg0: !quir.qubit<1>) { -// MLIR-CIRCUITS: %angle = quir.constant #quir.angle<3.140000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: %angle_0 = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: %angle_1 = quir.constant #quir.angle<3.140000e+00 : !quir.angle<64>> +// MLIR-CIRCUITS: %angle = quir.constant #quir.angle<3.140000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: %angle_0 = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: %angle_1 = quir.constant #quir.angle<3.140000e+00> : !quir.angle<64> // MLIR-CIRCUITS: quir.builtin_U %arg0, %angle, %angle_0, %angle_1 : !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> // MLIR-CIRCUITS: quir.call_gate @h(%arg0) : (!quir.qubit<1>) -> () // MLIR-CIRCUITS: quir.return -// MLIR: func @main() -> i32 { +// MLIR: func.func @main() -> i32 { // MLIR: [[QUBIT0:%.*]] = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> qubit $0; diff --git a/test/Frontend/OpenQASM3/gates-issue-655-2.qasm b/test/Frontend/OpenQASM3/gates-issue-655-2.qasm index bb446ead6..663c049b9 100644 --- a/test/Frontend/OpenQASM3/gates-issue-655-2.qasm +++ b/test/Frontend/OpenQASM3/gates-issue-655-2.qasm @@ -20,30 +20,30 @@ OPENQASM 3.0; // parameters. // MLIR-CIRCUITS: quir.circuit @circuit_0([[ARG0:%.*]]: !quir.qubit<1>) { -// MLIR-CIRCUITS: [[ANGLE_1_1:%.*]] = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_1_2:%.*]] = quir.constant #quir.angle<1.000000e-01 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_1_3:%.*]] = quir.constant #quir.angle<2.000000e-01 : !quir.angle<64>> +// MLIR-CIRCUITS: [[ANGLE_1_1:%.*]] = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_1_2:%.*]] = quir.constant #quir.angle<1.000000e-01> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_1_3:%.*]] = quir.constant #quir.angle<2.000000e-01> : !quir.angle<64> // MLIR-CIRCUITS: quir.builtin_U [[ARG0]], [[ANGLE_1_1]], [[ANGLE_1_2]], [[ANGLE_1_3]] -// MLIR-CIRCUITS: [[ANGLE_2_1:%.*]] = quir.constant #quir.angle<1.000000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_2_2:%.*]] = quir.constant #quir.angle<1.100000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_2_3:%.*]] = quir.constant #quir.angle<1.250000e+00 : !quir.angle<64>> +// MLIR-CIRCUITS: [[ANGLE_2_1:%.*]] = quir.constant #quir.angle<1.000000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_2_2:%.*]] = quir.constant #quir.angle<1.100000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_2_3:%.*]] = quir.constant #quir.angle<1.250000e+00> : !quir.angle<64> // MLIR-CIRCUITS: quir.builtin_U [[ARG0]], [[ANGLE_2_1]], [[ANGLE_2_2]], [[ANGLE_2_3]] -// MLIR-CIRCUITS: quir.return +// MLIR-CIRCUITS: quir.return // MLIR: [[QUBIT0:%.*]] = quir.declare_qubit {id = 0 : qubit $0; // AST-PRETTY: UGateOpNode(params=[AngleNode(value=0.0, bits=64), AngleNode(value=0.1, bits=64), AngleNode(value=0.2, bits=64)], qubits=[], qcparams=[$0]) -// MLIR-NO-CIRCUITS: [[ANGLE_1_1:%.*]] = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_1_2:%.*]] = quir.constant #quir.angle<1.000000e-01 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_1_3:%.*]] = quir.constant #quir.angle<2.000000e-01 : !quir.angle<64>> +// MLIR-NO-CIRCUITS: [[ANGLE_1_1:%.*]] = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_1_2:%.*]] = quir.constant #quir.angle<1.000000e-01> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_1_3:%.*]] = quir.constant #quir.angle<2.000000e-01> : !quir.angle<64> // MLIR-NO-CIRCUITS: quir.builtin_U [[QUBIT0]], [[ANGLE_1_1]], [[ANGLE_1_2]], [[ANGLE_1_3]] U(0.0, 0.1, 0.2) $0; // AST-PRETTY: UGateOpNode(params=[AngleNode(value=1.0, bits=64), AngleNode(value=1.1, bits=64), AngleNode(value=1.25, bits=64)], qubits=[], qcparams=[$0]) -// MLIR-NO-CIRCUITS: [[ANGLE_2_1:%.*]] = quir.constant #quir.angle<1.000000e+00 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_2_2:%.*]] = quir.constant #quir.angle<1.100000e+00 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_2_3:%.*]] = quir.constant #quir.angle<1.250000e+00 : !quir.angle<64>> +// MLIR-NO-CIRCUITS: [[ANGLE_2_1:%.*]] = quir.constant #quir.angle<1.000000e+00> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_2_2:%.*]] = quir.constant #quir.angle<1.100000e+00> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_2_3:%.*]] = quir.constant #quir.angle<1.250000e+00> : !quir.angle<64> // MLIR-NO-CIRCUITS: quir.builtin_U [[QUBIT0]], [[ANGLE_2_1]], [[ANGLE_2_2]], [[ANGLE_2_3]] // MLIR-CIRCUITS: quir.call_circuit @circuit_0(%0) : (!quir.qubit<1>) -> () U(1.0, 1.1, 1.25) $0; diff --git a/test/Frontend/OpenQASM3/gates-issue-655.qasm b/test/Frontend/OpenQASM3/gates-issue-655.qasm index 4594dc5dd..9cdf62bb0 100644 --- a/test/Frontend/OpenQASM3/gates-issue-655.qasm +++ b/test/Frontend/OpenQASM3/gates-issue-655.qasm @@ -20,25 +20,25 @@ OPENQASM 3.0; // parameters. // MLIR-CIRCUITS: quir.circuit @circuit_0([[ARG0:.*]]: !quir.qubit<1>) { -// MLIR-CIRCUITS: [[ANGLE_1_1:%.*]] = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_1_2:%.*]] = quir.constant #quir.angle<1.000000e-01 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_1_3:%.*]] = quir.constant #quir.angle<2.000000e-01 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_1_4:%.*]] = quir.constant #quir.angle<2.500000e-01 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_1_5:%.*]] = quir.constant #quir.angle<4.000000e-01 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_1_6:%.*]] = quir.constant #quir.angle<5.000000e-01 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_1_7:%.*]] = quir.constant #quir.angle<7.500000e-01 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_1_8:%.*]] = quir.constant #quir.angle<8.000000e-01 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_1_9:%.*]] = quir.constant #quir.angle<9.000000e-01 : !quir.angle<64>> +// MLIR-CIRCUITS: [[ANGLE_1_1:%.*]] = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_1_2:%.*]] = quir.constant #quir.angle<1.000000e-01> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_1_3:%.*]] = quir.constant #quir.angle<2.000000e-01> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_1_4:%.*]] = quir.constant #quir.angle<2.500000e-01> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_1_5:%.*]] = quir.constant #quir.angle<4.000000e-01> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_1_6:%.*]] = quir.constant #quir.angle<5.000000e-01> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_1_7:%.*]] = quir.constant #quir.angle<7.500000e-01> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_1_8:%.*]] = quir.constant #quir.angle<8.000000e-01> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_1_9:%.*]] = quir.constant #quir.angle<9.000000e-01> : !quir.angle<64> // MLIR-CIRCUITS: quir.call_gate @star([[ARG0]], [[ANGLE_1_1]], [[ANGLE_1_2]], [[ANGLE_1_3]], [[ANGLE_1_4]], [[ANGLE_1_5]], [[ANGLE_1_6]], [[ANGLE_1_7]], [[ANGLE_1_8]], [[ANGLE_1_9]]) -// MLIR-CIRCUITS: [[ANGLE_2_1:%.*]] = quir.constant #quir.angle<1.000000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_2_2:%.*]] = quir.constant #quir.angle<1.100000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_2_3:%.*]] = quir.constant #quir.angle<1.250000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_2_4:%.*]] = quir.constant #quir.angle<1.500000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_2_5:%.*]] = quir.constant #quir.angle<1.750000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_2_6:%.*]] = quir.constant #quir.angle<1.800000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_2_7:%.*]] = quir.constant #quir.angle<2.000000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_2_8:%.*]] = quir.constant #quir.angle<2.250000e+00 : !quir.angle<64>> -// MLIR-CIRCUITS: [[ANGLE_2_9:%.*]] = quir.constant #quir.angle<2.500000e+00 : !quir.angle<64>> +// MLIR-CIRCUITS: [[ANGLE_2_1:%.*]] = quir.constant #quir.angle<1.000000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_2_2:%.*]] = quir.constant #quir.angle<1.100000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_2_3:%.*]] = quir.constant #quir.angle<1.250000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_2_4:%.*]] = quir.constant #quir.angle<1.500000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_2_5:%.*]] = quir.constant #quir.angle<1.750000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_2_6:%.*]] = quir.constant #quir.angle<1.800000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_2_7:%.*]] = quir.constant #quir.angle<2.000000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_2_8:%.*]] = quir.constant #quir.angle<2.250000e+00> : !quir.angle<64> +// MLIR-CIRCUITS: [[ANGLE_2_9:%.*]] = quir.constant #quir.angle<2.500000e+00> : !quir.angle<64> // MLIR-CIRCUITS: quir.call_gate @star([[ARG0]], [[ANGLE_2_1]], [[ANGLE_2_2]], [[ANGLE_2_3]], [[ANGLE_2_4]], [[ANGLE_2_5]], [[ANGLE_2_6]], [[ANGLE_2_7]], [[ANGLE_2_8]], [[ANGLE_2_9]]) // MLIR-CIRCUITS: quir.return @@ -48,28 +48,28 @@ qubit $0; gate star(alpha, beta, gamma, delta, epsilon, zeta, eta, theta, iota) q { } // AST-PRETTY: GateGenericNode(name=star, params=[AngleNode(value=0.0, bits=64), AngleNode(value=0.1, bits=64), AngleNode(value=0.2, bits=64), AngleNode(value=0.25, bits=64), AngleNode(value=0.4, bits=64), AngleNode(value=0.5, bits=64), AngleNode(value=0.75, bits=64), AngleNode(value=0.8, bits=64), AngleNode(value=0.9, bits=64)], qubits=[], qcparams=[$0]) -// MLIR-NO-CIRCUITS: [[ANGLE_1_1:%.*]] = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_1_2:%.*]] = quir.constant #quir.angle<1.000000e-01 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_1_3:%.*]] = quir.constant #quir.angle<2.000000e-01 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_1_4:%.*]] = quir.constant #quir.angle<2.500000e-01 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_1_5:%.*]] = quir.constant #quir.angle<4.000000e-01 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_1_6:%.*]] = quir.constant #quir.angle<5.000000e-01 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_1_7:%.*]] = quir.constant #quir.angle<7.500000e-01 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_1_8:%.*]] = quir.constant #quir.angle<8.000000e-01 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_1_9:%.*]] = quir.constant #quir.angle<9.000000e-01 : !quir.angle<64>> +// MLIR-NO-CIRCUITS: [[ANGLE_1_1:%.*]] = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_1_2:%.*]] = quir.constant #quir.angle<1.000000e-01> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_1_3:%.*]] = quir.constant #quir.angle<2.000000e-01> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_1_4:%.*]] = quir.constant #quir.angle<2.500000e-01> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_1_5:%.*]] = quir.constant #quir.angle<4.000000e-01> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_1_6:%.*]] = quir.constant #quir.angle<5.000000e-01> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_1_7:%.*]] = quir.constant #quir.angle<7.500000e-01> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_1_8:%.*]] = quir.constant #quir.angle<8.000000e-01> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_1_9:%.*]] = quir.constant #quir.angle<9.000000e-01> : !quir.angle<64> // MLIR-NO-CIRCUITS: quir.call_gate @star([[QUBIT0]], [[ANGLE_1_1]], [[ANGLE_1_2]], [[ANGLE_1_3]], [[ANGLE_1_4]], [[ANGLE_1_5]], [[ANGLE_1_6]], [[ANGLE_1_7]], [[ANGLE_1_8]], [[ANGLE_1_9]]) star(0.0, 0.1, 0.2, 0.25, 0.4, 0.5, 0.75, 0.8, 0.9) $0; // AST-PRETTY: GateGenericNode(name=star, params=[AngleNode(value=1.0, bits=64), AngleNode(value=1.1, bits=64), AngleNode(value=1.25, bits=64), AngleNode(value=1.5, bits=64), AngleNode(value=1.75, bits=64), AngleNode(value=1.8, bits=64), AngleNode(value=2.0, bits=64), AngleNode(value=2.25, bits=64), AngleNode(value=2.5, bits=64)], qubits=[], qcparams=[$0] -// MLIR-NO-CIRCUITS: [[ANGLE_2_1:%.*]] = quir.constant #quir.angle<1.000000e+00 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_2_2:%.*]] = quir.constant #quir.angle<1.100000e+00 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_2_3:%.*]] = quir.constant #quir.angle<1.250000e+00 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_2_4:%.*]] = quir.constant #quir.angle<1.500000e+00 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_2_5:%.*]] = quir.constant #quir.angle<1.750000e+00 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_2_6:%.*]] = quir.constant #quir.angle<1.800000e+00 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_2_7:%.*]] = quir.constant #quir.angle<2.000000e+00 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_2_8:%.*]] = quir.constant #quir.angle<2.250000e+00 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: [[ANGLE_2_9:%.*]] = quir.constant #quir.angle<2.500000e+00 : !quir.angle<64>> +// MLIR-NO-CIRCUITS: [[ANGLE_2_1:%.*]] = quir.constant #quir.angle<1.000000e+00> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_2_2:%.*]] = quir.constant #quir.angle<1.100000e+00> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_2_3:%.*]] = quir.constant #quir.angle<1.250000e+00> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_2_4:%.*]] = quir.constant #quir.angle<1.500000e+00> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_2_5:%.*]] = quir.constant #quir.angle<1.750000e+00> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_2_6:%.*]] = quir.constant #quir.angle<1.800000e+00> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_2_7:%.*]] = quir.constant #quir.angle<2.000000e+00> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_2_8:%.*]] = quir.constant #quir.angle<2.250000e+00> : !quir.angle<64> +// MLIR-NO-CIRCUITS: [[ANGLE_2_9:%.*]] = quir.constant #quir.angle<2.500000e+00> : !quir.angle<64> // MLIR-NO-CIRCUITS: quir.call_gate @star([[QUBIT0]], [[ANGLE_2_1]], [[ANGLE_2_2]], [[ANGLE_2_3]], [[ANGLE_2_4]], [[ANGLE_2_5]], [[ANGLE_2_6]], [[ANGLE_2_7]], [[ANGLE_2_8]], [[ANGLE_2_9]]) // MLIR-CIRCUITS: quir.call_circuit @circuit_0(%0) : (!quir.qubit<1>) -> () star(1.0, 1.1, 1.25, 1.5, 1.75, 1.8, 2.0, 2.25, 2.5) $0; diff --git a/test/Frontend/OpenQASM3/input-parameters-if.qasm b/test/Frontend/OpenQASM3/input-parameters-if.qasm index 1ab96ff1c..0486387db 100644 --- a/test/Frontend/OpenQASM3/input-parameters-if.qasm +++ b/test/Frontend/OpenQASM3/input-parameters-if.qasm @@ -22,11 +22,11 @@ bit is_excited; bit other; bit result; -gate x q { } +gate x q { } gate rz(phi) q { } input angle theta = 3.141; -// CHECK: qcs.declare_parameter @_QX64_5thetaEE_ : !quir.angle<64> = #quir.angle<3.141000e+00 : !quir.angle<64>> +// CHECK: qcs.declare_parameter @_QX64_5thetaEE_ : !quir.angle<64> = #quir.angle<3.141000e+00> : !quir.angle<64> x $2; rz(theta) $2; @@ -46,7 +46,7 @@ is_excited = measure $2; // CHECK-NEXT: quir.return %0 : i1 // CHECK-NEXT: } -// CHECK: func @main() -> i32 { +// CHECK: func.func @main() -> i32 { // CHECK: scf.for %arg0 = %c0 to %c1000 step %c1 { // CHECK: [[QUBIT2:%.*]] = quir.declare_qubit {id = 2 : i32} : !quir.qubit<1> // CHECK: [[QUBIT3:%.*]] = quir.declare_qubit {id = 3 : i32} : !quir.qubit<1> diff --git a/test/Frontend/OpenQASM3/input-parameters-while.qasm b/test/Frontend/OpenQASM3/input-parameters-while.qasm index 19deb4880..34260805b 100644 --- a/test/Frontend/OpenQASM3/input-parameters-while.qasm +++ b/test/Frontend/OpenQASM3/input-parameters-while.qasm @@ -21,28 +21,28 @@ gate h q { gate rz(phi) q { } input angle theta = 3.141; -// CHECK: qcs.declare_parameter @_QX64_5thetaEE_ : !quir.angle<64> = #quir.angle<3.141000e+00 : !quir.angle<64>> +// CHECK: qcs.declare_parameter @_QX64_5thetaEE_ : !quir.angle<64> = #quir.angle<3.141000e+00> : !quir.angle<64> qubit $0; int n = 1; bit is_excited; -// CHECK: func @h(%arg0: !quir.qubit<1>) { +// CHECK: func.func @h(%arg0: !quir.qubit<1>) { // CHECK: quir.call_circuit @circuit_0(%arg0) : (!quir.qubit<1>) -> () -// CHECK-NEXT: return +// CHECK-NEXT: return // CHECK-NEXT: } // CHECK: quir.circuit @circuit_0(%arg0: !quir.qubit<1>) { -// CHECK-NEXT: %angle = quir.constant #quir.angle<1.57079632679 : !quir.angle<64>> -// CHECK-NEXT: %angle_0 = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> -// CHECK-NEXT: %angle_1 = quir.constant #quir.angle<3.1415926535900001 : !quir.angle<64>> +// CHECK-NEXT: %angle = quir.constant #quir.angle<1.57079632679> : !quir.angle<64> +// CHECK-NEXT: %angle_0 = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> +// CHECK-NEXT: %angle_1 = quir.constant #quir.angle<3.1415926535900001> : !quir.angle<64> // CHECK-NEXT: quir.builtin_U %arg0, %angle, %angle_0, %angle_1 : !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> // CHECK-NEXT: quir.return // CHECK-NEXT: } -// CHECK: func @rz(%arg0: !quir.qubit<1>, %arg1: !quir.angle<64>) { -// CHECK-NEXT: return +// CHECK: func.func @rz(%arg0: !quir.qubit<1>, %arg1: !quir.angle<64>) { +// CHECK-NEXT: return // CHECK-NEXT: } // CHECK: quir.circuit @circuit_1(%arg0: !quir.qubit<1>) -> i1 { @@ -54,10 +54,10 @@ bit is_excited; // CHECK: quir.circuit @circuit_2(%arg0: !quir.qubit<1>, %arg1: !quir.angle<64>) { // CHECK-NEXT: quir.call_gate @h(%arg0) : (!quir.qubit<1>) -> () // CHECK quir.call_gate @rz(%arg0, %arg1) : (!quir.qubit<1>) -> () -// CHECK: quir.return +// CHECK: quir.return // CHECK-NEXT: } -// CHECK: func @main() -> i32 { +// CHECK: func.func @main() -> i32 { // CHECK: scf.for %arg0 = %c0 to %c1000 step %c1 { // CHECK: [[QUBIT:%.*]] = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> // CHECK: scf.while : () -> () { @@ -73,7 +73,7 @@ while (n != 0) { // CHECK: oq3.cbit_assign_bit @is_excited<1> [0] : i1 = [[MEASURE]] // CHECK: [[EXCITED:%.*]] = oq3.variable_load @is_excited : !quir.cbit<1> // CHECK: [[COND2:%.*]] = "oq3.cast"([[EXCITED]]) : (!quir.cbit<1>) -> i1 - + // CHECK: scf.if [[COND2]] { if (is_excited) { // CHECK: [[THETA:%.*]] = oq3.variable_load @theta : !quir.angle<64> diff --git a/test/Frontend/OpenQASM3/input-parameters.qasm b/test/Frontend/OpenQASM3/input-parameters.qasm index e666619cb..b8e1d33e0 100644 --- a/test/Frontend/OpenQASM3/input-parameters.qasm +++ b/test/Frontend/OpenQASM3/input-parameters.qasm @@ -17,7 +17,7 @@ OPENQASM 3; // This test case validates that input and output modifiers for variables are // parsed correctly and are reflected in generated QUIR. -// TODO: putting resets in circuits has been disabled. The XX-tests +// TODO: putting resets in circuits has been disabled. The XX-tests // are the correct tests if it is re-enabled. The CHECK-XX should be removed // in that case @@ -28,7 +28,7 @@ gate sx q { } gate rz(phi) q { } input angle theta = 3.141; -// CHECK: qcs.declare_parameter @_QX64_5thetaEE_ : !quir.angle<64> = #quir.angle<3.141000e+00 : !quir.angle<64>> +// CHECK: qcs.declare_parameter @_QX64_5thetaEE_ : !quir.angle<64> = #quir.angle<3.141000e+00> : !quir.angle<64> input float[64] theta2 = 1.56; // CHECK: qcs.declare_parameter @_QDDd64_6theta2EE_ : f64 = 1.560000e+00 : f64 @@ -54,15 +54,15 @@ c = measure $0; // CHECK: quir.circuit @circuit_0(%arg0: !quir.qubit<1>, %arg1: !quir.angle<64>) { // XX-CHECK-NEXT: quir.reset %arg0 : !quir.qubit<1> // CHECK-NEXT: quir.call_gate @sx(%arg0) : (!quir.qubit<1>) -> () -// CHECK: quir.return -// CHECK-NEXT: } +// CHECK: quir.return +// CHECK-NEXT: } // CHECK: quir.circuit @circuit_1(%arg0: !quir.qubit<1>) -> i1 { // CHECK-NEXT: %0 = quir.measure(%arg0) : (!quir.qubit<1>) -> i1 // CHECK-NEXT: quir.return %0 : i1 // CHECK-NEXT: } -// CHECK: func @main() -> i32 { +// CHECK: func.func @main() -> i32 { // CHECK: scf.for %arg0 = %c0 to %c1000 step %c1 { // CHECK: %0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1> // CHECK: %1 = quir.declare_qubit {id = 2 : i32} : !quir.qubit<1> diff --git a/test/Frontend/OpenQASM3/main.qasm b/test/Frontend/OpenQASM3/main.qasm index 5e14338a1..449499779 100644 --- a/test/Frontend/OpenQASM3/main.qasm +++ b/test/Frontend/OpenQASM3/main.qasm @@ -15,7 +15,7 @@ OPENQASM 3.0; // that they have been altered from the originals. // MLIR: module { -// MLIR: func @main() -> i32 { +// MLIR: func.func @main() -> i32 { qubit $0; diff --git a/test/Frontend/OpenQASM3/multi-param-gatedef.qasm b/test/Frontend/OpenQASM3/multi-param-gatedef.qasm index 2dca094d1..4a6e2cb14 100644 --- a/test/Frontend/OpenQASM3/multi-param-gatedef.qasm +++ b/test/Frontend/OpenQASM3/multi-param-gatedef.qasm @@ -15,14 +15,14 @@ OPENQASM 3.0; // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -// MLIR-NO-CIRCUITS: func @g([[QUBIT:%.*]]: !quir.qubit<1>, [[ANGLE:%.*]]: !quir.angle<{{.*}}>) { +// MLIR-NO-CIRCUITS: func.func @g([[QUBIT:%.*]]: !quir.qubit<1>, [[ANGLE:%.*]]: !quir.angle<{{.*}}>) { // MLIR-CIRCUITS:quir.circuit @circuit_0([[ANGLE:%.*]]: !quir.angle<64>, [[QUBIT:%.*]]: !quir.qubit<1>) { // MLIR: quir.builtin_U [[QUBIT]], {{.*}}, {{.*}}, [[ANGLE]] : !quir.qubit<1>, !quir.angle<{{.*}}>, !quir.angle<{{.*}}>, !quir.angle<{{.*}}> gate g (theta) q { U(0.0, 0.0, theta) q; } -// MLIR-NO-CIRCUITS: func @g3([[QUBIT0:%.*]]: !quir.qubit<1>, [[QUBIT1:%.*]]: !quir.qubit<1>, [[ANGLE0:%.*]]: !quir.angle<{{.*}}>, [[ANGLE1:%.*]]: !quir.angle<{{.*}}>, [[ANGLE2:%.*]]: !quir.angle<{{.*}}>) { +// MLIR-NO-CIRCUITS: func.func @g3([[QUBIT0:%.*]]: !quir.qubit<1>, [[QUBIT1:%.*]]: !quir.qubit<1>, [[ANGLE0:%.*]]: !quir.angle<{{.*}}>, [[ANGLE1:%.*]]: !quir.angle<{{.*}}>, [[ANGLE2:%.*]]: !quir.angle<{{.*}}>) { // MLIR-CIRCUITS: quir.circuit @circuit_1({{.*}}: !quir.{{.*}}, {{.*}}: !quir.{{.*}}, {{.*}}: !quir.{{.*}}, {{.*}}: !quir.{{.*}}, {{.*}}: !quir.{{.*}}) { // NOTE can not enforce parameter ordering on the builtin_U because the order of the quir.circuit parameters changes when tested with github actions // MLIR: quir.builtin_U {{.*}}, {{.*}}, {{.*}}, {{.*}} : !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> diff --git a/test/Frontend/OpenQASM3/multi-qubit-gatedef.qasm b/test/Frontend/OpenQASM3/multi-qubit-gatedef.qasm index 9446aec9a..75747480f 100644 --- a/test/Frontend/OpenQASM3/multi-qubit-gatedef.qasm +++ b/test/Frontend/OpenQASM3/multi-qubit-gatedef.qasm @@ -15,7 +15,7 @@ OPENQASM 3.0; // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -// MLIR: func @g([[QUBIT0:%.*]]: !quir.qubit<1>, [[QUBIT1:%.*]]: !quir.qubit<1>) { +// MLIR: func.func @g([[QUBIT0:%.*]]: !quir.qubit<1>, [[QUBIT1:%.*]]: !quir.qubit<1>) { // MLIR-CIRCUITS: quir.circuit @circuit_0([[QUBIT1:%.*]]: !quir.qubit<1>, [[QUBIT0:%.*]]: !quir.qubit<1>) { gate g qa, qb { // MLIR: quir.builtin_U [[QUBIT0]]{{.*}} @@ -24,7 +24,7 @@ gate g qa, qb { U(1.57079632679, 0.0, 3.14159265359) qb; } -// MLIR: func @g4(%arg0: !quir.qubit<1>, %arg1: !quir.qubit<1>, %arg2: !quir.qubit<1>) { +// MLIR: func.func @g4(%arg0: !quir.qubit<1>, %arg1: !quir.qubit<1>, %arg2: !quir.qubit<1>) { // MLIR-CIRCUITS: quir.circuit @circuit_1([[QUBIT0:%.*]]: !quir.qubit<1>, [[QUBIT1:%.*]]: !quir.qubit<1>, [[QUBIT2:%.*]]: !quir.qubit<1>) { gate g4 qa, qb, qc { U(1.57079632679, 0.0, 3.14159265359) qa; diff --git a/test/Frontend/OpenQASM3/nested-gatecalls.qasm b/test/Frontend/OpenQASM3/nested-gatecalls.qasm index 34e507139..bc1b7ba92 100644 --- a/test/Frontend/OpenQASM3/nested-gatecalls.qasm +++ b/test/Frontend/OpenQASM3/nested-gatecalls.qasm @@ -15,21 +15,21 @@ OPENQASM 3.0; // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -// MLIR-NO-CIRCUITS: func @g([[QUBIT:%.*]]: !quir.qubit<1>, [[ANGLE:%.*]]: !quir.angle<64>) { +// MLIR-NO-CIRCUITS: func.func @g([[QUBIT:%.*]]: !quir.qubit<1>, [[ANGLE:%.*]]: !quir.angle<64>) { // MLIR-CIRCUITS: quir.circuit @circuit_0([[ANGLE:%.*]]: !quir.angle<64>, [[QUBIT:%.*]]: !quir.qubit<1>) { // MLIR: quir.builtin_U [[QUBIT]], {{.*}}, {{.*}}, [[ANGLE]] : !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> gate g (theta) q { U(0.0, 0.0, theta) q; } -// MLIR-NO-CIRCUITS: func @q1([[QUBIT1:%.*]]: !quir.qubit<1>, [[ANGLE1:%.*]]: !quir.angle<64>) { +// MLIR-NO-CIRCUITS: func.func @q1([[QUBIT1:%.*]]: !quir.qubit<1>, [[ANGLE1:%.*]]: !quir.angle<64>) { // MLIR-CIRCUITS: quir.circuit @circuit_1([[ANGLE1:%.*]]: !quir.angle<64>, [[QUBIT1:%.*]]: !quir.qubit<1>) { // MLIR: quir.call_gate @g([[QUBIT1]], [[ANGLE1]]) : (!quir.qubit<1>, !quir.angle<64>) -> () gate q1 (theta) q { g(theta) q; } -// MLIR-NO-CIRCUITS: func @g2([[QUBIT0:%.*]]: !quir.qubit<1>, [[QUBIT1:%.*]]: !quir.qubit<1>, [[ANGLE0:%.*]]: !quir.angle<64>, [[ANGLE1:%.*]]: !quir.angle<64>) { +// MLIR-NO-CIRCUITS: func.func @g2([[QUBIT0:%.*]]: !quir.qubit<1>, [[QUBIT1:%.*]]: !quir.qubit<1>, [[ANGLE0:%.*]]: !quir.angle<64>, [[ANGLE1:%.*]]: !quir.angle<64>) { // MLIR-CIRCUITS: quir.circuit @circuit_2({{.*}}: !quir.{{.*}}, {{.*}}: !quir.{{.*}}, {{.*}}: !quir.{{.*}}, {{.*}}: !quir.{{.*}}) { // NOTE can not enforce parameter ordering on the builtin_U because the order of the quir.circuit parameters changes when tested with github actions // MLIR: quir.call_gate @g({{.*}}, {{.*}}) : (!quir.qubit<1>, !quir.angle<64>) -> () @@ -39,15 +39,15 @@ gate g2 (theta, lambda) qa, qb { g(lambda) qb; } -// MLIR-NO-CIRCUITS: func @g3([[QUBIT0:%.*]]: !quir.qubit<1>, [[QUBIT1:%.*]]: !quir.qubit<1>, [[ANGLE0:%.*]]: !quir.angle<64>, [[ANGLE1:%.*]]: !quir.angle<64>, [[ANGLE2:%.*]]: !quir.angle<64>) { +// MLIR-NO-CIRCUITS: func.func @g3([[QUBIT0:%.*]]: !quir.qubit<1>, [[QUBIT1:%.*]]: !quir.qubit<1>, [[ANGLE0:%.*]]: !quir.angle<64>, [[ANGLE1:%.*]]: !quir.angle<64>, [[ANGLE2:%.*]]: !quir.angle<64>) { // MLIR-CIRCUITS: quir.circuit @circuit_3({{.*}}: !quir.{{.*}}, {{.*}}: !quir.{{.*}}, {{.*}}: !quir.{{.*}}, {{.*}}: !quir.{{.*}}, {{.*}}: !quir.{{.*}}) { // qa = %arg0, qb = %arg1, theta = %arg2, lambda = %arg3, phi = %arg4 -// MLIR: {{.*}} = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> -// MLIR: {{.*}} = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> +// MLIR: {{.*}} = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> +// MLIR: {{.*}} = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> // NOTE can not enforce parameter ordering on the builtin_U because the order of the quir.circuit parameters changes when tested with github actions // MLIR: quir.call_gate @g2({{.*}}, {{.*}}, {{.*}}, {{.*}}) : (!quir.qubit<1>, !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>) -> () -// MLIR: {{.*}} = quir.constant #quir.angle<3.140000e+00 : !quir.angle<64>> +// MLIR: {{.*}} = quir.constant #quir.angle<3.140000e+00> : !quir.angle<64> // MLIR: quir.call_gate @g2({{.*}}, {{.*}}, {{.*}},{{.*}}) : (!quir.qubit<1>, !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>) -> () // MLIR: quir.call_gate @g2({{.*}}, {{.*}}, {{.*}}, {{.*}}) : (!quir.qubit<1>, !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>) -> () gate g3 (theta, lambda, phi) qa, qb { @@ -56,7 +56,7 @@ gate g3 (theta, lambda, phi) qa, qb { g2(phi, lambda) qa, qb; } -// MLIR: func @main() -> i32 { +// MLIR: func.func @main() -> i32 { // MLIR: [[QUBIT2:%.*]] = quir.declare_qubit {id = 2 : i32} : !quir.qubit<1> // MLIR: [[QUBIT3:%.*]] = quir.declare_qubit {id = 3 : i32} : !quir.qubit<1> diff --git a/test/Frontend/OpenQASM3/rz-issue-655.qasm b/test/Frontend/OpenQASM3/rz-issue-655.qasm index e64db8708..4002d4e5c 100644 --- a/test/Frontend/OpenQASM3/rz-issue-655.qasm +++ b/test/Frontend/OpenQASM3/rz-issue-655.qasm @@ -20,11 +20,11 @@ OPENQASM 3.0; // angle parameters. // MLIR-CIRCUITS: quir.circuit @circuit_0([[QUBIT0:%.*]]: !quir.qubit<1>) { -// MLIR-CIRCUITS: [[ANGLE1:%.*]] = quir.constant #quir.angle<1.000000e+00 : !quir.angle<64>> +// MLIR-CIRCUITS: [[ANGLE1:%.*]] = quir.constant #quir.angle<1.000000e+00> : !quir.angle<64> // MLIR-CIRCUITS: quir.call_gate @rz([[QUBIT0]], [[ANGLE1]]) -// MLIR-CIRCUITS: [[ANGLE2:%.*]] = quir.constant #quir.angle<2.000000e+00 : !quir.angle<64>> +// MLIR-CIRCUITS: [[ANGLE2:%.*]] = quir.constant #quir.angle<2.000000e+00> : !quir.angle<64> // MLIR-CIRCUITS: quir.call_gate @rz([[QUBIT0]], [[ANGLE2]]) -// MLIR-CIRCUITS: [[ANGLE3:%.*]] = quir.constant #quir.angle<3.000000e+00 : !quir.angle<64>> +// MLIR-CIRCUITS: [[ANGLE3:%.*]] = quir.constant #quir.angle<3.000000e+00> : !quir.angle<64> // MLIR-CIRCUITS: quir.call_gate @rz([[QUBIT0]], [[ANGLE3]]) // MLIR-CIRCUITS: quir.return @@ -34,17 +34,17 @@ qubit $0; gate rz(theta) q {} // AST-PRETTY: GateGenericNode(name=rz, params=[AngleNode(value=1.0, bits=64)], qubits=[], qcparams=[$0]) -// MLIR-NO-CIRCUITS: [[ANGLE1:%.*]] = quir.constant #quir.angle<1.000000e+00 : !quir.angle<64>> +// MLIR-NO-CIRCUITS: [[ANGLE1:%.*]] = quir.constant #quir.angle<1.000000e+00> : !quir.angle<64> // MLIR-NO-CIRCUITS: quir.call_gate @rz([[QUBIT0]], [[ANGLE1]]) rz(1.0) $0; // AST-PRETTY: GateGenericNode(name=rz, params=[AngleNode(value=2.0, bits=64)], qubits=[], qcparams=[$0]) -// MLIR-NO-CIRCUITS: [[ANGLE2:%.*]] = quir.constant #quir.angle<2.000000e+00 : !quir.angle<64>> +// MLIR-NO-CIRCUITS: [[ANGLE2:%.*]] = quir.constant #quir.angle<2.000000e+00> : !quir.angle<64> // MLIR-NO-CIRCUITS: quir.call_gate @rz([[QUBIT0]], [[ANGLE2]]) rz(2.0) $0; // AST-PRETTY: GateGenericNode(name=rz, params=[AngleNode(value=3.0, bits=64)], qubits=[], qcparams=[$0]) -// MLIR-NO-CIRCUITS: [[ANGLE3:%.*]] = quir.constant #quir.angle<3.000000e+00 : !quir.angle<64>> +// MLIR-NO-CIRCUITS: [[ANGLE3:%.*]] = quir.constant #quir.angle<3.000000e+00> : !quir.angle<64> // MLIR-NO-CIRCUITS: quir.call_gate @rz([[QUBIT0]], [[ANGLE3]]) // MLIR-CIRCUITS: quir.call_circuit @circuit_0(%0) : (!quir.qubit<1>) -> () rz(3.0) $0; diff --git a/test/Frontend/OpenQASM3/switch-1.qasm b/test/Frontend/OpenQASM3/switch-1.qasm index 85543dd76..9e1820d89 100644 --- a/test/Frontend/OpenQASM3/switch-1.qasm +++ b/test/Frontend/OpenQASM3/switch-1.qasm @@ -19,11 +19,11 @@ OPENQASM 3.0; int i = 15; qubit $0; // MLIR: quir.switch %{{.*}}{ -// MLIR-NO-CIRCUITS: %angle = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: %angle_0 = quir.constant #quir.angle<1.000000e-01 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: %angle_1 = quir.constant #quir.angle<2.000000e-01 : !quir.angle<64>> +// MLIR-NO-CIRCUITS: %angle = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> +// MLIR-NO-CIRCUITS: %angle_0 = quir.constant #quir.angle<1.000000e-01> : !quir.angle<64> +// MLIR-NO-CIRCUITS: %angle_1 = quir.constant #quir.angle<2.000000e-01> : !quir.angle<64> // MLIR-NO-CIRCUITS: quir.builtin_U %{{.*}}, %angle, %angle_0, %angle_1 : !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> -// MLIR-CIRCUITS: quir.call_circuit @circuit_0(%0) : (!quir.qubit<1>) -> () +// MLIR-CIRCUITS: quir.call_circuit @circuit_0(%0) : (!quir.qubit<1>) -> () // MLIR: }[1 : { // MLIR: }2 : { // MLIR: }3 : { diff --git a/test/Frontend/OpenQASM3/switch-2.qasm b/test/Frontend/OpenQASM3/switch-2.qasm index eca4f604b..421071010 100644 --- a/test/Frontend/OpenQASM3/switch-2.qasm +++ b/test/Frontend/OpenQASM3/switch-2.qasm @@ -27,11 +27,11 @@ bit c1; qubit[8] $0; // MLIR: quir.switch %{{.*}}{ -// MLIR-NO-CIRCUITS: %angle = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: %angle_0 = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: %angle_1 = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> +// MLIR-NO-CIRCUITS: %angle = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> +// MLIR-NO-CIRCUITS: %angle_0 = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> +// MLIR-NO-CIRCUITS: %angle_1 = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> // MLIR-NO-CIRCUITS: quir.builtin_U %{{.*}}, %angle, %angle_0, %angle_1 : !quir.qubit<8>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> -// MLIR-CIRCUITS: quir.call_circuit @circuit_0(%{{.*}}) : (!quir.qubit<8>) -> () +// MLIR-CIRCUITS: quir.call_circuit @circuit_0(%{{.*}}) : (!quir.qubit<8>) -> () // MLIR: }[1 : { // MLIR: %{{.*}} = oq3.variable_load @k : i32 // MLIR: oq3.variable_assign @j : i32 = %{{.*}} @@ -40,11 +40,11 @@ qubit[8] $0; // MLIR: %{{.*}} = "oq3.cast"(%{{.*}}) : (i32) -> f64 // MLIR: oq3.variable_assign @d : f64 = %{{.*}} // MLIR: }3 : { -// MLIR-NO-CIRCUITS: %angle = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: %angle_0 = quir.constant #quir.angle<1.000000e-01 : !quir.angle<64>> -// MLIR-NO-CIRCUITS: %angle_1 = quir.constant #quir.angle<2.000000e-01 : !quir.angle<64>> +// MLIR-NO-CIRCUITS: %angle = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> +// MLIR-NO-CIRCUITS: %angle_0 = quir.constant #quir.angle<1.000000e-01> : !quir.angle<64> +// MLIR-NO-CIRCUITS: %angle_1 = quir.constant #quir.angle<2.000000e-01> : !quir.angle<64> // MLIR-NO-CIRCUITS: quir.builtin_U %{{.*}}, %angle, %angle_0, %angle_1 : !quir.qubit<8>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> -// MLIR-CIRCUITS: quir.call_circuit @circuit_1(%{{.*}}) : (!quir.qubit<8>) -> () +// MLIR-CIRCUITS: quir.call_circuit @circuit_1(%{{.*}}) : (!quir.qubit<8>) -> () // MLIR: }] // AST-PRETTY: SwitchStatementNode(SwitchQuantity(name=i, type=ASTTypeIdentifier), switch (i) { diff --git a/test/Frontend/OpenQASM3/teleport.qasm b/test/Frontend/OpenQASM3/teleport.qasm index ed9a43881..4c3e344bd 100644 --- a/test/Frontend/OpenQASM3/teleport.qasm +++ b/test/Frontend/OpenQASM3/teleport.qasm @@ -33,7 +33,7 @@ OPENQASM 3.0; // AST-PRETTY: , // AST-PRETTY: ] // AST-PRETTY: ) -// MLIR: func @h(%arg0: !quir.qubit<1>) { +// MLIR: func.func @h(%arg0: !quir.qubit<1>) { gate h q { U(1.57079632679, 0, 3.14159265359) q; } @@ -49,12 +49,12 @@ gate h q { // AST-PRETTY: , // AST-PRETTY: ] // AST-PRETTY: ) -// MLIR: func @z(%arg0: !quir.qubit<1>) { +// MLIR: func.func @z(%arg0: !quir.qubit<1>) { gate z q { U(0, 0, 3.14159265359) q; } -// MLIR: func @x(%arg0: !quir.qubit<1>) { +// MLIR: func.func @x(%arg0: !quir.qubit<1>) { gate x q { U(3.14159265359, 0, 3.14159265359) q; } @@ -93,9 +93,9 @@ cx $1, $2; // AST-PRETTY: DeclarationNode(type=ASTTypeDuration, DurationNode(duration=30, unit=Nanoseconds, name=for_0)) // AST-PRETTY: DeclarationNode(type=ASTTypeDuration, DurationNode(duration=40, unit=Nanoseconds, name=for_1)) // AST-PRETTY: DeclarationNode(type=ASTTypeDuration, DurationNode(duration=50, unit=Nanoseconds, name=for_2)) -// MLIR: [[DURATION0:%.*]] = quir.constant #quir.duration<3.000000e+01 : > -// MLIR: [[DURATION1:%.*]] = quir.constant #quir.duration<4.000000e+01 : > -// MLIR: [[DURATION2:%.*]] = quir.constant #quir.duration<5.000000e+01 : > +// MLIR: [[DURATION0:%.*]] = quir.constant #quir.duration<3.000000e+01> : !quir.duration +// MLIR: [[DURATION1:%.*]] = quir.constant #quir.duration<4.000000e+01> : !quir.duration +// MLIR: [[DURATION2:%.*]] = quir.constant #quir.duration<5.000000e+01> : !quir.duration duration for_0 = 30ns; duration for_1 = 40ns; duration for_2 = 50ns; diff --git a/test/Frontend/OpenQASM3/test-include.qasm b/test/Frontend/OpenQASM3/test-include.qasm index ddf0d3a41..85adbf85b 100644 --- a/test/Frontend/OpenQASM3/test-include.qasm +++ b/test/Frontend/OpenQASM3/test-include.qasm @@ -14,7 +14,7 @@ OPENQASM 3.0; // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -// CHECK: func @rz +// CHECK: func.func @rz include "test-include.inc"; qubit $0; rz(0) $0; diff --git a/test/Frontend/OpenQASM3/while-1.qasm b/test/Frontend/OpenQASM3/while-1.qasm index 0051f2b2e..20b71feae 100644 --- a/test/Frontend/OpenQASM3/while-1.qasm +++ b/test/Frontend/OpenQASM3/while-1.qasm @@ -25,21 +25,20 @@ int n = 1; bit is_excited; -// MLIR-CIRCUITS: func @h(%arg0: !quir.qubit<1>) { +// MLIR-CIRCUITS: func.func @h(%arg0: !quir.qubit<1>) { // MLIR-CIRCUITS: quir.call_circuit @circuit_0(%arg0) : (!quir.qubit<1>) -> () -// MLIR-CIRCUITS: return +// MLIR-CIRCUITS: return // MLIR-CIRCUITS: quir.circuit @circuit_0(%arg0: !quir.qubit<1>) { -// MLIR-CIRCUITS: %angle = quir.constant #quir.angle<1.57079632679 : !quir.angle<64>> +// MLIR-CIRCUITS: %angle = quir.constant #quir.angle<1.57079632679> : !quir.angle<64> // MLIR-CIRCUITS: quir.builtin_U %arg0, %angle, %angle_0, %angle_1 : !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> // MLIR-CIRCUITS: quir.return - + // MLIR-CIRCUITS: quir.circuit @circuit_1(%arg0: !quir.qubit<1>) -> i1 { // MLIR-CIRCUITS: quir.call_gate @h(%arg0) : (!quir.qubit<1>) -> () -// MLIR-CIRCUITS: %cst = constant unit // MLIR-CIRCUITS: %0 = quir.measure(%arg0) : (!quir.qubit<1>) -> i1 // MLIR-CIRCUITS: quir.return %0 : i1 - + // MLIR-CIRCUITS: quir.circuit @circuit_2(%arg0: !quir.qubit<1>) { // MLIR-CIRCUITS: quir.call_gate @h(%arg0) : (!quir.qubit<1>) -> () // MLIR-CIRCUITS: quir.return @@ -57,7 +56,6 @@ while (n != 0) { // AST-PRETTY: ops=[ // AST-PRETTY: UGateOpNode(params=[AngleNode(value=1.57079632679000003037, bits=64), AngleNode(value=0.0, bits=64), AngleNode(value=3.14159265359000006157, bits=64)], qubits=[], qcparams=[q]) // MLIR-NO-CIRCUITS: quir.call_gate @h(%0) : (!quir.qubit<1>) -> () - // MLIR-NO-CIRCUITS: %cst = constant unit h $0; // MLIR-NO-CIRCUITS: %2 = quir.measure(%0) : (!quir.qubit<1>) -> i1 // MLIR-CIRCUITS: %2 = quir.call_circuit @circuit_1(%0) : (!quir.qubit<1>) -> i1 @@ -68,15 +66,14 @@ while (n != 0) { // MLIR: scf.if %4 { if (is_excited) { // MLIR-NO-CIRCUITS: quir.call_gate @h(%0) : (!quir.qubit<1>) -> () - // MLIR-NO-CIRCUITS: %cst_1 = constant unit // MLIR-CIRCUITS: quir.call_circuit @circuit_2(%0) : (!quir.qubit<1>) -> () // MLIR: } h $0; } // error: Binary operation ASTOpTypeSub not supported yet. // n = n - 1; - // MLIR: %c0_i32_0 = arith.constant 0 : i32 - // MLIR: oq3.variable_assign @n : i32 = %c0_i32_0 + // MLIR: [[REG:.*]] = arith.constant 0 : i32 + // MLIR: oq3.variable_assign @n : i32 = [[REG]] n = 0; // workaround for n = n - 1 // MLIR: scf.yield } diff --git a/test/Frontend/OpenQASM3/while-2.qasm b/test/Frontend/OpenQASM3/while-2.qasm index ac0f22fa3..aabab597b 100644 --- a/test/Frontend/OpenQASM3/while-2.qasm +++ b/test/Frontend/OpenQASM3/while-2.qasm @@ -38,8 +38,7 @@ while (n != 0) { // MLIR: scf.if %3 { if (n == 2) { // MLIR-NO-CIRCUITS: quir.call_gate @h(%0) : (!quir.qubit<1>) -> () - // MLIR-NO-CIRCUITS: %cst = constant unit - // MLIR-CIRCUITS: quir.call_circuit @circuit_1(%0) : (!quir.qubit<1>) -> () + // MLIR-CIRCUITS: quir.call_circuit @circuit_1(%0) : (!quir.qubit<1>) -> () // MLIR: %c1_i32 = arith.constant 1 : i32 // MLIR: oq3.variable_assign @n : i32 = %c1_i32 h $0; @@ -47,12 +46,11 @@ while (n != 0) { // MLIR: } else { } else { // MLIR-NO-CIRCUITS: quir.call_gate @h(%0) : (!quir.qubit<1>) -> () - // MLIR-NO-CIRCUITS: %cst = constant unit // MLIR-NO-CIRCUITS: %4 = quir.measure(%0) : (!quir.qubit<1>) -> i1 // MLIR-CIRCUITS: %4 = quir.call_circuit @circuit_2(%0) : (!quir.qubit<1>) -> i1 // MLIR: oq3.cbit_assign_bit @is_excited<1> [0] : i1 = %4 - // MLIR: %c0_i32_1 = arith.constant 0 : i32 - // MLIR: oq3.variable_assign @n : i32 = %c0_i32_1 + // MLIR: [[REG:.*]] = arith.constant 0 : i32 + // MLIR: oq3.variable_assign @n : i32 = [[REG]] h $0; is_excited = measure $0; n = 0; diff --git a/test/Frontend/OpenQASM3/while-3.qasm b/test/Frontend/OpenQASM3/while-3.qasm index fae299d49..37f1a1a3f 100644 --- a/test/Frontend/OpenQASM3/while-3.qasm +++ b/test/Frontend/OpenQASM3/while-3.qasm @@ -52,7 +52,6 @@ while (i != 0) { // AST-PRETTY: ] // AST-PRETTY: ) // MLIR-NO-CIRCUITS: quir.call_gate @h(%0) : (!quir.qubit<1>) -> () - // MLIR-NO-CIRCUITS: %cst = constant unit // MLIR-CIRCUITS: quir.call_circuit @circuit_1(%0) : (!quir.qubit<1>) -> () // MLIR: [[CONSTANT1:%c0_i32_.]] = arith.constant 0 : i32 // MLIR: oq3.variable_assign @j : i32 = [[CONSTANT1]] @@ -62,9 +61,9 @@ while (i != 0) { // AST-PRETTY: BinaryOpNode(type=ASTOpTypeAssign, left=IdentifierNode(name=j, bits=32), right=IntNode(signed=true, value=0, bits=32)) j = 0; } - // MLIR-NO-CIRCUITS: %angle = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> - // MLIR-NO-CIRCUITS: %angle_1 = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> - // MLIR-NO-CIRCUITS: %angle_2 = quir.constant #quir.angle<0.000000e+00 : !quir.angle<64>> + // MLIR-NO-CIRCUITS: %angle = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> + // MLIR-NO-CIRCUITS: %angle_1 = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> + // MLIR-NO-CIRCUITS: %angle_2 = quir.constant #quir.angle<0.000000e+00> : !quir.angle<64> // MLIR-NO-CIRCUITS: quir.builtin_U %0, %angle, %angle_1, %angle_2 : !quir.qubit<1>, !quir.angle<64>, !quir.angle<64>, !quir.angle<64> U (0, 0, 0) $0; // MLIR-NO-CIRCUITS: %2 = quir.measure(%0) : (!quir.qubit<1>) -> i1 diff --git a/test/unittest/HAL/TargetSystemRegistryTest.cpp b/test/unittest/HAL/TargetSystemRegistryTest.cpp index b5cf90d06..3db1e47d6 100644 --- a/test/unittest/HAL/TargetSystemRegistryTest.cpp +++ b/test/unittest/HAL/TargetSystemRegistryTest.cpp @@ -35,12 +35,14 @@ TEST(TargetSystemRegistry, LookupMockTarget) { auto targetInfoOpt = qssc::hal::registry::TargetSystemRegistry::lookupPluginInfo(mockName); - EXPECT_TRUE(targetInfoOpt.hasValue()); - auto *targetInfo = targetInfoOpt.getValue(); + ASSERT_TRUE(targetInfoOpt.has_value()); + if (targetInfoOpt.has_value()) { + auto *targetInfo = targetInfoOpt.value(); - ASSERT_NE(targetInfo, nullptr); - EXPECT_EQ(targetInfo->getName(), mockName); + ASSERT_NE(targetInfo, nullptr); + EXPECT_EQ(targetInfo->getName(), mockName); + } } } // anonymous namespace diff --git a/test/unittest/Payload/PayloadRegistryTest.cpp b/test/unittest/Payload/PayloadRegistryTest.cpp index cc74ab334..c688b4779 100644 --- a/test/unittest/Payload/PayloadRegistryTest.cpp +++ b/test/unittest/Payload/PayloadRegistryTest.cpp @@ -28,9 +28,10 @@ TEST(PayloadRegistry, LookupZipPayload) { auto payloadInfoOpt = qssc::payload::registry::PayloadRegistry::lookupPluginInfo(zipName); - EXPECT_TRUE(payloadInfoOpt.hasValue()); + const bool payloadInfoPresent = payloadInfoOpt.has_value(); + EXPECT_TRUE(payloadInfoPresent); - auto *payloadInfo = payloadInfoOpt.getValue(); + auto *payloadInfo = payloadInfoOpt.value(); ASSERT_NE(payloadInfo, nullptr); EXPECT_EQ(payloadInfo->getName(), zipName); diff --git a/test/unittest/quir-dialect.cpp b/test/unittest/quir-dialect.cpp index 0264b0d82..c3110bcb0 100644 --- a/test/unittest/quir-dialect.cpp +++ b/test/unittest/quir-dialect.cpp @@ -16,9 +16,18 @@ #include "Dialect/QUIR/IR/QUIRDialect.h" #include "Dialect/QUIR/IR/QUIROps.h" +#include "Dialect/QUIR/IR/QUIRTraits.h" +#include "Dialect/QUIR/IR/QUIRTypes.h" #include "Dialect/QUIR/Utils/Utils.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/DialectRegistry.h" +#include "mlir/IR/Location.h" +#include "mlir/IR/MLIRContext.h" +#include "mlir/IR/ValueRange.h" #include "mlir/Interfaces/SideEffectInterfaces.h" +#include "mlir/Support/LLVM.h" #include "gtest/gtest.h" @@ -83,7 +92,7 @@ TEST_F(QUIRDialect, MeasureSideEffects) { builder.getIntegerAttr(builder.getI32Type(), 0)); auto measureOp = builder.create( - unkownLoc, builder.getI1Type(), qubitDecl.res()); + unkownLoc, builder.getI1Type(), qubitDecl.getRes()); EXPECT_TRUE(measureOp); diff --git a/tools/qss-opt/qss-opt.cpp b/tools/qss-opt/qss-opt.cpp index 627c64665..2bf7477b6 100644 --- a/tools/qss-opt/qss-opt.cpp +++ b/tools/qss-opt/qss-opt.cpp @@ -20,123 +20,86 @@ // //===----------------------------------------------------------------------===// +#include "Dialect/RegisterDialects.h" +#include "Dialect/RegisterPasses.h" +#include "HAL/TargetSystemRegistry.h" +#include "Payload/PayloadRegistry.h" + +#include "mlir/Debug/Counter.h" #include "mlir/IR/AsmState.h" -#include "mlir/IR/Dialect.h" +#include "mlir/IR/DialectRegistry.h" #include "mlir/IR/MLIRContext.h" -#include "mlir/InitAllDialects.h" -#include "mlir/InitAllPasses.h" +#include "mlir/InitAllExtensions.h" #include "mlir/Pass/PassManager.h" #include "mlir/Support/FileUtilities.h" -#include "mlir/Support/MlirOptMain.h" +#include "mlir/Support/LogicalResult.h" +#include "mlir/Support/Timing.h" +#include "mlir/Tools/mlir-opt/MlirOptMain.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Error.h" #include "llvm/Support/InitLLVM.h" +#include "llvm/Support/Process.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/raw_ostream.h" -#include "HAL/PassRegistration.h" -#include "HAL/TargetSystemRegistry.h" - -#include "Payload/PayloadRegistry.h" - -#include "Dialect/OQ3/IR/OQ3Dialect.h" -#include "Dialect/OQ3/Transforms/Passes.h" -#include "Dialect/Pulse/IR/PulseDialect.h" -#include "Dialect/Pulse/Transforms/Passes.h" -#include "Dialect/QCS/IR/QCSDialect.h" -#include "Dialect/QCS/Utils/ParameterInitialValueAnalysis.h" -#include "Dialect/QUIR/IR/QUIRDialect.h" -#include "Dialect/QUIR/Transforms/Passes.h" +#include +#include +#include // NOLINT: fileno is not in cstdio as suggested +#include +#include +#include +using namespace qssc; using namespace qssc::hal; -static llvm::cl::opt configurationPath( +namespace { +const std::string toolName = "qss-opt"; + +llvm::cl::opt configurationPath( "config", llvm::cl::desc("Path to configuration file or directory (depends on the " "target), - means use the config service"), llvm::cl::value_desc("path")); -static llvm::cl::opt +llvm::cl::opt targetStr("target", llvm::cl::desc( "Target architecture. Required for machine code generation."), llvm::cl::value_desc("targetName")); -static llvm::cl::opt +llvm::cl::opt addTargetPasses("add-target-passes", llvm::cl::desc("Add target-specific passes"), llvm::cl::init(false)); -static llvm::cl::opt inputFilename(llvm::cl::Positional, - llvm::cl::desc(""), - llvm::cl::init("-")); - -static llvm::cl::opt - outputFilename("o", llvm::cl::desc("Output filename"), - llvm::cl::value_desc("filename"), llvm::cl::init("-")); +llvm::cl::opt inputFilename(llvm::cl::Positional, + llvm::cl::desc(""), + llvm::cl::init("-")); -static llvm::cl::opt splitInputFile( - "split-input-file", - llvm::cl::desc("Split the input file into pieces and process each " - "chunk independently, delimited by '// -----'"), - llvm::cl::init(false)); +llvm::cl::opt outputFilename("o", + llvm::cl::desc("Output filename"), + llvm::cl::value_desc("filename"), + llvm::cl::init("-")); -static llvm::cl::opt verifyDiagnostics( - "verify-diagnostics", - llvm::cl::desc("Check that emitted diagnostics match " - "expected-* lines on the corresponding line"), - llvm::cl::init(false)); +} // anonymous namespace -static llvm::cl::opt verifyPasses( - "verify-each", - llvm::cl::desc("Run the verifier after each transformation pass"), - llvm::cl::init(true)); - -static llvm::cl::opt allowUnregisteredDialects( - "allow-unregistered-dialect", - llvm::cl::desc("Allow operation with no registered dialects"), - llvm::cl::init(false)); - -auto main(int argc, char **argv) -> int { - mlir::registerAllPasses(); - mlir::registerConversionPasses(); - mlir::oq3::registerOQ3Passes(); - mlir::oq3::registerOQ3PassPipeline(); - mlir::qcs::registerQCSPasses(); - mlir::quir::registerQuirPasses(); - mlir::quir::registerQuirPassPipeline(); - mlir::pulse::registerPulsePasses(); - mlir::pulse::registerPulsePassPipeline(); - - if (auto err = registerTargetPasses()) { - llvm::errs() << err; - return 1; - } - - if (auto err = registerTargetPipelines()) { - llvm::errs() << err; - return 1; - } - - mlir::DialectRegistry registry; - // Add the following to include *all* MLIR Core dialects, or selectively - // include what you need like above. You only need to register dialects that - // will be *parsed* by the tool, not the one generated - registerAllDialects(registry); - registry.insert(); - - llvm::InitLLVM y(argc, argv); +llvm::Expected> +registerAndParseCLIOptions(int argc, char **argv, llvm::StringRef toolName, + mlir::DialectRegistry ®istry) { // Register any command line options. + mlir::MlirOptMainConfig::registerCLOptions(registry); mlir::registerAsmPrinterCLOptions(); mlir::registerMLIRContextCLOptions(); mlir::registerPassManagerCLOptions(); - mlir::PassPipelineCLParser passPipeline("", "Compiler passes to run"); + mlir::registerDefaultTimingManagerCLOptions(); + mlir::tracing::DebugCounter::registerCLOptions(); // Build the list of dialects as a header for the --help message. - std::string helpHeader = "qss-opt\n"; + std::string helpHeader = (toolName + "\n").str(); { llvm::raw_string_ostream os(helpHeader); os << "Available Dialects: "; @@ -161,16 +124,18 @@ auto main(int argc, char **argv) -> int { // Parse pass names in main to ensure static initialization completed. llvm::cl::ParseCommandLineOptions(argc, argv, helpHeader); + // The below must be performed after CL parsing + // Create target if one was specified. if (!targetStr.empty()) { auto targetInfo = registry::TargetSystemRegistry::lookupPluginInfo(targetStr); - if (!targetInfo) { - llvm::errs() << "Error: Target " + targetStr + " is not registered.\n"; - return 1; - } + if (!targetInfo) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Error: Target " + targetStr + + " is not registered.\n"); - llvm::Optional conf{}; + std::optional conf{}; if (!configurationPath.empty()) conf.emplace(configurationPath); @@ -179,32 +144,83 @@ auto main(int argc, char **argv) -> int { // TargetInfo::getTarget. // We do this only because MlirOptMain does not expose the MLIRContext // it creates for us. - if (!targetInfo.getValue()->createTarget(nullptr, conf)) { - llvm::errs() << "Error: Target " + targetStr + " could not be created.\n"; - return 1; - } + if (!targetInfo.value()->createTarget(nullptr, conf)) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Error: Target " + targetStr + + " could not be created.\n"); } + return std::make_pair(inputFilename.getValue(), outputFilename.getValue()); +} + +mlir::LogicalResult QSSCOptMain(int argc, char **argv, + llvm::StringRef inputFilename, + llvm::StringRef outputFilename, + mlir::DialectRegistry ®istry) { + + llvm::InitLLVM const y(argc, argv); + + mlir::MlirOptMainConfig const config = + mlir::MlirOptMainConfig::createFromCLOptions(); + + // When reading from stdin and the input is a tty, it is often a user mistake + // and the process "appears to be stuck". Print a message to let the user know + // about it! + if (inputFilename == "-" && + llvm::sys::Process::FileDescriptorIsDisplayed(fileno(stdin))) + llvm::errs() << "(processing input from stdin now, hit ctrl-c/ctrl-d to " + "interrupt)\n"; + // Set up the input file. std::string errorMessage; auto file = mlir::openInputFile(inputFilename, &errorMessage); if (!file) { llvm::errs() << errorMessage << "\n"; - return 1; + return mlir::failure(); } auto output = mlir::openOutputFile(outputFilename, &errorMessage); if (!output) { llvm::errs() << errorMessage << "\n"; - return 1; + return mlir::failure(); } - if (failed(mlir::MlirOptMain(output->os(), std::move(file), passPipeline, - registry, splitInputFile, verifyDiagnostics, - verifyPasses, allowUnregisteredDialects, false))) - return 1; + if (mlir::failed( + mlir::MlirOptMain(output->os(), std::move(file), registry, config))) + return mlir::failure(); // Keep the output file if the invocation of MlirOptMain was successful. output->keep(); + return mlir::success(); +} + +auto main(int argc, char **argv) -> int { + + // Register the standard passes with MLIR. + // Must precede the command line parsing. + if (auto err = qssc::dialect::registerPasses()) { + llvm::errs() << err << "\n"; + return 1; + } + + mlir::DialectRegistry registry; + qssc::dialect::registerDialects(registry); + mlir::registerAllExtensions(registry); + + // Register and parse command line options. + std::string inputFilename, outputFilename; + auto expectedFileNames = + registerAndParseCLIOptions(argc, argv, toolName, registry); + if (auto err = expectedFileNames.takeError()) { + llvm::errs() << err << "\n"; + return 1; + } + + std::tie(inputFilename, outputFilename) = expectedFileNames.get(); + + if (mlir::failed( + QSSCOptMain(argc, argv, inputFilename, outputFilename, registry))) + return 1; + return 0; }