From 35c240a6d62648c2dea61eef1b67a3b6138a31a3 Mon Sep 17 00:00:00 2001 From: Anatol Bussejahn Date: Mon, 27 Apr 2026 22:52:27 +0200 Subject: [PATCH 01/48] =?UTF-8?q?=E2=9C=A8=20Add=20translation=20for=20QAS?= =?UTF-8?q?M3=20->=20QC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QC/Translation/TranslateQASM3ToQC.h | 35 + .../lib/Dialect/QC/Translation/CMakeLists.txt | 4 +- .../QC/Translation/TranslateQASM3ToQC.cpp | 1136 +++++++++++++++++ mlir/tools/mqt-cc/mqt-cc.cpp | 20 +- 4 files changed, 1189 insertions(+), 6 deletions(-) create mode 100644 mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h create mode 100644 mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp diff --git a/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h b/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h new file mode 100644 index 0000000000..b178c027c9 --- /dev/null +++ b/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 - 2026 Chair for Design Automation, TUM + * Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH + * All rights reserved. + * + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License + */ + +#pragma once + +#include +#include +#include + +#include +#include + +namespace mlir::qc { + +/** + * @brief Import a QASM3 program directly into the QC dialect. + * + * @details Bypasses qc::QuantumComputation: the parser produces an AST walked + * by an InstVisitor that emits QC dialect ops via QCProgramBuilder. + * Returns nullptr on failure (diagnostics written to llvm::errs()). + */ +[[nodiscard]] OwningOpRef +translateQASM3ToQC(MLIRContext* context, const std::string& filename); + +[[nodiscard]] OwningOpRef translateQASM3ToQC(MLIRContext* context, + std::istream& input); + +} // namespace mlir::qc diff --git a/mlir/lib/Dialect/QC/Translation/CMakeLists.txt b/mlir/lib/Dialect/QC/Translation/CMakeLists.txt index a514f33df6..c1d403de3a 100644 --- a/mlir/lib/Dialect/QC/Translation/CMakeLists.txt +++ b/mlir/lib/Dialect/QC/Translation/CMakeLists.txt @@ -9,13 +9,15 @@ add_mlir_library( MLIRQCTranslation TranslateQuantumComputationToQC.cpp + TranslateQASM3ToQC.cpp LINK_LIBS MLIRArithDialect MLIRFuncDialect MLIRSCFDialect MLIRQCDialect MLIRQCProgramBuilder - MQT::CoreIR) + MQT::CoreIR + MQT::CoreQASM) mqt_mlir_target_use_project_options(MLIRQCTranslation) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp new file mode 100644 index 0000000000..b3f0269da6 --- /dev/null +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -0,0 +1,1136 @@ +/* + * Copyright (c) 2023 - 2026 Chair for Design Automation, TUM + * Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH + * All rights reserved. + * + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License + */ + +#include "mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h" + +#include "ir/Definitions.hpp" +#include "ir/operations/IfElseOperation.hpp" +#include "mlir/Dialect/QC/Builder/QCProgramBuilder.h" +#include "mlir/Dialect/QC/IR/QCOps.h" +#include "qasm3/Exception.hpp" +#include "qasm3/Gate.hpp" +#include "qasm3/InstVisitor.hpp" +#include "qasm3/NestedEnvironment.hpp" +#include "qasm3/Parser.hpp" +#include "qasm3/Statement.hpp" +#include "qasm3/StdGates.hpp" +#include "qasm3/Types.hpp" +#include "qasm3/passes/ConstEvalPass.hpp" +#include "qasm3/passes/TypeCheckPass.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mlir::qc { + +namespace { + +//===----------------------------------------------------------------------===// +// Gate dispatch table +//===----------------------------------------------------------------------===// + +/// Signature: (builder, gate-operands, evaluated-parameters). +/// For gates with implicit controls (cx, ccx, ...) all qubits including +/// the controls are in the qubits array, matching QASM3 operand order. +using GateFn = std::function, + llvm::ArrayRef)>; + +/** + * Build the static gate-name → GateFn dispatch table. + * Each entry maps a QASM3 gate identifier to a lambda that emits the + * corresponding QC dialect op via QCProgramBuilder. + */ +static llvm::StringMap buildGateDispatch() { + llvm::StringMap d; + + // 0-target, 1-param + d["gphase"] = [](auto& b, auto /*q*/, auto p) { b.gphase(p[0]); }; + + // 1-target, 0-param + d["id"] = [](auto& b, auto q, auto) { b.id(q[0]); }; + d["x"] = [](auto& b, auto q, auto) { b.x(q[0]); }; + d["y"] = [](auto& b, auto q, auto) { b.y(q[0]); }; + d["z"] = [](auto& b, auto q, auto) { b.z(q[0]); }; + d["h"] = [](auto& b, auto q, auto) { b.h(q[0]); }; + d["s"] = [](auto& b, auto q, auto) { b.s(q[0]); }; + d["sdg"] = [](auto& b, auto q, auto) { b.sdg(q[0]); }; + d["t"] = [](auto& b, auto q, auto) { b.t(q[0]); }; + d["tdg"] = [](auto& b, auto q, auto) { b.tdg(q[0]); }; + d["sx"] = [](auto& b, auto q, auto) { b.sx(q[0]); }; + d["sxdg"] = [](auto& b, auto q, auto) { b.sxdg(q[0]); }; + + // 1-target, 1-param + d["rx"] = [](auto& b, auto q, auto p) { b.rx(p[0], q[0]); }; + d["ry"] = [](auto& b, auto q, auto p) { b.ry(p[0], q[0]); }; + d["rz"] = [](auto& b, auto q, auto p) { b.rz(p[0], q[0]); }; + d["p"] = [](auto& b, auto q, auto p) { b.p(p[0], q[0]); }; + d["u1"] = [](auto& b, auto q, auto p) { b.p(p[0], q[0]); }; // alias + d["phase"] = [](auto& b, auto q, auto p) { b.p(p[0], q[0]); }; // alias + + // 1-target, 2-param + d["r"] = [](auto& b, auto q, auto p) { b.r(p[0], p[1], q[0]); }; + d["u2"] = [](auto& b, auto q, auto p) { b.u2(p[0], p[1], q[0]); }; + + // 1-target, 3-param + d["U"] = [](auto& b, auto q, auto p) { b.u(p[0], p[1], p[2], q[0]); }; + d["u3"] = [](auto& b, auto q, auto p) { + b.u(p[0], p[1], p[2], q[0]); + }; // alias + d["u"] = [](auto& b, auto q, auto p) { + b.u(p[0], p[1], p[2], q[0]); + }; // alias + + // 1-ctrl + 1-target, 0-param (q[0]=ctrl, q[1]=target) + d["cx"] = [](auto& b, auto q, auto) { b.cx(q[0], q[1]); }; + d["cnot"] = [](auto& b, auto q, auto) { b.cx(q[0], q[1]); }; // alias + d["cy"] = [](auto& b, auto q, auto) { b.cy(q[0], q[1]); }; + d["cz"] = [](auto& b, auto q, auto) { b.cz(q[0], q[1]); }; + d["ch"] = [](auto& b, auto q, auto) { b.ch(q[0], q[1]); }; + d["csx"] = [](auto& b, auto q, auto) { b.csx(q[0], q[1]); }; + + // 1-ctrl + 1-target, 1-param + d["crx"] = [](auto& b, auto q, auto p) { b.crx(p[0], q[0], q[1]); }; + d["cry"] = [](auto& b, auto q, auto p) { b.cry(p[0], q[0], q[1]); }; + d["crz"] = [](auto& b, auto q, auto p) { b.crz(p[0], q[0], q[1]); }; + d["cp"] = [](auto& b, auto q, auto p) { b.cp(p[0], q[0], q[1]); }; + d["cphase"] = [](auto& b, auto q, auto p) { + b.cp(p[0], q[0], q[1]); + }; // alias + + // 2-ctrl + 1-target, 0-param (q[0],q[1]=ctrl, q[2]=target) + d["ccx"] = [](auto& b, auto q, auto) { b.mcx({q[0], q[1]}, q[2]); }; + d["toffoli"] = [](auto& b, auto q, auto) { + b.mcx({q[0], q[1]}, q[2]); + }; // alias + d["ccz"] = [](auto& b, auto q, auto) { b.mcz({q[0], q[1]}, q[2]); }; + + // 2-target, 0-param + d["swap"] = [](auto& b, auto q, auto) { b.swap(q[0], q[1]); }; + d["iswap"] = [](auto& b, auto q, auto) { b.iswap(q[0], q[1]); }; + d["dcx"] = [](auto& b, auto q, auto) { b.dcx(q[0], q[1]); }; + d["ecr"] = [](auto& b, auto q, auto) { b.ecr(q[0], q[1]); }; + + // 1-ctrl + 2-target, 0-param (q[0]=ctrl, q[1],q[2]=targets) + d["cswap"] = [](auto& b, auto q, auto) { b.cswap(q[0], q[1], q[2]); }; + d["fredkin"] = [](auto& b, auto q, auto) { + b.cswap(q[0], q[1], q[2]); + }; // alias + + // 2-target, 2-param + d["xx_plus_yy"] = [](auto& b, auto q, auto p) { + b.xx_plus_yy(p[0], p[1], q[0], q[1]); + }; + d["xx_minus_yy"] = [](auto& b, auto q, auto p) { + b.xx_minus_yy(p[0], p[1], q[0], q[1]); + }; + + // 2-target, 1-param + d["rxx"] = [](auto& b, auto q, auto p) { b.rxx(p[0], q[0], q[1]); }; + d["ryy"] = [](auto& b, auto q, auto p) { b.ryy(p[0], q[0], q[1]); }; + d["rzx"] = [](auto& b, auto q, auto p) { b.rzx(p[0], q[0], q[1]); }; + d["rzz"] = [](auto& b, auto q, auto p) { b.rzz(p[0], q[0], q[1]); }; + + // MCX variants: q[0..N-2] are controls, q[N-1] is the target. + // These are not in stdgates.inc but are widely used (Qiskit-style). + auto mcxFn = [](auto& b, auto q, auto) { b.mcx(q.drop_back(1), q.back()); }; + d["mcx"] = mcxFn; + d["mcx_gray"] = mcxFn; + d["mcphase"] = [](auto& b, auto q, auto p) { + b.mcp(p[0], q.drop_back(1), q.back()); + }; + // vchain/recursive carry ancilla qubits; strip them using Qiskit's formula + d["mcx_vchain"] = [](auto& b, auto q, auto) { + const size_t n = q.size() - ((q.size() + 1) / 2) + 2; + b.mcx(q.slice(0, n - 1), q[n - 1]); + }; + d["mcx_recursive"] = [](auto& b, auto q, auto) { + const size_t n = (q.size() > 5) ? q.size() - 1 : q.size(); + b.mcx(q.slice(0, n - 1), q[n - 1]); + }; + + return d; +} + +/// Static gate dispatch table, built once at startup. +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) +static const llvm::StringMap GATE_DISPATCH = buildGateDispatch(); + +//===----------------------------------------------------------------------===// +// MLIRQasmImporter +//===----------------------------------------------------------------------===// + +/// Local qubit scope used during compound gate body expansion. +/// Maps argument name → vector of MLIR qubit Values. +using QubitScope = llvm::StringMap>; + +/** AST visitor that translates a QASM3 program directly into the QC dialect. + * + * Implements qasm3::InstVisitor to walk the AST produced by qasm3::Parser and + * emit QC dialect ops via QCProgramBuilder, bypassing qc::QuantumComputation. + * Const-evaluation and type-checking passes run in lock-step with the walk. + */ +class MLIRQasmImporter final : public qasm3::InstVisitor { +public: + explicit MLIRQasmImporter(MLIRContext* ctx) + : builder(ctx), typeCheckPass(constEvalPass), + gates(qasm3::STANDARD_GATES) { + initBuiltins(); + builder.initialize(); + } + + void + visitProgram(const std::vector>& program) { + for (const auto& stmt : program) { + constEvalPass.processStatement(*stmt); + typeCheckPass.processStatement(*stmt); + stmt->accept(this); + } + } + + OwningOpRef finalize() { return builder.finalize(); } + +private: + QCProgramBuilder builder; + qasm3::const_eval::ConstEvalPass constEvalPass; + qasm3::type_checking::TypeCheckPass typeCheckPass; + qasm3::NestedEnvironment> + declarations; + + /// Top-level qubit registers: register name → SSA Values + QubitScope qubitRegisters; + + /// Classical bit registers: register name → ClassicalRegister + llvm::StringMap classicalRegisters; + + /// Measurement result tracking: register name → vector of i1 Values. + /// Updated each time a measure is emitted. Used for if/else conditions. + llvm::StringMap> bitValues; + + /// Gate library: standard gates + user-defined compound gates + std::map> gates; + + bool openQASM2CompatMode{false}; + + //===--- Initialization -----------------------------------------------===// + + /// Seed the const-eval and type-check passes with QASM3 built-in constants + /// (pi, euler, tau) and prime the type environment with their types. + void initBuiltins() { + using namespace qasm3::const_eval; + using namespace qasm3::type_checking; + auto floatTy = InferredType{std::dynamic_pointer_cast( + std::make_shared>(qasm3::Float, 64))}; + + auto addConstant = [&](const std::string& name, double val) { + constEvalPass.addConst(name, ConstEvalValue(val)); + typeCheckPass.addBuiltin(name, floatTy); + }; + + addConstant("pi", ::qc::PI); + addConstant("π", ::qc::PI); + addConstant("tau", ::qc::TAU); + addConstant("τ", ::qc::TAU); + addConstant("euler", ::qc::E); + addConstant("ℇ", ::qc::E); + + // MCX variants: not in OQ3 stdlib, variable qubit arity. + // GateInfo fields are not arity-checked for StandardGate in this importer; + // the GATE_DISPATCH lambdas handle the variable-arity logic at call time. + const qasm3::GateInfo mcxInfo{.nControls = 0, + .nTargets = 0, + .nParameters = 0, + .type = ::qc::OpType::X}; + const qasm3::GateInfo mcphaseInfo{.nControls = 0, + .nTargets = 0, + .nParameters = 1, + .type = ::qc::OpType::P}; + gates["mcx"] = std::make_shared(mcxInfo); + gates["mcx_gray"] = std::make_shared(mcxInfo); + gates["mcx_vchain"] = std::make_shared(mcxInfo); + gates["mcx_recursive"] = std::make_shared(mcxInfo); + gates["mcphase"] = std::make_shared(mcphaseInfo); + } + + //===--- InstVisitor overrides ----------------------------------------===// + + void visitVersionDeclaration(const std::shared_ptr + versionDeclaration) override { + if (versionDeclaration->version < 3) { + openQASM2CompatMode = true; + } + } + + void visitDeclarationStatement( + std::shared_ptr stmt) override { + const auto& id = stmt->identifier; + if (declarations.find(id).has_value()) { + throw qasm3::CompilerError("Identifier '" + id + "' already declared.", + stmt->debugInfo); + } + declarations.emplace(id, stmt); + + const auto ty = std::get<1>(stmt->type); + const auto sizedTy = + std::dynamic_pointer_cast>(ty); + if (!sizedTy) { + throw qasm3::CompilerError("Only sized types are supported.", + stmt->debugInfo); + } + const auto size = static_cast(sizedTy->getDesignator()); + + switch (sizedTy->type) { + case qasm3::Qubit: { + auto reg = builder.allocQubitRegister(size); + llvm::SmallVector qubits; + qubits.reserve(static_cast(size)); + for (int64_t i = 0; i < size; ++i) { + qubits.push_back(reg[static_cast(i)]); + } + qubitRegisters[id] = std::move(qubits); + break; + } + case qasm3::Bit: + case qasm3::Int: + case qasm3::Uint: { + classicalRegisters[id] = builder.allocClassicalBitRegister(size, id); + break; + } + default: + break; + } + + // Handle initializer (measure only) + if (stmt->expression) { + const auto& expr = stmt->expression->expression; + if (const auto measureExpr = + std::dynamic_pointer_cast(expr)) { + auto lhsId = std::make_shared(id); + visitMeasureAssignment(lhsId, measureExpr, stmt->debugInfo); + return; + } + if (stmt->isConst) { + return; // nothing to emit + } + throw qasm3::CompilerError( + "Only measure statements are supported as initializers.", + stmt->debugInfo); + } + } + + void visitAssignmentStatement( + std::shared_ptr stmt) override { + const auto& id = stmt->identifier->identifier; + assert(declarations.find(id).has_value() && "Checked by type check pass"); + assert(!declarations.find(id)->get()->isConst && + "Checked by type check pass"); + + const auto& expr = stmt->expression->expression; + if (const auto measureExpr = + std::dynamic_pointer_cast(expr)) { + visitMeasureAssignment(stmt->identifier, measureExpr, stmt->debugInfo); + return; + } + + // TODO: In the future, handle classical computation. + throw qasm3::CompilerError("Classical computation not yet supported.", + stmt->debugInfo); + } + + void + visitGateStatement(std::shared_ptr stmt) override { + auto id = stmt->identifier; + if (stmt->isOpaque) { + if (gates.find(id) == gates.end()) { + throw qasm3::CompilerError("Unsupported opaque gate '" + id + "'.", + stmt->debugInfo); + } + return; + } + if (gates.count(id) != 0U) { + if (std::dynamic_pointer_cast(gates[id])) { + return; // ignore redeclaration of standard gate + } + throw qasm3::CompilerError("Gate '" + id + "' already declared.", + stmt->debugInfo); + } + std::vector paramNames; + for (const auto& p : stmt->parameters->identifiers) { + if (std::ranges::find(paramNames, p->identifier) != paramNames.end()) { + throw qasm3::CompilerError("Parameter '" + p->identifier + + "' already declared in gate '" + id + + "'.", + stmt->debugInfo); + } + paramNames.push_back(p->identifier); + } + std::vector qubitNames; + for (const auto& q : stmt->qubits->identifiers) { + if (std::ranges::find(qubitNames, q->identifier) != qubitNames.end()) { + throw qasm3::CompilerError("Qubit '" + q->identifier + + "' already declared in gate '" + id + + "'.", + stmt->debugInfo); + } + qubitNames.push_back(q->identifier); + } + gates[id] = std::make_shared( + std::move(paramNames), std::move(qubitNames), stmt->statements); + } + + void visitGateCallStatement( + std::shared_ptr stmt) override { + applyGateCallStatement(stmt, qubitRegisters); + } + + /** Emit measure ops for \p target = measure \p measureExpr. + * Handles both full-register and single-bit assignments; wires measure + * results into the classical register's bit-value map for later use. + */ + void visitMeasureAssignment( + const std::shared_ptr& target, + const std::shared_ptr& measureExpr, + const std::shared_ptr& debugInfo) { + auto qubits = resolveGateOperand(measureExpr->gate, debugInfo); + auto bits = resolveClassicalBits(target, debugInfo); + if (qubits.size() != bits.size()) { + throw qasm3::CompilerError( + "Classical and quantum registers must have the same width in measure " + "statement. Classical register '" + + target->identifier + "' has " + std::to_string(bits.size()) + + " bits, but quantum register '" + measureExpr->gate->getName() + + "' has " + std::to_string(qubits.size()) + " qubits.", + debugInfo); + } + for (size_t i = 0; i < qubits.size(); ++i) { + // Use the MeasureOp directly to capture the i1 result for if/else + auto measureOp = MeasureOp::create( + builder, qubits[i], builder.getStringAttr(bits[i].registerName), + builder.getI64IntegerAttr(bits[i].registerSize), + builder.getI64IntegerAttr(bits[i].registerIndex)); + Value result = measureOp.getResult(); + + // Track the result for use in if/else conditions + const auto& regName = bits[i].registerName; + auto& regBits = bitValues[regName]; + const auto idx = static_cast(bits[i].registerIndex); + if (regBits.size() <= idx) { + regBits.resize(idx + 1); + } + regBits[idx] = result; + } + } + + void visitBarrierStatement( + std::shared_ptr stmt) override { + llvm::SmallVector qubits; + for (const auto& gate : stmt->gates) { + auto resolved = resolveGateOperand(gate, stmt->debugInfo); + qubits.append(resolved.begin(), resolved.end()); + } + builder.barrier(qubits); + } + + void + visitResetStatement(std::shared_ptr stmt) override { + for (auto q : resolveGateOperand(stmt->gate, stmt->debugInfo)) { + builder.reset(q); + } + } + + void visitIfStatement(std::shared_ptr stmt) override { + if (stmt->thenStatements.empty() && stmt->elseStatements.empty()) { + return; + } + + Value condition = translateCondition(stmt->condition, stmt->debugInfo); + const bool hasElse = !stmt->elseStatements.empty(); + + auto ifOp = + scf::IfOp::create(builder, condition, /*withElseRegion=*/hasElse); + + // Then block + builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); + emitBlockStatements(stmt->thenStatements, stmt->debugInfo); + + // Else block + if (hasElse) { + builder.setInsertionPointToStart(&ifOp.getElseRegion().front()); + emitBlockStatements(stmt->elseStatements, stmt->debugInfo); + } + + // Restore insertion point after the if op + builder.setInsertionPointAfter(ifOp); + } + + void + visitInitialLayout(std::shared_ptr layout) override { + throw qasm3::CompilerError( + "Initial layout pragmas are not supported in direct MLIR import.", + layout->debugInfo); + } + + void visitOutputPermutation( + std::shared_ptr perm) override { + throw qasm3::CompilerError( + "Output permutation pragmas are not supported in direct MLIR import.", + perm->debugInfo); + } + + //===--- Core gate application ----------------------------------------===// + + /// Apply a gate call statement, resolving qubits from \p scope. + /// For top-level calls pass \p qubitRegisters; for compound gate bodies + /// pass the local argument scope. + void + applyGateCallStatement(const std::shared_ptr& stmt, + const QubitScope& scope) { + const auto& id = stmt->identifier; + + auto it = gates.find(id); + // `resolvedId` may differ from `id` when OQ2 compat strips 'c' prefixes. + std::string resolvedId = id; + size_t implicitCompatControls = 0; + + // OQ2 compat mode: strip leading 'c' prefixes and treat each as + // an additional positive control. E.g. "cmygate q0, q1" with compat on + // becomes ctrl @ mygate q0, q1 when "mygate" is in the gate library. + if (it == gates.end() && openQASM2CompatMode) { + while (!resolvedId.empty() && resolvedId.front() == 'c') { + resolvedId = resolvedId.substr(1); + ++implicitCompatControls; + } + if (implicitCompatControls > 0) { + it = gates.find(resolvedId); + } + } + if (it == gates.end()) { + throw qasm3::CompilerError("Unknown gate '" + id + "'.", stmt->debugInfo); + } + + // Evaluate parameters to doubles + std::vector params; + params.reserve(stmt->arguments.size()); + for (const auto& arg : stmt->arguments) { + auto result = constEvalPass.visit(arg); + if (!result.has_value()) { + throw qasm3::CompilerError( + "Gate parameter could not be const-evaluated.", stmt->debugInfo); + } + params.push_back(result->toExpr()->asFP()); + } + + // Parse modifiers: accumulate pos/neg controls and invert flag + bool invert = false; + size_t nModifierControls = 0; + // (count, isPositive) per ctrl modifier, in order + llvm::SmallVector> ctrlSpec; + for (const auto& mod : stmt->modifiers) { + if (std::dynamic_pointer_cast(mod)) { + invert = !invert; + } else if (const auto* ctrlMod = + dynamic_cast(mod.get())) { + const size_t n = + evaluatePositiveConstant(ctrlMod->expression, stmt->debugInfo, 1); + ctrlSpec.emplace_back(n, ctrlMod->ctrlType); + nModifierControls += n; + } else { + // TODO: add pow(n) support here once PowOp lands in main — detect + // qasm3::PowGateModifier, evaluate n, wrap gate emission in PowOp. + throw qasm3::CompilerError( + "Only ctrl/negctrl/inv modifiers are supported.", stmt->debugInfo); + } + } + + // Expand each operand to its qubit Values + std::vector> expandedOperands; + expandedOperands.reserve(stmt->operands.size()); + for (const auto& operand : stmt->operands) { + expandedOperands.push_back( + resolveGateOperandInScope(operand, scope, stmt->debugInfo)); + } + + // First nModifierControls slots are modifier-derived controls + llvm::SmallVector posControls; + llvm::SmallVector negControls; + size_t ctrlIdx = 0; + for (const auto& [n, positive] : ctrlSpec) { + for (size_t i = 0; i < n; ++i, ++ctrlIdx) { + if (expandedOperands[ctrlIdx].size() != 1) { + throw qasm3::CompilerError("Control operand must be a single qubit.", + stmt->debugInfo); + } + if (positive) { + posControls.push_back(expandedOperands[ctrlIdx][0]); + } else { + negControls.push_back(expandedOperands[ctrlIdx][0]); + } + } + } + + // OQ2 compat implicit controls follow modifier controls + for (size_t i = 0; i < implicitCompatControls; ++i, ++ctrlIdx) { + if (ctrlIdx >= expandedOperands.size() || + expandedOperands[ctrlIdx].size() != 1) { + throw qasm3::CompilerError( + "Implicit OQ2 control operand must be a single qubit.", + stmt->debugInfo); + } + posControls.push_back(expandedOperands[ctrlIdx][0]); + } + const size_t totalCtrlCount = nModifierControls + implicitCompatControls; + + // Remaining slots are the gate's own operands (may broadcast) + std::vector> gateOperands( + expandedOperands.begin() + static_cast(totalCtrlCount), + expandedOperands.end()); + + // Compound gate: inline expand + if (const auto* compound = + dynamic_cast(it->second.get())) { + applyCompoundGate(*compound, gateOperands, posControls, negControls, + params, invert, stmt->debugInfo); + return; + } + + // Standard gate: validate param count then determine broadcast width + if (it->second->getNParameters() != params.size()) { + throw qasm3::CompilerError( + "Gate '" + id + "' takes " + + std::to_string(it->second->getNParameters()) + + " parameters, but " + std::to_string(params.size()) + + " were supplied.", + stmt->debugInfo); + } + + // Standard gate: determine broadcast width + size_t broadcastWidth = 0; + for (const auto& ops : gateOperands) { + if (ops.size() > 1) { + if (broadcastWidth == 0) { + broadcastWidth = ops.size(); + } else if (broadcastWidth != ops.size()) { + throw qasm3::CompilerError( + "Broadcast operands must all have the same width.", + stmt->debugInfo); + } + } + } + if (broadcastWidth == 0) { + broadcastWidth = 1; + } + + const auto dispIt = GATE_DISPATCH.find(resolvedId); + if (dispIt == GATE_DISPATCH.end()) { + throw qasm3::CompilerError("No MLIR mapping for gate '" + id + "'.", + stmt->debugInfo); + } + + for (size_t b = 0; b < broadcastWidth; ++b) { + llvm::SmallVector iterQubits; + iterQubits.reserve(gateOperands.size()); + for (const auto& ops : gateOperands) { + iterQubits.push_back(ops.size() > 1 ? ops[b] : ops[0]); + } + + // Check that no qubit appears twice across targets and controls. + llvm::SmallDenseSet seen; + for (auto q : + llvm::concat(iterQubits, posControls, negControls)) { + if (!seen.insert(q).second) { + throw qasm3::CompilerError("Duplicate qubit in gate '" + id + + "' operands.", + stmt->debugInfo); + } + } + + emitGate(dispIt->second, iterQubits, params, posControls, negControls, + invert); + } + } + + /// Emit a single gate application, wrapping with ctrl/inv as needed. + void emitGate(const GateFn& gateFn, llvm::ArrayRef qubits, + llvm::ArrayRef params, + llvm::ArrayRef posControls, + llvm::ArrayRef negControls, bool invert) { + auto inner = [&] { gateFn(builder, qubits, params); }; + + auto withInv = [&] { + if (invert) { + builder.inv(llvm::function_ref(inner)); + } else { + inner(); + } + }; + + if (posControls.empty() && negControls.empty()) { + withInv(); + return; + } + + // Negative controls: X-bracket + for (auto q : negControls) { + builder.x(q); + } + llvm::SmallVector allControls(posControls.begin(), + posControls.end()); + allControls.append(negControls.begin(), negControls.end()); + builder.ctrl(allControls, llvm::function_ref(withInv)); + for (auto q : negControls) { + builder.x(q); + } + } + + /// Inline-expand a compound (user-defined) gate. + void + applyCompoundGate(const qasm3::CompoundGate& gate, + const std::vector>& gateOperands, + llvm::ArrayRef posControls, + llvm::ArrayRef negControls, + llvm::ArrayRef params, bool invert, + const std::shared_ptr& debugInfo) { + if (gate.targetNames.size() != gateOperands.size()) { + throw qasm3::CompilerError("Compound gate operand count mismatch.", + debugInfo); + } + if (gate.parameterNames.size() != params.size()) { + throw qasm3::CompilerError("Compound gate parameter count mismatch.", + debugInfo); + } + + // Build local scope: argument name → Values + QubitScope localScope; + for (size_t i = 0; i < gate.targetNames.size(); ++i) { + localScope[gate.targetNames[i]] = llvm::SmallVector( + gateOperands[i].begin(), gateOperands[i].end()); + } + + // Bind parameters as constants + constEvalPass.pushEnv(); + for (size_t i = 0; i < gate.parameterNames.size(); ++i) { + constEvalPass.addConst(gate.parameterNames[i], + qasm3::const_eval::ConstEvalValue(params[i])); + } + + auto bodyFn = [&] { + for (const auto& bodyStmt : gate.body) { + if (const auto gateCall = + std::dynamic_pointer_cast(bodyStmt)) { + applyGateCallStatement(gateCall, localScope); + } else if (const auto barrier = + std::dynamic_pointer_cast( + bodyStmt)) { + llvm::SmallVector qubits; + for (const auto& g : barrier->gates) { + auto resolved = + resolveGateOperandInScope(g, localScope, barrier->debugInfo); + qubits.append(resolved.begin(), resolved.end()); + } + builder.barrier(qubits); + } else if (const auto reset = + std::dynamic_pointer_cast( + bodyStmt)) { + for (auto q : resolveGateOperandInScope(reset->gate, localScope, + reset->debugInfo)) { + builder.reset(q); + } + } + } + }; + + auto withInv = [&] { + if (invert) { + builder.inv(llvm::function_ref(bodyFn)); + } else { + bodyFn(); + } + }; + + if (posControls.empty() && negControls.empty()) { + withInv(); + } else { + for (auto q : negControls) { + builder.x(q); + } + llvm::SmallVector allControls(posControls.begin(), + posControls.end()); + allControls.append(negControls.begin(), negControls.end()); + builder.ctrl(allControls, llvm::function_ref(withInv)); + for (auto q : negControls) { + builder.x(q); + } + } + + constEvalPass.popEnv(); + } + + //===--- If/else helpers ------------------------------------------------===// + + /// Emit quantum statements inside an if/else block. + void emitBlockStatements( + const std::vector>& statements, + const std::shared_ptr& debugInfo) { + for (const auto& statement : statements) { + auto gateCall = + std::dynamic_pointer_cast(statement); + if (gateCall == nullptr) { + throw qasm3::CompilerError( + "Only quantum statements are supported in if/else blocks.", + debugInfo); + } + applyGateCallStatement(gateCall, qubitRegisters); + } + } + + /// Translate a QASM3 condition expression to an i1 MLIR Value. + /// Supports: + /// - Single bit: `c[0]` or `!c[0]` / `~c[0]` + /// - Register comparison: `creg == N`, `creg != N`, etc. + [[nodiscard]] Value + translateCondition(const std::shared_ptr& condition, + const std::shared_ptr& debugInfo) { + // Case 1: Binary comparison (creg == N, creg != N, etc.) + if (const auto binaryExpr = + std::dynamic_pointer_cast(condition)) { + return translateBinaryCondition(binaryExpr, debugInfo); + } + + // Case 2: Unary negation (!c[0] or ~c[0]) + if (const auto unaryExpr = + std::dynamic_pointer_cast(condition)) { + assert(unaryExpr->op == qasm3::UnaryExpression::LogicalNot || + unaryExpr->op == qasm3::UnaryExpression::BitwiseNot); + const auto idExpr = std::dynamic_pointer_cast( + unaryExpr->operand); + Value bitVal = lookupBitValue(idExpr, debugInfo); + // Negate: XOR with true + Value trueVal = arith::ConstantOp::create( + builder, builder.getIntegerAttr(builder.getI1Type(), 1)); + return arith::XOrIOp::create(builder, bitVal, trueVal); + } + + // Case 3: Single bit (c[0] — truthy) + if (const auto idExpr = + std::dynamic_pointer_cast(condition)) { + return lookupBitValue(idExpr, debugInfo); + } + + throw qasm3::CompilerError( + "Unsupported condition expression in if statement.", debugInfo); + } + + /// Translate a binary comparison condition (creg == N, etc.) + [[nodiscard]] Value translateBinaryCondition( + const std::shared_ptr& binaryExpr, + const std::shared_ptr& debugInfo) { + const auto comparisonKind = qasm3::getComparisonKind(binaryExpr->op); + if (!comparisonKind) { + throw qasm3::CompilerError("Unsupported comparison operator.", debugInfo); + } + + // Determine which side is the identifier and which is the constant + auto lhsIsIdentifier = + std::dynamic_pointer_cast(binaryExpr->lhs); + + const auto& idExpr = + lhsIsIdentifier ? std::dynamic_pointer_cast( + binaryExpr->lhs) + : std::dynamic_pointer_cast( + binaryExpr->rhs); + const auto& constExpr = + lhsIsIdentifier + ? std::dynamic_pointer_cast(binaryExpr->rhs) + : std::dynamic_pointer_cast(binaryExpr->lhs); + + if (!idExpr || !constExpr) { + throw qasm3::CompilerError( + "Only classical registers and constants are supported in conditions.", + debugInfo); + } + + const auto& regName = idExpr->identifier; + const uint64_t expectedVal = constExpr->getUInt(); + + // Look up classical register to get its size + auto cregIt = classicalRegisters.find(regName); + if (cregIt == classicalRegisters.end()) { + throw qasm3::CompilerError("Unknown classical register '" + regName + + "' in condition.", + debugInfo); + } + const auto regSize = static_cast(cregIt->second.size); + + auto bitIt = bitValues.find(regName); + if (bitIt == bitValues.end()) { + throw qasm3::CompilerError( + "Classical register '" + regName + + "' has no measurement results to use in condition.", + debugInfo); + } + const auto& regBits = bitIt->second; + + const auto intWidth = std::max(regSize, static_cast(64)); + auto intTy = builder.getIntegerType(static_cast(intWidth)); + + // Indexed access (c[i] == N): compare the single bit directly + if (!idExpr->indices.empty()) { + const auto idx = evaluatePositiveConstant( + idExpr->indices[0]->indexExpressions[0], debugInfo); + if (idx >= regBits.size() || !regBits[idx]) { + throw qasm3::CompilerError( + "Bit " + std::to_string(idx) + " of register '" + regName + + "' was not measured before use in condition.", + debugInfo); + } + Value extended = arith::ExtUIOp::create(builder, intTy, regBits[idx]); + Value expected = arith::ConstantOp::create( + builder, builder.getIntegerAttr(intTy, expectedVal)); + auto pred = convertComparisonKind(*comparisonKind); + return arith::CmpIOp::create(builder, pred, extended, expected); + } + + // Full-register access (c == N): compose bits into an integer + // result = b0 | (b1 << 1) | (b2 << 2) | ... + Value composed = + arith::ConstantOp::create(builder, builder.getIntegerAttr(intTy, 0)); + + for (size_t i = 0; i < regSize; ++i) { + if (i >= regBits.size() || !regBits[i]) { + throw qasm3::CompilerError( + "Bit " + std::to_string(i) + " of register '" + regName + + "' was not measured before use in condition.", + debugInfo); + } + // Extend i1 to integer type + Value extended = arith::ExtUIOp::create(builder, intTy, regBits[i]); + if (i > 0) { + Value shiftAmt = arith::ConstantOp::create( + builder, builder.getIntegerAttr(intTy, i)); + extended = arith::ShLIOp::create(builder, extended, shiftAmt); + } + composed = arith::OrIOp::create(builder, composed, extended); + } + + // Compare + Value expectedConst = arith::ConstantOp::create( + builder, builder.getIntegerAttr(intTy, expectedVal)); + + auto pred = convertComparisonKind(*comparisonKind); + return arith::CmpIOp::create(builder, pred, composed, expectedConst); + } + + /// Look up the most recent measurement result for a single classical bit. + [[nodiscard]] Value + lookupBitValue(const std::shared_ptr& idExpr, + const std::shared_ptr& debugInfo) const { + const auto& regName = idExpr->identifier; + auto it = bitValues.find(regName); + if (it == bitValues.end()) { + throw qasm3::CompilerError( + "Classical register '" + regName + + "' has no measurement results to use in condition.", + debugInfo); + } + const auto& regBits = it->second; + + // Single bit — must be indexed + if (idExpr->indices.empty()) { + if (regBits.size() != 1) { + throw qasm3::CompilerError( + "Condition on full register '" + regName + + "' requires a comparison operator (e.g. creg == 0).", + debugInfo); + } + if (!regBits[0]) { + throw qasm3::CompilerError( + "Bit 0 of register '" + regName + + "' was not measured before use in condition.", + debugInfo); + } + return regBits[0]; + } + + const auto idx = evaluatePositiveConstant( + idExpr->indices[0]->indexExpressions[0], debugInfo); + if (idx >= regBits.size() || !regBits[idx]) { + throw qasm3::CompilerError( + "Bit " + std::to_string(idx) + " of register '" + regName + + "' was not measured before use in condition.", + debugInfo); + } + return regBits[idx]; + } + + /// Convert qc::ComparisonKind to arith::CmpIPredicate. + static arith::CmpIPredicate convertComparisonKind(::qc::ComparisonKind kind) { + switch (kind) { + case ::qc::ComparisonKind::Eq: + return arith::CmpIPredicate::eq; + case ::qc::ComparisonKind::Neq: + return arith::CmpIPredicate::ne; + case ::qc::ComparisonKind::Lt: + return arith::CmpIPredicate::ult; + case ::qc::ComparisonKind::Leq: + return arith::CmpIPredicate::ule; + case ::qc::ComparisonKind::Gt: + return arith::CmpIPredicate::ugt; + case ::qc::ComparisonKind::Geq: + return arith::CmpIPredicate::uge; + } + llvm_unreachable("unknown ComparisonKind"); + } + + //===--- Operand resolution helpers ------------------------------------===// + + /// Resolve a gate operand against the top-level qubit register map. + llvm::SmallVector + resolveGateOperand(const std::shared_ptr& operand, + const std::shared_ptr& debugInfo) { + return resolveGateOperandInScope(operand, qubitRegisters, debugInfo); + } + + /** Resolve a gate operand against \p scope (top-level registers or a + * compound-gate local argument scope). Returns the MLIR Values for the + * qubit(s) named by \p operand — a full register or a single indexed qubit. + */ + llvm::SmallVector resolveGateOperandInScope( + const std::shared_ptr& operand, + const QubitScope& scope, + const std::shared_ptr& debugInfo) { + if (operand->isHardwareQubit()) { + return {builder.staticQubit(operand->getHardwareQubit())}; + } + + const auto idExpr = operand->getIdentifier(); + const auto& name = idExpr->identifier; + + auto it = scope.find(name); + if (it == scope.end()) { + throw qasm3::CompilerError("Unknown qubit register '" + name + "'.", + debugInfo); + } + const auto& qubits = it->second; + + if (idExpr->indices.empty()) { + return qubits; // full register + } + + if (idExpr->indices.size() > 1) { + throw qasm3::CompilerError("Only single-index expressions are supported.", + debugInfo); + } + const auto& indexExpression = idExpr->indices[0]->indexExpressions[0]; + const auto idx = evaluatePositiveConstant(indexExpression, debugInfo); + if (idx >= qubits.size()) { + throw qasm3::CompilerError("Qubit index out of bounds.", debugInfo); + } + return {qubits[idx]}; + } + + /** Resolve \p target to a list of classical bits in a known register. + * Returns all bits for an unindexed identifier, or a single bit otherwise. + */ + std::vector resolveClassicalBits( + const std::shared_ptr& target, + const std::shared_ptr& debugInfo) const { + const auto& name = target->identifier; + auto it = classicalRegisters.find(name); + if (it == classicalRegisters.end()) { + throw qasm3::CompilerError("Unknown classical register '" + name + "'.", + debugInfo); + } + const auto& creg = it->second; + + std::vector bits; + if (target->indices.empty()) { + for (int64_t i = 0; i < creg.size; ++i) { + bits.push_back(creg[i]); + } + return bits; + } + const auto& indexExpression = target->indices[0]->indexExpressions[0]; + const auto idx = evaluatePositiveConstant(indexExpression, debugInfo); + bits.push_back(creg[idx]); + return bits; + } + + /// Evaluate \p expr as a non-negative integer constant. + /// Returns \p defaultValue if \p expr is null; throws on non-constant input. + static size_t + evaluatePositiveConstant(const std::shared_ptr& expr, + const std::shared_ptr& debugInfo, + size_t defaultValue = 0) { + if (!expr) { + return defaultValue; + } + const auto constVal = std::dynamic_pointer_cast(expr); + if (!constVal) { + throw qasm3::CompilerError("Expected a constant integer expression.", + debugInfo); + } + return static_cast(constVal->getUInt()); + } +}; + +} // namespace + +//===----------------------------------------------------------------------===// +// Public API +//===----------------------------------------------------------------------===// + +OwningOpRef translateQASM3ToQC(MLIRContext* context, + std::istream& input) { + try { + qasm3::Parser parser(input); + const auto program = parser.parseProgram(); + MLIRQasmImporter importer(context); + importer.visitProgram(program); + return importer.finalize(); + } catch (const qasm3::CompilerError& e) { + llvm::errs() << "QASM3 import error: " << e.what() << "\n"; + return nullptr; + } catch (const std::exception& e) { + llvm::errs() << "QASM3 import error: " << e.what() << "\n"; + return nullptr; + } +} + +OwningOpRef translateQASM3ToQC(MLIRContext* context, + const std::string& filename) { + std::ifstream file(filename); + if (!file.good()) { + llvm::errs() << "Could not open file '" << filename << "'\n"; + return nullptr; + } + return translateQASM3ToQC(context, file); +} + +} // namespace mlir::qc diff --git a/mlir/tools/mqt-cc/mqt-cc.cpp b/mlir/tools/mqt-cc/mqt-cc.cpp index 0781ed84e7..7522d052c2 100644 --- a/mlir/tools/mqt-cc/mqt-cc.cpp +++ b/mlir/tools/mqt-cc/mqt-cc.cpp @@ -11,6 +11,7 @@ #include "ir/QuantumComputation.hpp" #include "mlir/Compiler/CompilerPipeline.h" #include "mlir/Dialect/QC/IR/QCDialect.h" +#include "mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h" #include "mlir/Dialect/QC/Translation/TranslateQuantumComputationToQC.h" #include "mlir/Dialect/QCO/IR/QCODialect.h" #include "mlir/Dialect/QTensor/IR/QTensorDialect.h" @@ -86,15 +87,13 @@ static llvm::cl::opt enableHadamardLifting( llvm::cl::init(false)); /** - * @brief Load and parse a .qasm file + * @brief Load and parse a .qasm file via the legacy QuantumComputation path. */ -static OwningOpRef loadQASMFile(llvm::StringRef filename, - MLIRContext* context) { +static OwningOpRef loadQASMFileLegacy(llvm::StringRef filename, + MLIRContext* context) { try { - // Parse the input QASM file const ::qc::QuantumComputation qc = qasm3::Importer::importf(filename.str()); - // Translate to MLIR dialect QC return translateQuantumComputationToQC(context, qc); } catch (const qasm3::CompilerError& exception) { llvm::errs() << "Failed to parse QASM file '" << filename << "': '" @@ -106,6 +105,17 @@ static OwningOpRef loadQASMFile(llvm::StringRef filename, return nullptr; } +/** + * @brief Load and parse a .qasm file, dispatching to the chosen import path. + */ +static OwningOpRef loadQASMFile(StringRef filename, + MLIRContext* context) { + if (directImport) { + return mlir::qc::translateQASM3ToQC(context, filename.str()); + } + return loadQASMFileLegacy(filename, context); +} + /** * @brief Load and parse a .mlir file */ From dac020c680b8047e67fac0906834c0b19b8125bd Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Wed, 29 Apr 2026 13:06:39 +0200 Subject: [PATCH 02/48] Fix build error --- mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index b3f0269da6..cb057b9802 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -26,8 +26,8 @@ #include "qasm3/passes/TypeCheckPass.hpp" #include +#include #include -#include #include #include #include From 8036f1fca0568e803b1a5ec7bb98616652c1f052 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Wed, 29 Apr 2026 16:17:47 +0200 Subject: [PATCH 03/48] Adapt to new include style --- .../QC/Translation/TranslateQASM3ToQC.h | 1 - .../QC/Translation/TranslateQASM3ToQC.cpp | 71 +++++++++---------- 2 files changed, 33 insertions(+), 39 deletions(-) diff --git a/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h b/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h index b178c027c9..1923654d37 100644 --- a/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h +++ b/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h @@ -12,7 +12,6 @@ #include #include -#include #include #include diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index cb057b9802..4ae900ba88 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -25,10 +25,8 @@ #include "qasm3/passes/ConstEvalPass.hpp" #include "qasm3/passes/TypeCheckPass.hpp" -#include #include #include -#include #include #include #include @@ -37,6 +35,7 @@ #include #include #include +#include #include #include @@ -60,8 +59,8 @@ namespace { /// Signature: (builder, gate-operands, evaluated-parameters). /// For gates with implicit controls (cx, ccx, ...) all qubits including /// the controls are in the qubits array, matching QASM3 operand order. -using GateFn = std::function, - llvm::ArrayRef)>; +using GateFn = + std::function, ArrayRef)>; /** * Build the static gate-name → GateFn dispatch table. @@ -189,7 +188,7 @@ static const llvm::StringMap GATE_DISPATCH = buildGateDispatch(); /// Local qubit scope used during compound gate body expansion. /// Maps argument name → vector of MLIR qubit Values. -using QubitScope = llvm::StringMap>; +using QubitScope = llvm::StringMap>; /** AST visitor that translates a QASM3 program directly into the QC dialect. * @@ -232,7 +231,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { /// Measurement result tracking: register name → vector of i1 Values. /// Updated each time a measure is emitted. Used for if/else conditions. - llvm::StringMap> bitValues; + llvm::StringMap> bitValues; /// Gate library: standard gates + user-defined compound gates std::map> gates; @@ -309,7 +308,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { switch (sizedTy->type) { case qasm3::Qubit: { auto reg = builder.allocQubitRegister(size); - llvm::SmallVector qubits; + SmallVector qubits; qubits.reserve(static_cast(size)); for (int64_t i = 0; i < size; ++i) { qubits.push_back(reg[static_cast(i)]); @@ -450,7 +449,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { void visitBarrierStatement( std::shared_ptr stmt) override { - llvm::SmallVector qubits; + SmallVector qubits; for (const auto& gate : stmt->gates) { auto resolved = resolveGateOperand(gate, stmt->debugInfo); qubits.append(resolved.begin(), resolved.end()); @@ -551,7 +550,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { bool invert = false; size_t nModifierControls = 0; // (count, isPositive) per ctrl modifier, in order - llvm::SmallVector> ctrlSpec; + SmallVector> ctrlSpec; for (const auto& mod : stmt->modifiers) { if (std::dynamic_pointer_cast(mod)) { invert = !invert; @@ -570,7 +569,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } // Expand each operand to its qubit Values - std::vector> expandedOperands; + std::vector> expandedOperands; expandedOperands.reserve(stmt->operands.size()); for (const auto& operand : stmt->operands) { expandedOperands.push_back( @@ -578,8 +577,8 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } // First nModifierControls slots are modifier-derived controls - llvm::SmallVector posControls; - llvm::SmallVector negControls; + SmallVector posControls; + SmallVector negControls; size_t ctrlIdx = 0; for (const auto& [n, positive] : ctrlSpec) { for (size_t i = 0; i < n; ++i, ++ctrlIdx) { @@ -608,7 +607,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { const size_t totalCtrlCount = nModifierControls + implicitCompatControls; // Remaining slots are the gate's own operands (may broadcast) - std::vector> gateOperands( + std::vector> gateOperands( expandedOperands.begin() + static_cast(totalCtrlCount), expandedOperands.end()); @@ -654,7 +653,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } for (size_t b = 0; b < broadcastWidth; ++b) { - llvm::SmallVector iterQubits; + SmallVector iterQubits; iterQubits.reserve(gateOperands.size()); for (const auto& ops : gateOperands) { iterQubits.push_back(ops.size() > 1 ? ops[b] : ops[0]); @@ -677,15 +676,14 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } /// Emit a single gate application, wrapping with ctrl/inv as needed. - void emitGate(const GateFn& gateFn, llvm::ArrayRef qubits, - llvm::ArrayRef params, - llvm::ArrayRef posControls, - llvm::ArrayRef negControls, bool invert) { + void emitGate(const GateFn& gateFn, ArrayRef qubits, + ArrayRef params, ArrayRef posControls, + ArrayRef negControls, bool invert) { auto inner = [&] { gateFn(builder, qubits, params); }; auto withInv = [&] { if (invert) { - builder.inv(llvm::function_ref(inner)); + builder.inv(function_ref(inner)); } else { inner(); } @@ -700,23 +698,21 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { for (auto q : negControls) { builder.x(q); } - llvm::SmallVector allControls(posControls.begin(), - posControls.end()); + SmallVector allControls(posControls.begin(), posControls.end()); allControls.append(negControls.begin(), negControls.end()); - builder.ctrl(allControls, llvm::function_ref(withInv)); + builder.ctrl(allControls, function_ref(withInv)); for (auto q : negControls) { builder.x(q); } } /// Inline-expand a compound (user-defined) gate. - void - applyCompoundGate(const qasm3::CompoundGate& gate, - const std::vector>& gateOperands, - llvm::ArrayRef posControls, - llvm::ArrayRef negControls, - llvm::ArrayRef params, bool invert, - const std::shared_ptr& debugInfo) { + void applyCompoundGate(const qasm3::CompoundGate& gate, + const std::vector>& gateOperands, + ArrayRef posControls, + ArrayRef negControls, ArrayRef params, + bool invert, + const std::shared_ptr& debugInfo) { if (gate.targetNames.size() != gateOperands.size()) { throw qasm3::CompilerError("Compound gate operand count mismatch.", debugInfo); @@ -729,8 +725,8 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { // Build local scope: argument name → Values QubitScope localScope; for (size_t i = 0; i < gate.targetNames.size(); ++i) { - localScope[gate.targetNames[i]] = llvm::SmallVector( - gateOperands[i].begin(), gateOperands[i].end()); + localScope[gate.targetNames[i]] = + SmallVector(gateOperands[i].begin(), gateOperands[i].end()); } // Bind parameters as constants @@ -748,7 +744,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } else if (const auto barrier = std::dynamic_pointer_cast( bodyStmt)) { - llvm::SmallVector qubits; + SmallVector qubits; for (const auto& g : barrier->gates) { auto resolved = resolveGateOperandInScope(g, localScope, barrier->debugInfo); @@ -768,7 +764,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { auto withInv = [&] { if (invert) { - builder.inv(llvm::function_ref(bodyFn)); + builder.inv(function_ref(bodyFn)); } else { bodyFn(); } @@ -780,10 +776,9 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { for (auto q : negControls) { builder.x(q); } - llvm::SmallVector allControls(posControls.begin(), - posControls.end()); + SmallVector allControls(posControls.begin(), posControls.end()); allControls.append(negControls.begin(), negControls.end()); - builder.ctrl(allControls, llvm::function_ref(withInv)); + builder.ctrl(allControls, function_ref(withInv)); for (auto q : negControls) { builder.x(q); } @@ -1011,7 +1006,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { //===--- Operand resolution helpers ------------------------------------===// /// Resolve a gate operand against the top-level qubit register map. - llvm::SmallVector + SmallVector resolveGateOperand(const std::shared_ptr& operand, const std::shared_ptr& debugInfo) { return resolveGateOperandInScope(operand, qubitRegisters, debugInfo); @@ -1021,7 +1016,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { * compound-gate local argument scope). Returns the MLIR Values for the * qubit(s) named by \p operand — a full register or a single indexed qubit. */ - llvm::SmallVector resolveGateOperandInScope( + SmallVector resolveGateOperandInScope( const std::shared_ptr& operand, const QubitScope& scope, const std::shared_ptr& debugInfo) { From ad156d3a3f41f3bb11f41d2187d0b999ddf0ef4d Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 21 May 2026 13:19:47 +0200 Subject: [PATCH 04/48] Begin to fix linter errors --- .../QC/Translation/TranslateQASM3ToQC.cpp | 257 +++++++++--------- 1 file changed, 129 insertions(+), 128 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 4ae900ba88..3423977e5a 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -12,6 +12,7 @@ #include "ir/Definitions.hpp" #include "ir/operations/IfElseOperation.hpp" +#include "ir/operations/OpType.hpp" #include "mlir/Dialect/QC/Builder/QCProgramBuilder.h" #include "mlir/Dialect/QC/IR/QCOps.h" #include "qasm3/Exception.hpp" @@ -28,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -37,8 +39,11 @@ #include #include +#include +#include #include #include +#include #include #include #include @@ -52,140 +57,18 @@ namespace mlir::qc { namespace { -//===----------------------------------------------------------------------===// -// Gate dispatch table -//===----------------------------------------------------------------------===// - /// Signature: (builder, gate-operands, evaluated-parameters). /// For gates with implicit controls (cx, ccx, ...) all qubits including /// the controls are in the qubits array, matching QASM3 operand order. using GateFn = std::function, ArrayRef)>; -/** - * Build the static gate-name → GateFn dispatch table. - * Each entry maps a QASM3 gate identifier to a lambda that emits the - * corresponding QC dialect op via QCProgramBuilder. - */ -static llvm::StringMap buildGateDispatch() { - llvm::StringMap d; - - // 0-target, 1-param - d["gphase"] = [](auto& b, auto /*q*/, auto p) { b.gphase(p[0]); }; - - // 1-target, 0-param - d["id"] = [](auto& b, auto q, auto) { b.id(q[0]); }; - d["x"] = [](auto& b, auto q, auto) { b.x(q[0]); }; - d["y"] = [](auto& b, auto q, auto) { b.y(q[0]); }; - d["z"] = [](auto& b, auto q, auto) { b.z(q[0]); }; - d["h"] = [](auto& b, auto q, auto) { b.h(q[0]); }; - d["s"] = [](auto& b, auto q, auto) { b.s(q[0]); }; - d["sdg"] = [](auto& b, auto q, auto) { b.sdg(q[0]); }; - d["t"] = [](auto& b, auto q, auto) { b.t(q[0]); }; - d["tdg"] = [](auto& b, auto q, auto) { b.tdg(q[0]); }; - d["sx"] = [](auto& b, auto q, auto) { b.sx(q[0]); }; - d["sxdg"] = [](auto& b, auto q, auto) { b.sxdg(q[0]); }; - - // 1-target, 1-param - d["rx"] = [](auto& b, auto q, auto p) { b.rx(p[0], q[0]); }; - d["ry"] = [](auto& b, auto q, auto p) { b.ry(p[0], q[0]); }; - d["rz"] = [](auto& b, auto q, auto p) { b.rz(p[0], q[0]); }; - d["p"] = [](auto& b, auto q, auto p) { b.p(p[0], q[0]); }; - d["u1"] = [](auto& b, auto q, auto p) { b.p(p[0], q[0]); }; // alias - d["phase"] = [](auto& b, auto q, auto p) { b.p(p[0], q[0]); }; // alias - - // 1-target, 2-param - d["r"] = [](auto& b, auto q, auto p) { b.r(p[0], p[1], q[0]); }; - d["u2"] = [](auto& b, auto q, auto p) { b.u2(p[0], p[1], q[0]); }; - - // 1-target, 3-param - d["U"] = [](auto& b, auto q, auto p) { b.u(p[0], p[1], p[2], q[0]); }; - d["u3"] = [](auto& b, auto q, auto p) { - b.u(p[0], p[1], p[2], q[0]); - }; // alias - d["u"] = [](auto& b, auto q, auto p) { - b.u(p[0], p[1], p[2], q[0]); - }; // alias - - // 1-ctrl + 1-target, 0-param (q[0]=ctrl, q[1]=target) - d["cx"] = [](auto& b, auto q, auto) { b.cx(q[0], q[1]); }; - d["cnot"] = [](auto& b, auto q, auto) { b.cx(q[0], q[1]); }; // alias - d["cy"] = [](auto& b, auto q, auto) { b.cy(q[0], q[1]); }; - d["cz"] = [](auto& b, auto q, auto) { b.cz(q[0], q[1]); }; - d["ch"] = [](auto& b, auto q, auto) { b.ch(q[0], q[1]); }; - d["csx"] = [](auto& b, auto q, auto) { b.csx(q[0], q[1]); }; - - // 1-ctrl + 1-target, 1-param - d["crx"] = [](auto& b, auto q, auto p) { b.crx(p[0], q[0], q[1]); }; - d["cry"] = [](auto& b, auto q, auto p) { b.cry(p[0], q[0], q[1]); }; - d["crz"] = [](auto& b, auto q, auto p) { b.crz(p[0], q[0], q[1]); }; - d["cp"] = [](auto& b, auto q, auto p) { b.cp(p[0], q[0], q[1]); }; - d["cphase"] = [](auto& b, auto q, auto p) { - b.cp(p[0], q[0], q[1]); - }; // alias - - // 2-ctrl + 1-target, 0-param (q[0],q[1]=ctrl, q[2]=target) - d["ccx"] = [](auto& b, auto q, auto) { b.mcx({q[0], q[1]}, q[2]); }; - d["toffoli"] = [](auto& b, auto q, auto) { - b.mcx({q[0], q[1]}, q[2]); - }; // alias - d["ccz"] = [](auto& b, auto q, auto) { b.mcz({q[0], q[1]}, q[2]); }; - - // 2-target, 0-param - d["swap"] = [](auto& b, auto q, auto) { b.swap(q[0], q[1]); }; - d["iswap"] = [](auto& b, auto q, auto) { b.iswap(q[0], q[1]); }; - d["dcx"] = [](auto& b, auto q, auto) { b.dcx(q[0], q[1]); }; - d["ecr"] = [](auto& b, auto q, auto) { b.ecr(q[0], q[1]); }; - - // 1-ctrl + 2-target, 0-param (q[0]=ctrl, q[1],q[2]=targets) - d["cswap"] = [](auto& b, auto q, auto) { b.cswap(q[0], q[1], q[2]); }; - d["fredkin"] = [](auto& b, auto q, auto) { - b.cswap(q[0], q[1], q[2]); - }; // alias - - // 2-target, 2-param - d["xx_plus_yy"] = [](auto& b, auto q, auto p) { - b.xx_plus_yy(p[0], p[1], q[0], q[1]); - }; - d["xx_minus_yy"] = [](auto& b, auto q, auto p) { - b.xx_minus_yy(p[0], p[1], q[0], q[1]); - }; - - // 2-target, 1-param - d["rxx"] = [](auto& b, auto q, auto p) { b.rxx(p[0], q[0], q[1]); }; - d["ryy"] = [](auto& b, auto q, auto p) { b.ryy(p[0], q[0], q[1]); }; - d["rzx"] = [](auto& b, auto q, auto p) { b.rzx(p[0], q[0], q[1]); }; - d["rzz"] = [](auto& b, auto q, auto p) { b.rzz(p[0], q[0], q[1]); }; - - // MCX variants: q[0..N-2] are controls, q[N-1] is the target. - // These are not in stdgates.inc but are widely used (Qiskit-style). - auto mcxFn = [](auto& b, auto q, auto) { b.mcx(q.drop_back(1), q.back()); }; - d["mcx"] = mcxFn; - d["mcx_gray"] = mcxFn; - d["mcphase"] = [](auto& b, auto q, auto p) { - b.mcp(p[0], q.drop_back(1), q.back()); - }; - // vchain/recursive carry ancilla qubits; strip them using Qiskit's formula - d["mcx_vchain"] = [](auto& b, auto q, auto) { - const size_t n = q.size() - ((q.size() + 1) / 2) + 2; - b.mcx(q.slice(0, n - 1), q[n - 1]); - }; - d["mcx_recursive"] = [](auto& b, auto q, auto) { - const size_t n = (q.size() > 5) ? q.size() - 1 : q.size(); - b.mcx(q.slice(0, n - 1), q[n - 1]); - }; - - return d; -} +// Forward declaration +llvm::StringMap buildGateDispatch(); /// Static gate dispatch table, built once at startup. -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) static const llvm::StringMap GATE_DISPATCH = buildGateDispatch(); -//===----------------------------------------------------------------------===// -// MLIRQasmImporter -//===----------------------------------------------------------------------===// - /// Local qubit scope used during compound gate body expansion. /// Maps argument name → vector of MLIR qubit Values. using QubitScope = llvm::StringMap>; @@ -278,6 +161,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { gates["mcphase"] = std::make_shared(mcphaseInfo); } +public: //===--- InstVisitor overrides ----------------------------------------===// void visitVersionDeclaration(const std::shared_ptr @@ -367,13 +251,13 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { visitGateStatement(std::shared_ptr stmt) override { auto id = stmt->identifier; if (stmt->isOpaque) { - if (gates.find(id) == gates.end()) { + if (!gates.contains(id)) { throw qasm3::CompilerError("Unsupported opaque gate '" + id + "'.", stmt->debugInfo); } return; } - if (gates.count(id) != 0U) { + if (gates.contains(id)) { if (std::dynamic_pointer_cast(gates[id])) { return; // ignore redeclaration of standard gate } @@ -1050,10 +934,11 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { return {qubits[idx]}; } - /** Resolve \p target to a list of classical bits in a known register. + /** + * Resolve \p target to a list of classical bits in a known register. * Returns all bits for an unindexed identifier, or a single bit otherwise. */ - std::vector resolveClassicalBits( + [[nodiscard]] std::vector resolveClassicalBits( const std::shared_ptr& target, const std::shared_ptr& debugInfo) const { const auto& name = target->identifier; @@ -1097,6 +982,122 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } // namespace +/** + * Build the static gate-name → GateFn dispatch table. + * Each entry maps a QASM3 gate identifier to a lambda that emits the + * corresponding QC dialect op via QCProgramBuilder. + */ +static llvm::StringMap buildGateDispatch() { + llvm::StringMap d; + + // 0-target, 1-param + d["gphase"] = [](auto& b, auto /*q*/, auto p) { b.gphase(p[0]); }; + + // 1-target, 0-param + d["id"] = [](auto& b, auto q, auto) { b.id(q[0]); }; + d["x"] = [](auto& b, auto q, auto) { b.x(q[0]); }; + d["y"] = [](auto& b, auto q, auto) { b.y(q[0]); }; + d["z"] = [](auto& b, auto q, auto) { b.z(q[0]); }; + d["h"] = [](auto& b, auto q, auto) { b.h(q[0]); }; + d["s"] = [](auto& b, auto q, auto) { b.s(q[0]); }; + d["sdg"] = [](auto& b, auto q, auto) { b.sdg(q[0]); }; + d["t"] = [](auto& b, auto q, auto) { b.t(q[0]); }; + d["tdg"] = [](auto& b, auto q, auto) { b.tdg(q[0]); }; + d["sx"] = [](auto& b, auto q, auto) { b.sx(q[0]); }; + d["sxdg"] = [](auto& b, auto q, auto) { b.sxdg(q[0]); }; + + // 1-target, 1-param + d["rx"] = [](auto& b, auto q, auto p) { b.rx(p[0], q[0]); }; + d["ry"] = [](auto& b, auto q, auto p) { b.ry(p[0], q[0]); }; + d["rz"] = [](auto& b, auto q, auto p) { b.rz(p[0], q[0]); }; + d["p"] = [](auto& b, auto q, auto p) { b.p(p[0], q[0]); }; + d["u1"] = [](auto& b, auto q, auto p) { b.p(p[0], q[0]); }; // alias + d["phase"] = [](auto& b, auto q, auto p) { b.p(p[0], q[0]); }; // alias + + // 1-target, 2-param + d["r"] = [](auto& b, auto q, auto p) { b.r(p[0], p[1], q[0]); }; + d["u2"] = [](auto& b, auto q, auto p) { b.u2(p[0], p[1], q[0]); }; + + // 1-target, 3-param + d["U"] = [](auto& b, auto q, auto p) { b.u(p[0], p[1], p[2], q[0]); }; + d["u3"] = [](auto& b, auto q, auto p) { + b.u(p[0], p[1], p[2], q[0]); + }; // alias + d["u"] = [](auto& b, auto q, auto p) { + b.u(p[0], p[1], p[2], q[0]); + }; // alias + + // 1-ctrl + 1-target, 0-param (q[0]=ctrl, q[1]=target) + d["cx"] = [](auto& b, auto q, auto) { b.cx(q[0], q[1]); }; + d["cnot"] = [](auto& b, auto q, auto) { b.cx(q[0], q[1]); }; // alias + d["cy"] = [](auto& b, auto q, auto) { b.cy(q[0], q[1]); }; + d["cz"] = [](auto& b, auto q, auto) { b.cz(q[0], q[1]); }; + d["ch"] = [](auto& b, auto q, auto) { b.ch(q[0], q[1]); }; + d["csx"] = [](auto& b, auto q, auto) { b.csx(q[0], q[1]); }; + + // 1-ctrl + 1-target, 1-param + d["crx"] = [](auto& b, auto q, auto p) { b.crx(p[0], q[0], q[1]); }; + d["cry"] = [](auto& b, auto q, auto p) { b.cry(p[0], q[0], q[1]); }; + d["crz"] = [](auto& b, auto q, auto p) { b.crz(p[0], q[0], q[1]); }; + d["cp"] = [](auto& b, auto q, auto p) { b.cp(p[0], q[0], q[1]); }; + d["cphase"] = [](auto& b, auto q, auto p) { + b.cp(p[0], q[0], q[1]); + }; // alias + + // 2-ctrl + 1-target, 0-param (q[0],q[1]=ctrl, q[2]=target) + d["ccx"] = [](auto& b, auto q, auto) { b.mcx({q[0], q[1]}, q[2]); }; + d["toffoli"] = [](auto& b, auto q, auto) { + b.mcx({q[0], q[1]}, q[2]); + }; // alias + d["ccz"] = [](auto& b, auto q, auto) { b.mcz({q[0], q[1]}, q[2]); }; + + // 2-target, 0-param + d["swap"] = [](auto& b, auto q, auto) { b.swap(q[0], q[1]); }; + d["iswap"] = [](auto& b, auto q, auto) { b.iswap(q[0], q[1]); }; + d["dcx"] = [](auto& b, auto q, auto) { b.dcx(q[0], q[1]); }; + d["ecr"] = [](auto& b, auto q, auto) { b.ecr(q[0], q[1]); }; + + // 1-ctrl + 2-target, 0-param (q[0]=ctrl, q[1],q[2]=targets) + d["cswap"] = [](auto& b, auto q, auto) { b.cswap(q[0], q[1], q[2]); }; + d["fredkin"] = [](auto& b, auto q, auto) { + b.cswap(q[0], q[1], q[2]); + }; // alias + + // 2-target, 2-param + d["xx_plus_yy"] = [](auto& b, auto q, auto p) { + b.xx_plus_yy(p[0], p[1], q[0], q[1]); + }; + d["xx_minus_yy"] = [](auto& b, auto q, auto p) { + b.xx_minus_yy(p[0], p[1], q[0], q[1]); + }; + + // 2-target, 1-param + d["rxx"] = [](auto& b, auto q, auto p) { b.rxx(p[0], q[0], q[1]); }; + d["ryy"] = [](auto& b, auto q, auto p) { b.ryy(p[0], q[0], q[1]); }; + d["rzx"] = [](auto& b, auto q, auto p) { b.rzx(p[0], q[0], q[1]); }; + d["rzz"] = [](auto& b, auto q, auto p) { b.rzz(p[0], q[0], q[1]); }; + + // MCX variants: q[0..N-2] are controls, q[N-1] is the target. + // These are not in stdgates.inc but are widely used (Qiskit-style). + auto mcxFn = [](auto& b, auto q, auto) { b.mcx(q.drop_back(1), q.back()); }; + d["mcx"] = mcxFn; + d["mcx_gray"] = mcxFn; + d["mcphase"] = [](auto& b, auto q, auto p) { + b.mcp(p[0], q.drop_back(1), q.back()); + }; + // vchain/recursive carry ancilla qubits; strip them using Qiskit's formula + d["mcx_vchain"] = [](auto& b, auto q, auto) { + const size_t n = q.size() - ((q.size() + 1) / 2) + 2; + b.mcx(q.slice(0, n - 1), q[n - 1]); + }; + d["mcx_recursive"] = [](auto& b, auto q, auto) { + const size_t n = (q.size() > 5) ? q.size() - 1 : q.size(); + b.mcx(q.slice(0, n - 1), q[n - 1]); + }; + + return d; +} + //===----------------------------------------------------------------------===// // Public API //===----------------------------------------------------------------------===// From a22ab4fa7fadb7707dfa793f23b8d332afc33e1a Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 21 May 2026 13:22:03 +0200 Subject: [PATCH 05/48] Remove explicit namespace specifier --- mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 3423977e5a..c7328efb2c 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -545,8 +545,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { // Check that no qubit appears twice across targets and controls. llvm::SmallDenseSet seen; - for (auto q : - llvm::concat(iterQubits, posControls, negControls)) { + for (auto q : concat(iterQubits, posControls, negControls)) { if (!seen.insert(q).second) { throw qasm3::CompilerError("Duplicate qubit in gate '" + id + "' operands.", From 71c4bcd0dc153e24f2636a64f2a1487089a6a42d Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 21 May 2026 13:25:04 +0200 Subject: [PATCH 06/48] Drop support for legacy loader --- mlir/tools/mqt-cc/mqt-cc.cpp | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/mlir/tools/mqt-cc/mqt-cc.cpp b/mlir/tools/mqt-cc/mqt-cc.cpp index 7522d052c2..7fa2ad7177 100644 --- a/mlir/tools/mqt-cc/mqt-cc.cpp +++ b/mlir/tools/mqt-cc/mqt-cc.cpp @@ -86,34 +86,12 @@ static llvm::cl::opt enableHadamardLifting( llvm::cl::desc("Apply Hadamard lifting during optimization"), llvm::cl::init(false)); -/** - * @brief Load and parse a .qasm file via the legacy QuantumComputation path. - */ -static OwningOpRef loadQASMFileLegacy(llvm::StringRef filename, - MLIRContext* context) { - try { - const ::qc::QuantumComputation qc = - qasm3::Importer::importf(filename.str()); - return translateQuantumComputationToQC(context, qc); - } catch (const qasm3::CompilerError& exception) { - llvm::errs() << "Failed to parse QASM file '" << filename << "': '" - << exception.what() << "'\n"; - } catch (const std::exception& exception) { - llvm::errs() << "Failed to load QASM file '" << filename << "': '" - << exception.what() << "'\n"; - } - return nullptr; -} - /** * @brief Load and parse a .qasm file, dispatching to the chosen import path. */ static OwningOpRef loadQASMFile(StringRef filename, MLIRContext* context) { - if (directImport) { - return mlir::qc::translateQASM3ToQC(context, filename.str()); - } - return loadQASMFileLegacy(filename, context); + return mlir::qc::translateQASM3ToQC(context, filename.str()); } /** From e99fcca41d4b461af2b5ef518fbde09cd28b2c0e Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 21 May 2026 13:36:47 +0200 Subject: [PATCH 07/48] Add first test --- .../QC/Translation/TranslateQASM3ToQC.cpp | 233 +++++++++--------- .../Dialect/QC/Translation/CMakeLists.txt | 2 +- .../QC/Translation/test_qasm3_translation.cpp | 105 ++++++++ mlir/unittests/programs/qasm_programs/x.qasm | 4 + test/circuits/bell.qasm | 5 - 5 files changed, 225 insertions(+), 124 deletions(-) create mode 100644 mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp create mode 100644 mlir/unittests/programs/qasm_programs/x.qasm delete mode 100644 test/circuits/bell.qasm diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index c7328efb2c..1ca95a3276 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -63,8 +63,121 @@ namespace { using GateFn = std::function, ArrayRef)>; -// Forward declaration -llvm::StringMap buildGateDispatch(); +/** + * Build the static gate-name → GateFn dispatch table. + * Each entry maps a QASM3 gate identifier to a lambda that emits the + * corresponding QC dialect op via QCProgramBuilder. + */ +llvm::StringMap buildGateDispatch() { + llvm::StringMap d; + + // 0-target, 1-param + d["gphase"] = [](auto& b, auto /*q*/, auto p) { b.gphase(p[0]); }; + + // 1-target, 0-param + d["id"] = [](auto& b, auto q, auto) { b.id(q[0]); }; + d["x"] = [](auto& b, auto q, auto) { b.x(q[0]); }; + d["y"] = [](auto& b, auto q, auto) { b.y(q[0]); }; + d["z"] = [](auto& b, auto q, auto) { b.z(q[0]); }; + d["h"] = [](auto& b, auto q, auto) { b.h(q[0]); }; + d["s"] = [](auto& b, auto q, auto) { b.s(q[0]); }; + d["sdg"] = [](auto& b, auto q, auto) { b.sdg(q[0]); }; + d["t"] = [](auto& b, auto q, auto) { b.t(q[0]); }; + d["tdg"] = [](auto& b, auto q, auto) { b.tdg(q[0]); }; + d["sx"] = [](auto& b, auto q, auto) { b.sx(q[0]); }; + d["sxdg"] = [](auto& b, auto q, auto) { b.sxdg(q[0]); }; + + // 1-target, 1-param + d["rx"] = [](auto& b, auto q, auto p) { b.rx(p[0], q[0]); }; + d["ry"] = [](auto& b, auto q, auto p) { b.ry(p[0], q[0]); }; + d["rz"] = [](auto& b, auto q, auto p) { b.rz(p[0], q[0]); }; + d["p"] = [](auto& b, auto q, auto p) { b.p(p[0], q[0]); }; + d["u1"] = [](auto& b, auto q, auto p) { b.p(p[0], q[0]); }; // alias + d["phase"] = [](auto& b, auto q, auto p) { b.p(p[0], q[0]); }; // alias + + // 1-target, 2-param + d["r"] = [](auto& b, auto q, auto p) { b.r(p[0], p[1], q[0]); }; + d["u2"] = [](auto& b, auto q, auto p) { b.u2(p[0], p[1], q[0]); }; + + // 1-target, 3-param + d["U"] = [](auto& b, auto q, auto p) { b.u(p[0], p[1], p[2], q[0]); }; + d["u3"] = [](auto& b, auto q, auto p) { + b.u(p[0], p[1], p[2], q[0]); + }; // alias + d["u"] = [](auto& b, auto q, auto p) { + b.u(p[0], p[1], p[2], q[0]); + }; // alias + + // 1-ctrl + 1-target, 0-param (q[0]=ctrl, q[1]=target) + d["cx"] = [](auto& b, auto q, auto) { b.cx(q[0], q[1]); }; + d["cnot"] = [](auto& b, auto q, auto) { b.cx(q[0], q[1]); }; // alias + d["cy"] = [](auto& b, auto q, auto) { b.cy(q[0], q[1]); }; + d["cz"] = [](auto& b, auto q, auto) { b.cz(q[0], q[1]); }; + d["ch"] = [](auto& b, auto q, auto) { b.ch(q[0], q[1]); }; + d["csx"] = [](auto& b, auto q, auto) { b.csx(q[0], q[1]); }; + + // 1-ctrl + 1-target, 1-param + d["crx"] = [](auto& b, auto q, auto p) { b.crx(p[0], q[0], q[1]); }; + d["cry"] = [](auto& b, auto q, auto p) { b.cry(p[0], q[0], q[1]); }; + d["crz"] = [](auto& b, auto q, auto p) { b.crz(p[0], q[0], q[1]); }; + d["cp"] = [](auto& b, auto q, auto p) { b.cp(p[0], q[0], q[1]); }; + d["cphase"] = [](auto& b, auto q, auto p) { + b.cp(p[0], q[0], q[1]); + }; // alias + + // 2-ctrl + 1-target, 0-param (q[0],q[1]=ctrl, q[2]=target) + d["ccx"] = [](auto& b, auto q, auto) { b.mcx({q[0], q[1]}, q[2]); }; + d["toffoli"] = [](auto& b, auto q, auto) { + b.mcx({q[0], q[1]}, q[2]); + }; // alias + d["ccz"] = [](auto& b, auto q, auto) { b.mcz({q[0], q[1]}, q[2]); }; + + // 2-target, 0-param + d["swap"] = [](auto& b, auto q, auto) { b.swap(q[0], q[1]); }; + d["iswap"] = [](auto& b, auto q, auto) { b.iswap(q[0], q[1]); }; + d["dcx"] = [](auto& b, auto q, auto) { b.dcx(q[0], q[1]); }; + d["ecr"] = [](auto& b, auto q, auto) { b.ecr(q[0], q[1]); }; + + // 1-ctrl + 2-target, 0-param (q[0]=ctrl, q[1],q[2]=targets) + d["cswap"] = [](auto& b, auto q, auto) { b.cswap(q[0], q[1], q[2]); }; + d["fredkin"] = [](auto& b, auto q, auto) { + b.cswap(q[0], q[1], q[2]); + }; // alias + + // 2-target, 2-param + d["xx_plus_yy"] = [](auto& b, auto q, auto p) { + b.xx_plus_yy(p[0], p[1], q[0], q[1]); + }; + d["xx_minus_yy"] = [](auto& b, auto q, auto p) { + b.xx_minus_yy(p[0], p[1], q[0], q[1]); + }; + + // 2-target, 1-param + d["rxx"] = [](auto& b, auto q, auto p) { b.rxx(p[0], q[0], q[1]); }; + d["ryy"] = [](auto& b, auto q, auto p) { b.ryy(p[0], q[0], q[1]); }; + d["rzx"] = [](auto& b, auto q, auto p) { b.rzx(p[0], q[0], q[1]); }; + d["rzz"] = [](auto& b, auto q, auto p) { b.rzz(p[0], q[0], q[1]); }; + + // MCX variants: q[0..N-2] are controls, q[N-1] is the target. + // These are not in stdgates.inc but are widely used (Qiskit-style). + auto mcxFn = [](auto& b, auto q, auto) { b.mcx(q.drop_back(1), q.back()); }; + d["mcx"] = mcxFn; + d["mcx_gray"] = mcxFn; + d["mcphase"] = [](auto& b, auto q, auto p) { + b.mcp(p[0], q.drop_back(1), q.back()); + }; + // vchain/recursive carry ancilla qubits; strip them using Qiskit's formula + d["mcx_vchain"] = [](auto& b, auto q, auto) { + const size_t n = q.size() - ((q.size() + 1) / 2) + 2; + b.mcx(q.slice(0, n - 1), q[n - 1]); + }; + d["mcx_recursive"] = [](auto& b, auto q, auto) { + const size_t n = (q.size() > 5) ? q.size() - 1 : q.size(); + b.mcx(q.slice(0, n - 1), q[n - 1]); + }; + + return d; +} /// Static gate dispatch table, built once at startup. static const llvm::StringMap GATE_DISPATCH = buildGateDispatch(); @@ -981,122 +1094,6 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } // namespace -/** - * Build the static gate-name → GateFn dispatch table. - * Each entry maps a QASM3 gate identifier to a lambda that emits the - * corresponding QC dialect op via QCProgramBuilder. - */ -static llvm::StringMap buildGateDispatch() { - llvm::StringMap d; - - // 0-target, 1-param - d["gphase"] = [](auto& b, auto /*q*/, auto p) { b.gphase(p[0]); }; - - // 1-target, 0-param - d["id"] = [](auto& b, auto q, auto) { b.id(q[0]); }; - d["x"] = [](auto& b, auto q, auto) { b.x(q[0]); }; - d["y"] = [](auto& b, auto q, auto) { b.y(q[0]); }; - d["z"] = [](auto& b, auto q, auto) { b.z(q[0]); }; - d["h"] = [](auto& b, auto q, auto) { b.h(q[0]); }; - d["s"] = [](auto& b, auto q, auto) { b.s(q[0]); }; - d["sdg"] = [](auto& b, auto q, auto) { b.sdg(q[0]); }; - d["t"] = [](auto& b, auto q, auto) { b.t(q[0]); }; - d["tdg"] = [](auto& b, auto q, auto) { b.tdg(q[0]); }; - d["sx"] = [](auto& b, auto q, auto) { b.sx(q[0]); }; - d["sxdg"] = [](auto& b, auto q, auto) { b.sxdg(q[0]); }; - - // 1-target, 1-param - d["rx"] = [](auto& b, auto q, auto p) { b.rx(p[0], q[0]); }; - d["ry"] = [](auto& b, auto q, auto p) { b.ry(p[0], q[0]); }; - d["rz"] = [](auto& b, auto q, auto p) { b.rz(p[0], q[0]); }; - d["p"] = [](auto& b, auto q, auto p) { b.p(p[0], q[0]); }; - d["u1"] = [](auto& b, auto q, auto p) { b.p(p[0], q[0]); }; // alias - d["phase"] = [](auto& b, auto q, auto p) { b.p(p[0], q[0]); }; // alias - - // 1-target, 2-param - d["r"] = [](auto& b, auto q, auto p) { b.r(p[0], p[1], q[0]); }; - d["u2"] = [](auto& b, auto q, auto p) { b.u2(p[0], p[1], q[0]); }; - - // 1-target, 3-param - d["U"] = [](auto& b, auto q, auto p) { b.u(p[0], p[1], p[2], q[0]); }; - d["u3"] = [](auto& b, auto q, auto p) { - b.u(p[0], p[1], p[2], q[0]); - }; // alias - d["u"] = [](auto& b, auto q, auto p) { - b.u(p[0], p[1], p[2], q[0]); - }; // alias - - // 1-ctrl + 1-target, 0-param (q[0]=ctrl, q[1]=target) - d["cx"] = [](auto& b, auto q, auto) { b.cx(q[0], q[1]); }; - d["cnot"] = [](auto& b, auto q, auto) { b.cx(q[0], q[1]); }; // alias - d["cy"] = [](auto& b, auto q, auto) { b.cy(q[0], q[1]); }; - d["cz"] = [](auto& b, auto q, auto) { b.cz(q[0], q[1]); }; - d["ch"] = [](auto& b, auto q, auto) { b.ch(q[0], q[1]); }; - d["csx"] = [](auto& b, auto q, auto) { b.csx(q[0], q[1]); }; - - // 1-ctrl + 1-target, 1-param - d["crx"] = [](auto& b, auto q, auto p) { b.crx(p[0], q[0], q[1]); }; - d["cry"] = [](auto& b, auto q, auto p) { b.cry(p[0], q[0], q[1]); }; - d["crz"] = [](auto& b, auto q, auto p) { b.crz(p[0], q[0], q[1]); }; - d["cp"] = [](auto& b, auto q, auto p) { b.cp(p[0], q[0], q[1]); }; - d["cphase"] = [](auto& b, auto q, auto p) { - b.cp(p[0], q[0], q[1]); - }; // alias - - // 2-ctrl + 1-target, 0-param (q[0],q[1]=ctrl, q[2]=target) - d["ccx"] = [](auto& b, auto q, auto) { b.mcx({q[0], q[1]}, q[2]); }; - d["toffoli"] = [](auto& b, auto q, auto) { - b.mcx({q[0], q[1]}, q[2]); - }; // alias - d["ccz"] = [](auto& b, auto q, auto) { b.mcz({q[0], q[1]}, q[2]); }; - - // 2-target, 0-param - d["swap"] = [](auto& b, auto q, auto) { b.swap(q[0], q[1]); }; - d["iswap"] = [](auto& b, auto q, auto) { b.iswap(q[0], q[1]); }; - d["dcx"] = [](auto& b, auto q, auto) { b.dcx(q[0], q[1]); }; - d["ecr"] = [](auto& b, auto q, auto) { b.ecr(q[0], q[1]); }; - - // 1-ctrl + 2-target, 0-param (q[0]=ctrl, q[1],q[2]=targets) - d["cswap"] = [](auto& b, auto q, auto) { b.cswap(q[0], q[1], q[2]); }; - d["fredkin"] = [](auto& b, auto q, auto) { - b.cswap(q[0], q[1], q[2]); - }; // alias - - // 2-target, 2-param - d["xx_plus_yy"] = [](auto& b, auto q, auto p) { - b.xx_plus_yy(p[0], p[1], q[0], q[1]); - }; - d["xx_minus_yy"] = [](auto& b, auto q, auto p) { - b.xx_minus_yy(p[0], p[1], q[0], q[1]); - }; - - // 2-target, 1-param - d["rxx"] = [](auto& b, auto q, auto p) { b.rxx(p[0], q[0], q[1]); }; - d["ryy"] = [](auto& b, auto q, auto p) { b.ryy(p[0], q[0], q[1]); }; - d["rzx"] = [](auto& b, auto q, auto p) { b.rzx(p[0], q[0], q[1]); }; - d["rzz"] = [](auto& b, auto q, auto p) { b.rzz(p[0], q[0], q[1]); }; - - // MCX variants: q[0..N-2] are controls, q[N-1] is the target. - // These are not in stdgates.inc but are widely used (Qiskit-style). - auto mcxFn = [](auto& b, auto q, auto) { b.mcx(q.drop_back(1), q.back()); }; - d["mcx"] = mcxFn; - d["mcx_gray"] = mcxFn; - d["mcphase"] = [](auto& b, auto q, auto p) { - b.mcp(p[0], q.drop_back(1), q.back()); - }; - // vchain/recursive carry ancilla qubits; strip them using Qiskit's formula - d["mcx_vchain"] = [](auto& b, auto q, auto) { - const size_t n = q.size() - ((q.size() + 1) / 2) + 2; - b.mcx(q.slice(0, n - 1), q[n - 1]); - }; - d["mcx_recursive"] = [](auto& b, auto q, auto) { - const size_t n = (q.size() > 5) ? q.size() - 1 : q.size(); - b.mcx(q.slice(0, n - 1), q[n - 1]); - }; - - return d; -} - //===----------------------------------------------------------------------===// // Public API //===----------------------------------------------------------------------===// diff --git a/mlir/unittests/Dialect/QC/Translation/CMakeLists.txt b/mlir/unittests/Dialect/QC/Translation/CMakeLists.txt index de8c687a8f..a42274d66b 100644 --- a/mlir/unittests/Dialect/QC/Translation/CMakeLists.txt +++ b/mlir/unittests/Dialect/QC/Translation/CMakeLists.txt @@ -8,7 +8,7 @@ file(GLOB_RECURSE TEST_SOURCES "*.cpp") -set(target_name mqt-core-mlir-unittest-quantum-computation-translation) +set(target_name mqt-core-mlir-unittest-qc-translation) add_executable(${target_name} ${TEST_SOURCES}) target_link_libraries( diff --git a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp new file mode 100644 index 0000000000..9589d70de3 --- /dev/null +++ b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2023 - 2026 Chair for Design Automation, TUM + * Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH + * All rights reserved. + * + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License + */ + +#include "TestCaseUtils.h" +#include "ir/QuantumComputation.hpp" +#include "mlir/Dialect/QC/Builder/QCProgramBuilder.h" +#include "mlir/Dialect/QC/IR/QCDialect.h" +#include "mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h" +#include "mlir/Support/IRVerification.h" +#include "mlir/Support/Passes.h" +#include "qc_programs.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace { + +struct QASM3TranslationTestCase { + std::string name; + std::string path; + mqt::test::NamedBuilder referenceBuilder; + + friend std::ostream& operator<<(std::ostream& os, + const QASM3TranslationTestCase& test); +}; + +// NOLINTNEXTLINE(llvm-prefer-static-over-anonymous-namespace) +std::ostream& operator<<(std::ostream& os, + const QASM3TranslationTestCase& test) { + return os << "QASM3Translation{" << test.name << ", original=" << test.path + << ", reference=" + << mqt::test::displayName(test.referenceBuilder.name) << "}"; +} + +class QASM3TranslationTest + : public testing::TestWithParam { +protected: + std::unique_ptr context; + + void SetUp() override { + mlir::DialectRegistry registry; + registry.insert(); + context = std::make_unique(); + context->appendDialectRegistry(registry); + context->loadAllAvailableDialects(); + } +}; + +} // namespace + +TEST_P(QASM3TranslationTest, ProgramEquivalence) { + const auto& [name, path, referenceBuilder] = GetParam(); + const auto testName = " (" + name + ")"; + const auto programPath = (std::filesystem::path(__FILE__).parent_path() / + "../../../programs/qasm_programs" / path) + .lexically_normal() + .string(); + mqt::test::DeferredPrinter printer; + + auto translated = mlir::qc::translateQASM3ToQC(context.get(), programPath); + ASSERT_TRUE(translated); + printer.record(translated.get(), "Translated QC IR" + testName); + EXPECT_TRUE(mlir::verify(*translated).succeeded()); + + EXPECT_TRUE(runQCCleanupPipeline(translated.get()).succeeded()); + printer.record(translated.get(), "Canonicalized Translated QC IR" + testName); + EXPECT_TRUE(mlir::verify(*translated).succeeded()); + + auto reference = + mlir::qc::QCProgramBuilder::build(context.get(), referenceBuilder.fn); + ASSERT_TRUE(reference); + printer.record(reference.get(), "Reference QC IR" + testName); + EXPECT_TRUE(mlir::verify(*reference).succeeded()); + + EXPECT_TRUE(runQCCleanupPipeline(reference.get()).succeeded()); + printer.record(reference.get(), "Canonicalized Reference QC IR" + testName); + EXPECT_TRUE(mlir::verify(*reference).succeeded()); + + EXPECT_TRUE( + areModulesEquivalentWithPermutations(translated.get(), reference.get())); +} + +INSTANTIATE_TEST_SUITE_P(QASM3TranslationProgramsTest, QASM3TranslationTest, + testing::Values(QASM3TranslationTestCase{ + "X", "x.qasm", MQT_NAMED_BUILDER(mlir::qc::x)})); diff --git a/mlir/unittests/programs/qasm_programs/x.qasm b/mlir/unittests/programs/qasm_programs/x.qasm new file mode 100644 index 0000000000..743166105e --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/x.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +x q[0]; diff --git a/test/circuits/bell.qasm b/test/circuits/bell.qasm deleted file mode 100644 index c8b3cff498..0000000000 --- a/test/circuits/bell.qasm +++ /dev/null @@ -1,5 +0,0 @@ -OPENQASM 2.0; -//include "qelib1.inc"; -qreg q[2]; -U(pi/2,0,pi) q[0]; -CX q[0],q[1]; From f6d248cfbc04a1218605603770b841af3b41f0d8 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 21 May 2026 14:17:40 +0200 Subject: [PATCH 08/48] Fix some more linter errors --- mlir/tools/mqt-cc/mqt-cc.cpp | 5 +--- .../QC/Translation/test_qasm3_translation.cpp | 30 +++++++++---------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/mlir/tools/mqt-cc/mqt-cc.cpp b/mlir/tools/mqt-cc/mqt-cc.cpp index 7fa2ad7177..8cdaa52f2d 100644 --- a/mlir/tools/mqt-cc/mqt-cc.cpp +++ b/mlir/tools/mqt-cc/mqt-cc.cpp @@ -8,15 +8,11 @@ * Licensed under the MIT License */ -#include "ir/QuantumComputation.hpp" #include "mlir/Compiler/CompilerPipeline.h" #include "mlir/Dialect/QC/IR/QCDialect.h" #include "mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h" -#include "mlir/Dialect/QC/Translation/TranslateQuantumComputationToQC.h" #include "mlir/Dialect/QCO/IR/QCODialect.h" #include "mlir/Dialect/QTensor/IR/QTensorDialect.h" -#include "qasm3/Exception.hpp" -#include "qasm3/Importer.hpp" #include #include @@ -34,6 +30,7 @@ #include #include #include +#include #include #include diff --git a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp index 9589d70de3..855bcb50bc 100644 --- a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp +++ b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp @@ -9,7 +9,6 @@ */ #include "TestCaseUtils.h" -#include "ir/QuantumComputation.hpp" #include "mlir/Dialect/QC/Builder/QCProgramBuilder.h" #include "mlir/Dialect/QC/IR/QCDialect.h" #include "mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h" @@ -31,12 +30,14 @@ #include #include +using namespace mlir; + namespace { struct QASM3TranslationTestCase { std::string name; std::string path; - mqt::test::NamedBuilder referenceBuilder; + mqt::test::NamedBuilder referenceBuilder; friend std::ostream& operator<<(std::ostream& os, const QASM3TranslationTestCase& test); @@ -53,14 +54,13 @@ std::ostream& operator<<(std::ostream& os, class QASM3TranslationTest : public testing::TestWithParam { protected: - std::unique_ptr context; + std::unique_ptr context; void SetUp() override { - mlir::DialectRegistry registry; - registry.insert(); - context = std::make_unique(); + DialectRegistry registry; + registry.insert(); + context = std::make_unique(); context->appendDialectRegistry(registry); context->loadAllAvailableDialects(); } @@ -77,24 +77,24 @@ TEST_P(QASM3TranslationTest, ProgramEquivalence) { .string(); mqt::test::DeferredPrinter printer; - auto translated = mlir::qc::translateQASM3ToQC(context.get(), programPath); + auto translated = qc::translateQASM3ToQC(context.get(), programPath); ASSERT_TRUE(translated); printer.record(translated.get(), "Translated QC IR" + testName); - EXPECT_TRUE(mlir::verify(*translated).succeeded()); + EXPECT_TRUE(verify(*translated).succeeded()); EXPECT_TRUE(runQCCleanupPipeline(translated.get()).succeeded()); printer.record(translated.get(), "Canonicalized Translated QC IR" + testName); - EXPECT_TRUE(mlir::verify(*translated).succeeded()); + EXPECT_TRUE(verify(*translated).succeeded()); auto reference = - mlir::qc::QCProgramBuilder::build(context.get(), referenceBuilder.fn); + qc::QCProgramBuilder::build(context.get(), referenceBuilder.fn); ASSERT_TRUE(reference); printer.record(reference.get(), "Reference QC IR" + testName); - EXPECT_TRUE(mlir::verify(*reference).succeeded()); + EXPECT_TRUE(verify(*reference).succeeded()); EXPECT_TRUE(runQCCleanupPipeline(reference.get()).succeeded()); printer.record(reference.get(), "Canonicalized Reference QC IR" + testName); - EXPECT_TRUE(mlir::verify(*reference).succeeded()); + EXPECT_TRUE(verify(*reference).succeeded()); EXPECT_TRUE( areModulesEquivalentWithPermutations(translated.get(), reference.get())); @@ -102,4 +102,4 @@ TEST_P(QASM3TranslationTest, ProgramEquivalence) { INSTANTIATE_TEST_SUITE_P(QASM3TranslationProgramsTest, QASM3TranslationTest, testing::Values(QASM3TranslationTestCase{ - "X", "x.qasm", MQT_NAMED_BUILDER(mlir::qc::x)})); + "X", "x.qasm", MQT_NAMED_BUILDER(qc::x)})); From 5aa5f7420cf29e27af85a4ee2fa822239dc5aaa4 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 21 May 2026 14:52:07 +0200 Subject: [PATCH 09/48] Add more test cases --- .../QC/Translation/test_qasm3_translation.cpp | 292 +++++++++++++++++- .../qasm_programs/alloc_large_register.qasm | 3 + .../alloc_multiple_qubit_registers.qasm | 4 + .../programs/qasm_programs/alloc_qubit.qasm | 3 + .../qasm_programs/alloc_qubit_register.qasm | 3 + .../programs/qasm_programs/barrier.qasm | 4 + .../barrier_multiple_qubits.qasm | 4 + .../qasm_programs/barrier_two_qubits.qasm | 4 + .../unittests/programs/qasm_programs/dcx.qasm | 4 + .../unittests/programs/qasm_programs/ecr.qasm | 4 + .../programs/qasm_programs/global_phase.qasm | 3 + mlir/unittests/programs/qasm_programs/h.qasm | 4 + .../programs/qasm_programs/identity.qasm | 4 + .../programs/qasm_programs/if_else.qasm | 10 + .../programs/qasm_programs/inverse_iswap.qasm | 4 + .../inverse_multiple_controlled_iswap.qasm | 4 + .../programs/qasm_programs/iswap.qasm | 4 + ..._classical_registers_and_measurements.qasm | 8 + .../multiple_controlled_dcx.qasm | 4 + .../multiple_controlled_ecr.qasm | 4 + .../qasm_programs/multiple_controlled_h.qasm | 4 + .../multiple_controlled_identity.qasm | 4 + .../multiple_controlled_iswap.qasm | 4 + .../qasm_programs/multiple_controlled_p.qasm | 4 + .../qasm_programs/multiple_controlled_r.qasm | 4 + .../qasm_programs/multiple_controlled_rx.qasm | 4 + .../multiple_controlled_rxx.qasm | 4 + .../qasm_programs/multiple_controlled_ry.qasm | 4 + .../multiple_controlled_ryy.qasm | 4 + .../qasm_programs/multiple_controlled_rz.qasm | 4 + .../multiple_controlled_rzx.qasm | 4 + .../multiple_controlled_rzz.qasm | 4 + .../qasm_programs/multiple_controlled_s.qasm | 4 + .../multiple_controlled_sdg.qasm | 4 + .../multiple_controlled_swap.qasm | 4 + .../qasm_programs/multiple_controlled_sx.qasm | 4 + .../multiple_controlled_sxdg.qasm | 4 + .../qasm_programs/multiple_controlled_t.qasm | 4 + .../multiple_controlled_tdg.qasm | 4 + .../qasm_programs/multiple_controlled_u.qasm | 4 + .../qasm_programs/multiple_controlled_u2.qasm | 4 + .../qasm_programs/multiple_controlled_x.qasm | 4 + .../multiple_controlled_xx_minus_yy.qasm | 4 + .../multiple_controlled_xx_plus_yy.qasm | 4 + .../qasm_programs/multiple_controlled_y.qasm | 4 + .../qasm_programs/multiple_controlled_z.qasm | 4 + mlir/unittests/programs/qasm_programs/p.qasm | 4 + mlir/unittests/programs/qasm_programs/r.qasm | 4 + ...epeated_measurement_to_different_bits.qasm | 7 + .../repeated_measurement_to_same_bit.qasm | 7 + .../repeated_reset_after_single_op.qasm | 7 + ...reset_multiple_qubits_after_single_op.qasm | 7 + .../reset_qubit_after_single_op.qasm | 5 + mlir/unittests/programs/qasm_programs/rx.qasm | 4 + .../unittests/programs/qasm_programs/rxx.qasm | 4 + mlir/unittests/programs/qasm_programs/ry.qasm | 4 + .../unittests/programs/qasm_programs/ryy.qasm | 4 + mlir/unittests/programs/qasm_programs/rz.qasm | 4 + .../unittests/programs/qasm_programs/rzx.qasm | 4 + .../unittests/programs/qasm_programs/rzz.qasm | 4 + mlir/unittests/programs/qasm_programs/s.qasm | 4 + .../unittests/programs/qasm_programs/sdg.qasm | 4 + .../programs/qasm_programs/simple_if.qasm | 8 + .../qasm_programs/single_controlled_dcx.qasm | 4 + .../qasm_programs/single_controlled_ecr.qasm | 4 + .../qasm_programs/single_controlled_h.qasm | 4 + .../single_controlled_identity.qasm | 4 + .../single_controlled_iswap.qasm | 4 + .../qasm_programs/single_controlled_p.qasm | 4 + .../qasm_programs/single_controlled_r.qasm | 4 + .../qasm_programs/single_controlled_rx.qasm | 4 + .../qasm_programs/single_controlled_rxx.qasm | 4 + .../qasm_programs/single_controlled_ry.qasm | 4 + .../qasm_programs/single_controlled_ryy.qasm | 4 + .../qasm_programs/single_controlled_rz.qasm | 4 + .../qasm_programs/single_controlled_rzx.qasm | 4 + .../qasm_programs/single_controlled_rzz.qasm | 4 + .../qasm_programs/single_controlled_s.qasm | 4 + .../qasm_programs/single_controlled_sdg.qasm | 4 + .../qasm_programs/single_controlled_swap.qasm | 4 + .../qasm_programs/single_controlled_sx.qasm | 4 + .../qasm_programs/single_controlled_sxdg.qasm | 4 + .../qasm_programs/single_controlled_t.qasm | 4 + .../qasm_programs/single_controlled_tdg.qasm | 4 + .../qasm_programs/single_controlled_u.qasm | 4 + .../qasm_programs/single_controlled_u2.qasm | 4 + .../qasm_programs/single_controlled_x.qasm | 4 + .../single_controlled_xx_minus_yy.qasm | 4 + .../single_controlled_xx_plus_yy.qasm | 4 + .../qasm_programs/single_controlled_y.qasm | 4 + .../qasm_programs/single_controlled_z.qasm | 4 + .../single_measurement_to_single_bit.qasm | 5 + .../programs/qasm_programs/swap.qasm | 4 + mlir/unittests/programs/qasm_programs/sx.qasm | 4 + .../programs/qasm_programs/sxdg.qasm | 4 + mlir/unittests/programs/qasm_programs/t.qasm | 4 + .../unittests/programs/qasm_programs/tdg.qasm | 4 + .../qasm_programs/triple_controlled_rxx.qasm | 4 + mlir/unittests/programs/qasm_programs/u.qasm | 4 + mlir/unittests/programs/qasm_programs/u2.qasm | 4 + .../programs/qasm_programs/xx_minus_yy.qasm | 4 + .../programs/qasm_programs/xx_plus_yy.qasm | 4 + mlir/unittests/programs/qasm_programs/y.qasm | 4 + mlir/unittests/programs/qasm_programs/z.qasm | 4 + 104 files changed, 714 insertions(+), 14 deletions(-) create mode 100644 mlir/unittests/programs/qasm_programs/alloc_large_register.qasm create mode 100644 mlir/unittests/programs/qasm_programs/alloc_multiple_qubit_registers.qasm create mode 100644 mlir/unittests/programs/qasm_programs/alloc_qubit.qasm create mode 100644 mlir/unittests/programs/qasm_programs/alloc_qubit_register.qasm create mode 100644 mlir/unittests/programs/qasm_programs/barrier.qasm create mode 100644 mlir/unittests/programs/qasm_programs/barrier_multiple_qubits.qasm create mode 100644 mlir/unittests/programs/qasm_programs/barrier_two_qubits.qasm create mode 100644 mlir/unittests/programs/qasm_programs/dcx.qasm create mode 100644 mlir/unittests/programs/qasm_programs/ecr.qasm create mode 100644 mlir/unittests/programs/qasm_programs/global_phase.qasm create mode 100644 mlir/unittests/programs/qasm_programs/h.qasm create mode 100644 mlir/unittests/programs/qasm_programs/identity.qasm create mode 100644 mlir/unittests/programs/qasm_programs/if_else.qasm create mode 100644 mlir/unittests/programs/qasm_programs/inverse_iswap.qasm create mode 100644 mlir/unittests/programs/qasm_programs/inverse_multiple_controlled_iswap.qasm create mode 100644 mlir/unittests/programs/qasm_programs/iswap.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_classical_registers_and_measurements.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_dcx.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_ecr.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_h.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_identity.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_iswap.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_p.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_r.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_rx.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_rxx.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_ry.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_ryy.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_rz.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_rzx.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_rzz.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_s.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_sdg.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_swap.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_sx.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_sxdg.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_t.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_tdg.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_u.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_u2.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_x.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_xx_minus_yy.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_xx_plus_yy.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_y.qasm create mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_z.qasm create mode 100644 mlir/unittests/programs/qasm_programs/p.qasm create mode 100644 mlir/unittests/programs/qasm_programs/r.qasm create mode 100644 mlir/unittests/programs/qasm_programs/repeated_measurement_to_different_bits.qasm create mode 100644 mlir/unittests/programs/qasm_programs/repeated_measurement_to_same_bit.qasm create mode 100644 mlir/unittests/programs/qasm_programs/repeated_reset_after_single_op.qasm create mode 100644 mlir/unittests/programs/qasm_programs/reset_multiple_qubits_after_single_op.qasm create mode 100644 mlir/unittests/programs/qasm_programs/reset_qubit_after_single_op.qasm create mode 100644 mlir/unittests/programs/qasm_programs/rx.qasm create mode 100644 mlir/unittests/programs/qasm_programs/rxx.qasm create mode 100644 mlir/unittests/programs/qasm_programs/ry.qasm create mode 100644 mlir/unittests/programs/qasm_programs/ryy.qasm create mode 100644 mlir/unittests/programs/qasm_programs/rz.qasm create mode 100644 mlir/unittests/programs/qasm_programs/rzx.qasm create mode 100644 mlir/unittests/programs/qasm_programs/rzz.qasm create mode 100644 mlir/unittests/programs/qasm_programs/s.qasm create mode 100644 mlir/unittests/programs/qasm_programs/sdg.qasm create mode 100644 mlir/unittests/programs/qasm_programs/simple_if.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_dcx.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_ecr.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_h.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_identity.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_iswap.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_p.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_r.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_rx.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_rxx.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_ry.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_ryy.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_rz.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_rzx.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_rzz.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_s.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_sdg.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_swap.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_sx.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_sxdg.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_t.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_tdg.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_u.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_u2.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_x.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_xx_minus_yy.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_xx_plus_yy.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_y.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_z.qasm create mode 100644 mlir/unittests/programs/qasm_programs/single_measurement_to_single_bit.qasm create mode 100644 mlir/unittests/programs/qasm_programs/swap.qasm create mode 100644 mlir/unittests/programs/qasm_programs/sx.qasm create mode 100644 mlir/unittests/programs/qasm_programs/sxdg.qasm create mode 100644 mlir/unittests/programs/qasm_programs/t.qasm create mode 100644 mlir/unittests/programs/qasm_programs/tdg.qasm create mode 100644 mlir/unittests/programs/qasm_programs/triple_controlled_rxx.qasm create mode 100644 mlir/unittests/programs/qasm_programs/u.qasm create mode 100644 mlir/unittests/programs/qasm_programs/u2.qasm create mode 100644 mlir/unittests/programs/qasm_programs/xx_minus_yy.qasm create mode 100644 mlir/unittests/programs/qasm_programs/xx_plus_yy.qasm create mode 100644 mlir/unittests/programs/qasm_programs/y.qasm create mode 100644 mlir/unittests/programs/qasm_programs/z.qasm diff --git a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp index 855bcb50bc..b06490e1b4 100644 --- a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp +++ b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp @@ -69,37 +69,301 @@ class QASM3TranslationTest } // namespace TEST_P(QASM3TranslationTest, ProgramEquivalence) { - const auto& [name, path, referenceBuilder] = GetParam(); - const auto testName = " (" + name + ")"; - const auto programPath = (std::filesystem::path(__FILE__).parent_path() / - "../../../programs/qasm_programs" / path) - .lexically_normal() - .string(); + const auto name = " (" + GetParam().name + ")"; + const auto path = (std::filesystem::path(__FILE__).parent_path() / + "../../../programs/qasm_programs" / GetParam().path) + .lexically_normal() + .string(); + const auto referenceBuilder = GetParam().referenceBuilder; mqt::test::DeferredPrinter printer; - auto translated = qc::translateQASM3ToQC(context.get(), programPath); + auto translated = qc::translateQASM3ToQC(context.get(), path); ASSERT_TRUE(translated); - printer.record(translated.get(), "Translated QC IR" + testName); + printer.record(translated.get(), "Translated QC IR" + name); EXPECT_TRUE(verify(*translated).succeeded()); EXPECT_TRUE(runQCCleanupPipeline(translated.get()).succeeded()); - printer.record(translated.get(), "Canonicalized Translated QC IR" + testName); + printer.record(translated.get(), "Canonicalized Translated QC IR" + name); EXPECT_TRUE(verify(*translated).succeeded()); auto reference = qc::QCProgramBuilder::build(context.get(), referenceBuilder.fn); ASSERT_TRUE(reference); - printer.record(reference.get(), "Reference QC IR" + testName); + printer.record(reference.get(), "Reference QC IR" + name); EXPECT_TRUE(verify(*reference).succeeded()); EXPECT_TRUE(runQCCleanupPipeline(reference.get()).succeeded()); - printer.record(reference.get(), "Canonicalized Reference QC IR" + testName); + printer.record(reference.get(), "Canonicalized Reference QC IR" + name); EXPECT_TRUE(verify(*reference).succeeded()); EXPECT_TRUE( areModulesEquivalentWithPermutations(translated.get(), reference.get())); } -INSTANTIATE_TEST_SUITE_P(QASM3TranslationProgramsTest, QASM3TranslationTest, - testing::Values(QASM3TranslationTestCase{ - "X", "x.qasm", MQT_NAMED_BUILDER(qc::x)})); +INSTANTIATE_TEST_SUITE_P( + QASM3TranslationProgramsTest, QASM3TranslationTest, + testing::Values( + + QASM3TranslationTestCase{"AllocQubit", "alloc_qubit.qasm", + MQT_NAMED_BUILDER(qc::allocQubit)}, + QASM3TranslationTestCase{"AllocQubitRegister", + "alloc_qubit_register.qasm", + MQT_NAMED_BUILDER(qc::allocQubitRegister)}, + QASM3TranslationTestCase{ + "AllocMultipleQubitRegisters", + "alloc_multiple_qubit_registers.qasm", + MQT_NAMED_BUILDER(qc::allocMultipleQubitRegisters)}, + QASM3TranslationTestCase{"AllocLargeRegister", + "alloc_large_register.qasm", + MQT_NAMED_BUILDER(qc::allocLargeRegister)}, + QASM3TranslationTestCase{ + "SingleMeasurementToSingleBit", + "single_measurement_to_single_bit.qasm", + MQT_NAMED_BUILDER(qc::singleMeasurementToSingleBit)}, + QASM3TranslationTestCase{ + "RepeatedMeasurementToSameBit", + "repeated_measurement_to_same_bit.qasm", + MQT_NAMED_BUILDER(qc::repeatedMeasurementToSameBit)}, + QASM3TranslationTestCase{ + "RepeatedMeasurementToDifferentBits", + "repeated_measurement_to_different_bits.qasm", + MQT_NAMED_BUILDER(qc::repeatedMeasurementToDifferentBits)}, + QASM3TranslationTestCase{ + "MultipleClassicalRegistersAndMeasurements", + "multiple_classical_registers_and_measurements.qasm", + MQT_NAMED_BUILDER(qc::multipleClassicalRegistersAndMeasurements)}, + QASM3TranslationTestCase{ + "ResetQubitAfterSingleOp", "reset_qubit_after_single_op.qasm", + MQT_NAMED_BUILDER(qc::resetQubitAfterSingleOp)}, + QASM3TranslationTestCase{ + "ResetMultipleQubitsAfterSingleOp", + "reset_multiple_qubits_after_single_op.qasm", + MQT_NAMED_BUILDER(qc::resetMultipleQubitsAfterSingleOp)}, + QASM3TranslationTestCase{ + "RepeatedResetAfterSingleOp", "repeated_reset_after_single_op.qasm", + MQT_NAMED_BUILDER(qc::repeatedResetAfterSingleOp)}, + QASM3TranslationTestCase{"GlobalPhase", "global_phase.qasm", + MQT_NAMED_BUILDER(qc::globalPhase)}, + QASM3TranslationTestCase{"Identity", "identity.qasm", + MQT_NAMED_BUILDER(qc::identity)}, + QASM3TranslationTestCase{ + "SingleControlledIdentity", "single_controlled_identity.qasm", + MQT_NAMED_BUILDER(qc::singleControlledIdentity)}, + QASM3TranslationTestCase{ + "MultipleControlledIdentity", "multiple_controlled_identity.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledIdentity)}, + QASM3TranslationTestCase{"X", "x.qasm", MQT_NAMED_BUILDER(qc::x)}, + QASM3TranslationTestCase{"SingleControlledX", + "single_controlled_x.qasm", + MQT_NAMED_BUILDER(qc::singleControlledX)}, + QASM3TranslationTestCase{"MultipleControlledX", + "multiple_controlled_x.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledX)}, + QASM3TranslationTestCase{"Y", "y.qasm", MQT_NAMED_BUILDER(qc::y)}, + QASM3TranslationTestCase{"SingleControlledY", + "single_controlled_y.qasm", + MQT_NAMED_BUILDER(qc::singleControlledY)}, + QASM3TranslationTestCase{"MultipleControlledY", + "multiple_controlled_y.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledY)}, + QASM3TranslationTestCase{"Z", "z.qasm", MQT_NAMED_BUILDER(qc::z)}, + QASM3TranslationTestCase{"SingleControlledZ", + "single_controlled_z.qasm", + MQT_NAMED_BUILDER(qc::singleControlledZ)}, + QASM3TranslationTestCase{"MultipleControlledZ", + "multiple_controlled_z.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledZ)}, + QASM3TranslationTestCase{"H", "h.qasm", MQT_NAMED_BUILDER(qc::h)}, + QASM3TranslationTestCase{"SingleControlledH", + "single_controlled_h.qasm", + MQT_NAMED_BUILDER(qc::singleControlledH)}, + QASM3TranslationTestCase{"MultipleControlledH", + "multiple_controlled_h.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledH)}, + QASM3TranslationTestCase{"S", "s.qasm", MQT_NAMED_BUILDER(qc::s)}, + QASM3TranslationTestCase{"SingleControlledS", + "single_controlled_s.qasm", + MQT_NAMED_BUILDER(qc::singleControlledS)}, + QASM3TranslationTestCase{"MultipleControlledS", + "multiple_controlled_s.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledS)}, + QASM3TranslationTestCase{"Sdg", "sdg.qasm", MQT_NAMED_BUILDER(qc::sdg)}, + QASM3TranslationTestCase{"SingleControlledSdg", + "single_controlled_sdg.qasm", + MQT_NAMED_BUILDER(qc::singleControlledSdg)}, + QASM3TranslationTestCase{"MultipleControlledSdg", + "multiple_controlled_sdg.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledSdg)}, + QASM3TranslationTestCase{"T", "t.qasm", MQT_NAMED_BUILDER(qc::t_)}, + QASM3TranslationTestCase{"SingleControlledT", + "single_controlled_t.qasm", + MQT_NAMED_BUILDER(qc::singleControlledT)}, + QASM3TranslationTestCase{"MultipleControlledT", + "multiple_controlled_t.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledT)}, + QASM3TranslationTestCase{"Tdg", "tdg.qasm", MQT_NAMED_BUILDER(qc::tdg)}, + QASM3TranslationTestCase{"SingleControlledTdg", + "single_controlled_tdg.qasm", + MQT_NAMED_BUILDER(qc::singleControlledTdg)}, + QASM3TranslationTestCase{"MultipleControlledTdg", + "multiple_controlled_tdg.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledTdg)}, + QASM3TranslationTestCase{"SX", "sx.qasm", MQT_NAMED_BUILDER(qc::sx)}, + QASM3TranslationTestCase{"SingleControlledSX", + "single_controlled_sx.qasm", + MQT_NAMED_BUILDER(qc::singleControlledSx)}, + QASM3TranslationTestCase{"MultipleControlledSX", + "multiple_controlled_sx.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledSx)}, + QASM3TranslationTestCase{"SXdg", "sxdg.qasm", + MQT_NAMED_BUILDER(qc::sxdg)}, + QASM3TranslationTestCase{"SingleControlledSXdg", + "single_controlled_sxdg.qasm", + MQT_NAMED_BUILDER(qc::singleControlledSxdg)}, + QASM3TranslationTestCase{"MultipleControlledSXdg", + "multiple_controlled_sxdg.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledSxdg)}, + QASM3TranslationTestCase{"RX", "rx.qasm", MQT_NAMED_BUILDER(qc::rx)}, + QASM3TranslationTestCase{"SingleControlledRX", + "single_controlled_rx.qasm", + MQT_NAMED_BUILDER(qc::singleControlledRx)}, + QASM3TranslationTestCase{"MultipleControlledRX", + "multiple_controlled_rx.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledRx)}, + QASM3TranslationTestCase{"RY", "ry.qasm", MQT_NAMED_BUILDER(qc::ry)}, + QASM3TranslationTestCase{"SingleControlledRY", + "single_controlled_ry.qasm", + MQT_NAMED_BUILDER(qc::singleControlledRy)}, + QASM3TranslationTestCase{"MultipleControlledRY", + "multiple_controlled_ry.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledRy)}, + QASM3TranslationTestCase{"RZ", "rz.qasm", MQT_NAMED_BUILDER(qc::rz)}, + QASM3TranslationTestCase{"SingleControlledRZ", + "single_controlled_rz.qasm", + MQT_NAMED_BUILDER(qc::singleControlledRz)}, + QASM3TranslationTestCase{"MultipleControlledRZ", + "multiple_controlled_rz.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledRz)}, + QASM3TranslationTestCase{"P", "p.qasm", MQT_NAMED_BUILDER(qc::p)}, + QASM3TranslationTestCase{"SingleControlledP", + "single_controlled_p.qasm", + MQT_NAMED_BUILDER(qc::singleControlledP)}, + QASM3TranslationTestCase{"MultipleControlledP", + "multiple_controlled_p.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledP)}, + QASM3TranslationTestCase{"R", "r.qasm", MQT_NAMED_BUILDER(qc::r)}, + QASM3TranslationTestCase{"SingleControlledR", + "single_controlled_r.qasm", + MQT_NAMED_BUILDER(qc::singleControlledR)}, + QASM3TranslationTestCase{"MultipleControlledR", + "multiple_controlled_r.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledR)}, + QASM3TranslationTestCase{"U2", "u2.qasm", MQT_NAMED_BUILDER(qc::u2)}, + QASM3TranslationTestCase{"SingleControlledU2", + "single_controlled_u2.qasm", + MQT_NAMED_BUILDER(qc::singleControlledU2)}, + QASM3TranslationTestCase{"MultipleControlledU2", + "multiple_controlled_u2.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledU2)}, + QASM3TranslationTestCase{"U", "u.qasm", MQT_NAMED_BUILDER(qc::u)}, + QASM3TranslationTestCase{"SingleControlledU", + "single_controlled_u.qasm", + MQT_NAMED_BUILDER(qc::singleControlledU)}, + QASM3TranslationTestCase{"MultipleControlledU", + "multiple_controlled_u.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledU)}, + QASM3TranslationTestCase{"SWAP", "swap.qasm", + MQT_NAMED_BUILDER(qc::swap)}, + QASM3TranslationTestCase{"SingleControlledSWAP", + "single_controlled_swap.qasm", + MQT_NAMED_BUILDER(qc::singleControlledSwap)}, + QASM3TranslationTestCase{"MultipleControlledSWAP", + "multiple_controlled_swap.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledSwap)}, + QASM3TranslationTestCase{"iSWAP", "iswap.qasm", + MQT_NAMED_BUILDER(qc::iswap)}, + QASM3TranslationTestCase{"SingleControllediSWAP", + "single_controlled_iswap.qasm", + MQT_NAMED_BUILDER(qc::singleControlledIswap)}, + QASM3TranslationTestCase{ + "MultipleControllediSWAP", "multiple_controlled_iswap.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledIswap)}, + QASM3TranslationTestCase{"InverseISWAP", "inverse_iswap.qasm", + MQT_NAMED_BUILDER(qc::inverseIswap)}, + QASM3TranslationTestCase{ + "InverseMultiControlledISWAP", + "inverse_multiple_controlled_iswap.qasm", + MQT_NAMED_BUILDER(qc::inverseMultipleControlledIswap)}, + QASM3TranslationTestCase{"DCX", "dcx.qasm", MQT_NAMED_BUILDER(qc::dcx)}, + QASM3TranslationTestCase{"SingleControlledDCX", + "single_controlled_dcx.qasm", + MQT_NAMED_BUILDER(qc::singleControlledDcx)}, + QASM3TranslationTestCase{"MultipleControlledDCX", + "multiple_controlled_dcx.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledDcx)}, + QASM3TranslationTestCase{"ECR", "ecr.qasm", MQT_NAMED_BUILDER(qc::ecr)}, + QASM3TranslationTestCase{"SingleControlledECR", + "single_controlled_ecr.qasm", + MQT_NAMED_BUILDER(qc::singleControlledEcr)}, + QASM3TranslationTestCase{"MultipleControlledECR", + "multiple_controlled_ecr.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledEcr)}, + QASM3TranslationTestCase{"RXX", "rxx.qasm", MQT_NAMED_BUILDER(qc::rxx)}, + QASM3TranslationTestCase{"SingleControlledRXX", + "single_controlled_rxx.qasm", + MQT_NAMED_BUILDER(qc::singleControlledRxx)}, + QASM3TranslationTestCase{"MultipleControlledRXX", + "multiple_controlled_rxx.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledRxx)}, + QASM3TranslationTestCase{"TripleControlledRXX", + "triple_controlled_rxx.qasm", + MQT_NAMED_BUILDER(qc::tripleControlledRxx)}, + QASM3TranslationTestCase{"RYY", "ryy.qasm", MQT_NAMED_BUILDER(qc::ryy)}, + QASM3TranslationTestCase{"SingleControlledRYY", + "single_controlled_ryy.qasm", + MQT_NAMED_BUILDER(qc::singleControlledRyy)}, + QASM3TranslationTestCase{"MultipleControlledRYY", + "multiple_controlled_ryy.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledRyy)}, + QASM3TranslationTestCase{"RZX", "rzx.qasm", MQT_NAMED_BUILDER(qc::rzx)}, + QASM3TranslationTestCase{"SingleControlledRZX", + "single_controlled_rzx.qasm", + MQT_NAMED_BUILDER(qc::singleControlledRzx)}, + QASM3TranslationTestCase{"MultipleControlledRZX", + "multiple_controlled_rzx.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledRzx)}, + QASM3TranslationTestCase{"RZZ", "rzz.qasm", MQT_NAMED_BUILDER(qc::rzz)}, + QASM3TranslationTestCase{"SingleControlledRZZ", + "single_controlled_rzz.qasm", + MQT_NAMED_BUILDER(qc::singleControlledRzz)}, + QASM3TranslationTestCase{"MultipleControlledRZZ", + "multiple_controlled_rzz.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledRzz)}, + QASM3TranslationTestCase{"XXPlusYY", "xx_plus_yy.qasm", + MQT_NAMED_BUILDER(qc::xxPlusYY)}, + QASM3TranslationTestCase{ + "SingleControlledXXPlusYY", "single_controlled_xx_plus_yy.qasm", + MQT_NAMED_BUILDER(qc::singleControlledXxPlusYY)}, + QASM3TranslationTestCase{ + "MultipleControlledXXPlusYY", "multiple_controlled_xx_plus_yy.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledXxPlusYY)}, + QASM3TranslationTestCase{"XXMinusYY", "xx_minus_yy.qasm", + MQT_NAMED_BUILDER(qc::xxMinusYY)}, + QASM3TranslationTestCase{ + "SingleControlledXXMinusYY", "single_controlled_xx_minus_yy.qasm", + MQT_NAMED_BUILDER(qc::singleControlledXxMinusYY)}, + QASM3TranslationTestCase{ + "MultipleControlledXXMinusYY", + "multiple_controlled_xx_minus_yy.qasm", + MQT_NAMED_BUILDER(qc::multipleControlledXxMinusYY)}, + QASM3TranslationTestCase{"Barrier", "barrier.qasm", + MQT_NAMED_BUILDER(qc::barrier)}, + QASM3TranslationTestCase{"BarrierTwoQubits", "barrier_two_qubits.qasm", + MQT_NAMED_BUILDER(qc::barrierTwoQubits)}, + QASM3TranslationTestCase{"BarrierMultipleQubits", + "barrier_multiple_qubits.qasm", + MQT_NAMED_BUILDER(qc::barrierMultipleQubits)}, + QASM3TranslationTestCase{"SimpleIf", "simple_if.qasm", + MQT_NAMED_BUILDER(qc::simpleIf)}, + QASM3TranslationTestCase{"IfElse", "if_else.qasm", + MQT_NAMED_BUILDER(qc::ifElse)})); diff --git a/mlir/unittests/programs/qasm_programs/alloc_large_register.qasm b/mlir/unittests/programs/qasm_programs/alloc_large_register.qasm new file mode 100644 index 0000000000..71e739f093 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/alloc_large_register.qasm @@ -0,0 +1,3 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[100] q; diff --git a/mlir/unittests/programs/qasm_programs/alloc_multiple_qubit_registers.qasm b/mlir/unittests/programs/qasm_programs/alloc_multiple_qubit_registers.qasm new file mode 100644 index 0000000000..8170a1b74e --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/alloc_multiple_qubit_registers.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q0; +qubit[3] q1; diff --git a/mlir/unittests/programs/qasm_programs/alloc_qubit.qasm b/mlir/unittests/programs/qasm_programs/alloc_qubit.qasm new file mode 100644 index 0000000000..e554e3ead6 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/alloc_qubit.qasm @@ -0,0 +1,3 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit q; diff --git a/mlir/unittests/programs/qasm_programs/alloc_qubit_register.qasm b/mlir/unittests/programs/qasm_programs/alloc_qubit_register.qasm new file mode 100644 index 0000000000..bae5459616 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/alloc_qubit_register.qasm @@ -0,0 +1,3 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; diff --git a/mlir/unittests/programs/qasm_programs/barrier.qasm b/mlir/unittests/programs/qasm_programs/barrier.qasm new file mode 100644 index 0000000000..0f8146de84 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/barrier.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +barrier q[0]; diff --git a/mlir/unittests/programs/qasm_programs/barrier_multiple_qubits.qasm b/mlir/unittests/programs/qasm_programs/barrier_multiple_qubits.qasm new file mode 100644 index 0000000000..461527b1af --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/barrier_multiple_qubits.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +barrier q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/barrier_two_qubits.qasm b/mlir/unittests/programs/qasm_programs/barrier_two_qubits.qasm new file mode 100644 index 0000000000..ca131706a2 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/barrier_two_qubits.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +barrier q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/dcx.qasm b/mlir/unittests/programs/qasm_programs/dcx.qasm new file mode 100644 index 0000000000..1d3b7bdd1d --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/dcx.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +dcx q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/ecr.qasm b/mlir/unittests/programs/qasm_programs/ecr.qasm new file mode 100644 index 0000000000..3a405f64f8 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/ecr.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ecr q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/global_phase.qasm b/mlir/unittests/programs/qasm_programs/global_phase.qasm new file mode 100644 index 0000000000..2532e2dd25 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/global_phase.qasm @@ -0,0 +1,3 @@ +OPENQASM 3.0; +include "stdgates.inc"; +gphase(0.123); diff --git a/mlir/unittests/programs/qasm_programs/h.qasm b/mlir/unittests/programs/qasm_programs/h.qasm new file mode 100644 index 0000000000..9e9234ecac --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/h.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +h q[0]; diff --git a/mlir/unittests/programs/qasm_programs/identity.qasm b/mlir/unittests/programs/qasm_programs/identity.qasm new file mode 100644 index 0000000000..b8452cf533 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/identity.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +id q[0]; diff --git a/mlir/unittests/programs/qasm_programs/if_else.qasm b/mlir/unittests/programs/qasm_programs/if_else.qasm new file mode 100644 index 0000000000..c62256c538 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/if_else.qasm @@ -0,0 +1,10 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +h q[0]; +bit c = measure q[0]; +if (c) { + x q[0]; +} else { + z q[0]; +} diff --git a/mlir/unittests/programs/qasm_programs/inverse_iswap.qasm b/mlir/unittests/programs/qasm_programs/inverse_iswap.qasm new file mode 100644 index 0000000000..2465e6ccb6 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/inverse_iswap.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +inv @ iswap q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/inverse_multiple_controlled_iswap.qasm b/mlir/unittests/programs/qasm_programs/inverse_multiple_controlled_iswap.qasm new file mode 100644 index 0000000000..4b3069faa8 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/inverse_multiple_controlled_iswap.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +inv @ ctrl(2) @ iswap q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/iswap.qasm b/mlir/unittests/programs/qasm_programs/iswap.qasm new file mode 100644 index 0000000000..0ada326399 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/iswap.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +iswap q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_classical_registers_and_measurements.qasm b/mlir/unittests/programs/qasm_programs/multiple_classical_registers_and_measurements.qasm new file mode 100644 index 0000000000..529d4b5e01 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_classical_registers_and_measurements.qasm @@ -0,0 +1,8 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +bit[1] c0; +bit[2] c1; +measure q[0] -> c0[0]; +measure q[1] -> c1[0]; +measure q[2] -> c1[1]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_dcx.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_dcx.qasm new file mode 100644 index 0000000000..f6dfc9e878 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_dcx.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ dcx q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_ecr.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_ecr.qasm new file mode 100644 index 0000000000..de4b4a2260 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_ecr.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ ecr q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_h.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_h.qasm new file mode 100644 index 0000000000..bf0056c1d3 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_h.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ h q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_identity.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_identity.qasm new file mode 100644 index 0000000000..cf59ab3d28 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_identity.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ id q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_iswap.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_iswap.qasm new file mode 100644 index 0000000000..f93ee67e9b --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_iswap.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ iswap q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_p.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_p.qasm new file mode 100644 index 0000000000..b7b43a767f --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_p.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ p(0.123) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_r.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_r.qasm new file mode 100644 index 0000000000..a3d7c0f0e9 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_r.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ r(0.123, 0.456) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_rx.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_rx.qasm new file mode 100644 index 0000000000..166b7ff699 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_rx.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ rx(0.123) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_rxx.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_rxx.qasm new file mode 100644 index 0000000000..fc0a6cc3c3 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_rxx.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ rxx(0.123) q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_ry.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_ry.qasm new file mode 100644 index 0000000000..b15f92b362 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_ry.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ ry(0.456) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_ryy.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_ryy.qasm new file mode 100644 index 0000000000..854bbed0b7 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_ryy.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ ryy(0.123) q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_rz.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_rz.qasm new file mode 100644 index 0000000000..ffaece3669 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_rz.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ rz(0.789) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_rzx.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_rzx.qasm new file mode 100644 index 0000000000..03059967e4 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_rzx.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ rzx(0.123) q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_rzz.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_rzz.qasm new file mode 100644 index 0000000000..599e3e2324 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_rzz.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ rzz(0.123) q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_s.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_s.qasm new file mode 100644 index 0000000000..bdb4ff1289 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_s.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ s q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_sdg.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_sdg.qasm new file mode 100644 index 0000000000..89bd46f179 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_sdg.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ sdg q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_swap.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_swap.qasm new file mode 100644 index 0000000000..d6d80fe48c --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_swap.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ swap q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_sx.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_sx.qasm new file mode 100644 index 0000000000..1586502e77 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_sx.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ sx q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_sxdg.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_sxdg.qasm new file mode 100644 index 0000000000..981c691264 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_sxdg.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ sxdg q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_t.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_t.qasm new file mode 100644 index 0000000000..53dde4bbff --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_t.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ t q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_tdg.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_tdg.qasm new file mode 100644 index 0000000000..60f644e391 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_tdg.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ tdg q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_u.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_u.qasm new file mode 100644 index 0000000000..b49ada9f23 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_u.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ u(0.1, 0.2, 0.3) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_u2.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_u2.qasm new file mode 100644 index 0000000000..fc73530086 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_u2.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ u2(0.234, 0.567) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_x.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_x.qasm new file mode 100644 index 0000000000..4ff0ae8383 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_x.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ x q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_xx_minus_yy.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_xx_minus_yy.qasm new file mode 100644 index 0000000000..abf5985fd3 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_xx_minus_yy.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ xx_minus_yy(0.123, 0.456) q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_xx_plus_yy.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_xx_plus_yy.qasm new file mode 100644 index 0000000000..0509793dca --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_xx_plus_yy.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ xx_plus_yy(0.123, 0.456) q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_y.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_y.qasm new file mode 100644 index 0000000000..e4c556cc06 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_y.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ y q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_z.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_z.qasm new file mode 100644 index 0000000000..9d592a27ba --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/multiple_controlled_z.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ z q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/p.qasm b/mlir/unittests/programs/qasm_programs/p.qasm new file mode 100644 index 0000000000..6c52e0521d --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/p.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +p(0.123) q[0]; diff --git a/mlir/unittests/programs/qasm_programs/r.qasm b/mlir/unittests/programs/qasm_programs/r.qasm new file mode 100644 index 0000000000..ab7119c712 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/r.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +r(0.123, 0.456) q[0]; diff --git a/mlir/unittests/programs/qasm_programs/repeated_measurement_to_different_bits.qasm b/mlir/unittests/programs/qasm_programs/repeated_measurement_to_different_bits.qasm new file mode 100644 index 0000000000..618e5e8aa2 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/repeated_measurement_to_different_bits.qasm @@ -0,0 +1,7 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +bit[3] c; +measure q[0] -> c[0]; +measure q[0] -> c[1]; +measure q[0] -> c[2]; diff --git a/mlir/unittests/programs/qasm_programs/repeated_measurement_to_same_bit.qasm b/mlir/unittests/programs/qasm_programs/repeated_measurement_to_same_bit.qasm new file mode 100644 index 0000000000..1dcee58a02 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/repeated_measurement_to_same_bit.qasm @@ -0,0 +1,7 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +bit[1] c; +measure q[0] -> c[0]; +measure q[0] -> c[0]; +measure q[0] -> c[0]; diff --git a/mlir/unittests/programs/qasm_programs/repeated_reset_after_single_op.qasm b/mlir/unittests/programs/qasm_programs/repeated_reset_after_single_op.qasm new file mode 100644 index 0000000000..068073f7aa --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/repeated_reset_after_single_op.qasm @@ -0,0 +1,7 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +h q[0]; +reset q[0]; +reset q[0]; +reset q[0]; diff --git a/mlir/unittests/programs/qasm_programs/reset_multiple_qubits_after_single_op.qasm b/mlir/unittests/programs/qasm_programs/reset_multiple_qubits_after_single_op.qasm new file mode 100644 index 0000000000..a917c83849 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/reset_multiple_qubits_after_single_op.qasm @@ -0,0 +1,7 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +h q[0]; +reset q[0]; +h q[1]; +reset q[1]; diff --git a/mlir/unittests/programs/qasm_programs/reset_qubit_after_single_op.qasm b/mlir/unittests/programs/qasm_programs/reset_qubit_after_single_op.qasm new file mode 100644 index 0000000000..ec3876c49a --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/reset_qubit_after_single_op.qasm @@ -0,0 +1,5 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +h q[0]; +reset q[0]; diff --git a/mlir/unittests/programs/qasm_programs/rx.qasm b/mlir/unittests/programs/qasm_programs/rx.qasm new file mode 100644 index 0000000000..b5598e43bc --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/rx.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +rx(0.123) q[0]; diff --git a/mlir/unittests/programs/qasm_programs/rxx.qasm b/mlir/unittests/programs/qasm_programs/rxx.qasm new file mode 100644 index 0000000000..a039e1793d --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/rxx.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +rxx(0.123) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/ry.qasm b/mlir/unittests/programs/qasm_programs/ry.qasm new file mode 100644 index 0000000000..a981275476 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/ry.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +ry(0.456) q[0]; diff --git a/mlir/unittests/programs/qasm_programs/ryy.qasm b/mlir/unittests/programs/qasm_programs/ryy.qasm new file mode 100644 index 0000000000..b980249363 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/ryy.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ryy(0.123) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/rz.qasm b/mlir/unittests/programs/qasm_programs/rz.qasm new file mode 100644 index 0000000000..85b10988ca --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/rz.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +rz(0.789) q[0]; diff --git a/mlir/unittests/programs/qasm_programs/rzx.qasm b/mlir/unittests/programs/qasm_programs/rzx.qasm new file mode 100644 index 0000000000..226dc6ad25 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/rzx.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +rzx(0.123) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/rzz.qasm b/mlir/unittests/programs/qasm_programs/rzz.qasm new file mode 100644 index 0000000000..9af26ea2ef --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/rzz.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +rzz(0.123) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/s.qasm b/mlir/unittests/programs/qasm_programs/s.qasm new file mode 100644 index 0000000000..5eae687443 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/s.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +s q[0]; diff --git a/mlir/unittests/programs/qasm_programs/sdg.qasm b/mlir/unittests/programs/qasm_programs/sdg.qasm new file mode 100644 index 0000000000..964cd16efe --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/sdg.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +sdg q[0]; diff --git a/mlir/unittests/programs/qasm_programs/simple_if.qasm b/mlir/unittests/programs/qasm_programs/simple_if.qasm new file mode 100644 index 0000000000..849afb783c --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/simple_if.qasm @@ -0,0 +1,8 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +h q[0]; +bit c = measure q[0]; +if (c) { + x q[0]; +} diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_dcx.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_dcx.qasm new file mode 100644 index 0000000000..aeb9b73fa5 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_dcx.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ dcx q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_ecr.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_ecr.qasm new file mode 100644 index 0000000000..27a047d5da --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_ecr.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ ecr q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_h.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_h.qasm new file mode 100644 index 0000000000..92ef140657 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_h.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ h q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_identity.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_identity.qasm new file mode 100644 index 0000000000..d390c72cca --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_identity.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ id q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_iswap.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_iswap.qasm new file mode 100644 index 0000000000..d5b992b6ad --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_iswap.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ iswap q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_p.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_p.qasm new file mode 100644 index 0000000000..aaf6fa5a6a --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_p.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ p(0.123) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_r.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_r.qasm new file mode 100644 index 0000000000..19a1f43b69 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_r.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ r(0.123, 0.456) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_rx.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_rx.qasm new file mode 100644 index 0000000000..cc3ee01eb1 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_rx.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ rx(0.123) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_rxx.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_rxx.qasm new file mode 100644 index 0000000000..2237fbb5db --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_rxx.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ rxx(0.123) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_ry.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_ry.qasm new file mode 100644 index 0000000000..90ac2e40b4 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_ry.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ ry(0.456) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_ryy.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_ryy.qasm new file mode 100644 index 0000000000..14ad65ccc8 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_ryy.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ ryy(0.123) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_rz.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_rz.qasm new file mode 100644 index 0000000000..b551d82411 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_rz.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ rz(0.789) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_rzx.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_rzx.qasm new file mode 100644 index 0000000000..bd6f5b2356 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_rzx.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ rzx(0.123) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_rzz.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_rzz.qasm new file mode 100644 index 0000000000..902b8e6423 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_rzz.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ rzz(0.123) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_s.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_s.qasm new file mode 100644 index 0000000000..3a106d3a2d --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_s.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ s q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_sdg.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_sdg.qasm new file mode 100644 index 0000000000..f2515862e4 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_sdg.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ sdg q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_swap.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_swap.qasm new file mode 100644 index 0000000000..fddea0d328 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_swap.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ swap q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_sx.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_sx.qasm new file mode 100644 index 0000000000..4dd2915543 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_sx.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ sx q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_sxdg.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_sxdg.qasm new file mode 100644 index 0000000000..dd48f8caad --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_sxdg.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ sxdg q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_t.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_t.qasm new file mode 100644 index 0000000000..3add5c2958 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_t.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ t q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_tdg.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_tdg.qasm new file mode 100644 index 0000000000..d912f81565 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_tdg.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ tdg q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_u.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_u.qasm new file mode 100644 index 0000000000..034abf0fef --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_u.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ u(0.1, 0.2, 0.3) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_u2.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_u2.qasm new file mode 100644 index 0000000000..31e2811443 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_u2.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ u2(0.234, 0.567) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_x.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_x.qasm new file mode 100644 index 0000000000..c9697fa140 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_x.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ x q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_xx_minus_yy.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_xx_minus_yy.qasm new file mode 100644 index 0000000000..11caeb1dfa --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_xx_minus_yy.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ xx_minus_yy(0.123, 0.456) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_xx_plus_yy.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_xx_plus_yy.qasm new file mode 100644 index 0000000000..1ccb5ae4fd --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_xx_plus_yy.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ xx_plus_yy(0.123, 0.456) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_y.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_y.qasm new file mode 100644 index 0000000000..e3866216ce --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_y.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ y q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_z.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_z.qasm new file mode 100644 index 0000000000..fcf8128e7c --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_controlled_z.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ z q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_measurement_to_single_bit.qasm b/mlir/unittests/programs/qasm_programs/single_measurement_to_single_bit.qasm new file mode 100644 index 0000000000..b22d6a268c --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/single_measurement_to_single_bit.qasm @@ -0,0 +1,5 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +bit[1] c; +measure q[0] -> c[0]; diff --git a/mlir/unittests/programs/qasm_programs/swap.qasm b/mlir/unittests/programs/qasm_programs/swap.qasm new file mode 100644 index 0000000000..b34d111db6 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/swap.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +swap q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/sx.qasm b/mlir/unittests/programs/qasm_programs/sx.qasm new file mode 100644 index 0000000000..ba22a0d3e4 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/sx.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +sx q[0]; diff --git a/mlir/unittests/programs/qasm_programs/sxdg.qasm b/mlir/unittests/programs/qasm_programs/sxdg.qasm new file mode 100644 index 0000000000..98dc3d985c --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/sxdg.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +sxdg q[0]; diff --git a/mlir/unittests/programs/qasm_programs/t.qasm b/mlir/unittests/programs/qasm_programs/t.qasm new file mode 100644 index 0000000000..0cefa70c64 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/t.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +t q[0]; diff --git a/mlir/unittests/programs/qasm_programs/tdg.qasm b/mlir/unittests/programs/qasm_programs/tdg.qasm new file mode 100644 index 0000000000..8a8a75a925 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/tdg.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +tdg q[0]; diff --git a/mlir/unittests/programs/qasm_programs/triple_controlled_rxx.qasm b/mlir/unittests/programs/qasm_programs/triple_controlled_rxx.qasm new file mode 100644 index 0000000000..4d67e1a43d --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/triple_controlled_rxx.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[5] q; +ctrl(3) @ rxx(0.123) q[0], q[1], q[2], q[3], q[4]; diff --git a/mlir/unittests/programs/qasm_programs/u.qasm b/mlir/unittests/programs/qasm_programs/u.qasm new file mode 100644 index 0000000000..b291fd60c3 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/u.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +u(0.1, 0.2, 0.3) q[0]; diff --git a/mlir/unittests/programs/qasm_programs/u2.qasm b/mlir/unittests/programs/qasm_programs/u2.qasm new file mode 100644 index 0000000000..3be1fcda9c --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/u2.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +u2(0.234, 0.567) q[0]; diff --git a/mlir/unittests/programs/qasm_programs/xx_minus_yy.qasm b/mlir/unittests/programs/qasm_programs/xx_minus_yy.qasm new file mode 100644 index 0000000000..5c24a15edd --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/xx_minus_yy.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +xx_minus_yy(0.123, 0.456) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/xx_plus_yy.qasm b/mlir/unittests/programs/qasm_programs/xx_plus_yy.qasm new file mode 100644 index 0000000000..8667800627 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/xx_plus_yy.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +xx_plus_yy(0.123, 0.456) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/y.qasm b/mlir/unittests/programs/qasm_programs/y.qasm new file mode 100644 index 0000000000..b418d084b9 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/y.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +y q[0]; diff --git a/mlir/unittests/programs/qasm_programs/z.qasm b/mlir/unittests/programs/qasm_programs/z.qasm new file mode 100644 index 0000000000..239658928e --- /dev/null +++ b/mlir/unittests/programs/qasm_programs/z.qasm @@ -0,0 +1,4 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +z q[0]; From 987f667fcc587d45e0f20ff4e96c9ef1207a064e Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 21 May 2026 15:46:06 +0200 Subject: [PATCH 10/48] Fix some more linter errors --- mlir/tools/mqt-cc/mqt-cc.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/mlir/tools/mqt-cc/mqt-cc.cpp b/mlir/tools/mqt-cc/mqt-cc.cpp index 8cdaa52f2d..0ecfc75c58 100644 --- a/mlir/tools/mqt-cc/mqt-cc.cpp +++ b/mlir/tools/mqt-cc/mqt-cc.cpp @@ -33,7 +33,6 @@ #include #include -#include #include #include From 16a3da76f82f90c4bc067eda0cfb7512286b2a2b Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 21 May 2026 16:40:41 +0200 Subject: [PATCH 11/48] Replace .qasm files with in-source strings --- .../Dialect/QC/Translation/CMakeLists.txt | 1 + .../QC/Translation/test_qasm3_translation.cpp | 245 +++---- mlir/unittests/programs/CMakeLists.txt | 4 + mlir/unittests/programs/qasm_programs.cpp | 664 ++++++++++++++++++ mlir/unittests/programs/qasm_programs.h | 330 +++++++++ .../qasm_programs/alloc_large_register.qasm | 3 - .../alloc_multiple_qubit_registers.qasm | 4 - .../programs/qasm_programs/alloc_qubit.qasm | 3 - .../qasm_programs/alloc_qubit_register.qasm | 3 - .../programs/qasm_programs/barrier.qasm | 4 - .../barrier_multiple_qubits.qasm | 4 - .../qasm_programs/barrier_two_qubits.qasm | 4 - .../unittests/programs/qasm_programs/dcx.qasm | 4 - .../unittests/programs/qasm_programs/ecr.qasm | 4 - .../programs/qasm_programs/global_phase.qasm | 3 - mlir/unittests/programs/qasm_programs/h.qasm | 4 - .../programs/qasm_programs/identity.qasm | 4 - .../programs/qasm_programs/if_else.qasm | 10 - .../programs/qasm_programs/inverse_iswap.qasm | 4 - .../inverse_multiple_controlled_iswap.qasm | 4 - .../programs/qasm_programs/iswap.qasm | 4 - ..._classical_registers_and_measurements.qasm | 8 - .../multiple_controlled_dcx.qasm | 4 - .../multiple_controlled_ecr.qasm | 4 - .../qasm_programs/multiple_controlled_h.qasm | 4 - .../multiple_controlled_identity.qasm | 4 - .../multiple_controlled_iswap.qasm | 4 - .../qasm_programs/multiple_controlled_p.qasm | 4 - .../qasm_programs/multiple_controlled_r.qasm | 4 - .../qasm_programs/multiple_controlled_rx.qasm | 4 - .../multiple_controlled_rxx.qasm | 4 - .../qasm_programs/multiple_controlled_ry.qasm | 4 - .../multiple_controlled_ryy.qasm | 4 - .../qasm_programs/multiple_controlled_rz.qasm | 4 - .../multiple_controlled_rzx.qasm | 4 - .../multiple_controlled_rzz.qasm | 4 - .../qasm_programs/multiple_controlled_s.qasm | 4 - .../multiple_controlled_sdg.qasm | 4 - .../multiple_controlled_swap.qasm | 4 - .../qasm_programs/multiple_controlled_sx.qasm | 4 - .../multiple_controlled_sxdg.qasm | 4 - .../qasm_programs/multiple_controlled_t.qasm | 4 - .../multiple_controlled_tdg.qasm | 4 - .../qasm_programs/multiple_controlled_u.qasm | 4 - .../qasm_programs/multiple_controlled_u2.qasm | 4 - .../qasm_programs/multiple_controlled_x.qasm | 4 - .../multiple_controlled_xx_minus_yy.qasm | 4 - .../multiple_controlled_xx_plus_yy.qasm | 4 - .../qasm_programs/multiple_controlled_y.qasm | 4 - .../qasm_programs/multiple_controlled_z.qasm | 4 - mlir/unittests/programs/qasm_programs/p.qasm | 4 - mlir/unittests/programs/qasm_programs/r.qasm | 4 - ...epeated_measurement_to_different_bits.qasm | 7 - .../repeated_measurement_to_same_bit.qasm | 7 - .../repeated_reset_after_single_op.qasm | 7 - ...reset_multiple_qubits_after_single_op.qasm | 7 - .../reset_qubit_after_single_op.qasm | 5 - mlir/unittests/programs/qasm_programs/rx.qasm | 4 - .../unittests/programs/qasm_programs/rxx.qasm | 4 - mlir/unittests/programs/qasm_programs/ry.qasm | 4 - .../unittests/programs/qasm_programs/ryy.qasm | 4 - mlir/unittests/programs/qasm_programs/rz.qasm | 4 - .../unittests/programs/qasm_programs/rzx.qasm | 4 - .../unittests/programs/qasm_programs/rzz.qasm | 4 - mlir/unittests/programs/qasm_programs/s.qasm | 4 - .../unittests/programs/qasm_programs/sdg.qasm | 4 - .../programs/qasm_programs/simple_if.qasm | 8 - .../qasm_programs/single_controlled_dcx.qasm | 4 - .../qasm_programs/single_controlled_ecr.qasm | 4 - .../qasm_programs/single_controlled_h.qasm | 4 - .../single_controlled_identity.qasm | 4 - .../single_controlled_iswap.qasm | 4 - .../qasm_programs/single_controlled_p.qasm | 4 - .../qasm_programs/single_controlled_r.qasm | 4 - .../qasm_programs/single_controlled_rx.qasm | 4 - .../qasm_programs/single_controlled_rxx.qasm | 4 - .../qasm_programs/single_controlled_ry.qasm | 4 - .../qasm_programs/single_controlled_ryy.qasm | 4 - .../qasm_programs/single_controlled_rz.qasm | 4 - .../qasm_programs/single_controlled_rzx.qasm | 4 - .../qasm_programs/single_controlled_rzz.qasm | 4 - .../qasm_programs/single_controlled_s.qasm | 4 - .../qasm_programs/single_controlled_sdg.qasm | 4 - .../qasm_programs/single_controlled_swap.qasm | 4 - .../qasm_programs/single_controlled_sx.qasm | 4 - .../qasm_programs/single_controlled_sxdg.qasm | 4 - .../qasm_programs/single_controlled_t.qasm | 4 - .../qasm_programs/single_controlled_tdg.qasm | 4 - .../qasm_programs/single_controlled_u.qasm | 4 - .../qasm_programs/single_controlled_u2.qasm | 4 - .../qasm_programs/single_controlled_x.qasm | 4 - .../single_controlled_xx_minus_yy.qasm | 4 - .../single_controlled_xx_plus_yy.qasm | 4 - .../qasm_programs/single_controlled_y.qasm | 4 - .../qasm_programs/single_controlled_z.qasm | 4 - .../single_measurement_to_single_bit.qasm | 5 - .../programs/qasm_programs/swap.qasm | 4 - mlir/unittests/programs/qasm_programs/sx.qasm | 4 - .../programs/qasm_programs/sxdg.qasm | 4 - mlir/unittests/programs/qasm_programs/t.qasm | 4 - .../unittests/programs/qasm_programs/tdg.qasm | 4 - .../qasm_programs/triple_controlled_rxx.qasm | 4 - mlir/unittests/programs/qasm_programs/u.qasm | 4 - mlir/unittests/programs/qasm_programs/u2.qasm | 4 - mlir/unittests/programs/qasm_programs/x.qasm | 4 - .../programs/qasm_programs/xx_minus_yy.qasm | 4 - .../programs/qasm_programs/xx_plus_yy.qasm | 4 - mlir/unittests/programs/qasm_programs/y.qasm | 4 - mlir/unittests/programs/qasm_programs/z.qasm | 4 - 109 files changed, 1110 insertions(+), 574 deletions(-) create mode 100644 mlir/unittests/programs/qasm_programs.cpp create mode 100644 mlir/unittests/programs/qasm_programs.h delete mode 100644 mlir/unittests/programs/qasm_programs/alloc_large_register.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/alloc_multiple_qubit_registers.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/alloc_qubit.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/alloc_qubit_register.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/barrier.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/barrier_multiple_qubits.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/barrier_two_qubits.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/dcx.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/ecr.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/global_phase.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/h.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/identity.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/if_else.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/inverse_iswap.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/inverse_multiple_controlled_iswap.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/iswap.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_classical_registers_and_measurements.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_dcx.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_ecr.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_h.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_identity.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_iswap.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_p.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_r.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_rx.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_rxx.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_ry.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_ryy.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_rz.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_rzx.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_rzz.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_s.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_sdg.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_swap.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_sx.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_sxdg.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_t.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_tdg.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_u.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_u2.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_x.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_xx_minus_yy.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_xx_plus_yy.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_y.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/multiple_controlled_z.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/p.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/r.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/repeated_measurement_to_different_bits.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/repeated_measurement_to_same_bit.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/repeated_reset_after_single_op.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/reset_multiple_qubits_after_single_op.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/reset_qubit_after_single_op.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/rx.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/rxx.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/ry.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/ryy.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/rz.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/rzx.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/rzz.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/s.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/sdg.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/simple_if.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_dcx.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_ecr.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_h.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_identity.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_iswap.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_p.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_r.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_rx.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_rxx.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_ry.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_ryy.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_rz.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_rzx.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_rzz.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_s.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_sdg.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_swap.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_sx.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_sxdg.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_t.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_tdg.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_u.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_u2.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_x.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_xx_minus_yy.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_xx_plus_yy.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_y.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_controlled_z.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/single_measurement_to_single_bit.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/swap.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/sx.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/sxdg.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/t.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/tdg.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/triple_controlled_rxx.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/u.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/u2.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/x.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/xx_minus_yy.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/xx_plus_yy.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/y.qasm delete mode 100644 mlir/unittests/programs/qasm_programs/z.qasm diff --git a/mlir/unittests/Dialect/QC/Translation/CMakeLists.txt b/mlir/unittests/Dialect/QC/Translation/CMakeLists.txt index a42274d66b..c711b25c8a 100644 --- a/mlir/unittests/Dialect/QC/Translation/CMakeLists.txt +++ b/mlir/unittests/Dialect/QC/Translation/CMakeLists.txt @@ -19,6 +19,7 @@ target_link_libraries( MLIRQCProgramBuilder MLIRQCTranslation MLIRQCPrograms + MLIRQASMPrograms MLIRQuantumComputationPrograms MQT::CoreIR) diff --git a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp index b06490e1b4..dc0134b6ae 100644 --- a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp +++ b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp @@ -14,6 +14,7 @@ #include "mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h" #include "mlir/Support/IRVerification.h" #include "mlir/Support/Passes.h" +#include "qasm_programs.h" #include "qc_programs.h" #include @@ -25,9 +26,9 @@ #include #include -#include #include #include +#include #include using namespace mlir; @@ -36,7 +37,7 @@ namespace { struct QASM3TranslationTestCase { std::string name; - std::string path; + std::string source; mqt::test::NamedBuilder referenceBuilder; friend std::ostream& operator<<(std::ostream& os, @@ -46,8 +47,7 @@ struct QASM3TranslationTestCase { // NOLINTNEXTLINE(llvm-prefer-static-over-anonymous-namespace) std::ostream& operator<<(std::ostream& os, const QASM3TranslationTestCase& test) { - return os << "QASM3Translation{" << test.name << ", original=" << test.path - << ", reference=" + return os << "QASM3Translation{" << test.name << ", reference=" << mqt::test::displayName(test.referenceBuilder.name) << "}"; } @@ -70,14 +70,12 @@ class QASM3TranslationTest TEST_P(QASM3TranslationTest, ProgramEquivalence) { const auto name = " (" + GetParam().name + ")"; - const auto path = (std::filesystem::path(__FILE__).parent_path() / - "../../../programs/qasm_programs" / GetParam().path) - .lexically_normal() - .string(); + const auto& source = GetParam().source; const auto referenceBuilder = GetParam().referenceBuilder; mqt::test::DeferredPrinter printer; - auto translated = qc::translateQASM3ToQC(context.get(), path); + std::istringstream input(source); + auto translated = qc::translateQASM3ToQC(context.get(), input); ASSERT_TRUE(translated); printer.record(translated.get(), "Translated QC IR" + name); EXPECT_TRUE(verify(*translated).succeeded()); @@ -104,266 +102,245 @@ INSTANTIATE_TEST_SUITE_P( QASM3TranslationProgramsTest, QASM3TranslationTest, testing::Values( - QASM3TranslationTestCase{"AllocQubit", "alloc_qubit.qasm", + QASM3TranslationTestCase{"AllocQubit", qasm::allocQubit, MQT_NAMED_BUILDER(qc::allocQubit)}, - QASM3TranslationTestCase{"AllocQubitRegister", - "alloc_qubit_register.qasm", + QASM3TranslationTestCase{"AllocQubitRegister", qasm::allocQubitRegister, MQT_NAMED_BUILDER(qc::allocQubitRegister)}, QASM3TranslationTestCase{ - "AllocMultipleQubitRegisters", - "alloc_multiple_qubit_registers.qasm", + "AllocMultipleQubitRegisters", qasm::allocMultipleQubitRegisters, MQT_NAMED_BUILDER(qc::allocMultipleQubitRegisters)}, - QASM3TranslationTestCase{"AllocLargeRegister", - "alloc_large_register.qasm", + QASM3TranslationTestCase{"AllocLargeRegister", qasm::allocLargeRegister, MQT_NAMED_BUILDER(qc::allocLargeRegister)}, QASM3TranslationTestCase{ - "SingleMeasurementToSingleBit", - "single_measurement_to_single_bit.qasm", + "SingleMeasurementToSingleBit", qasm::singleMeasurementToSingleBit, MQT_NAMED_BUILDER(qc::singleMeasurementToSingleBit)}, QASM3TranslationTestCase{ - "RepeatedMeasurementToSameBit", - "repeated_measurement_to_same_bit.qasm", + "RepeatedMeasurementToSameBit", qasm::repeatedMeasurementToSameBit, MQT_NAMED_BUILDER(qc::repeatedMeasurementToSameBit)}, QASM3TranslationTestCase{ "RepeatedMeasurementToDifferentBits", - "repeated_measurement_to_different_bits.qasm", + qasm::repeatedMeasurementToDifferentBits, MQT_NAMED_BUILDER(qc::repeatedMeasurementToDifferentBits)}, QASM3TranslationTestCase{ "MultipleClassicalRegistersAndMeasurements", - "multiple_classical_registers_and_measurements.qasm", + qasm::multipleClassicalRegistersAndMeasurements, MQT_NAMED_BUILDER(qc::multipleClassicalRegistersAndMeasurements)}, QASM3TranslationTestCase{ - "ResetQubitAfterSingleOp", "reset_qubit_after_single_op.qasm", + "ResetQubitAfterSingleOp", qasm::resetQubitAfterSingleOp, MQT_NAMED_BUILDER(qc::resetQubitAfterSingleOp)}, QASM3TranslationTestCase{ "ResetMultipleQubitsAfterSingleOp", - "reset_multiple_qubits_after_single_op.qasm", + qasm::resetMultipleQubitsAfterSingleOp, MQT_NAMED_BUILDER(qc::resetMultipleQubitsAfterSingleOp)}, QASM3TranslationTestCase{ - "RepeatedResetAfterSingleOp", "repeated_reset_after_single_op.qasm", + "RepeatedResetAfterSingleOp", qasm::repeatedResetAfterSingleOp, MQT_NAMED_BUILDER(qc::repeatedResetAfterSingleOp)}, - QASM3TranslationTestCase{"GlobalPhase", "global_phase.qasm", + QASM3TranslationTestCase{"GlobalPhase", qasm::globalPhase, MQT_NAMED_BUILDER(qc::globalPhase)}, - QASM3TranslationTestCase{"Identity", "identity.qasm", + QASM3TranslationTestCase{"Identity", qasm::identity, MQT_NAMED_BUILDER(qc::identity)}, QASM3TranslationTestCase{ - "SingleControlledIdentity", "single_controlled_identity.qasm", + "SingleControlledIdentity", qasm::singleControlledIdentity, MQT_NAMED_BUILDER(qc::singleControlledIdentity)}, QASM3TranslationTestCase{ - "MultipleControlledIdentity", "multiple_controlled_identity.qasm", + "MultipleControlledIdentity", qasm::multipleControlledIdentity, MQT_NAMED_BUILDER(qc::multipleControlledIdentity)}, - QASM3TranslationTestCase{"X", "x.qasm", MQT_NAMED_BUILDER(qc::x)}, - QASM3TranslationTestCase{"SingleControlledX", - "single_controlled_x.qasm", + QASM3TranslationTestCase{"X", qasm::x, MQT_NAMED_BUILDER(qc::x)}, + QASM3TranslationTestCase{"SingleControlledX", qasm::singleControlledX, MQT_NAMED_BUILDER(qc::singleControlledX)}, QASM3TranslationTestCase{"MultipleControlledX", - "multiple_controlled_x.qasm", + qasm::multipleControlledX, MQT_NAMED_BUILDER(qc::multipleControlledX)}, - QASM3TranslationTestCase{"Y", "y.qasm", MQT_NAMED_BUILDER(qc::y)}, - QASM3TranslationTestCase{"SingleControlledY", - "single_controlled_y.qasm", + QASM3TranslationTestCase{"Y", qasm::y, MQT_NAMED_BUILDER(qc::y)}, + QASM3TranslationTestCase{"SingleControlledY", qasm::singleControlledY, MQT_NAMED_BUILDER(qc::singleControlledY)}, QASM3TranslationTestCase{"MultipleControlledY", - "multiple_controlled_y.qasm", + qasm::multipleControlledY, MQT_NAMED_BUILDER(qc::multipleControlledY)}, - QASM3TranslationTestCase{"Z", "z.qasm", MQT_NAMED_BUILDER(qc::z)}, - QASM3TranslationTestCase{"SingleControlledZ", - "single_controlled_z.qasm", + QASM3TranslationTestCase{"Z", qasm::z, MQT_NAMED_BUILDER(qc::z)}, + QASM3TranslationTestCase{"SingleControlledZ", qasm::singleControlledZ, MQT_NAMED_BUILDER(qc::singleControlledZ)}, QASM3TranslationTestCase{"MultipleControlledZ", - "multiple_controlled_z.qasm", + qasm::multipleControlledZ, MQT_NAMED_BUILDER(qc::multipleControlledZ)}, - QASM3TranslationTestCase{"H", "h.qasm", MQT_NAMED_BUILDER(qc::h)}, - QASM3TranslationTestCase{"SingleControlledH", - "single_controlled_h.qasm", + QASM3TranslationTestCase{"H", qasm::h, MQT_NAMED_BUILDER(qc::h)}, + QASM3TranslationTestCase{"SingleControlledH", qasm::singleControlledH, MQT_NAMED_BUILDER(qc::singleControlledH)}, QASM3TranslationTestCase{"MultipleControlledH", - "multiple_controlled_h.qasm", + qasm::multipleControlledH, MQT_NAMED_BUILDER(qc::multipleControlledH)}, - QASM3TranslationTestCase{"S", "s.qasm", MQT_NAMED_BUILDER(qc::s)}, - QASM3TranslationTestCase{"SingleControlledS", - "single_controlled_s.qasm", + QASM3TranslationTestCase{"S", qasm::s, MQT_NAMED_BUILDER(qc::s)}, + QASM3TranslationTestCase{"SingleControlledS", qasm::singleControlledS, MQT_NAMED_BUILDER(qc::singleControlledS)}, QASM3TranslationTestCase{"MultipleControlledS", - "multiple_controlled_s.qasm", + qasm::multipleControlledS, MQT_NAMED_BUILDER(qc::multipleControlledS)}, - QASM3TranslationTestCase{"Sdg", "sdg.qasm", MQT_NAMED_BUILDER(qc::sdg)}, + QASM3TranslationTestCase{"Sdg", qasm::sdg, MQT_NAMED_BUILDER(qc::sdg)}, QASM3TranslationTestCase{"SingleControlledSdg", - "single_controlled_sdg.qasm", + qasm::singleControlledSdg, MQT_NAMED_BUILDER(qc::singleControlledSdg)}, QASM3TranslationTestCase{"MultipleControlledSdg", - "multiple_controlled_sdg.qasm", + qasm::multipleControlledSdg, MQT_NAMED_BUILDER(qc::multipleControlledSdg)}, - QASM3TranslationTestCase{"T", "t.qasm", MQT_NAMED_BUILDER(qc::t_)}, - QASM3TranslationTestCase{"SingleControlledT", - "single_controlled_t.qasm", + QASM3TranslationTestCase{"T", qasm::t_, MQT_NAMED_BUILDER(qc::t_)}, + QASM3TranslationTestCase{"SingleControlledT", qasm::singleControlledT, MQT_NAMED_BUILDER(qc::singleControlledT)}, QASM3TranslationTestCase{"MultipleControlledT", - "multiple_controlled_t.qasm", + qasm::multipleControlledT, MQT_NAMED_BUILDER(qc::multipleControlledT)}, - QASM3TranslationTestCase{"Tdg", "tdg.qasm", MQT_NAMED_BUILDER(qc::tdg)}, + QASM3TranslationTestCase{"Tdg", qasm::tdg, MQT_NAMED_BUILDER(qc::tdg)}, QASM3TranslationTestCase{"SingleControlledTdg", - "single_controlled_tdg.qasm", + qasm::singleControlledTdg, MQT_NAMED_BUILDER(qc::singleControlledTdg)}, QASM3TranslationTestCase{"MultipleControlledTdg", - "multiple_controlled_tdg.qasm", + qasm::multipleControlledTdg, MQT_NAMED_BUILDER(qc::multipleControlledTdg)}, - QASM3TranslationTestCase{"SX", "sx.qasm", MQT_NAMED_BUILDER(qc::sx)}, - QASM3TranslationTestCase{"SingleControlledSX", - "single_controlled_sx.qasm", + QASM3TranslationTestCase{"SX", qasm::sx, MQT_NAMED_BUILDER(qc::sx)}, + QASM3TranslationTestCase{"SingleControlledSX", qasm::singleControlledSx, MQT_NAMED_BUILDER(qc::singleControlledSx)}, QASM3TranslationTestCase{"MultipleControlledSX", - "multiple_controlled_sx.qasm", + qasm::multipleControlledSx, MQT_NAMED_BUILDER(qc::multipleControlledSx)}, - QASM3TranslationTestCase{"SXdg", "sxdg.qasm", + QASM3TranslationTestCase{"SXdg", qasm::sxdg, MQT_NAMED_BUILDER(qc::sxdg)}, QASM3TranslationTestCase{"SingleControlledSXdg", - "single_controlled_sxdg.qasm", + qasm::singleControlledSxdg, MQT_NAMED_BUILDER(qc::singleControlledSxdg)}, QASM3TranslationTestCase{"MultipleControlledSXdg", - "multiple_controlled_sxdg.qasm", + qasm::multipleControlledSxdg, MQT_NAMED_BUILDER(qc::multipleControlledSxdg)}, - QASM3TranslationTestCase{"RX", "rx.qasm", MQT_NAMED_BUILDER(qc::rx)}, - QASM3TranslationTestCase{"SingleControlledRX", - "single_controlled_rx.qasm", + QASM3TranslationTestCase{"RX", qasm::rx, MQT_NAMED_BUILDER(qc::rx)}, + QASM3TranslationTestCase{"SingleControlledRX", qasm::singleControlledRx, MQT_NAMED_BUILDER(qc::singleControlledRx)}, QASM3TranslationTestCase{"MultipleControlledRX", - "multiple_controlled_rx.qasm", + qasm::multipleControlledRx, MQT_NAMED_BUILDER(qc::multipleControlledRx)}, - QASM3TranslationTestCase{"RY", "ry.qasm", MQT_NAMED_BUILDER(qc::ry)}, - QASM3TranslationTestCase{"SingleControlledRY", - "single_controlled_ry.qasm", + QASM3TranslationTestCase{"RY", qasm::ry, MQT_NAMED_BUILDER(qc::ry)}, + QASM3TranslationTestCase{"SingleControlledRY", qasm::singleControlledRy, MQT_NAMED_BUILDER(qc::singleControlledRy)}, QASM3TranslationTestCase{"MultipleControlledRY", - "multiple_controlled_ry.qasm", + qasm::multipleControlledRy, MQT_NAMED_BUILDER(qc::multipleControlledRy)}, - QASM3TranslationTestCase{"RZ", "rz.qasm", MQT_NAMED_BUILDER(qc::rz)}, - QASM3TranslationTestCase{"SingleControlledRZ", - "single_controlled_rz.qasm", + QASM3TranslationTestCase{"RZ", qasm::rz, MQT_NAMED_BUILDER(qc::rz)}, + QASM3TranslationTestCase{"SingleControlledRZ", qasm::singleControlledRz, MQT_NAMED_BUILDER(qc::singleControlledRz)}, QASM3TranslationTestCase{"MultipleControlledRZ", - "multiple_controlled_rz.qasm", + qasm::multipleControlledRz, MQT_NAMED_BUILDER(qc::multipleControlledRz)}, - QASM3TranslationTestCase{"P", "p.qasm", MQT_NAMED_BUILDER(qc::p)}, - QASM3TranslationTestCase{"SingleControlledP", - "single_controlled_p.qasm", + QASM3TranslationTestCase{"P", qasm::p, MQT_NAMED_BUILDER(qc::p)}, + QASM3TranslationTestCase{"SingleControlledP", qasm::singleControlledP, MQT_NAMED_BUILDER(qc::singleControlledP)}, QASM3TranslationTestCase{"MultipleControlledP", - "multiple_controlled_p.qasm", + qasm::multipleControlledP, MQT_NAMED_BUILDER(qc::multipleControlledP)}, - QASM3TranslationTestCase{"R", "r.qasm", MQT_NAMED_BUILDER(qc::r)}, - QASM3TranslationTestCase{"SingleControlledR", - "single_controlled_r.qasm", + QASM3TranslationTestCase{"R", qasm::r, MQT_NAMED_BUILDER(qc::r)}, + QASM3TranslationTestCase{"SingleControlledR", qasm::singleControlledR, MQT_NAMED_BUILDER(qc::singleControlledR)}, QASM3TranslationTestCase{"MultipleControlledR", - "multiple_controlled_r.qasm", + qasm::multipleControlledR, MQT_NAMED_BUILDER(qc::multipleControlledR)}, - QASM3TranslationTestCase{"U2", "u2.qasm", MQT_NAMED_BUILDER(qc::u2)}, - QASM3TranslationTestCase{"SingleControlledU2", - "single_controlled_u2.qasm", + QASM3TranslationTestCase{"U2", qasm::u2, MQT_NAMED_BUILDER(qc::u2)}, + QASM3TranslationTestCase{"SingleControlledU2", qasm::singleControlledU2, MQT_NAMED_BUILDER(qc::singleControlledU2)}, QASM3TranslationTestCase{"MultipleControlledU2", - "multiple_controlled_u2.qasm", + qasm::multipleControlledU2, MQT_NAMED_BUILDER(qc::multipleControlledU2)}, - QASM3TranslationTestCase{"U", "u.qasm", MQT_NAMED_BUILDER(qc::u)}, - QASM3TranslationTestCase{"SingleControlledU", - "single_controlled_u.qasm", + QASM3TranslationTestCase{"U", qasm::u, MQT_NAMED_BUILDER(qc::u)}, + QASM3TranslationTestCase{"SingleControlledU", qasm::singleControlledU, MQT_NAMED_BUILDER(qc::singleControlledU)}, QASM3TranslationTestCase{"MultipleControlledU", - "multiple_controlled_u.qasm", + qasm::multipleControlledU, MQT_NAMED_BUILDER(qc::multipleControlledU)}, - QASM3TranslationTestCase{"SWAP", "swap.qasm", + QASM3TranslationTestCase{"SWAP", qasm::swap, MQT_NAMED_BUILDER(qc::swap)}, QASM3TranslationTestCase{"SingleControlledSWAP", - "single_controlled_swap.qasm", + qasm::singleControlledSwap, MQT_NAMED_BUILDER(qc::singleControlledSwap)}, QASM3TranslationTestCase{"MultipleControlledSWAP", - "multiple_controlled_swap.qasm", + qasm::multipleControlledSwap, MQT_NAMED_BUILDER(qc::multipleControlledSwap)}, - QASM3TranslationTestCase{"iSWAP", "iswap.qasm", + QASM3TranslationTestCase{"iSWAP", qasm::iswap, MQT_NAMED_BUILDER(qc::iswap)}, QASM3TranslationTestCase{"SingleControllediSWAP", - "single_controlled_iswap.qasm", + qasm::singleControlledIswap, MQT_NAMED_BUILDER(qc::singleControlledIswap)}, QASM3TranslationTestCase{ - "MultipleControllediSWAP", "multiple_controlled_iswap.qasm", + "MultipleControllediSWAP", qasm::multipleControlledIswap, MQT_NAMED_BUILDER(qc::multipleControlledIswap)}, - QASM3TranslationTestCase{"InverseISWAP", "inverse_iswap.qasm", + QASM3TranslationTestCase{"InverseISWAP", qasm::inverseIswap, MQT_NAMED_BUILDER(qc::inverseIswap)}, QASM3TranslationTestCase{ - "InverseMultiControlledISWAP", - "inverse_multiple_controlled_iswap.qasm", + "InverseMultiControlledISWAP", qasm::inverseMultipleControlledIswap, MQT_NAMED_BUILDER(qc::inverseMultipleControlledIswap)}, - QASM3TranslationTestCase{"DCX", "dcx.qasm", MQT_NAMED_BUILDER(qc::dcx)}, + QASM3TranslationTestCase{"DCX", qasm::dcx, MQT_NAMED_BUILDER(qc::dcx)}, QASM3TranslationTestCase{"SingleControlledDCX", - "single_controlled_dcx.qasm", + qasm::singleControlledDcx, MQT_NAMED_BUILDER(qc::singleControlledDcx)}, QASM3TranslationTestCase{"MultipleControlledDCX", - "multiple_controlled_dcx.qasm", + qasm::multipleControlledDcx, MQT_NAMED_BUILDER(qc::multipleControlledDcx)}, - QASM3TranslationTestCase{"ECR", "ecr.qasm", MQT_NAMED_BUILDER(qc::ecr)}, + QASM3TranslationTestCase{"ECR", qasm::ecr, MQT_NAMED_BUILDER(qc::ecr)}, QASM3TranslationTestCase{"SingleControlledECR", - "single_controlled_ecr.qasm", + qasm::singleControlledEcr, MQT_NAMED_BUILDER(qc::singleControlledEcr)}, QASM3TranslationTestCase{"MultipleControlledECR", - "multiple_controlled_ecr.qasm", + qasm::multipleControlledEcr, MQT_NAMED_BUILDER(qc::multipleControlledEcr)}, - QASM3TranslationTestCase{"RXX", "rxx.qasm", MQT_NAMED_BUILDER(qc::rxx)}, + QASM3TranslationTestCase{"RXX", qasm::rxx, MQT_NAMED_BUILDER(qc::rxx)}, QASM3TranslationTestCase{"SingleControlledRXX", - "single_controlled_rxx.qasm", + qasm::singleControlledRxx, MQT_NAMED_BUILDER(qc::singleControlledRxx)}, QASM3TranslationTestCase{"MultipleControlledRXX", - "multiple_controlled_rxx.qasm", + qasm::multipleControlledRxx, MQT_NAMED_BUILDER(qc::multipleControlledRxx)}, QASM3TranslationTestCase{"TripleControlledRXX", - "triple_controlled_rxx.qasm", + qasm::tripleControlledRxx, MQT_NAMED_BUILDER(qc::tripleControlledRxx)}, - QASM3TranslationTestCase{"RYY", "ryy.qasm", MQT_NAMED_BUILDER(qc::ryy)}, + QASM3TranslationTestCase{"RYY", qasm::ryy, MQT_NAMED_BUILDER(qc::ryy)}, QASM3TranslationTestCase{"SingleControlledRYY", - "single_controlled_ryy.qasm", + qasm::singleControlledRyy, MQT_NAMED_BUILDER(qc::singleControlledRyy)}, QASM3TranslationTestCase{"MultipleControlledRYY", - "multiple_controlled_ryy.qasm", + qasm::multipleControlledRyy, MQT_NAMED_BUILDER(qc::multipleControlledRyy)}, - QASM3TranslationTestCase{"RZX", "rzx.qasm", MQT_NAMED_BUILDER(qc::rzx)}, + QASM3TranslationTestCase{"RZX", qasm::rzx, MQT_NAMED_BUILDER(qc::rzx)}, QASM3TranslationTestCase{"SingleControlledRZX", - "single_controlled_rzx.qasm", + qasm::singleControlledRzx, MQT_NAMED_BUILDER(qc::singleControlledRzx)}, QASM3TranslationTestCase{"MultipleControlledRZX", - "multiple_controlled_rzx.qasm", + qasm::multipleControlledRzx, MQT_NAMED_BUILDER(qc::multipleControlledRzx)}, - QASM3TranslationTestCase{"RZZ", "rzz.qasm", MQT_NAMED_BUILDER(qc::rzz)}, + QASM3TranslationTestCase{"RZZ", qasm::rzz, MQT_NAMED_BUILDER(qc::rzz)}, QASM3TranslationTestCase{"SingleControlledRZZ", - "single_controlled_rzz.qasm", + qasm::singleControlledRzz, MQT_NAMED_BUILDER(qc::singleControlledRzz)}, QASM3TranslationTestCase{"MultipleControlledRZZ", - "multiple_controlled_rzz.qasm", + qasm::multipleControlledRzz, MQT_NAMED_BUILDER(qc::multipleControlledRzz)}, - QASM3TranslationTestCase{"XXPlusYY", "xx_plus_yy.qasm", + QASM3TranslationTestCase{"XXPlusYY", qasm::xxPlusYY, MQT_NAMED_BUILDER(qc::xxPlusYY)}, QASM3TranslationTestCase{ - "SingleControlledXXPlusYY", "single_controlled_xx_plus_yy.qasm", + "SingleControlledXXPlusYY", qasm::singleControlledXxPlusYY, MQT_NAMED_BUILDER(qc::singleControlledXxPlusYY)}, QASM3TranslationTestCase{ - "MultipleControlledXXPlusYY", "multiple_controlled_xx_plus_yy.qasm", + "MultipleControlledXXPlusYY", qasm::multipleControlledXxPlusYY, MQT_NAMED_BUILDER(qc::multipleControlledXxPlusYY)}, - QASM3TranslationTestCase{"XXMinusYY", "xx_minus_yy.qasm", + QASM3TranslationTestCase{"XXMinusYY", qasm::xxMinusYY, MQT_NAMED_BUILDER(qc::xxMinusYY)}, QASM3TranslationTestCase{ - "SingleControlledXXMinusYY", "single_controlled_xx_minus_yy.qasm", + "SingleControlledXXMinusYY", qasm::singleControlledXxMinusYY, MQT_NAMED_BUILDER(qc::singleControlledXxMinusYY)}, QASM3TranslationTestCase{ - "MultipleControlledXXMinusYY", - "multiple_controlled_xx_minus_yy.qasm", + "MultipleControlledXXMinusYY", qasm::multipleControlledXxMinusYY, MQT_NAMED_BUILDER(qc::multipleControlledXxMinusYY)}, - QASM3TranslationTestCase{"Barrier", "barrier.qasm", + QASM3TranslationTestCase{"Barrier", qasm::barrier, MQT_NAMED_BUILDER(qc::barrier)}, - QASM3TranslationTestCase{"BarrierTwoQubits", "barrier_two_qubits.qasm", + QASM3TranslationTestCase{"BarrierTwoQubits", qasm::barrierTwoQubits, MQT_NAMED_BUILDER(qc::barrierTwoQubits)}, QASM3TranslationTestCase{"BarrierMultipleQubits", - "barrier_multiple_qubits.qasm", + qasm::barrierMultipleQubits, MQT_NAMED_BUILDER(qc::barrierMultipleQubits)}, - QASM3TranslationTestCase{"SimpleIf", "simple_if.qasm", + QASM3TranslationTestCase{"SimpleIf", qasm::simpleIf, MQT_NAMED_BUILDER(qc::simpleIf)}, - QASM3TranslationTestCase{"IfElse", "if_else.qasm", + QASM3TranslationTestCase{"IfElse", qasm::ifElse, MQT_NAMED_BUILDER(qc::ifElse)})); diff --git a/mlir/unittests/programs/CMakeLists.txt b/mlir/unittests/programs/CMakeLists.txt index 8b58449e76..6bd97fef77 100644 --- a/mlir/unittests/programs/CMakeLists.txt +++ b/mlir/unittests/programs/CMakeLists.txt @@ -6,6 +6,10 @@ # # Licensed under the MIT License +add_library(MLIRQASMPrograms qasm_programs.cpp) +target_sources(MLIRQASMPrograms PUBLIC FILE_SET HEADERS BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES + qasm_programs.h) + add_library(MLIRQCPrograms qc_programs.cpp) target_link_libraries(MLIRQCPrograms PUBLIC MLIRQCProgramBuilder) target_sources(MLIRQCPrograms PUBLIC FILE_SET HEADERS BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES diff --git a/mlir/unittests/programs/qasm_programs.cpp b/mlir/unittests/programs/qasm_programs.cpp new file mode 100644 index 0000000000..0ab0469129 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs.cpp @@ -0,0 +1,664 @@ +/* + * Copyright (c) 2023 - 2026 Chair for Design Automation, TUM + * Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH + * All rights reserved. + * + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License + */ + +#include "qasm_programs.h" + +namespace mlir::qasm { + +const std::string allocQubit = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit q; +)qasm"; + +const std::string allocQubitRegister = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +)qasm"; + +const std::string allocMultipleQubitRegisters = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q0; +qubit[3] q1; +)qasm"; + +const std::string allocLargeRegister = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[100] q; +)qasm"; + +const std::string singleMeasurementToSingleBit = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +bit[1] c; +measure q[0] -> c[0]; +)qasm"; + +const std::string repeatedMeasurementToSameBit = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +bit[1] c; +measure q[0] -> c[0]; +measure q[0] -> c[0]; +measure q[0] -> c[0]; +)qasm"; + +const std::string repeatedMeasurementToDifferentBits = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +bit[3] c; +measure q[0] -> c[0]; +measure q[0] -> c[1]; +measure q[0] -> c[2]; +)qasm"; + +const std::string multipleClassicalRegistersAndMeasurements = + R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +bit[1] c0; +bit[2] c1; +measure q[0] -> c0[0]; +measure q[1] -> c1[0]; +measure q[2] -> c1[1]; +)qasm"; + +const std::string resetQubitAfterSingleOp = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +h q[0]; +reset q[0]; +)qasm"; + +const std::string resetMultipleQubitsAfterSingleOp = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +h q[0]; +reset q[0]; +h q[1]; +reset q[1]; +)qasm"; + +const std::string repeatedResetAfterSingleOp = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +h q[0]; +reset q[0]; +reset q[0]; +reset q[0]; +)qasm"; + +const std::string globalPhase = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +gphase(0.123); +)qasm"; + +const std::string identity = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +id q[0]; +)qasm"; + +const std::string singleControlledIdentity = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ id q[0], q[1]; +)qasm"; + +const std::string multipleControlledIdentity = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ id q[0], q[1], q[2]; +)qasm"; + +const std::string x = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +x q[0]; +)qasm"; + +const std::string singleControlledX = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ x q[0], q[1]; +)qasm"; + +const std::string multipleControlledX = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ x q[0], q[1], q[2]; +)qasm"; + +const std::string y = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +y q[0]; +)qasm"; + +const std::string singleControlledY = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ y q[0], q[1]; +)qasm"; + +const std::string multipleControlledY = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ y q[0], q[1], q[2]; +)qasm"; + +const std::string z = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +z q[0]; +)qasm"; + +const std::string singleControlledZ = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ z q[0], q[1]; +)qasm"; + +const std::string multipleControlledZ = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ z q[0], q[1], q[2]; +)qasm"; + +const std::string h = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +h q[0]; +)qasm"; + +const std::string singleControlledH = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ h q[0], q[1]; +)qasm"; + +const std::string multipleControlledH = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ h q[0], q[1], q[2]; +)qasm"; + +const std::string s = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +s q[0]; +)qasm"; + +const std::string singleControlledS = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ s q[0], q[1]; +)qasm"; + +const std::string multipleControlledS = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ s q[0], q[1], q[2]; +)qasm"; + +const std::string sdg = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +sdg q[0]; +)qasm"; + +const std::string singleControlledSdg = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ sdg q[0], q[1]; +)qasm"; + +const std::string multipleControlledSdg = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ sdg q[0], q[1], q[2]; +)qasm"; + +const std::string t_ = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +t q[0]; +)qasm"; + +const std::string singleControlledT = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ t q[0], q[1]; +)qasm"; + +const std::string multipleControlledT = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ t q[0], q[1], q[2]; +)qasm"; + +const std::string tdg = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +tdg q[0]; +)qasm"; + +const std::string singleControlledTdg = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ tdg q[0], q[1]; +)qasm"; + +const std::string multipleControlledTdg = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ tdg q[0], q[1], q[2]; +)qasm"; + +const std::string sx = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +sx q[0]; +)qasm"; + +const std::string singleControlledSx = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ sx q[0], q[1]; +)qasm"; + +const std::string multipleControlledSx = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ sx q[0], q[1], q[2]; +)qasm"; + +const std::string sxdg = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +sxdg q[0]; +)qasm"; + +const std::string singleControlledSxdg = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ sxdg q[0], q[1]; +)qasm"; + +const std::string multipleControlledSxdg = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ sxdg q[0], q[1], q[2]; +)qasm"; + +const std::string rx = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +rx(0.123) q[0]; +)qasm"; + +const std::string singleControlledRx = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ rx(0.123) q[0], q[1]; +)qasm"; + +const std::string multipleControlledRx = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ rx(0.123) q[0], q[1], q[2]; +)qasm"; + +const std::string ry = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +ry(0.456) q[0]; +)qasm"; + +const std::string singleControlledRy = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ ry(0.456) q[0], q[1]; +)qasm"; + +const std::string multipleControlledRy = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ ry(0.456) q[0], q[1], q[2]; +)qasm"; + +const std::string rz = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +rz(0.789) q[0]; +)qasm"; + +const std::string singleControlledRz = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ rz(0.789) q[0], q[1]; +)qasm"; + +const std::string multipleControlledRz = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ rz(0.789) q[0], q[1], q[2]; +)qasm"; + +const std::string p = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +p(0.123) q[0]; +)qasm"; + +const std::string singleControlledP = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ p(0.123) q[0], q[1]; +)qasm"; + +const std::string multipleControlledP = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ p(0.123) q[0], q[1], q[2]; +)qasm"; + +const std::string r = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +r(0.123, 0.456) q[0]; +)qasm"; + +const std::string singleControlledR = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ r(0.123, 0.456) q[0], q[1]; +)qasm"; + +const std::string multipleControlledR = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ r(0.123, 0.456) q[0], q[1], q[2]; +)qasm"; + +const std::string u2 = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +u2(0.234, 0.567) q[0]; +)qasm"; + +const std::string singleControlledU2 = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ u2(0.234, 0.567) q[0], q[1]; +)qasm"; + +const std::string multipleControlledU2 = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ u2(0.234, 0.567) q[0], q[1], q[2]; +)qasm"; + +const std::string u = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +u(0.1, 0.2, 0.3) q[0]; +)qasm"; + +const std::string singleControlledU = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ctrl @ u(0.1, 0.2, 0.3) q[0], q[1]; +)qasm"; + +const std::string multipleControlledU = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl(2) @ u(0.1, 0.2, 0.3) q[0], q[1], q[2]; +)qasm"; + +const std::string swap = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +swap q[0], q[1]; +)qasm"; + +const std::string singleControlledSwap = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ swap q[0], q[1], q[2]; +)qasm"; + +const std::string multipleControlledSwap = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ swap q[0], q[1], q[2], q[3]; +)qasm"; + +const std::string iswap = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +iswap q[0], q[1]; +)qasm"; + +const std::string singleControlledIswap = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ iswap q[0], q[1], q[2]; +)qasm"; + +const std::string multipleControlledIswap = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ iswap q[0], q[1], q[2], q[3]; +)qasm"; + +const std::string inverseIswap = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +inv @ iswap q[0], q[1]; +)qasm"; + +const std::string inverseMultipleControlledIswap = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +inv @ ctrl(2) @ iswap q[0], q[1], q[2], q[3]; +)qasm"; + +const std::string dcx = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +dcx q[0], q[1]; +)qasm"; + +const std::string singleControlledDcx = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ dcx q[0], q[1], q[2]; +)qasm"; + +const std::string multipleControlledDcx = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ dcx q[0], q[1], q[2], q[3]; +)qasm"; + +const std::string ecr = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ecr q[0], q[1]; +)qasm"; + +const std::string singleControlledEcr = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ ecr q[0], q[1], q[2]; +)qasm"; + +const std::string multipleControlledEcr = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ ecr q[0], q[1], q[2], q[3]; +)qasm"; + +const std::string rxx = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +rxx(0.123) q[0], q[1]; +)qasm"; + +const std::string singleControlledRxx = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ rxx(0.123) q[0], q[1], q[2]; +)qasm"; + +const std::string multipleControlledRxx = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ rxx(0.123) q[0], q[1], q[2], q[3]; +)qasm"; + +const std::string tripleControlledRxx = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[5] q; +ctrl(3) @ rxx(0.123) q[0], q[1], q[2], q[3], q[4]; +)qasm"; + +const std::string ryy = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +ryy(0.123) q[0], q[1]; +)qasm"; + +const std::string singleControlledRyy = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ ryy(0.123) q[0], q[1], q[2]; +)qasm"; + +const std::string multipleControlledRyy = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ ryy(0.123) q[0], q[1], q[2], q[3]; +)qasm"; + +const std::string rzx = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +rzx(0.123) q[0], q[1]; +)qasm"; + +const std::string singleControlledRzx = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ rzx(0.123) q[0], q[1], q[2]; +)qasm"; + +const std::string multipleControlledRzx = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ rzx(0.123) q[0], q[1], q[2], q[3]; +)qasm"; + +const std::string rzz = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +rzz(0.123) q[0], q[1]; +)qasm"; + +const std::string singleControlledRzz = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ rzz(0.123) q[0], q[1], q[2]; +)qasm"; + +const std::string multipleControlledRzz = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ rzz(0.123) q[0], q[1], q[2], q[3]; +)qasm"; + +const std::string xxPlusYY = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +xx_plus_yy(0.123, 0.456) q[0], q[1]; +)qasm"; + +const std::string singleControlledXxPlusYY = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ xx_plus_yy(0.123, 0.456) q[0], q[1], q[2]; +)qasm"; + +const std::string multipleControlledXxPlusYY = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ xx_plus_yy(0.123, 0.456) q[0], q[1], q[2], q[3]; +)qasm"; + +const std::string xxMinusYY = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +xx_minus_yy(0.123, 0.456) q[0], q[1]; +)qasm"; + +const std::string singleControlledXxMinusYY = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ xx_minus_yy(0.123, 0.456) q[0], q[1], q[2]; +)qasm"; + +const std::string multipleControlledXxMinusYY = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +ctrl(2) @ xx_minus_yy(0.123, 0.456) q[0], q[1], q[2], q[3]; +)qasm"; + +const std::string barrier = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +barrier q[0]; +)qasm"; + +const std::string barrierTwoQubits = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +barrier q[0], q[1]; +)qasm"; + +const std::string barrierMultipleQubits = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +barrier q[0], q[1], q[2]; +)qasm"; + +const std::string simpleIf = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +h q[0]; +bit c = measure q[0]; +if (c) { + x q[0]; +} +)qasm"; + +const std::string ifElse = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +h q[0]; +bit c = measure q[0]; +if (c) { + x q[0]; +} else { + z q[0]; +} +)qasm"; + +} // namespace mlir::qasm diff --git a/mlir/unittests/programs/qasm_programs.h b/mlir/unittests/programs/qasm_programs.h new file mode 100644 index 0000000000..6dc6fc37f9 --- /dev/null +++ b/mlir/unittests/programs/qasm_programs.h @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2023 - 2026 Chair for Design Automation, TUM + * Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH + * All rights reserved. + * + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License + */ + +#pragma once + +#include + +namespace mlir::qasm { + +/// Allocates a single qubit. +extern const std::string allocQubit; + +/// Allocates a qubit register of size `2`. +extern const std::string allocQubitRegister; + +/// Allocates two qubit registers of size `2` and `3`. +extern const std::string allocMultipleQubitRegisters; + +/// Allocates a large qubit register. +extern const std::string allocLargeRegister; + +/// Measures a single qubit into a single classical bit. +extern const std::string singleMeasurementToSingleBit; + +/// Repeatedly measures a single qubit into the same classical bit. +extern const std::string repeatedMeasurementToSameBit; + +/// Repeatedly measures a single qubit into different classical bits. +extern const std::string repeatedMeasurementToDifferentBits; + +/// Measures multiple qubits into multiple classical bits. +extern const std::string multipleClassicalRegistersAndMeasurements; + +/// Resets a single qubit after a single operation. +extern const std::string resetQubitAfterSingleOp; + +/// Resets multiple qubits after a single operation. +extern const std::string resetMultipleQubitsAfterSingleOp; + +/// Repeatedly resets a single qubit after a single operation. +extern const std::string repeatedResetAfterSingleOp; + +/// Creates a circuit with just a global phase. +extern const std::string globalPhase; + +/// Creates a circuit with just an identity gate. +extern const std::string identity; + +/// Creates a controlled identity gate with a single control qubit. +extern const std::string singleControlledIdentity; + +/// Creates a multi-controlled identity gate with multiple control qubits. +extern const std::string multipleControlledIdentity; + +/// Creates a circuit with just an X gate. +extern const std::string x; + +/// Creates a circuit with a single controlled X gate. +extern const std::string singleControlledX; + +/// Creates a circuit with a multi-controlled X gate. +extern const std::string multipleControlledX; + +/// Creates a circuit with just a Y gate. +extern const std::string y; + +/// Creates a circuit with a single controlled Y gate. +extern const std::string singleControlledY; + +/// Creates a circuit with a multi-controlled Y gate. +extern const std::string multipleControlledY; + +/// Creates a circuit with just a Z gate. +extern const std::string z; + +/// Creates a circuit with a single controlled Z gate. +extern const std::string singleControlledZ; + +/// Creates a circuit with a multi-controlled Z gate. +extern const std::string multipleControlledZ; + +/// Creates a circuit with just an H gate. +extern const std::string h; + +/// Creates a circuit with a single controlled H gate. +extern const std::string singleControlledH; + +/// Creates a circuit with a multi-controlled H gate. +extern const std::string multipleControlledH; + +/// Creates a circuit with just an S gate. +extern const std::string s; + +/// Creates a circuit with a single controlled S gate. +extern const std::string singleControlledS; + +/// Creates a circuit with a multi-controlled S gate. +extern const std::string multipleControlledS; + +/// Creates a circuit with just an Sdg gate. +extern const std::string sdg; + +/// Creates a circuit with a single controlled Sdg gate. +extern const std::string singleControlledSdg; + +/// Creates a circuit with a multi-controlled Sdg gate. +extern const std::string multipleControlledSdg; + +/// Creates a circuit with just a T gate. +extern const std::string t_; + +/// Creates a circuit with a single controlled T gate. +extern const std::string singleControlledT; + +/// Creates a circuit with a multi-controlled T gate. +extern const std::string multipleControlledT; + +/// Creates a circuit with just a Tdg gate. +extern const std::string tdg; + +/// Creates a circuit with a single controlled Tdg gate. +extern const std::string singleControlledTdg; + +/// Creates a circuit with a multi-controlled Tdg gate. +extern const std::string multipleControlledTdg; + +/// Creates a circuit with just an SX gate. +extern const std::string sx; + +/// Creates a circuit with a single controlled SX gate. +extern const std::string singleControlledSx; + +/// Creates a circuit with a multi-controlled SX gate. +extern const std::string multipleControlledSx; + +/// Creates a circuit with just an SXdg gate. +extern const std::string sxdg; + +/// Creates a circuit with a single controlled SXdg gate. +extern const std::string singleControlledSxdg; + +/// Creates a circuit with a multi-controlled SXdg gate. +extern const std::string multipleControlledSxdg; + +/// Creates a circuit with just an RX gate. +extern const std::string rx; + +/// Creates a circuit with a single controlled RX gate. +extern const std::string singleControlledRx; + +/// Creates a circuit with a multi-controlled RX gate. +extern const std::string multipleControlledRx; + +/// Creates a circuit with just an RY gate. +extern const std::string ry; + +/// Creates a circuit with a single controlled RY gate. +extern const std::string singleControlledRy; + +/// Creates a circuit with a multi-controlled RY gate. +extern const std::string multipleControlledRy; + +/// Creates a circuit with just an RZ gate. +extern const std::string rz; + +/// Creates a circuit with a single controlled RZ gate. +extern const std::string singleControlledRz; + +/// Creates a circuit with a multi-controlled RZ gate. +extern const std::string multipleControlledRz; + +/// Creates a circuit with just a P gate. +extern const std::string p; + +/// Creates a circuit with a single controlled P gate. +extern const std::string singleControlledP; + +/// Creates a circuit with a multi-controlled P gate. +extern const std::string multipleControlledP; + +/// Creates a circuit with just an R gate. +extern const std::string r; + +/// Creates a circuit with a single controlled R gate. +extern const std::string singleControlledR; + +/// Creates a circuit with a multi-controlled R gate. +extern const std::string multipleControlledR; + +/// Creates a circuit with just a U2 gate. +extern const std::string u2; + +/// Creates a circuit with a single controlled U2 gate. +extern const std::string singleControlledU2; + +/// Creates a circuit with a multi-controlled U2 gate. +extern const std::string multipleControlledU2; + +/// Creates a circuit with just a U gate. +extern const std::string u; + +/// Creates a circuit with a single controlled U gate. +extern const std::string singleControlledU; + +/// Creates a circuit with a multi-controlled U gate. +extern const std::string multipleControlledU; + +/// Creates a circuit with just a SWAP gate. +extern const std::string swap; + +/// Creates a circuit with a single controlled SWAP gate. +extern const std::string singleControlledSwap; + +/// Creates a circuit with a multi-controlled SWAP gate. +extern const std::string multipleControlledSwap; + +/// Creates a circuit with just an iSWAP gate. +extern const std::string iswap; + +/// Creates a circuit with a single controlled iSWAP gate. +extern const std::string singleControlledIswap; + +/// Creates a circuit with a multi-controlled iSWAP gate. +extern const std::string multipleControlledIswap; + +/// Creates a circuit with an inverse modifier applied to an iSWAP gate. +extern const std::string inverseIswap; + +/// Creates a circuit with an inverse modifier applied to a controlled iSWAP +/// gate. +extern const std::string inverseMultipleControlledIswap; + +/// Creates a circuit with just a DCX gate. +extern const std::string dcx; + +/// Creates a circuit with a single controlled DCX gate. +extern const std::string singleControlledDcx; + +/// Creates a circuit with a multi-controlled DCX gate. +extern const std::string multipleControlledDcx; + +/// Creates a circuit with just an ECR gate. +extern const std::string ecr; + +/// Creates a circuit with a single controlled ECR gate. +extern const std::string singleControlledEcr; + +/// Creates a circuit with a multi-controlled ECR gate. +extern const std::string multipleControlledEcr; + +/// Creates a circuit with just an RXX gate. +extern const std::string rxx; + +/// Creates a circuit with a single controlled RXX gate. +extern const std::string singleControlledRxx; + +/// Creates a circuit with a multi-controlled RXX gate. +extern const std::string multipleControlledRxx; + +/// Creates a circuit with a triple-controlled RXX gate. +extern const std::string tripleControlledRxx; + +/// Creates a circuit with just an RYY gate. +extern const std::string ryy; + +/// Creates a circuit with a single controlled RYY gate. +extern const std::string singleControlledRyy; + +/// Creates a circuit with a multi-controlled RYY gate. +extern const std::string multipleControlledRyy; + +/// Creates a circuit with just an RZX gate. +extern const std::string rzx; + +/// Creates a circuit with a single controlled RZX gate. +extern const std::string singleControlledRzx; + +/// Creates a circuit with a multi-controlled RZX gate. +extern const std::string multipleControlledRzx; + +/// Creates a circuit with just an RZZ gate. +extern const std::string rzz; + +/// Creates a circuit with a single controlled RZZ gate. +extern const std::string singleControlledRzz; + +/// Creates a circuit with a multi-controlled RZZ gate. +extern const std::string multipleControlledRzz; + +/// Creates a circuit with just an XXPlusYY gate. +extern const std::string xxPlusYY; + +/// Creates a circuit with a single controlled XXPlusYY gate. +extern const std::string singleControlledXxPlusYY; + +/// Creates a circuit with a multi-controlled XXPlusYY gate. +extern const std::string multipleControlledXxPlusYY; + +/// Creates a circuit with just an XXMinusYY gate. +extern const std::string xxMinusYY; + +/// Creates a circuit with a single controlled XXMinusYY gate. +extern const std::string singleControlledXxMinusYY; + +/// Creates a circuit with a multi-controlled XXMinusYY gate. +extern const std::string multipleControlledXxMinusYY; + +/// Creates a circuit with a barrier. +extern const std::string barrier; + +/// Creates a circuit with a barrier on two qubits. +extern const std::string barrierTwoQubits; + +/// Creates a circuit with a barrier on multiple qubits. +extern const std::string barrierMultipleQubits; + +/// Creates a circuit with a simple if operation with one qubit. +extern const std::string simpleIf; + +/// Creates a circuit with an if operation with an else branch. +extern const std::string ifElse; + +} // namespace mlir::qasm diff --git a/mlir/unittests/programs/qasm_programs/alloc_large_register.qasm b/mlir/unittests/programs/qasm_programs/alloc_large_register.qasm deleted file mode 100644 index 71e739f093..0000000000 --- a/mlir/unittests/programs/qasm_programs/alloc_large_register.qasm +++ /dev/null @@ -1,3 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[100] q; diff --git a/mlir/unittests/programs/qasm_programs/alloc_multiple_qubit_registers.qasm b/mlir/unittests/programs/qasm_programs/alloc_multiple_qubit_registers.qasm deleted file mode 100644 index 8170a1b74e..0000000000 --- a/mlir/unittests/programs/qasm_programs/alloc_multiple_qubit_registers.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q0; -qubit[3] q1; diff --git a/mlir/unittests/programs/qasm_programs/alloc_qubit.qasm b/mlir/unittests/programs/qasm_programs/alloc_qubit.qasm deleted file mode 100644 index e554e3ead6..0000000000 --- a/mlir/unittests/programs/qasm_programs/alloc_qubit.qasm +++ /dev/null @@ -1,3 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit q; diff --git a/mlir/unittests/programs/qasm_programs/alloc_qubit_register.qasm b/mlir/unittests/programs/qasm_programs/alloc_qubit_register.qasm deleted file mode 100644 index bae5459616..0000000000 --- a/mlir/unittests/programs/qasm_programs/alloc_qubit_register.qasm +++ /dev/null @@ -1,3 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; diff --git a/mlir/unittests/programs/qasm_programs/barrier.qasm b/mlir/unittests/programs/qasm_programs/barrier.qasm deleted file mode 100644 index 0f8146de84..0000000000 --- a/mlir/unittests/programs/qasm_programs/barrier.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -barrier q[0]; diff --git a/mlir/unittests/programs/qasm_programs/barrier_multiple_qubits.qasm b/mlir/unittests/programs/qasm_programs/barrier_multiple_qubits.qasm deleted file mode 100644 index 461527b1af..0000000000 --- a/mlir/unittests/programs/qasm_programs/barrier_multiple_qubits.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -barrier q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/barrier_two_qubits.qasm b/mlir/unittests/programs/qasm_programs/barrier_two_qubits.qasm deleted file mode 100644 index ca131706a2..0000000000 --- a/mlir/unittests/programs/qasm_programs/barrier_two_qubits.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -barrier q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/dcx.qasm b/mlir/unittests/programs/qasm_programs/dcx.qasm deleted file mode 100644 index 1d3b7bdd1d..0000000000 --- a/mlir/unittests/programs/qasm_programs/dcx.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -dcx q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/ecr.qasm b/mlir/unittests/programs/qasm_programs/ecr.qasm deleted file mode 100644 index 3a405f64f8..0000000000 --- a/mlir/unittests/programs/qasm_programs/ecr.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ecr q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/global_phase.qasm b/mlir/unittests/programs/qasm_programs/global_phase.qasm deleted file mode 100644 index 2532e2dd25..0000000000 --- a/mlir/unittests/programs/qasm_programs/global_phase.qasm +++ /dev/null @@ -1,3 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -gphase(0.123); diff --git a/mlir/unittests/programs/qasm_programs/h.qasm b/mlir/unittests/programs/qasm_programs/h.qasm deleted file mode 100644 index 9e9234ecac..0000000000 --- a/mlir/unittests/programs/qasm_programs/h.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -h q[0]; diff --git a/mlir/unittests/programs/qasm_programs/identity.qasm b/mlir/unittests/programs/qasm_programs/identity.qasm deleted file mode 100644 index b8452cf533..0000000000 --- a/mlir/unittests/programs/qasm_programs/identity.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -id q[0]; diff --git a/mlir/unittests/programs/qasm_programs/if_else.qasm b/mlir/unittests/programs/qasm_programs/if_else.qasm deleted file mode 100644 index c62256c538..0000000000 --- a/mlir/unittests/programs/qasm_programs/if_else.qasm +++ /dev/null @@ -1,10 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -h q[0]; -bit c = measure q[0]; -if (c) { - x q[0]; -} else { - z q[0]; -} diff --git a/mlir/unittests/programs/qasm_programs/inverse_iswap.qasm b/mlir/unittests/programs/qasm_programs/inverse_iswap.qasm deleted file mode 100644 index 2465e6ccb6..0000000000 --- a/mlir/unittests/programs/qasm_programs/inverse_iswap.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -inv @ iswap q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/inverse_multiple_controlled_iswap.qasm b/mlir/unittests/programs/qasm_programs/inverse_multiple_controlled_iswap.qasm deleted file mode 100644 index 4b3069faa8..0000000000 --- a/mlir/unittests/programs/qasm_programs/inverse_multiple_controlled_iswap.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[4] q; -inv @ ctrl(2) @ iswap q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/iswap.qasm b/mlir/unittests/programs/qasm_programs/iswap.qasm deleted file mode 100644 index 0ada326399..0000000000 --- a/mlir/unittests/programs/qasm_programs/iswap.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -iswap q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_classical_registers_and_measurements.qasm b/mlir/unittests/programs/qasm_programs/multiple_classical_registers_and_measurements.qasm deleted file mode 100644 index 529d4b5e01..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_classical_registers_and_measurements.qasm +++ /dev/null @@ -1,8 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -bit[1] c0; -bit[2] c1; -measure q[0] -> c0[0]; -measure q[1] -> c1[0]; -measure q[2] -> c1[1]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_dcx.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_dcx.qasm deleted file mode 100644 index f6dfc9e878..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_dcx.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[4] q; -ctrl(2) @ dcx q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_ecr.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_ecr.qasm deleted file mode 100644 index de4b4a2260..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_ecr.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[4] q; -ctrl(2) @ ecr q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_h.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_h.qasm deleted file mode 100644 index bf0056c1d3..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_h.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl(2) @ h q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_identity.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_identity.qasm deleted file mode 100644 index cf59ab3d28..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_identity.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl(2) @ id q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_iswap.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_iswap.qasm deleted file mode 100644 index f93ee67e9b..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_iswap.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[4] q; -ctrl(2) @ iswap q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_p.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_p.qasm deleted file mode 100644 index b7b43a767f..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_p.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl(2) @ p(0.123) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_r.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_r.qasm deleted file mode 100644 index a3d7c0f0e9..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_r.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl(2) @ r(0.123, 0.456) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_rx.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_rx.qasm deleted file mode 100644 index 166b7ff699..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_rx.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl(2) @ rx(0.123) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_rxx.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_rxx.qasm deleted file mode 100644 index fc0a6cc3c3..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_rxx.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[4] q; -ctrl(2) @ rxx(0.123) q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_ry.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_ry.qasm deleted file mode 100644 index b15f92b362..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_ry.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl(2) @ ry(0.456) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_ryy.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_ryy.qasm deleted file mode 100644 index 854bbed0b7..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_ryy.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[4] q; -ctrl(2) @ ryy(0.123) q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_rz.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_rz.qasm deleted file mode 100644 index ffaece3669..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_rz.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl(2) @ rz(0.789) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_rzx.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_rzx.qasm deleted file mode 100644 index 03059967e4..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_rzx.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[4] q; -ctrl(2) @ rzx(0.123) q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_rzz.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_rzz.qasm deleted file mode 100644 index 599e3e2324..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_rzz.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[4] q; -ctrl(2) @ rzz(0.123) q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_s.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_s.qasm deleted file mode 100644 index bdb4ff1289..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_s.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl(2) @ s q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_sdg.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_sdg.qasm deleted file mode 100644 index 89bd46f179..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_sdg.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl(2) @ sdg q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_swap.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_swap.qasm deleted file mode 100644 index d6d80fe48c..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_swap.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[4] q; -ctrl(2) @ swap q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_sx.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_sx.qasm deleted file mode 100644 index 1586502e77..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_sx.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl(2) @ sx q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_sxdg.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_sxdg.qasm deleted file mode 100644 index 981c691264..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_sxdg.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl(2) @ sxdg q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_t.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_t.qasm deleted file mode 100644 index 53dde4bbff..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_t.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl(2) @ t q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_tdg.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_tdg.qasm deleted file mode 100644 index 60f644e391..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_tdg.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl(2) @ tdg q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_u.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_u.qasm deleted file mode 100644 index b49ada9f23..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_u.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl(2) @ u(0.1, 0.2, 0.3) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_u2.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_u2.qasm deleted file mode 100644 index fc73530086..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_u2.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl(2) @ u2(0.234, 0.567) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_x.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_x.qasm deleted file mode 100644 index 4ff0ae8383..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_x.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl(2) @ x q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_xx_minus_yy.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_xx_minus_yy.qasm deleted file mode 100644 index abf5985fd3..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_xx_minus_yy.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[4] q; -ctrl(2) @ xx_minus_yy(0.123, 0.456) q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_xx_plus_yy.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_xx_plus_yy.qasm deleted file mode 100644 index 0509793dca..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_xx_plus_yy.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[4] q; -ctrl(2) @ xx_plus_yy(0.123, 0.456) q[0], q[1], q[2], q[3]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_y.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_y.qasm deleted file mode 100644 index e4c556cc06..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_y.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl(2) @ y q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/multiple_controlled_z.qasm b/mlir/unittests/programs/qasm_programs/multiple_controlled_z.qasm deleted file mode 100644 index 9d592a27ba..0000000000 --- a/mlir/unittests/programs/qasm_programs/multiple_controlled_z.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl(2) @ z q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/p.qasm b/mlir/unittests/programs/qasm_programs/p.qasm deleted file mode 100644 index 6c52e0521d..0000000000 --- a/mlir/unittests/programs/qasm_programs/p.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -p(0.123) q[0]; diff --git a/mlir/unittests/programs/qasm_programs/r.qasm b/mlir/unittests/programs/qasm_programs/r.qasm deleted file mode 100644 index ab7119c712..0000000000 --- a/mlir/unittests/programs/qasm_programs/r.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -r(0.123, 0.456) q[0]; diff --git a/mlir/unittests/programs/qasm_programs/repeated_measurement_to_different_bits.qasm b/mlir/unittests/programs/qasm_programs/repeated_measurement_to_different_bits.qasm deleted file mode 100644 index 618e5e8aa2..0000000000 --- a/mlir/unittests/programs/qasm_programs/repeated_measurement_to_different_bits.qasm +++ /dev/null @@ -1,7 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -bit[3] c; -measure q[0] -> c[0]; -measure q[0] -> c[1]; -measure q[0] -> c[2]; diff --git a/mlir/unittests/programs/qasm_programs/repeated_measurement_to_same_bit.qasm b/mlir/unittests/programs/qasm_programs/repeated_measurement_to_same_bit.qasm deleted file mode 100644 index 1dcee58a02..0000000000 --- a/mlir/unittests/programs/qasm_programs/repeated_measurement_to_same_bit.qasm +++ /dev/null @@ -1,7 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -bit[1] c; -measure q[0] -> c[0]; -measure q[0] -> c[0]; -measure q[0] -> c[0]; diff --git a/mlir/unittests/programs/qasm_programs/repeated_reset_after_single_op.qasm b/mlir/unittests/programs/qasm_programs/repeated_reset_after_single_op.qasm deleted file mode 100644 index 068073f7aa..0000000000 --- a/mlir/unittests/programs/qasm_programs/repeated_reset_after_single_op.qasm +++ /dev/null @@ -1,7 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -h q[0]; -reset q[0]; -reset q[0]; -reset q[0]; diff --git a/mlir/unittests/programs/qasm_programs/reset_multiple_qubits_after_single_op.qasm b/mlir/unittests/programs/qasm_programs/reset_multiple_qubits_after_single_op.qasm deleted file mode 100644 index a917c83849..0000000000 --- a/mlir/unittests/programs/qasm_programs/reset_multiple_qubits_after_single_op.qasm +++ /dev/null @@ -1,7 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -h q[0]; -reset q[0]; -h q[1]; -reset q[1]; diff --git a/mlir/unittests/programs/qasm_programs/reset_qubit_after_single_op.qasm b/mlir/unittests/programs/qasm_programs/reset_qubit_after_single_op.qasm deleted file mode 100644 index ec3876c49a..0000000000 --- a/mlir/unittests/programs/qasm_programs/reset_qubit_after_single_op.qasm +++ /dev/null @@ -1,5 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -h q[0]; -reset q[0]; diff --git a/mlir/unittests/programs/qasm_programs/rx.qasm b/mlir/unittests/programs/qasm_programs/rx.qasm deleted file mode 100644 index b5598e43bc..0000000000 --- a/mlir/unittests/programs/qasm_programs/rx.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -rx(0.123) q[0]; diff --git a/mlir/unittests/programs/qasm_programs/rxx.qasm b/mlir/unittests/programs/qasm_programs/rxx.qasm deleted file mode 100644 index a039e1793d..0000000000 --- a/mlir/unittests/programs/qasm_programs/rxx.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -rxx(0.123) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/ry.qasm b/mlir/unittests/programs/qasm_programs/ry.qasm deleted file mode 100644 index a981275476..0000000000 --- a/mlir/unittests/programs/qasm_programs/ry.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -ry(0.456) q[0]; diff --git a/mlir/unittests/programs/qasm_programs/ryy.qasm b/mlir/unittests/programs/qasm_programs/ryy.qasm deleted file mode 100644 index b980249363..0000000000 --- a/mlir/unittests/programs/qasm_programs/ryy.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ryy(0.123) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/rz.qasm b/mlir/unittests/programs/qasm_programs/rz.qasm deleted file mode 100644 index 85b10988ca..0000000000 --- a/mlir/unittests/programs/qasm_programs/rz.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -rz(0.789) q[0]; diff --git a/mlir/unittests/programs/qasm_programs/rzx.qasm b/mlir/unittests/programs/qasm_programs/rzx.qasm deleted file mode 100644 index 226dc6ad25..0000000000 --- a/mlir/unittests/programs/qasm_programs/rzx.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -rzx(0.123) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/rzz.qasm b/mlir/unittests/programs/qasm_programs/rzz.qasm deleted file mode 100644 index 9af26ea2ef..0000000000 --- a/mlir/unittests/programs/qasm_programs/rzz.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -rzz(0.123) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/s.qasm b/mlir/unittests/programs/qasm_programs/s.qasm deleted file mode 100644 index 5eae687443..0000000000 --- a/mlir/unittests/programs/qasm_programs/s.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -s q[0]; diff --git a/mlir/unittests/programs/qasm_programs/sdg.qasm b/mlir/unittests/programs/qasm_programs/sdg.qasm deleted file mode 100644 index 964cd16efe..0000000000 --- a/mlir/unittests/programs/qasm_programs/sdg.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -sdg q[0]; diff --git a/mlir/unittests/programs/qasm_programs/simple_if.qasm b/mlir/unittests/programs/qasm_programs/simple_if.qasm deleted file mode 100644 index 849afb783c..0000000000 --- a/mlir/unittests/programs/qasm_programs/simple_if.qasm +++ /dev/null @@ -1,8 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -h q[0]; -bit c = measure q[0]; -if (c) { - x q[0]; -} diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_dcx.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_dcx.qasm deleted file mode 100644 index aeb9b73fa5..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_dcx.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl @ dcx q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_ecr.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_ecr.qasm deleted file mode 100644 index 27a047d5da..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_ecr.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl @ ecr q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_h.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_h.qasm deleted file mode 100644 index 92ef140657..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_h.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ctrl @ h q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_identity.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_identity.qasm deleted file mode 100644 index d390c72cca..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_identity.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ctrl @ id q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_iswap.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_iswap.qasm deleted file mode 100644 index d5b992b6ad..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_iswap.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl @ iswap q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_p.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_p.qasm deleted file mode 100644 index aaf6fa5a6a..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_p.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ctrl @ p(0.123) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_r.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_r.qasm deleted file mode 100644 index 19a1f43b69..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_r.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ctrl @ r(0.123, 0.456) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_rx.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_rx.qasm deleted file mode 100644 index cc3ee01eb1..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_rx.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ctrl @ rx(0.123) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_rxx.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_rxx.qasm deleted file mode 100644 index 2237fbb5db..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_rxx.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl @ rxx(0.123) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_ry.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_ry.qasm deleted file mode 100644 index 90ac2e40b4..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_ry.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ctrl @ ry(0.456) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_ryy.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_ryy.qasm deleted file mode 100644 index 14ad65ccc8..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_ryy.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl @ ryy(0.123) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_rz.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_rz.qasm deleted file mode 100644 index b551d82411..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_rz.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ctrl @ rz(0.789) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_rzx.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_rzx.qasm deleted file mode 100644 index bd6f5b2356..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_rzx.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl @ rzx(0.123) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_rzz.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_rzz.qasm deleted file mode 100644 index 902b8e6423..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_rzz.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl @ rzz(0.123) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_s.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_s.qasm deleted file mode 100644 index 3a106d3a2d..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_s.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ctrl @ s q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_sdg.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_sdg.qasm deleted file mode 100644 index f2515862e4..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_sdg.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ctrl @ sdg q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_swap.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_swap.qasm deleted file mode 100644 index fddea0d328..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_swap.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl @ swap q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_sx.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_sx.qasm deleted file mode 100644 index 4dd2915543..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_sx.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ctrl @ sx q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_sxdg.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_sxdg.qasm deleted file mode 100644 index dd48f8caad..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_sxdg.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ctrl @ sxdg q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_t.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_t.qasm deleted file mode 100644 index 3add5c2958..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_t.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ctrl @ t q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_tdg.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_tdg.qasm deleted file mode 100644 index d912f81565..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_tdg.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ctrl @ tdg q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_u.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_u.qasm deleted file mode 100644 index 034abf0fef..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_u.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ctrl @ u(0.1, 0.2, 0.3) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_u2.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_u2.qasm deleted file mode 100644 index 31e2811443..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_u2.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ctrl @ u2(0.234, 0.567) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_x.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_x.qasm deleted file mode 100644 index c9697fa140..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_x.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ctrl @ x q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_xx_minus_yy.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_xx_minus_yy.qasm deleted file mode 100644 index 11caeb1dfa..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_xx_minus_yy.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl @ xx_minus_yy(0.123, 0.456) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_xx_plus_yy.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_xx_plus_yy.qasm deleted file mode 100644 index 1ccb5ae4fd..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_xx_plus_yy.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[3] q; -ctrl @ xx_plus_yy(0.123, 0.456) q[0], q[1], q[2]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_y.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_y.qasm deleted file mode 100644 index e3866216ce..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_y.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ctrl @ y q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_controlled_z.qasm b/mlir/unittests/programs/qasm_programs/single_controlled_z.qasm deleted file mode 100644 index fcf8128e7c..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_controlled_z.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -ctrl @ z q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/single_measurement_to_single_bit.qasm b/mlir/unittests/programs/qasm_programs/single_measurement_to_single_bit.qasm deleted file mode 100644 index b22d6a268c..0000000000 --- a/mlir/unittests/programs/qasm_programs/single_measurement_to_single_bit.qasm +++ /dev/null @@ -1,5 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -bit[1] c; -measure q[0] -> c[0]; diff --git a/mlir/unittests/programs/qasm_programs/swap.qasm b/mlir/unittests/programs/qasm_programs/swap.qasm deleted file mode 100644 index b34d111db6..0000000000 --- a/mlir/unittests/programs/qasm_programs/swap.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -swap q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/sx.qasm b/mlir/unittests/programs/qasm_programs/sx.qasm deleted file mode 100644 index ba22a0d3e4..0000000000 --- a/mlir/unittests/programs/qasm_programs/sx.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -sx q[0]; diff --git a/mlir/unittests/programs/qasm_programs/sxdg.qasm b/mlir/unittests/programs/qasm_programs/sxdg.qasm deleted file mode 100644 index 98dc3d985c..0000000000 --- a/mlir/unittests/programs/qasm_programs/sxdg.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -sxdg q[0]; diff --git a/mlir/unittests/programs/qasm_programs/t.qasm b/mlir/unittests/programs/qasm_programs/t.qasm deleted file mode 100644 index 0cefa70c64..0000000000 --- a/mlir/unittests/programs/qasm_programs/t.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -t q[0]; diff --git a/mlir/unittests/programs/qasm_programs/tdg.qasm b/mlir/unittests/programs/qasm_programs/tdg.qasm deleted file mode 100644 index 8a8a75a925..0000000000 --- a/mlir/unittests/programs/qasm_programs/tdg.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -tdg q[0]; diff --git a/mlir/unittests/programs/qasm_programs/triple_controlled_rxx.qasm b/mlir/unittests/programs/qasm_programs/triple_controlled_rxx.qasm deleted file mode 100644 index 4d67e1a43d..0000000000 --- a/mlir/unittests/programs/qasm_programs/triple_controlled_rxx.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[5] q; -ctrl(3) @ rxx(0.123) q[0], q[1], q[2], q[3], q[4]; diff --git a/mlir/unittests/programs/qasm_programs/u.qasm b/mlir/unittests/programs/qasm_programs/u.qasm deleted file mode 100644 index b291fd60c3..0000000000 --- a/mlir/unittests/programs/qasm_programs/u.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -u(0.1, 0.2, 0.3) q[0]; diff --git a/mlir/unittests/programs/qasm_programs/u2.qasm b/mlir/unittests/programs/qasm_programs/u2.qasm deleted file mode 100644 index 3be1fcda9c..0000000000 --- a/mlir/unittests/programs/qasm_programs/u2.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -u2(0.234, 0.567) q[0]; diff --git a/mlir/unittests/programs/qasm_programs/x.qasm b/mlir/unittests/programs/qasm_programs/x.qasm deleted file mode 100644 index 743166105e..0000000000 --- a/mlir/unittests/programs/qasm_programs/x.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -x q[0]; diff --git a/mlir/unittests/programs/qasm_programs/xx_minus_yy.qasm b/mlir/unittests/programs/qasm_programs/xx_minus_yy.qasm deleted file mode 100644 index 5c24a15edd..0000000000 --- a/mlir/unittests/programs/qasm_programs/xx_minus_yy.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -xx_minus_yy(0.123, 0.456) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/xx_plus_yy.qasm b/mlir/unittests/programs/qasm_programs/xx_plus_yy.qasm deleted file mode 100644 index 8667800627..0000000000 --- a/mlir/unittests/programs/qasm_programs/xx_plus_yy.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[2] q; -xx_plus_yy(0.123, 0.456) q[0], q[1]; diff --git a/mlir/unittests/programs/qasm_programs/y.qasm b/mlir/unittests/programs/qasm_programs/y.qasm deleted file mode 100644 index b418d084b9..0000000000 --- a/mlir/unittests/programs/qasm_programs/y.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -y q[0]; diff --git a/mlir/unittests/programs/qasm_programs/z.qasm b/mlir/unittests/programs/qasm_programs/z.qasm deleted file mode 100644 index 239658928e..0000000000 --- a/mlir/unittests/programs/qasm_programs/z.qasm +++ /dev/null @@ -1,4 +0,0 @@ -OPENQASM 3.0; -include "stdgates.inc"; -qubit[1] q; -z q[0]; From 24dccde5ab135fe034aa71d076b6e403f74d6174 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 21 May 2026 17:26:46 +0200 Subject: [PATCH 12/48] Fix some more linter errors --- mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp | 8 ++++++-- mlir/unittests/programs/qasm_programs.cpp | 6 ++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 1ca95a3276..3dedcbf5c4 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -63,12 +63,14 @@ namespace { using GateFn = std::function, ArrayRef)>; +} // namespace + /** * Build the static gate-name → GateFn dispatch table. * Each entry maps a QASM3 gate identifier to a lambda that emits the * corresponding QC dialect op via QCProgramBuilder. */ -llvm::StringMap buildGateDispatch() { +static llvm::StringMap buildGateDispatch() { llvm::StringMap d; // 0-target, 1-param @@ -179,8 +181,10 @@ llvm::StringMap buildGateDispatch() { return d; } +namespace { + /// Static gate dispatch table, built once at startup. -static const llvm::StringMap GATE_DISPATCH = buildGateDispatch(); +const llvm::StringMap GATE_DISPATCH = buildGateDispatch(); /// Local qubit scope used during compound gate body expansion. /// Maps argument name → vector of MLIR qubit Values. diff --git a/mlir/unittests/programs/qasm_programs.cpp b/mlir/unittests/programs/qasm_programs.cpp index 0ab0469129..6e9c1f858e 100644 --- a/mlir/unittests/programs/qasm_programs.cpp +++ b/mlir/unittests/programs/qasm_programs.cpp @@ -10,8 +10,12 @@ #include "qasm_programs.h" +#include + namespace mlir::qasm { +// NOLINTBEGIN(readability-identifier-naming) + const std::string allocQubit = R"qasm(OPENQASM 3.0; include "stdgates.inc"; qubit q; @@ -661,4 +665,6 @@ if (c) { } )qasm"; +// NOLINTEND(readability-identifier-naming) + } // namespace mlir::qasm From 9c4aaa093e1962e87706a2ab8d3b68ec1ec24053 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 21 May 2026 17:27:10 +0200 Subject: [PATCH 13/48] Slightly improve doctrings --- .../QC/Translation/TranslateQASM3ToQC.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 3dedcbf5c4..5659057ad9 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -66,8 +66,9 @@ using GateFn = } // namespace /** - * Build the static gate-name → GateFn dispatch table. - * Each entry maps a QASM3 gate identifier to a lambda that emits the + * @brief Build the static gate-name → GateFn dispatch table. + * + * @details Each entry maps a QASM3 gate identifier to a lambda that emits the * corresponding QC dialect op via QCProgramBuilder. */ static llvm::StringMap buildGateDispatch() { @@ -190,11 +191,14 @@ const llvm::StringMap GATE_DISPATCH = buildGateDispatch(); /// Maps argument name → vector of MLIR qubit Values. using QubitScope = llvm::StringMap>; -/** AST visitor that translates a QASM3 program directly into the QC dialect. +/** + * @brief AST visitor that translates a QASM3 program directly into the QC + * dialect. * - * Implements qasm3::InstVisitor to walk the AST produced by qasm3::Parser and - * emit QC dialect ops via QCProgramBuilder, bypassing qc::QuantumComputation. - * Const-evaluation and type-checking passes run in lock-step with the walk. + * @details Implements qasm3::InstVisitor to walk the AST produced by + * qasm3::Parser and emit QC dialect ops via QCProgramBuilder, bypassing + * qc::QuantumComputation. Const-evaluation and type-checking passes run in + * lock-step with the walk. */ class MLIRQasmImporter final : public qasm3::InstVisitor { public: From 10ddff2edbbdeb6db30736df8be32f29491f4578 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 21 May 2026 17:52:20 +0200 Subject: [PATCH 14/48] Drop support for register comparisons for now --- .../QC/Translation/TranslateQASM3ToQC.cpp | 130 +----------------- mlir/unittests/programs/qasm_programs.cpp | 2 - 2 files changed, 5 insertions(+), 127 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 5659057ad9..6c7f07edc2 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h" #include "ir/Definitions.hpp" -#include "ir/operations/IfElseOperation.hpp" #include "ir/operations/OpType.hpp" #include "mlir/Dialect/QC/Builder/QCProgramBuilder.h" #include "mlir/Dialect/QC/IR/QCOps.h" @@ -29,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -812,14 +810,15 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { /// Translate a QASM3 condition expression to an i1 MLIR Value. /// Supports: /// - Single bit: `c[0]` or `!c[0]` / `~c[0]` - /// - Register comparison: `creg == N`, `creg != N`, etc. [[nodiscard]] Value translateCondition(const std::shared_ptr& condition, const std::shared_ptr& debugInfo) { - // Case 1: Binary comparison (creg == N, creg != N, etc.) + // Case 1: Register comparison (creg == N, creg != N, etc.) if (const auto binaryExpr = std::dynamic_pointer_cast(condition)) { - return translateBinaryCondition(binaryExpr, debugInfo); + throw qasm3::CompilerError( + "Register comparisons cannot be translated to QC at the moment", + debugInfo); } // Case 2: Unary negation (!c[0] or ~c[0]) @@ -846,106 +845,6 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { "Unsupported condition expression in if statement.", debugInfo); } - /// Translate a binary comparison condition (creg == N, etc.) - [[nodiscard]] Value translateBinaryCondition( - const std::shared_ptr& binaryExpr, - const std::shared_ptr& debugInfo) { - const auto comparisonKind = qasm3::getComparisonKind(binaryExpr->op); - if (!comparisonKind) { - throw qasm3::CompilerError("Unsupported comparison operator.", debugInfo); - } - - // Determine which side is the identifier and which is the constant - auto lhsIsIdentifier = - std::dynamic_pointer_cast(binaryExpr->lhs); - - const auto& idExpr = - lhsIsIdentifier ? std::dynamic_pointer_cast( - binaryExpr->lhs) - : std::dynamic_pointer_cast( - binaryExpr->rhs); - const auto& constExpr = - lhsIsIdentifier - ? std::dynamic_pointer_cast(binaryExpr->rhs) - : std::dynamic_pointer_cast(binaryExpr->lhs); - - if (!idExpr || !constExpr) { - throw qasm3::CompilerError( - "Only classical registers and constants are supported in conditions.", - debugInfo); - } - - const auto& regName = idExpr->identifier; - const uint64_t expectedVal = constExpr->getUInt(); - - // Look up classical register to get its size - auto cregIt = classicalRegisters.find(regName); - if (cregIt == classicalRegisters.end()) { - throw qasm3::CompilerError("Unknown classical register '" + regName + - "' in condition.", - debugInfo); - } - const auto regSize = static_cast(cregIt->second.size); - - auto bitIt = bitValues.find(regName); - if (bitIt == bitValues.end()) { - throw qasm3::CompilerError( - "Classical register '" + regName + - "' has no measurement results to use in condition.", - debugInfo); - } - const auto& regBits = bitIt->second; - - const auto intWidth = std::max(regSize, static_cast(64)); - auto intTy = builder.getIntegerType(static_cast(intWidth)); - - // Indexed access (c[i] == N): compare the single bit directly - if (!idExpr->indices.empty()) { - const auto idx = evaluatePositiveConstant( - idExpr->indices[0]->indexExpressions[0], debugInfo); - if (idx >= regBits.size() || !regBits[idx]) { - throw qasm3::CompilerError( - "Bit " + std::to_string(idx) + " of register '" + regName + - "' was not measured before use in condition.", - debugInfo); - } - Value extended = arith::ExtUIOp::create(builder, intTy, regBits[idx]); - Value expected = arith::ConstantOp::create( - builder, builder.getIntegerAttr(intTy, expectedVal)); - auto pred = convertComparisonKind(*comparisonKind); - return arith::CmpIOp::create(builder, pred, extended, expected); - } - - // Full-register access (c == N): compose bits into an integer - // result = b0 | (b1 << 1) | (b2 << 2) | ... - Value composed = - arith::ConstantOp::create(builder, builder.getIntegerAttr(intTy, 0)); - - for (size_t i = 0; i < regSize; ++i) { - if (i >= regBits.size() || !regBits[i]) { - throw qasm3::CompilerError( - "Bit " + std::to_string(i) + " of register '" + regName + - "' was not measured before use in condition.", - debugInfo); - } - // Extend i1 to integer type - Value extended = arith::ExtUIOp::create(builder, intTy, regBits[i]); - if (i > 0) { - Value shiftAmt = arith::ConstantOp::create( - builder, builder.getIntegerAttr(intTy, i)); - extended = arith::ShLIOp::create(builder, extended, shiftAmt); - } - composed = arith::OrIOp::create(builder, composed, extended); - } - - // Compare - Value expectedConst = arith::ConstantOp::create( - builder, builder.getIntegerAttr(intTy, expectedVal)); - - auto pred = convertComparisonKind(*comparisonKind); - return arith::CmpIOp::create(builder, pred, composed, expectedConst); - } - /// Look up the most recent measurement result for a single classical bit. [[nodiscard]] Value lookupBitValue(const std::shared_ptr& idExpr, @@ -988,25 +887,6 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { return regBits[idx]; } - /// Convert qc::ComparisonKind to arith::CmpIPredicate. - static arith::CmpIPredicate convertComparisonKind(::qc::ComparisonKind kind) { - switch (kind) { - case ::qc::ComparisonKind::Eq: - return arith::CmpIPredicate::eq; - case ::qc::ComparisonKind::Neq: - return arith::CmpIPredicate::ne; - case ::qc::ComparisonKind::Lt: - return arith::CmpIPredicate::ult; - case ::qc::ComparisonKind::Leq: - return arith::CmpIPredicate::ule; - case ::qc::ComparisonKind::Gt: - return arith::CmpIPredicate::ugt; - case ::qc::ComparisonKind::Geq: - return arith::CmpIPredicate::uge; - } - llvm_unreachable("unknown ComparisonKind"); - } - //===--- Operand resolution helpers ------------------------------------===// /// Resolve a gate operand against the top-level qubit register map. @@ -1078,7 +958,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } const auto& indexExpression = target->indices[0]->indexExpressions[0]; const auto idx = evaluatePositiveConstant(indexExpression, debugInfo); - bits.push_back(creg[idx]); + bits.push_back(creg[static_cast(idx)]); return bits; } diff --git a/mlir/unittests/programs/qasm_programs.cpp b/mlir/unittests/programs/qasm_programs.cpp index 6e9c1f858e..3767f4da8f 100644 --- a/mlir/unittests/programs/qasm_programs.cpp +++ b/mlir/unittests/programs/qasm_programs.cpp @@ -15,7 +15,6 @@ namespace mlir::qasm { // NOLINTBEGIN(readability-identifier-naming) - const std::string allocQubit = R"qasm(OPENQASM 3.0; include "stdgates.inc"; qubit q; @@ -664,7 +663,6 @@ if (c) { z q[0]; } )qasm"; - // NOLINTEND(readability-identifier-naming) } // namespace mlir::qasm From 27f59a6edbbaa85a588849f1ce894312d66ee2fd Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 21 May 2026 17:58:13 +0200 Subject: [PATCH 15/48] Fix remaining linter errors --- mlir/unittests/programs/qasm_programs.cpp | 4 ++-- mlir/unittests/programs/qasm_programs.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mlir/unittests/programs/qasm_programs.cpp b/mlir/unittests/programs/qasm_programs.cpp index 3767f4da8f..93adef8919 100644 --- a/mlir/unittests/programs/qasm_programs.cpp +++ b/mlir/unittests/programs/qasm_programs.cpp @@ -12,9 +12,9 @@ #include +// NOLINTBEGIN(readability-identifier-naming) namespace mlir::qasm { -// NOLINTBEGIN(readability-identifier-naming) const std::string allocQubit = R"qasm(OPENQASM 3.0; include "stdgates.inc"; qubit q; @@ -663,6 +663,6 @@ if (c) { z q[0]; } )qasm"; -// NOLINTEND(readability-identifier-naming) } // namespace mlir::qasm +// NOLINTEND(readability-identifier-naming) diff --git a/mlir/unittests/programs/qasm_programs.h b/mlir/unittests/programs/qasm_programs.h index 6dc6fc37f9..a90a2fe53d 100644 --- a/mlir/unittests/programs/qasm_programs.h +++ b/mlir/unittests/programs/qasm_programs.h @@ -12,6 +12,7 @@ #include +// NOLINTBEGIN(readability-identifier-naming) namespace mlir::qasm { /// Allocates a single qubit. @@ -328,3 +329,4 @@ extern const std::string simpleIf; extern const std::string ifElse; } // namespace mlir::qasm +// NOLINTEND(readability-identifier-naming) From 286accf111155996b196964903b0aaadaf088449 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 21 May 2026 18:25:43 +0200 Subject: [PATCH 16/48] Address the Rabbit's comments --- .../QC/Translation/TranslateQASM3ToQC.h | 13 +++++-- .../QC/Translation/TranslateQASM3ToQC.cpp | 37 ++++++++++++------- mlir/tools/mqt-cc/mqt-cc.cpp | 4 +- 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h b/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h index 1923654d37..c3cfc1c2b2 100644 --- a/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h +++ b/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h @@ -19,15 +19,20 @@ namespace mlir::qc { /** - * @brief Import a QASM3 program directly into the QC dialect. + * @brief Translate an OpenQASM3 program to the QC dialect. * - * @details Bypasses qc::QuantumComputation: the parser produces an AST walked - * by an InstVisitor that emits QC dialect ops via QCProgramBuilder. - * Returns nullptr on failure (diagnostics written to llvm::errs()). + * @param context MLIRContext to create the module in. + * @param filename Path to the input OpenQASM3 file. */ [[nodiscard]] OwningOpRef translateQASM3ToQC(MLIRContext* context, const std::string& filename); +/** + * @brief Translate an OpenQASM3 program to the QC dialect. + * + * @param context MLIRContext to create the module in. + * @param input Stream containing the OpenQASM3 program. + */ [[nodiscard]] OwningOpRef translateQASM3ToQC(MLIRContext* context, std::istream& input); diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 6c7f07edc2..62a1920cde 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -326,7 +326,8 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { break; } default: - break; + throw qasm3::CompilerError("Unsupported declaration type.", + stmt->debugInfo); } // Handle initializer (measure only) @@ -433,11 +434,12 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } for (size_t i = 0; i < qubits.size(); ++i) { // Use the MeasureOp directly to capture the i1 result for if/else - auto measureOp = MeasureOp::create( - builder, qubits[i], builder.getStringAttr(bits[i].registerName), - builder.getI64IntegerAttr(bits[i].registerSize), - builder.getI64IntegerAttr(bits[i].registerIndex)); - Value result = measureOp.getResult(); + auto result = + MeasureOp::create(builder, qubits[i], + builder.getStringAttr(bits[i].registerName), + builder.getI64IntegerAttr(bits[i].registerSize), + builder.getI64IntegerAttr(bits[i].registerIndex)) + .getResult(); // Track the result for use in if/else conditions const auto& regName = bits[i].registerName; @@ -472,7 +474,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { return; } - Value condition = translateCondition(stmt->condition, stmt->debugInfo); + auto condition = translateCondition(stmt->condition, stmt->debugInfo); const bool hasElse = !stmt->elseStatements.empty(); auto ifOp = @@ -585,7 +587,8 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { size_t ctrlIdx = 0; for (const auto& [n, positive] : ctrlSpec) { for (size_t i = 0; i < n; ++i, ++ctrlIdx) { - if (expandedOperands[ctrlIdx].size() != 1) { + if (ctrlIdx >= expandedOperands.size() || + expandedOperands[ctrlIdx].size() != 1) { throw qasm3::CompilerError("Control operand must be a single qubit.", stmt->debugInfo); } @@ -664,7 +667,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { // Check that no qubit appears twice across targets and controls. llvm::SmallDenseSet seen; - for (auto q : concat(iterQubits, posControls, negControls)) { + for (auto q : concat(iterQubits, posControls, negControls)) { if (!seen.insert(q).second) { throw qasm3::CompilerError("Duplicate qubit in gate '" + id + "' operands.", @@ -817,7 +820,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { if (const auto binaryExpr = std::dynamic_pointer_cast(condition)) { throw qasm3::CompilerError( - "Register comparisons cannot be translated to QC at the moment", + "Register comparisons cannot be translated to QC at the moment.", debugInfo); } @@ -828,11 +831,17 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { unaryExpr->op == qasm3::UnaryExpression::BitwiseNot); const auto idExpr = std::dynamic_pointer_cast( unaryExpr->operand); - Value bitVal = lookupBitValue(idExpr, debugInfo); + if (!idExpr) { + throw qasm3::CompilerError("Unary expression has unsupported operand.", + debugInfo); + } + auto bitVal = lookupBitValue(idExpr, debugInfo); // Negate: XOR with true - Value trueVal = arith::ConstantOp::create( - builder, builder.getIntegerAttr(builder.getI1Type(), 1)); - return arith::XOrIOp::create(builder, bitVal, trueVal); + auto trueVal = + arith::ConstantOp::create( + builder, builder.getIntegerAttr(builder.getI1Type(), 1)) + .getResult(); + return arith::XOrIOp::create(builder, bitVal, trueVal).getResult(); } // Case 3: Single bit (c[0] — truthy) diff --git a/mlir/tools/mqt-cc/mqt-cc.cpp b/mlir/tools/mqt-cc/mqt-cc.cpp index 0ecfc75c58..58920533e7 100644 --- a/mlir/tools/mqt-cc/mqt-cc.cpp +++ b/mlir/tools/mqt-cc/mqt-cc.cpp @@ -87,7 +87,7 @@ static llvm::cl::opt enableHadamardLifting( */ static OwningOpRef loadQASMFile(StringRef filename, MLIRContext* context) { - return mlir::qc::translateQASM3ToQC(context, filename.str()); + return qc::translateQASM3ToQC(context, filename.str()); } /** @@ -137,7 +137,7 @@ int main(int argc, char** argv) { DialectRegistry registry; registry .insert(); MLIRContext context(registry); From 1953fff8da544226aa9a309f1b1b74d30fe98eb5 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 21 May 2026 20:19:43 +0200 Subject: [PATCH 17/48] Drop support for compound gates for now --- .../QC/Translation/TranslateQASM3ToQC.cpp | 123 ++---------------- 1 file changed, 8 insertions(+), 115 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 62a1920cde..2f872baeb4 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -37,7 +37,6 @@ #include #include -#include #include #include #include @@ -185,7 +184,6 @@ namespace { /// Static gate dispatch table, built once at startup. const llvm::StringMap GATE_DISPATCH = buildGateDispatch(); -/// Local qubit scope used during compound gate body expansion. /// Maps argument name → vector of MLIR qubit Values. using QubitScope = llvm::StringMap>; @@ -235,7 +233,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { /// Updated each time a measure is emitted. Used for if/else conditions. llvm::StringMap> bitValues; - /// Gate library: standard gates + user-defined compound gates + /// Gate library std::map> gates; bool openQASM2CompatMode{false}; @@ -384,28 +382,6 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { throw qasm3::CompilerError("Gate '" + id + "' already declared.", stmt->debugInfo); } - std::vector paramNames; - for (const auto& p : stmt->parameters->identifiers) { - if (std::ranges::find(paramNames, p->identifier) != paramNames.end()) { - throw qasm3::CompilerError("Parameter '" + p->identifier + - "' already declared in gate '" + id + - "'.", - stmt->debugInfo); - } - paramNames.push_back(p->identifier); - } - std::vector qubitNames; - for (const auto& q : stmt->qubits->identifiers) { - if (std::ranges::find(qubitNames, q->identifier) != qubitNames.end()) { - throw qasm3::CompilerError("Qubit '" + q->identifier + - "' already declared in gate '" + id + - "'.", - stmt->debugInfo); - } - qubitNames.push_back(q->identifier); - } - gates[id] = std::make_shared( - std::move(paramNames), std::move(qubitNames), stmt->statements); } void visitGateCallStatement( @@ -511,8 +487,6 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { //===--- Core gate application ----------------------------------------===// /// Apply a gate call statement, resolving qubits from \p scope. - /// For top-level calls pass \p qubitRegisters; for compound gate bodies - /// pass the local argument scope. void applyGateCallStatement(const std::shared_ptr& stmt, const QubitScope& scope) { @@ -617,12 +591,12 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { expandedOperands.begin() + static_cast(totalCtrlCount), expandedOperands.end()); - // Compound gate: inline expand + // Compound gate if (const auto* compound = dynamic_cast(it->second.get())) { - applyCompoundGate(*compound, gateOperands, posControls, negControls, - params, invert, stmt->debugInfo); - return; + throw qasm3::CompilerError( + "Compound gates cannot be translated to QC at the moment.", + stmt->debugInfo); } // Standard gate: validate param count then determine broadcast width @@ -711,87 +685,6 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } } - /// Inline-expand a compound (user-defined) gate. - void applyCompoundGate(const qasm3::CompoundGate& gate, - const std::vector>& gateOperands, - ArrayRef posControls, - ArrayRef negControls, ArrayRef params, - bool invert, - const std::shared_ptr& debugInfo) { - if (gate.targetNames.size() != gateOperands.size()) { - throw qasm3::CompilerError("Compound gate operand count mismatch.", - debugInfo); - } - if (gate.parameterNames.size() != params.size()) { - throw qasm3::CompilerError("Compound gate parameter count mismatch.", - debugInfo); - } - - // Build local scope: argument name → Values - QubitScope localScope; - for (size_t i = 0; i < gate.targetNames.size(); ++i) { - localScope[gate.targetNames[i]] = - SmallVector(gateOperands[i].begin(), gateOperands[i].end()); - } - - // Bind parameters as constants - constEvalPass.pushEnv(); - for (size_t i = 0; i < gate.parameterNames.size(); ++i) { - constEvalPass.addConst(gate.parameterNames[i], - qasm3::const_eval::ConstEvalValue(params[i])); - } - - auto bodyFn = [&] { - for (const auto& bodyStmt : gate.body) { - if (const auto gateCall = - std::dynamic_pointer_cast(bodyStmt)) { - applyGateCallStatement(gateCall, localScope); - } else if (const auto barrier = - std::dynamic_pointer_cast( - bodyStmt)) { - SmallVector qubits; - for (const auto& g : barrier->gates) { - auto resolved = - resolveGateOperandInScope(g, localScope, barrier->debugInfo); - qubits.append(resolved.begin(), resolved.end()); - } - builder.barrier(qubits); - } else if (const auto reset = - std::dynamic_pointer_cast( - bodyStmt)) { - for (auto q : resolveGateOperandInScope(reset->gate, localScope, - reset->debugInfo)) { - builder.reset(q); - } - } - } - }; - - auto withInv = [&] { - if (invert) { - builder.inv(function_ref(bodyFn)); - } else { - bodyFn(); - } - }; - - if (posControls.empty() && negControls.empty()) { - withInv(); - } else { - for (auto q : negControls) { - builder.x(q); - } - SmallVector allControls(posControls.begin(), posControls.end()); - allControls.append(negControls.begin(), negControls.end()); - builder.ctrl(allControls, function_ref(withInv)); - for (auto q : negControls) { - builder.x(q); - } - } - - constEvalPass.popEnv(); - } - //===--- If/else helpers ------------------------------------------------===// /// Emit quantum statements inside an if/else block. @@ -905,9 +798,9 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { return resolveGateOperandInScope(operand, qubitRegisters, debugInfo); } - /** Resolve a gate operand against \p scope (top-level registers or a - * compound-gate local argument scope). Returns the MLIR Values for the - * qubit(s) named by \p operand — a full register or a single indexed qubit. + /** + * Resolve a gate operand against \p scope. Returns the qubit Values named by + * \p operand. */ SmallVector resolveGateOperandInScope( const std::shared_ptr& operand, From 6e356ae377db3618169b9180682bca9a81c2d40b Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Tue, 2 Jun 2026 20:49:25 +0200 Subject: [PATCH 18/48] Adapt implementation to more-control --- .../QC/Translation/TranslateQASM3ToQC.cpp | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 2f872baeb4..9e88e11c93 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -58,7 +58,7 @@ namespace { /// For gates with implicit controls (cx, ccx, ...) all qubits including /// the controls are in the qubits array, matching QASM3 operand order. using GateFn = - std::function, ArrayRef)>; + std::function)>; } // namespace @@ -655,31 +655,32 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } /// Emit a single gate application, wrapping with ctrl/inv as needed. - void emitGate(const GateFn& gateFn, ArrayRef qubits, + void emitGate(const GateFn& gateFn, ArrayRef targets, ArrayRef params, ArrayRef posControls, ArrayRef negControls, bool invert) { - auto inner = [&] { gateFn(builder, qubits, params); }; + auto inner = [&](ValueRange qubits) { gateFn(builder, qubits, params); }; - auto withInv = [&] { + auto withInv = [&](ValueRange qubits) { if (invert) { - builder.inv(function_ref(inner)); + builder.inv(qubits, function_ref(inner)); } else { - inner(); + inner(qubits); } }; if (posControls.empty() && negControls.empty()) { - withInv(); + withInv(targets); return; } - // Negative controls: X-bracket + SmallVector controls; + controls.append(posControls.begin(), posControls.end()); + controls.append(negControls.begin(), negControls.end()); + for (auto q : negControls) { builder.x(q); } - SmallVector allControls(posControls.begin(), posControls.end()); - allControls.append(negControls.begin(), negControls.end()); - builder.ctrl(allControls, function_ref(withInv)); + builder.ctrl(controls, targets, function_ref(withInv)); for (auto q : negControls) { builder.x(q); } From 3260e76c8cec4be3f9b196d76a53e3d05c0982fd Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Tue, 2 Jun 2026 20:50:44 +0200 Subject: [PATCH 19/48] Remove TODO comments --- mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 9e88e11c93..170dbbeccb 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -360,7 +360,6 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { return; } - // TODO: In the future, handle classical computation. throw qasm3::CompilerError("Classical computation not yet supported.", stmt->debugInfo); } @@ -540,8 +539,6 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { ctrlSpec.emplace_back(n, ctrlMod->ctrlType); nModifierControls += n; } else { - // TODO: add pow(n) support here once PowOp lands in main — detect - // qasm3::PowGateModifier, evaluate n, wrap gate emission in PowOp. throw qasm3::CompilerError( "Only ctrl/negctrl/inv modifiers are supported.", stmt->debugInfo); } From 5f6e5c9d6e3b3e30af8915cfd7aae434e4e5c705 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Tue, 2 Jun 2026 20:52:21 +0200 Subject: [PATCH 20/48] Revert "Drop support for compound gates for now" This reverts commit 00835a8c5fe3c794c2774e73d7b739ba978efcf0. --- .../QC/Translation/TranslateQASM3ToQC.cpp | 123 ++++++++++++++++-- 1 file changed, 115 insertions(+), 8 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 170dbbeccb..773f46019a 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -184,6 +185,7 @@ namespace { /// Static gate dispatch table, built once at startup. const llvm::StringMap GATE_DISPATCH = buildGateDispatch(); +/// Local qubit scope used during compound gate body expansion. /// Maps argument name → vector of MLIR qubit Values. using QubitScope = llvm::StringMap>; @@ -233,7 +235,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { /// Updated each time a measure is emitted. Used for if/else conditions. llvm::StringMap> bitValues; - /// Gate library + /// Gate library: standard gates + user-defined compound gates std::map> gates; bool openQASM2CompatMode{false}; @@ -381,6 +383,28 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { throw qasm3::CompilerError("Gate '" + id + "' already declared.", stmt->debugInfo); } + std::vector paramNames; + for (const auto& p : stmt->parameters->identifiers) { + if (std::ranges::find(paramNames, p->identifier) != paramNames.end()) { + throw qasm3::CompilerError("Parameter '" + p->identifier + + "' already declared in gate '" + id + + "'.", + stmt->debugInfo); + } + paramNames.push_back(p->identifier); + } + std::vector qubitNames; + for (const auto& q : stmt->qubits->identifiers) { + if (std::ranges::find(qubitNames, q->identifier) != qubitNames.end()) { + throw qasm3::CompilerError("Qubit '" + q->identifier + + "' already declared in gate '" + id + + "'.", + stmt->debugInfo); + } + qubitNames.push_back(q->identifier); + } + gates[id] = std::make_shared( + std::move(paramNames), std::move(qubitNames), stmt->statements); } void visitGateCallStatement( @@ -486,6 +510,8 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { //===--- Core gate application ----------------------------------------===// /// Apply a gate call statement, resolving qubits from \p scope. + /// For top-level calls pass \p qubitRegisters; for compound gate bodies + /// pass the local argument scope. void applyGateCallStatement(const std::shared_ptr& stmt, const QubitScope& scope) { @@ -588,12 +614,12 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { expandedOperands.begin() + static_cast(totalCtrlCount), expandedOperands.end()); - // Compound gate + // Compound gate: inline expand if (const auto* compound = dynamic_cast(it->second.get())) { - throw qasm3::CompilerError( - "Compound gates cannot be translated to QC at the moment.", - stmt->debugInfo); + applyCompoundGate(*compound, gateOperands, posControls, negControls, + params, invert, stmt->debugInfo); + return; } // Standard gate: validate param count then determine broadcast width @@ -683,6 +709,87 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } } + /// Inline-expand a compound (user-defined) gate. + void applyCompoundGate(const qasm3::CompoundGate& gate, + const std::vector>& gateOperands, + ArrayRef posControls, + ArrayRef negControls, ArrayRef params, + bool invert, + const std::shared_ptr& debugInfo) { + if (gate.targetNames.size() != gateOperands.size()) { + throw qasm3::CompilerError("Compound gate operand count mismatch.", + debugInfo); + } + if (gate.parameterNames.size() != params.size()) { + throw qasm3::CompilerError("Compound gate parameter count mismatch.", + debugInfo); + } + + // Build local scope: argument name → Values + QubitScope localScope; + for (size_t i = 0; i < gate.targetNames.size(); ++i) { + localScope[gate.targetNames[i]] = + SmallVector(gateOperands[i].begin(), gateOperands[i].end()); + } + + // Bind parameters as constants + constEvalPass.pushEnv(); + for (size_t i = 0; i < gate.parameterNames.size(); ++i) { + constEvalPass.addConst(gate.parameterNames[i], + qasm3::const_eval::ConstEvalValue(params[i])); + } + + auto bodyFn = [&] { + for (const auto& bodyStmt : gate.body) { + if (const auto gateCall = + std::dynamic_pointer_cast(bodyStmt)) { + applyGateCallStatement(gateCall, localScope); + } else if (const auto barrier = + std::dynamic_pointer_cast( + bodyStmt)) { + SmallVector qubits; + for (const auto& g : barrier->gates) { + auto resolved = + resolveGateOperandInScope(g, localScope, barrier->debugInfo); + qubits.append(resolved.begin(), resolved.end()); + } + builder.barrier(qubits); + } else if (const auto reset = + std::dynamic_pointer_cast( + bodyStmt)) { + for (auto q : resolveGateOperandInScope(reset->gate, localScope, + reset->debugInfo)) { + builder.reset(q); + } + } + } + }; + + auto withInv = [&] { + if (invert) { + builder.inv(function_ref(bodyFn)); + } else { + bodyFn(); + } + }; + + if (posControls.empty() && negControls.empty()) { + withInv(); + } else { + for (auto q : negControls) { + builder.x(q); + } + SmallVector allControls(posControls.begin(), posControls.end()); + allControls.append(negControls.begin(), negControls.end()); + builder.ctrl(allControls, function_ref(withInv)); + for (auto q : negControls) { + builder.x(q); + } + } + + constEvalPass.popEnv(); + } + //===--- If/else helpers ------------------------------------------------===// /// Emit quantum statements inside an if/else block. @@ -796,9 +903,9 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { return resolveGateOperandInScope(operand, qubitRegisters, debugInfo); } - /** - * Resolve a gate operand against \p scope. Returns the qubit Values named by - * \p operand. + /** Resolve a gate operand against \p scope (top-level registers or a + * compound-gate local argument scope). Returns the MLIR Values for the + * qubit(s) named by \p operand — a full register or a single indexed qubit. */ SmallVector resolveGateOperandInScope( const std::shared_ptr& operand, From 8e738573abc39ee0c0088f99b351dcc147670e20 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Tue, 2 Jun 2026 21:29:36 +0200 Subject: [PATCH 21/48] Adapt conversion of compound gates --- .../QC/Translation/TranslateQASM3ToQC.cpp | 51 ++++++++++++------- .../QC/Translation/test_qasm3_translation.cpp | 10 +++- mlir/unittests/programs/qasm_programs.cpp | 31 +++++++++++ mlir/unittests/programs/qasm_programs.h | 10 ++++ 4 files changed, 83 insertions(+), 19 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 773f46019a..3bf7b431db 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -691,15 +691,15 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } }; - if (posControls.empty() && negControls.empty()) { - withInv(targets); - return; - } - SmallVector controls; controls.append(posControls.begin(), posControls.end()); controls.append(negControls.begin(), negControls.end()); + if (controls.empty()) { + withInv(targets); + return; + } + for (auto q : negControls) { builder.x(q); } @@ -726,10 +726,17 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } // Build local scope: argument name → Values - QubitScope localScope; + llvm::SmallVector targets; + llvm::StringMap> targetsMap; for (size_t i = 0; i < gate.targetNames.size(); ++i) { - localScope[gate.targetNames[i]] = - SmallVector(gateOperands[i].begin(), gateOperands[i].end()); + for (auto target : gateOperands[i]) { + auto it = llvm::find(targets, target); + if (it == targets.end()) { + targets.push_back(target); + } + targetsMap[gate.targetNames[i]].push_back( + std::distance(targets.begin(), it)); + } } // Bind parameters as constants @@ -739,7 +746,15 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { qasm3::const_eval::ConstEvalValue(params[i])); } - auto bodyFn = [&] { + auto bodyFn = [&](ValueRange qubits) { + QubitScope localScope; + for (const auto& [name, indices] : targetsMap) { + SmallVector args; + for (auto index : indices) { + args.push_back(qubits[index]); + } + localScope[name] = std::move(args); + } for (const auto& bodyStmt : gate.body) { if (const auto gateCall = std::dynamic_pointer_cast(bodyStmt)) { @@ -765,23 +780,25 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } }; - auto withInv = [&] { + auto withInv = [&](ValueRange qubits) { if (invert) { - builder.inv(function_ref(bodyFn)); + builder.inv(qubits, function_ref(bodyFn)); } else { - bodyFn(); + bodyFn(qubits); } }; - if (posControls.empty() && negControls.empty()) { - withInv(); + SmallVector controls; + controls.append(posControls.begin(), posControls.end()); + controls.append(negControls.begin(), negControls.end()); + + if (controls.empty()) { + withInv(targets); } else { for (auto q : negControls) { builder.x(q); } - SmallVector allControls(posControls.begin(), posControls.end()); - allControls.append(negControls.begin(), negControls.end()); - builder.ctrl(allControls, function_ref(withInv)); + builder.ctrl(controls, targets, function_ref(withInv)); for (auto q : negControls) { builder.x(q); } diff --git a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp index dc0134b6ae..639ef7253b 100644 --- a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp +++ b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp @@ -340,7 +340,13 @@ INSTANTIATE_TEST_SUITE_P( QASM3TranslationTestCase{"BarrierMultipleQubits", qasm::barrierMultipleQubits, MQT_NAMED_BUILDER(qc::barrierMultipleQubits)}, + QASM3TranslationTestCase{"CtrlTwo", qasm::ctrlTwo, + MQT_NAMED_BUILDER(mlir::qc::ctrlTwo)}, + QASM3TranslationTestCase{"CtrlTwoMixed", qasm::ctrlTwoMixed, + MQT_NAMED_BUILDER(mlir::qc::ctrlTwoMixed)}, QASM3TranslationTestCase{"SimpleIf", qasm::simpleIf, - MQT_NAMED_BUILDER(qc::simpleIf)}, + MQT_NAMED_BUILDER(mlir::qc::simpleIf)}, + QASM3TranslationTestCase{"IfTwoQubits", qasm::ifTwoQubits, + MQT_NAMED_BUILDER(mlir::qc::ifTwoQubits)}, QASM3TranslationTestCase{"IfElse", qasm::ifElse, - MQT_NAMED_BUILDER(qc::ifElse)})); + MQT_NAMED_BUILDER(mlir::qc::ifElse)})); diff --git a/mlir/unittests/programs/qasm_programs.cpp b/mlir/unittests/programs/qasm_programs.cpp index 93adef8919..a0fae54429 100644 --- a/mlir/unittests/programs/qasm_programs.cpp +++ b/mlir/unittests/programs/qasm_programs.cpp @@ -642,6 +642,26 @@ qubit[3] q; barrier q[0], q[1], q[2]; )qasm"; +const std::string ctrlTwo = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +gate compound q0, q1 { + x q0; + rxx(0.123) q0, q1; +} +ctrl(2) @ compound q[0], q[1], q[2], q[3]; +)qasm"; + +const std::string ctrlTwoMixed = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +gate compound q0, q1 { + ctrl @ x q0, q1; + rxx(0.123) q0, q1; +} +ctrl(2) @ compound q[0], q[1], q[2], q[3]; +)qasm"; + const std::string simpleIf = R"qasm(OPENQASM 3.0; include "stdgates.inc"; qubit[1] q; @@ -652,6 +672,17 @@ if (c) { } )qasm"; +const std::string ifTwoQubits = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +h q[0]; +bit c = measure q[0]; +if (c) { + x q[0]; + x q[1]; +} +)qasm"; + const std::string ifElse = R"qasm(OPENQASM 3.0; include "stdgates.inc"; qubit[1] q; diff --git a/mlir/unittests/programs/qasm_programs.h b/mlir/unittests/programs/qasm_programs.h index a90a2fe53d..4e33a08645 100644 --- a/mlir/unittests/programs/qasm_programs.h +++ b/mlir/unittests/programs/qasm_programs.h @@ -322,9 +322,19 @@ extern const std::string barrierTwoQubits; /// Creates a circuit with a barrier on multiple qubits. extern const std::string barrierMultipleQubits; +/// Creates a circuit with a control modifier applied to two gates. +extern const std::string ctrlTwo; + +/// Creates a circuit with a control modifier applied to a controlled and a +/// non-controlled gate. +extern const std::string ctrlTwoMixed; + /// Creates a circuit with a simple if operation with one qubit. extern const std::string simpleIf; +/// Creates a circuit with an if operation with two qubits. +extern const std::string ifTwoQubits; + /// Creates a circuit with an if operation with an else branch. extern const std::string ifElse; From fc7fa5b45dd4737a236f9ab0b684748b707a93c7 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Tue, 2 Jun 2026 20:55:20 +0200 Subject: [PATCH 22/48] Streamline docstrings --- .../Dialect/QC/Translation/TranslateQASM3ToQC.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 3bf7b431db..d17c95b4b8 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -412,9 +412,11 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { applyGateCallStatement(stmt, qubitRegisters); } - /** Emit measure ops for \p target = measure \p measureExpr. - * Handles both full-register and single-bit assignments; wires measure - * results into the classical register's bit-value map for later use. + /** + * @brief Emit measure ops for \p target = measure \p measureExpr. + * + * @details Handles both full-register and single-bit assignments; wires + * measure results into the classical register's bit-value map for later use. */ void visitMeasureAssignment( const std::shared_ptr& target, @@ -920,9 +922,8 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { return resolveGateOperandInScope(operand, qubitRegisters, debugInfo); } - /** Resolve a gate operand against \p scope (top-level registers or a - * compound-gate local argument scope). Returns the MLIR Values for the - * qubit(s) named by \p operand — a full register or a single indexed qubit. + /** + * @brief Resolve a gate operand against \p scope. */ SmallVector resolveGateOperandInScope( const std::shared_ptr& operand, From 36dd8d3d885aeaa9b189d21e2b71d83bd7e01b94 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Tue, 2 Jun 2026 21:41:27 +0200 Subject: [PATCH 23/48] Fix linter errors --- mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index d17c95b4b8..0415bf2a3a 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -732,7 +733,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { llvm::StringMap> targetsMap; for (size_t i = 0; i < gate.targetNames.size(); ++i) { for (auto target : gateOperands[i]) { - auto it = llvm::find(targets, target); + auto* it = llvm::find(targets, target); if (it == targets.end()) { targets.push_back(target); } From b9a1be8b72a16ecb627ef05c4e855d725b3a921e Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Tue, 9 Jun 2026 16:36:04 +0200 Subject: [PATCH 24/48] Fix linter error --- mlir/tools/mqt-cc/mqt-cc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/tools/mqt-cc/mqt-cc.cpp b/mlir/tools/mqt-cc/mqt-cc.cpp index 58920533e7..994eaf071b 100644 --- a/mlir/tools/mqt-cc/mqt-cc.cpp +++ b/mlir/tools/mqt-cc/mqt-cc.cpp @@ -85,7 +85,7 @@ static llvm::cl::opt enableHadamardLifting( /** * @brief Load and parse a .qasm file, dispatching to the chosen import path. */ -static OwningOpRef loadQASMFile(StringRef filename, +static OwningOpRef loadQASMFile(llvm::StringRef filename, MLIRContext* context) { return qc::translateQASM3ToQC(context, filename.str()); } From d9ada9cd28b957b0e6ae82070473f56b621c38de Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Fri, 12 Jun 2026 12:35:50 +0200 Subject: [PATCH 25/48] Address the Rabbit's comments from #1671 --- .../QC/Translation/TranslateQASM3ToQC.cpp | 14 +++++---- .../QC/Translation/test_qasm3_translation.cpp | 29 +++++++++++++++---- mlir/unittests/programs/CMakeLists.txt | 16 ++++++++-- mlir/unittests/programs/qasm_programs.cpp | 12 ++++++++ mlir/unittests/programs/qasm_programs.h | 7 +++++ 5 files changed, 65 insertions(+), 13 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 0415bf2a3a..26ae19922d 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -300,6 +300,10 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } declarations.emplace(id, stmt); + if (stmt->isConst) { + return; // nothing to emit + } + const auto ty = std::get<1>(stmt->type); const auto sizedTy = std::dynamic_pointer_cast>(ty); @@ -340,9 +344,6 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { visitMeasureAssignment(lhsId, measureExpr, stmt->debugInfo); return; } - if (stmt->isConst) { - return; // nothing to emit - } throw qasm3::CompilerError( "Only measure statements are supported as initializers.", stmt->debugInfo); @@ -734,11 +735,14 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { for (size_t i = 0; i < gate.targetNames.size(); ++i) { for (auto target : gateOperands[i]) { auto* it = llvm::find(targets, target); + size_t index = 0; if (it == targets.end()) { + index = targets.size(); targets.push_back(target); + } else { + index = static_cast(std::distance(targets.begin(), it)); } - targetsMap[gate.targetNames[i]].push_back( - std::distance(targets.begin(), it)); + targetsMap[gate.targetNames[i]].push_back(index); } } diff --git a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp index 639ef7253b..54e14dcd8d 100644 --- a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp +++ b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp @@ -68,6 +68,20 @@ class QASM3TranslationTest } // namespace +static void singleNegControlledX(qc::QCProgramBuilder& b) { + auto q = b.allocQubitRegister(2); + b.x(q[0]); + b.cx(q[0], q[1]); + b.x(q[0]); +} + +static void mixedControlledX(qc::QCProgramBuilder& b) { + auto q = b.allocQubitRegister(3); + b.x(q[1]); + b.mcx({q[0], q[1]}, q[2]); + b.x(q[1]); +} + TEST_P(QASM3TranslationTest, ProgramEquivalence) { const auto name = " (" + GetParam().name + ")"; const auto& source = GetParam().source; @@ -148,6 +162,11 @@ INSTANTIATE_TEST_SUITE_P( QASM3TranslationTestCase{"X", qasm::x, MQT_NAMED_BUILDER(qc::x)}, QASM3TranslationTestCase{"SingleControlledX", qasm::singleControlledX, MQT_NAMED_BUILDER(qc::singleControlledX)}, + QASM3TranslationTestCase{"SingleNegControlledX", + qasm::singleNegControlledX, + MQT_NAMED_BUILDER(singleNegControlledX)}, + QASM3TranslationTestCase{"MixedControlledX", qasm::mixedControlledX, + MQT_NAMED_BUILDER(mixedControlledX)}, QASM3TranslationTestCase{"MultipleControlledX", qasm::multipleControlledX, MQT_NAMED_BUILDER(qc::multipleControlledX)}, @@ -341,12 +360,12 @@ INSTANTIATE_TEST_SUITE_P( qasm::barrierMultipleQubits, MQT_NAMED_BUILDER(qc::barrierMultipleQubits)}, QASM3TranslationTestCase{"CtrlTwo", qasm::ctrlTwo, - MQT_NAMED_BUILDER(mlir::qc::ctrlTwo)}, + MQT_NAMED_BUILDER(qc::ctrlTwo)}, QASM3TranslationTestCase{"CtrlTwoMixed", qasm::ctrlTwoMixed, - MQT_NAMED_BUILDER(mlir::qc::ctrlTwoMixed)}, + MQT_NAMED_BUILDER(qc::ctrlTwoMixed)}, QASM3TranslationTestCase{"SimpleIf", qasm::simpleIf, - MQT_NAMED_BUILDER(mlir::qc::simpleIf)}, + MQT_NAMED_BUILDER(qc::simpleIf)}, QASM3TranslationTestCase{"IfTwoQubits", qasm::ifTwoQubits, - MQT_NAMED_BUILDER(mlir::qc::ifTwoQubits)}, + MQT_NAMED_BUILDER(qc::ifTwoQubits)}, QASM3TranslationTestCase{"IfElse", qasm::ifElse, - MQT_NAMED_BUILDER(mlir::qc::ifElse)})); + MQT_NAMED_BUILDER(qc::ifElse)})); diff --git a/mlir/unittests/programs/CMakeLists.txt b/mlir/unittests/programs/CMakeLists.txt index 6bd97fef77..7fc03cf3d4 100644 --- a/mlir/unittests/programs/CMakeLists.txt +++ b/mlir/unittests/programs/CMakeLists.txt @@ -7,21 +7,31 @@ # Licensed under the MIT License add_library(MLIRQASMPrograms qasm_programs.cpp) +target_link_libraries(MLIRQASMPrograms PRIVATE MQT::ProjectOptions) target_sources(MLIRQASMPrograms PUBLIC FILE_SET HEADERS BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES qasm_programs.h) add_library(MLIRQCPrograms qc_programs.cpp) -target_link_libraries(MLIRQCPrograms PUBLIC MLIRQCProgramBuilder) +target_link_libraries( + MLIRQCPrograms + PUBLIC MLIRQCProgramBuilder + PRIVATE MQT::ProjectOptions) target_sources(MLIRQCPrograms PUBLIC FILE_SET HEADERS BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES qc_programs.h) add_library(MLIRQCOPrograms qco_programs.cpp) -target_link_libraries(MLIRQCOPrograms PUBLIC MLIRQCOProgramBuilder) +target_link_libraries( + MLIRQCOPrograms + PUBLIC MLIRQCOProgramBuilder + PRIVATE MQT::ProjectOptions) target_sources(MLIRQCOPrograms PUBLIC FILE_SET HEADERS BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES qco_programs.h) add_library(MLIRQIRPrograms qir_programs.cpp) -target_link_libraries(MLIRQIRPrograms PUBLIC MLIRQIRProgramBuilder) +target_link_libraries( + MLIRQIRPrograms + PUBLIC MLIRQIRProgramBuilder + PRIVATE MQT::ProjectOptions) target_sources(MLIRQIRPrograms PUBLIC FILE_SET HEADERS BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES qir_programs.h) diff --git a/mlir/unittests/programs/qasm_programs.cpp b/mlir/unittests/programs/qasm_programs.cpp index a0fae54429..a63c8ebbd6 100644 --- a/mlir/unittests/programs/qasm_programs.cpp +++ b/mlir/unittests/programs/qasm_programs.cpp @@ -132,12 +132,24 @@ qubit[2] q; ctrl @ x q[0], q[1]; )qasm"; +const std::string singleNegControlledX = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +negctrl @ x q[0], q[1]; +)qasm"; + const std::string multipleControlledX = R"qasm(OPENQASM 3.0; include "stdgates.inc"; qubit[3] q; ctrl(2) @ x q[0], q[1], q[2]; )qasm"; +const std::string mixedControlledX = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +ctrl @ negctrl @ x q[0], q[1], q[2]; +)qasm"; + const std::string y = R"qasm(OPENQASM 3.0; include "stdgates.inc"; qubit[1] q; diff --git a/mlir/unittests/programs/qasm_programs.h b/mlir/unittests/programs/qasm_programs.h index 4e33a08645..432aca489a 100644 --- a/mlir/unittests/programs/qasm_programs.h +++ b/mlir/unittests/programs/qasm_programs.h @@ -66,9 +66,16 @@ extern const std::string x; /// Creates a circuit with a single controlled X gate. extern const std::string singleControlledX; +/// Creates a circuit with a single negatively controlled X gate. +extern const std::string singleNegControlledX; + /// Creates a circuit with a multi-controlled X gate. extern const std::string multipleControlledX; +/// Creates a circuit with an X gate that is positively and negatively +/// controlled. +extern const std::string mixedControlledX; + /// Creates a circuit with just a Y gate. extern const std::string y; From 0ef19d97efc7ac34ea83584105845ca4ad715a65 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Fri, 12 Jun 2026 13:05:20 +0200 Subject: [PATCH 26/48] Improve coverage a bit --- .../QC/Translation/TranslateQASM3ToQC.cpp | 31 ++++++------------- .../QC/Translation/test_qasm3_translation.cpp | 9 ++++-- mlir/unittests/programs/qasm_programs.cpp | 17 ++++++++++ mlir/unittests/programs/qasm_programs.h | 9 ++++++ 4 files changed, 42 insertions(+), 24 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 26ae19922d..cee5aff6cf 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -762,28 +762,15 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } localScope[name] = std::move(args); } - for (const auto& bodyStmt : gate.body) { - if (const auto gateCall = - std::dynamic_pointer_cast(bodyStmt)) { - applyGateCallStatement(gateCall, localScope); - } else if (const auto barrier = - std::dynamic_pointer_cast( - bodyStmt)) { - SmallVector qubits; - for (const auto& g : barrier->gates) { - auto resolved = - resolveGateOperandInScope(g, localScope, barrier->debugInfo); - qubits.append(resolved.begin(), resolved.end()); - } - builder.barrier(qubits); - } else if (const auto reset = - std::dynamic_pointer_cast( - bodyStmt)) { - for (auto q : resolveGateOperandInScope(reset->gate, localScope, - reset->debugInfo)) { - builder.reset(q); - } + for (const auto& statement : gate.body) { + const auto gateCall = + std::dynamic_pointer_cast(statement); + if (gateCall == nullptr) { + throw qasm3::CompilerError("Compound operations with non-quantum " + "statements are not supported.", + debugInfo); } + applyGateCallStatement(gateCall, localScope); } }; @@ -825,7 +812,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { std::dynamic_pointer_cast(statement); if (gateCall == nullptr) { throw qasm3::CompilerError( - "Only quantum statements are supported in if/else blocks.", + "If statements with non-quantum statements are not supported.", debugInfo); } applyGateCallStatement(gateCall, qubitRegisters); diff --git a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp index 54e14dcd8d..e9b61cfb94 100644 --- a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp +++ b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp @@ -165,11 +165,16 @@ INSTANTIATE_TEST_SUITE_P( QASM3TranslationTestCase{"SingleNegControlledX", qasm::singleNegControlledX, MQT_NAMED_BUILDER(singleNegControlledX)}, - QASM3TranslationTestCase{"MixedControlledX", qasm::mixedControlledX, - MQT_NAMED_BUILDER(mixedControlledX)}, QASM3TranslationTestCase{"MultipleControlledX", qasm::multipleControlledX, MQT_NAMED_BUILDER(qc::multipleControlledX)}, + QASM3TranslationTestCase{"MixedControlledX", qasm::mixedControlledX, + MQT_NAMED_BUILDER(mixedControlledX)}, + QASM3TranslationTestCase{"InverseX", qasm::inverseX, + MQT_NAMED_BUILDER(qc::inverseX)}, + QASM3TranslationTestCase{ + "InverseMultipleControlledX", qasm::inverseMultipleControlledX, + MQT_NAMED_BUILDER(qc::inverseMultipleControlledX)}, QASM3TranslationTestCase{"Y", qasm::y, MQT_NAMED_BUILDER(qc::y)}, QASM3TranslationTestCase{"SingleControlledY", qasm::singleControlledY, MQT_NAMED_BUILDER(qc::singleControlledY)}, diff --git a/mlir/unittests/programs/qasm_programs.cpp b/mlir/unittests/programs/qasm_programs.cpp index a63c8ebbd6..8daa0ba1f2 100644 --- a/mlir/unittests/programs/qasm_programs.cpp +++ b/mlir/unittests/programs/qasm_programs.cpp @@ -102,6 +102,11 @@ include "stdgates.inc"; gphase(0.123); )qasm"; +const std::string inverseGlobalPhase = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +inv @ gphase(-0.123); +)qasm"; + const std::string identity = R"qasm(OPENQASM 3.0; include "stdgates.inc"; qubit[1] q; @@ -150,6 +155,18 @@ qubit[3] q; ctrl @ negctrl @ x q[0], q[1], q[2]; )qasm"; +const std::string inverseX = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +inv @ x q[0]; +)qasm"; + +const std::string inverseMultipleControlledX = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[3] q; +inv @ ctrl(2) @ x q[0], q[1], q[2]; +)qasm"; + const std::string y = R"qasm(OPENQASM 3.0; include "stdgates.inc"; qubit[1] q; diff --git a/mlir/unittests/programs/qasm_programs.h b/mlir/unittests/programs/qasm_programs.h index 432aca489a..66b6eac392 100644 --- a/mlir/unittests/programs/qasm_programs.h +++ b/mlir/unittests/programs/qasm_programs.h @@ -51,6 +51,9 @@ extern const std::string repeatedResetAfterSingleOp; /// Creates a circuit with just a global phase. extern const std::string globalPhase; +/// Creates a circuit with an inverse modifier applied to a global phase gate. +extern const std::string inverseGlobalPhase; + /// Creates a circuit with just an identity gate. extern const std::string identity; @@ -76,6 +79,12 @@ extern const std::string multipleControlledX; /// controlled. extern const std::string mixedControlledX; +/// Creates a circuit with an inverse modifier applied to an X gate. +extern const std::string inverseX; + +/// Creates a circuit with an inverse modifier applied to a controlled X gate. +extern const std::string inverseMultipleControlledX; + /// Creates a circuit with just a Y gate. extern const std::string y; From e0d2781c467d7c12e6d6a901a1292627d346602b Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Fri, 12 Jun 2026 19:19:51 +0200 Subject: [PATCH 27/48] Clean up and simplify --- .../QC/Translation/TranslateQASM3ToQC.cpp | 835 +++++++++--------- 1 file changed, 408 insertions(+), 427 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index cee5aff6cf..b91eea9847 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -56,27 +57,29 @@ namespace mlir::qc { namespace { -/// Signature: (builder, gate-operands, evaluated-parameters). -/// For gates with implicit controls (cx, ccx, ...) all qubits including -/// the controls are in the qubits array, matching QASM3 operand order. +/// Signature: (builder, gate operands, evaluated parameters). +/// For gates with implicit controls (cx, ccx, ...), all qubits including +/// the controls are part of the range, matching QASM3 operand order. using GateFn = std::function)>; } // namespace /** - * @brief Build the static gate-name → GateFn dispatch table. + * @brief Build the table mapping QASM3 gate identifiers to QCProgramBuilder + * emitters. * - * @details Each entry maps a QASM3 gate identifier to a lambda that emits the - * corresponding QC dialect op via QCProgramBuilder. + * @details + * Each entry maps a QASM3 gate identifier to a lambda that emits the + * corresponding QC operation via the QCProgramBuilder. */ static llvm::StringMap buildGateDispatch() { llvm::StringMap d; - // 0-target, 1-param + // ZeroTargetOneParameter d["gphase"] = [](auto& b, auto /*q*/, auto p) { b.gphase(p[0]); }; - // 1-target, 0-param + // OneTargetZeroParameter d["id"] = [](auto& b, auto q, auto) { b.id(q[0]); }; d["x"] = [](auto& b, auto q, auto) { b.x(q[0]); }; d["y"] = [](auto& b, auto q, auto) { b.y(q[0]); }; @@ -89,7 +92,7 @@ static llvm::StringMap buildGateDispatch() { d["sx"] = [](auto& b, auto q, auto) { b.sx(q[0]); }; d["sxdg"] = [](auto& b, auto q, auto) { b.sxdg(q[0]); }; - // 1-target, 1-param + // OneTargetOneParameter d["rx"] = [](auto& b, auto q, auto p) { b.rx(p[0], q[0]); }; d["ry"] = [](auto& b, auto q, auto p) { b.ry(p[0], q[0]); }; d["rz"] = [](auto& b, auto q, auto p) { b.rz(p[0], q[0]); }; @@ -97,20 +100,37 @@ static llvm::StringMap buildGateDispatch() { d["u1"] = [](auto& b, auto q, auto p) { b.p(p[0], q[0]); }; // alias d["phase"] = [](auto& b, auto q, auto p) { b.p(p[0], q[0]); }; // alias - // 1-target, 2-param + // OneTargetTwoParameter d["r"] = [](auto& b, auto q, auto p) { b.r(p[0], p[1], q[0]); }; d["u2"] = [](auto& b, auto q, auto p) { b.u2(p[0], p[1], q[0]); }; - // 1-target, 3-param - d["U"] = [](auto& b, auto q, auto p) { b.u(p[0], p[1], p[2], q[0]); }; - d["u3"] = [](auto& b, auto q, auto p) { - b.u(p[0], p[1], p[2], q[0]); - }; // alias - d["u"] = [](auto& b, auto q, auto p) { - b.u(p[0], p[1], p[2], q[0]); - }; // alias + // OneTargetThreeParameter + auto uFn = [](auto& b, auto q, auto p) { b.u(p[0], p[1], p[2], q[0]); }; + d["U"] = uFn; + d["u3"] = uFn; // alias + d["u"] = uFn; // alias + + // TwoTargetZeroParameter + d["swap"] = [](auto& b, auto q, auto) { b.swap(q[0], q[1]); }; + d["iswap"] = [](auto& b, auto q, auto) { b.iswap(q[0], q[1]); }; + d["dcx"] = [](auto& b, auto q, auto) { b.dcx(q[0], q[1]); }; + d["ecr"] = [](auto& b, auto q, auto) { b.ecr(q[0], q[1]); }; + + // TwoTargetOneParameter + d["rxx"] = [](auto& b, auto q, auto p) { b.rxx(p[0], q[0], q[1]); }; + d["ryy"] = [](auto& b, auto q, auto p) { b.ryy(p[0], q[0], q[1]); }; + d["rzx"] = [](auto& b, auto q, auto p) { b.rzx(p[0], q[0], q[1]); }; + d["rzz"] = [](auto& b, auto q, auto p) { b.rzz(p[0], q[0], q[1]); }; + + // TwoTargetTwoParameter + d["xx_plus_yy"] = [](auto& b, auto q, auto p) { + b.xx_plus_yy(p[0], p[1], q[0], q[1]); + }; + d["xx_minus_yy"] = [](auto& b, auto q, auto p) { + b.xx_minus_yy(p[0], p[1], q[0], q[1]); + }; - // 1-ctrl + 1-target, 0-param (q[0]=ctrl, q[1]=target) + // Controlled OneTargetZeroParameter d["cx"] = [](auto& b, auto q, auto) { b.cx(q[0], q[1]); }; d["cnot"] = [](auto& b, auto q, auto) { b.cx(q[0], q[1]); }; // alias d["cy"] = [](auto& b, auto q, auto) { b.cy(q[0], q[1]); }; @@ -118,7 +138,7 @@ static llvm::StringMap buildGateDispatch() { d["ch"] = [](auto& b, auto q, auto) { b.ch(q[0], q[1]); }; d["csx"] = [](auto& b, auto q, auto) { b.csx(q[0], q[1]); }; - // 1-ctrl + 1-target, 1-param + // Controlled OneTargetOneParameter d["crx"] = [](auto& b, auto q, auto p) { b.crx(p[0], q[0], q[1]); }; d["cry"] = [](auto& b, auto q, auto p) { b.cry(p[0], q[0], q[1]); }; d["crz"] = [](auto& b, auto q, auto p) { b.crz(p[0], q[0], q[1]); }; @@ -127,83 +147,63 @@ static llvm::StringMap buildGateDispatch() { b.cp(p[0], q[0], q[1]); }; // alias - // 2-ctrl + 1-target, 0-param (q[0],q[1]=ctrl, q[2]=target) - d["ccx"] = [](auto& b, auto q, auto) { b.mcx({q[0], q[1]}, q[2]); }; - d["toffoli"] = [](auto& b, auto q, auto) { - b.mcx({q[0], q[1]}, q[2]); - }; // alias - d["ccz"] = [](auto& b, auto q, auto) { b.mcz({q[0], q[1]}, q[2]); }; - - // 2-target, 0-param - d["swap"] = [](auto& b, auto q, auto) { b.swap(q[0], q[1]); }; - d["iswap"] = [](auto& b, auto q, auto) { b.iswap(q[0], q[1]); }; - d["dcx"] = [](auto& b, auto q, auto) { b.dcx(q[0], q[1]); }; - d["ecr"] = [](auto& b, auto q, auto) { b.ecr(q[0], q[1]); }; - - // 1-ctrl + 2-target, 0-param (q[0]=ctrl, q[1],q[2]=targets) + // Controlled TwoTargetZeroParameter d["cswap"] = [](auto& b, auto q, auto) { b.cswap(q[0], q[1], q[2]); }; d["fredkin"] = [](auto& b, auto q, auto) { b.cswap(q[0], q[1], q[2]); }; // alias - // 2-target, 2-param - d["xx_plus_yy"] = [](auto& b, auto q, auto p) { - b.xx_plus_yy(p[0], p[1], q[0], q[1]); - }; - d["xx_minus_yy"] = [](auto& b, auto q, auto p) { - b.xx_minus_yy(p[0], p[1], q[0], q[1]); - }; - - // 2-target, 1-param - d["rxx"] = [](auto& b, auto q, auto p) { b.rxx(p[0], q[0], q[1]); }; - d["ryy"] = [](auto& b, auto q, auto p) { b.ryy(p[0], q[0], q[1]); }; - d["rzx"] = [](auto& b, auto q, auto p) { b.rzx(p[0], q[0], q[1]); }; - d["rzz"] = [](auto& b, auto q, auto p) { b.rzz(p[0], q[0], q[1]); }; - - // MCX variants: q[0..N-2] are controls, q[N-1] is the target. - // These are not in stdgates.inc but are widely used (Qiskit-style). + // Multi-controlled gates auto mcxFn = [](auto& b, auto q, auto) { b.mcx(q.drop_back(1), q.back()); }; d["mcx"] = mcxFn; d["mcx_gray"] = mcxFn; - d["mcphase"] = [](auto& b, auto q, auto p) { - b.mcp(p[0], q.drop_back(1), q.back()); - }; - // vchain/recursive carry ancilla qubits; strip them using Qiskit's formula + d["mcx_vchain"] = [](auto& b, auto q, auto) { const size_t n = q.size() - ((q.size() + 1) / 2) + 2; b.mcx(q.slice(0, n - 1), q[n - 1]); }; + d["mcx_recursive"] = [](auto& b, auto q, auto) { const size_t n = (q.size() > 5) ? q.size() - 1 : q.size(); b.mcx(q.slice(0, n - 1), q[n - 1]); }; + d["mcphase"] = [](auto& b, auto q, auto p) { + b.mcp(p[0], q.drop_back(1), q.back()); + }; + return d; } +static llvm::StringMap> convertToStringMap( + const std::map>& sourceMap) { + llvm::StringMap> targetMap; + for (auto& [key, value] : sourceMap) { + targetMap.insert(std::make_pair(key, std::move(value))); + } + return targetMap; +} + namespace { -/// Static gate dispatch table, built once at startup. +/// Map from QASM3 gate identifier to QCProgramBuilder emitter. const llvm::StringMap GATE_DISPATCH = buildGateDispatch(); -/// Local qubit scope used during compound gate body expansion. -/// Maps argument name → vector of MLIR qubit Values. +/// Map of qubits in the current scope. using QubitScope = llvm::StringMap>; /** - * @brief AST visitor that translates a QASM3 program directly into the QC - * dialect. + * @brief AST visitor that translates a QASM3 program to a QC program. * - * @details Implements qasm3::InstVisitor to walk the AST produced by - * qasm3::Parser and emit QC dialect ops via QCProgramBuilder, bypassing - * qc::QuantumComputation. Const-evaluation and type-checking passes run in - * lock-step with the walk. + * @details + * Implements qasm3::InstVisitor to walk the AST produced by qasm3::Parser and + * emit QC operations via the QCProgramBuilder. */ class MLIRQasmImporter final : public qasm3::InstVisitor { public: explicit MLIRQasmImporter(MLIRContext* ctx) : builder(ctx), typeCheckPass(constEvalPass), - gates(qasm3::STANDARD_GATES) { + gates(convertToStringMap(qasm3::STANDARD_GATES)) { initBuiltins(); builder.initialize(); } @@ -226,34 +226,34 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { qasm3::NestedEnvironment> declarations; - /// Top-level qubit registers: register name → SSA Values + /// Map from qubit-register name to allocated qubit values. QubitScope qubitRegisters; - /// Classical bit registers: register name → ClassicalRegister + /// Map from classical-register name to ClassicalRegister. llvm::StringMap classicalRegisters; - /// Measurement result tracking: register name → vector of i1 Values. - /// Updated each time a measure is emitted. Used for if/else conditions. + /// Map from classical-register name to measurement results. llvm::StringMap> bitValues; - /// Gate library: standard gates + user-defined compound gates - std::map> gates; + /// Map from gate identifier to QASM3 definition. + llvm::StringMap> gates; bool openQASM2CompatMode{false}; //===--- Initialization -----------------------------------------------===// - /// Seed the const-eval and type-check passes with QASM3 built-in constants - /// (pi, euler, tau) and prime the type environment with their types. void initBuiltins() { using namespace qasm3::const_eval; using namespace qasm3::type_checking; - auto floatTy = InferredType{std::dynamic_pointer_cast( - std::make_shared>(qasm3::Float, 64))}; - auto addConstant = [&](const std::string& name, double val) { - constEvalPass.addConst(name, ConstEvalValue(val)); - typeCheckPass.addBuiltin(name, floatTy); + auto floatType = + InferredType{std::dynamic_pointer_cast( + std::make_shared>(qasm3::Float, + 64))}; + + auto addConstant = [&](const std::string& name, double value) { + constEvalPass.addConst(name, ConstEvalValue(value)); + typeCheckPass.addBuiltin(name, floatType); }; addConstant("pi", ::qc::PI); @@ -263,27 +263,63 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { addConstant("euler", ::qc::E); addConstant("ℇ", ::qc::E); - // MCX variants: not in OQ3 stdlib, variable qubit arity. - // GateInfo fields are not arity-checked for StandardGate in this importer; - // the GATE_DISPATCH lambdas handle the variable-arity logic at call time. const qasm3::GateInfo mcxInfo{.nControls = 0, .nTargets = 0, .nParameters = 0, .type = ::qc::OpType::X}; - const qasm3::GateInfo mcphaseInfo{.nControls = 0, - .nTargets = 0, - .nParameters = 1, - .type = ::qc::OpType::P}; gates["mcx"] = std::make_shared(mcxInfo); gates["mcx_gray"] = std::make_shared(mcxInfo); gates["mcx_vchain"] = std::make_shared(mcxInfo); gates["mcx_recursive"] = std::make_shared(mcxInfo); + + const qasm3::GateInfo mcphaseInfo{.nControls = 0, + .nTargets = 0, + .nParameters = 1, + .type = ::qc::OpType::P}; gates["mcphase"] = std::make_shared(mcphaseInfo); } public: //===--- InstVisitor overrides ----------------------------------------===// + void + visitGateStatement(std::shared_ptr stmt) override { + const auto& id = stmt->identifier; + if (stmt->isOpaque) { + if (!gates.contains(id)) { + throw qasm3::CompilerError("Unsupported opaque gate '" + id + "'.", + stmt->debugInfo); + } + return; + } + if (gates.contains(id)) { + throw qasm3::CompilerError("Gate '" + id + "' already declared.", + stmt->debugInfo); + } + std::vector params; + for (const auto& p : stmt->parameters->identifiers) { + const auto& param = p->identifier; + if (std::ranges::find(params, param) != params.end()) { + throw qasm3::CompilerError( + "Parameter '" + param + "' already declared in gate '" + id + "'.", + stmt->debugInfo); + } + params.push_back(param); + } + std::vector targets; + for (const auto& t : stmt->qubits->identifiers) { + const auto& target = t->identifier; + if (std::ranges::find(targets, target) != targets.end()) { + throw qasm3::CompilerError( + "Target '" + target + "' already declared in gate '" + id + "'.", + stmt->debugInfo); + } + targets.push_back(target); + } + gates[id] = std::make_shared( + std::move(params), std::move(targets), stmt->statements); + } + void visitVersionDeclaration(const std::shared_ptr versionDeclaration) override { if (versionDeclaration->version < 3) { @@ -301,27 +337,23 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { declarations.emplace(id, stmt); if (stmt->isConst) { - return; // nothing to emit + // Nothing to emit + return; } - const auto ty = std::get<1>(stmt->type); - const auto sizedTy = - std::dynamic_pointer_cast>(ty); - if (!sizedTy) { + const auto sizedType = + std::dynamic_pointer_cast>( + std::get<1>(stmt->type)); + if (!sizedType) { throw qasm3::CompilerError("Only sized types are supported.", stmt->debugInfo); } - const auto size = static_cast(sizedTy->getDesignator()); + const auto size = static_cast(sizedType->getDesignator()); - switch (sizedTy->type) { + switch (sizedType->type) { case qasm3::Qubit: { - auto reg = builder.allocQubitRegister(size); - SmallVector qubits; - qubits.reserve(static_cast(size)); - for (int64_t i = 0; i < size; ++i) { - qubits.push_back(reg[static_cast(i)]); - } - qubitRegisters[id] = std::move(qubits); + const auto& reg = builder.allocQubitRegister(size); + qubitRegisters[id] = std::move(reg.qubits); break; } case qasm3::Bit: @@ -335,123 +367,83 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { stmt->debugInfo); } - // Handle initializer (measure only) + // Handle declarations through measure expressions if (stmt->expression) { - const auto& expr = stmt->expression->expression; + const auto& innerExpr = stmt->expression->expression; if (const auto measureExpr = - std::dynamic_pointer_cast(expr)) { - auto lhsId = std::make_shared(id); - visitMeasureAssignment(lhsId, measureExpr, stmt->debugInfo); + std::dynamic_pointer_cast(innerExpr)) { + auto target = std::make_shared(id); + visitMeasureAssignment(target, measureExpr, stmt->debugInfo); return; } throw qasm3::CompilerError( - "Only measure statements are supported as initializers.", - stmt->debugInfo); + "Only measure expressions can declare variables.", stmt->debugInfo); } } + void + visitInitialLayout(std::shared_ptr layout) override { + throw qasm3::CompilerError("InitialLayout pragmas are not supported.", + layout->debugInfo); + } + + void visitOutputPermutation( + std::shared_ptr perm) override { + throw qasm3::CompilerError("OutputPermutation pragmas are not supported.", + perm->debugInfo); + } + + void visitGateCallStatement( + std::shared_ptr stmt) override { + applyGateCallStatement(stmt, qubitRegisters); + } + void visitAssignmentStatement( std::shared_ptr stmt) override { - const auto& id = stmt->identifier->identifier; - assert(declarations.find(id).has_value() && "Checked by type check pass"); - assert(!declarations.find(id)->get()->isConst && - "Checked by type check pass"); + const auto& innerId = stmt->identifier->identifier; + assert(declarations.find(innerId).has_value()); + assert(!declarations.find(innerId)->get()->isConst); - const auto& expr = stmt->expression->expression; + const auto& innerExpr = stmt->expression->expression; if (const auto measureExpr = - std::dynamic_pointer_cast(expr)) { + std::dynamic_pointer_cast(innerExpr)) { visitMeasureAssignment(stmt->identifier, measureExpr, stmt->debugInfo); return; } - throw qasm3::CompilerError("Classical computation not yet supported.", + throw qasm3::CompilerError("Classical computations are not supported.", stmt->debugInfo); } - void - visitGateStatement(std::shared_ptr stmt) override { - auto id = stmt->identifier; - if (stmt->isOpaque) { - if (!gates.contains(id)) { - throw qasm3::CompilerError("Unsupported opaque gate '" + id + "'.", - stmt->debugInfo); - } - return; - } - if (gates.contains(id)) { - if (std::dynamic_pointer_cast(gates[id])) { - return; // ignore redeclaration of standard gate - } - throw qasm3::CompilerError("Gate '" + id + "' already declared.", - stmt->debugInfo); - } - std::vector paramNames; - for (const auto& p : stmt->parameters->identifiers) { - if (std::ranges::find(paramNames, p->identifier) != paramNames.end()) { - throw qasm3::CompilerError("Parameter '" + p->identifier + - "' already declared in gate '" + id + - "'.", - stmt->debugInfo); - } - paramNames.push_back(p->identifier); - } - std::vector qubitNames; - for (const auto& q : stmt->qubits->identifiers) { - if (std::ranges::find(qubitNames, q->identifier) != qubitNames.end()) { - throw qasm3::CompilerError("Qubit '" + q->identifier + - "' already declared in gate '" + id + - "'.", - stmt->debugInfo); - } - qubitNames.push_back(q->identifier); - } - gates[id] = std::make_shared( - std::move(paramNames), std::move(qubitNames), stmt->statements); - } - - void visitGateCallStatement( - std::shared_ptr stmt) override { - applyGateCallStatement(stmt, qubitRegisters); - } - - /** - * @brief Emit measure ops for \p target = measure \p measureExpr. - * - * @details Handles both full-register and single-bit assignments; wires - * measure results into the classical register's bit-value map for later use. - */ void visitMeasureAssignment( const std::shared_ptr& target, const std::shared_ptr& measureExpr, const std::shared_ptr& debugInfo) { - auto qubits = resolveGateOperand(measureExpr->gate, debugInfo); - auto bits = resolveClassicalBits(target, debugInfo); - if (qubits.size() != bits.size()) { - throw qasm3::CompilerError( - "Classical and quantum registers must have the same width in measure " - "statement. Classical register '" + - target->identifier + "' has " + std::to_string(bits.size()) + - " bits, but quantum register '" + measureExpr->gate->getName() + - "' has " + std::to_string(qubits.size()) + " qubits.", - debugInfo); + const auto& bits = resolveClassicalBits(target, debugInfo); + const auto& operand = resolveGateOperand(measureExpr->gate, debugInfo); + SmallVector qubits; + if (std::holds_alternative(operand)) { + qubits.push_back(std::get(operand)); + } else { + qubits = std::get>(operand); } - for (size_t i = 0; i < qubits.size(); ++i) { - // Use the MeasureOp directly to capture the i1 result for if/else - auto result = - MeasureOp::create(builder, qubits[i], - builder.getStringAttr(bits[i].registerName), - builder.getI64IntegerAttr(bits[i].registerSize), - builder.getI64IntegerAttr(bits[i].registerIndex)) - .getResult(); - - // Track the result for use in if/else conditions - const auto& regName = bits[i].registerName; - auto& regBits = bitValues[regName]; - const auto idx = static_cast(bits[i].registerIndex); - if (regBits.size() <= idx) { - regBits.resize(idx + 1); + if (bits.size() != qubits.size()) { + throw qasm3::CompilerError("The classical register and the quantum " + "register must have the same width.", + debugInfo); + } + for (const auto& [bit, qubit] : llvm::zip_equal(bits, qubits)) { + auto result = MeasureOp::create( + builder, qubit, builder.getStringAttr(bit.registerName), + builder.getI64IntegerAttr(bit.registerSize), + builder.getI64IntegerAttr(bit.registerIndex)) + .getResult(); + auto& regBits = bitValues[bit.registerName]; + const auto index = static_cast(bit.registerIndex); + if (regBits.size() <= index) { + regBits.resize(index + 1); } - regBits[idx] = result; + regBits[index] = result; } } @@ -459,30 +451,44 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { std::shared_ptr stmt) override { SmallVector qubits; for (const auto& gate : stmt->gates) { - auto resolved = resolveGateOperand(gate, stmt->debugInfo); - qubits.append(resolved.begin(), resolved.end()); + const auto& operand = resolveGateOperand(gate, stmt->debugInfo); + if (std::holds_alternative(operand)) { + qubits.push_back(std::get(operand)); + } else { + llvm::append_range(qubits, std::get>(operand)); + } } builder.barrier(qubits); } void visitResetStatement(std::shared_ptr stmt) override { - for (auto q : resolveGateOperand(stmt->gate, stmt->debugInfo)) { - builder.reset(q); + const auto& operand = resolveGateOperand(stmt->gate, stmt->debugInfo); + if (std::holds_alternative(operand)) { + builder.reset(std::get(operand)); + } else { + for (auto qubit : std::get>(operand)) { + builder.reset(qubit); + } } } void visitIfStatement(std::shared_ptr stmt) override { - if (stmt->thenStatements.empty() && stmt->elseStatements.empty()) { - return; + if (stmt->thenStatements.empty()) { + throw qasm3::CompilerError( + "If statements with empty then blocks are not supported.", + stmt->debugInfo); } auto condition = translateCondition(stmt->condition, stmt->debugInfo); - const bool hasElse = !stmt->elseStatements.empty(); + const auto hasElse = !stmt->elseStatements.empty(); auto ifOp = scf::IfOp::create(builder, condition, /*withElseRegion=*/hasElse); + // Save current insertion point + OpBuilder::InsertionGuard guard(builder); + // Then block builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); emitBlockStatements(stmt->thenStatements, stmt->debugInfo); @@ -492,157 +498,146 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { builder.setInsertionPointToStart(&ifOp.getElseRegion().front()); emitBlockStatements(stmt->elseStatements, stmt->debugInfo); } - - // Restore insertion point after the if op - builder.setInsertionPointAfter(ifOp); - } - - void - visitInitialLayout(std::shared_ptr layout) override { - throw qasm3::CompilerError( - "Initial layout pragmas are not supported in direct MLIR import.", - layout->debugInfo); - } - - void visitOutputPermutation( - std::shared_ptr perm) override { - throw qasm3::CompilerError( - "Output permutation pragmas are not supported in direct MLIR import.", - perm->debugInfo); } //===--- Core gate application ----------------------------------------===// - /// Apply a gate call statement, resolving qubits from \p scope. - /// For top-level calls pass \p qubitRegisters; for compound gate bodies - /// pass the local argument scope. + /** + * @brief Apply a GateCallStatement by emitting the corresponding QC + * operations. + * + * @param stmt The GateCallStatement to apply. + * @param scope The current qubit scope for resolving operands. If called from + * the main visitor, this is the top-level qubitRegisters map. If called + * recursively for a compound gate, this is the local scope of the + * CompoundGate. + */ void applyGateCallStatement(const std::shared_ptr& stmt, const QubitScope& scope) { const auto& id = stmt->identifier; - auto it = gates.find(id); - // `resolvedId` may differ from `id` when OQ2 compat strips 'c' prefixes. - std::string resolvedId = id; - size_t implicitCompatControls = 0; - - // OQ2 compat mode: strip leading 'c' prefixes and treat each as - // an additional positive control. E.g. "cmygate q0, q1" with compat on - // becomes ctrl @ mygate q0, q1 when "mygate" is in the gate library. - if (it == gates.end() && openQASM2CompatMode) { + + // OpenQASM 2 compatibility: + // Strip leading c characters and treat them as implicit controls + auto resolvedId = id; + size_t numCompatControls = 0; + if (openQASM2CompatMode && it == gates.end()) { while (!resolvedId.empty() && resolvedId.front() == 'c') { resolvedId = resolvedId.substr(1); - ++implicitCompatControls; + ++numCompatControls; } - if (implicitCompatControls > 0) { + if (numCompatControls > 0) { it = gates.find(resolvedId); } } + if (it == gates.end()) { throw qasm3::CompilerError("Unknown gate '" + id + "'.", stmt->debugInfo); } // Evaluate parameters to doubles - std::vector params; + SmallVector params; params.reserve(stmt->arguments.size()); for (const auto& arg : stmt->arguments) { auto result = constEvalPass.visit(arg); if (!result.has_value()) { - throw qasm3::CompilerError( - "Gate parameter could not be const-evaluated.", stmt->debugInfo); + throw qasm3::CompilerError("Gate parameter could not be evaluated.", + stmt->debugInfo); } params.push_back(result->toExpr()->asFP()); } - // Parse modifiers: accumulate pos/neg controls and invert flag - bool invert = false; - size_t nModifierControls = 0; - // (count, isPositive) per ctrl modifier, in order - SmallVector> ctrlSpec; + // Expand operands to MLIR values + SmallVector>> operands; + operands.reserve(stmt->operands.size()); + for (const auto& operand : stmt->operands) { + operands.push_back( + resolveGateOperandInScope(operand, scope, stmt->debugInfo)); + } + + auto invert = false; + size_t numControls = 0; + SmallVector posControls; + SmallVector negControls; + + // Parse modifiers for (const auto& mod : stmt->modifiers) { if (std::dynamic_pointer_cast(mod)) { invert = !invert; } else if (const auto* ctrlMod = dynamic_cast(mod.get())) { - const size_t n = + const auto n = evaluatePositiveConstant(ctrlMod->expression, stmt->debugInfo, 1); - ctrlSpec.emplace_back(n, ctrlMod->ctrlType); - nModifierControls += n; + for (size_t i = 0; i < n; ++i, ++numControls) { + if (numControls >= operands.size()) { + throw qasm3::CompilerError("Control index out of bounds.", + stmt->debugInfo); + } + const auto& qubit = operands[numControls]; + if (std::holds_alternative>(qubit)) { + throw qasm3::CompilerError("Control operand must be a qubit.", + stmt->debugInfo); + } + if (ctrlMod->ctrlType) { + posControls.push_back(std::get(qubit)); + } else { + negControls.push_back(std::get(qubit)); + } + } } else { throw qasm3::CompilerError( - "Only ctrl/negctrl/inv modifiers are supported.", stmt->debugInfo); + "Only ctrl, negctrl, and inv modifiers are supported.", + stmt->debugInfo); } } - // Expand each operand to its qubit Values - std::vector> expandedOperands; - expandedOperands.reserve(stmt->operands.size()); - for (const auto& operand : stmt->operands) { - expandedOperands.push_back( - resolveGateOperandInScope(operand, scope, stmt->debugInfo)); - } - - // First nModifierControls slots are modifier-derived controls - SmallVector posControls; - SmallVector negControls; - size_t ctrlIdx = 0; - for (const auto& [n, positive] : ctrlSpec) { - for (size_t i = 0; i < n; ++i, ++ctrlIdx) { - if (ctrlIdx >= expandedOperands.size() || - expandedOperands[ctrlIdx].size() != 1) { - throw qasm3::CompilerError("Control operand must be a single qubit.", - stmt->debugInfo); - } - if (positive) { - posControls.push_back(expandedOperands[ctrlIdx][0]); - } else { - negControls.push_back(expandedOperands[ctrlIdx][0]); - } + // OpenQASM 2 compatibility: + // Append implicit controls + for (size_t i = 0; i < numCompatControls; ++i, ++numControls) { + if (numControls >= operands.size()) { + throw qasm3::CompilerError("Control index out of bounds.", + stmt->debugInfo); } - } - - // OQ2 compat implicit controls follow modifier controls - for (size_t i = 0; i < implicitCompatControls; ++i, ++ctrlIdx) { - if (ctrlIdx >= expandedOperands.size() || - expandedOperands[ctrlIdx].size() != 1) { - throw qasm3::CompilerError( - "Implicit OQ2 control operand must be a single qubit.", - stmt->debugInfo); + const auto& qubit = operands[numControls]; + if (std::holds_alternative>(qubit)) { + throw qasm3::CompilerError("Control operand must be a qubit.", + stmt->debugInfo); } - posControls.push_back(expandedOperands[ctrlIdx][0]); + posControls.push_back(std::get(qubit)); } - const size_t totalCtrlCount = nModifierControls + implicitCompatControls; - // Remaining slots are the gate's own operands (may broadcast) - std::vector> gateOperands( - expandedOperands.begin() + static_cast(totalCtrlCount), - expandedOperands.end()); + // Remaining operands belong to the gate itself + auto gateOperands = + llvm::to_vector(llvm::drop_begin(operands, numControls)); - // Compound gate: inline expand + // Inline compound gate if (const auto* compound = dynamic_cast(it->second.get())) { - applyCompoundGate(*compound, gateOperands, posControls, negControls, - params, invert, stmt->debugInfo); + applyCompoundGate(*compound, params, gateOperands, posControls, + negControls, invert, stmt->debugInfo); return; } - // Standard gate: validate param count then determine broadcast width + // Emit standard gate + const auto dispIt = GATE_DISPATCH.find(resolvedId); + if (dispIt == GATE_DISPATCH.end()) { + throw qasm3::CompilerError("Unknown gate '" + id + "'.", stmt->debugInfo); + } + if (it->second->getNParameters() != params.size()) { - throw qasm3::CompilerError( - "Gate '" + id + "' takes " + - std::to_string(it->second->getNParameters()) + - " parameters, but " + std::to_string(params.size()) + - " were supplied.", - stmt->debugInfo); + throw qasm3::CompilerError("Invalid number of parameters for gate '" + + id + "'.", + stmt->debugInfo); } - // Standard gate: determine broadcast width size_t broadcastWidth = 0; - for (const auto& ops : gateOperands) { - if (ops.size() > 1) { + for (const auto& operand : gateOperands) { + if (std::holds_alternative>(operand)) { + const auto& qubits = std::get>(operand); if (broadcastWidth == 0) { - broadcastWidth = ops.size(); - } else if (broadcastWidth != ops.size()) { + broadcastWidth = qubits.size(); + } else if (broadcastWidth != qubits.size()) { throw qasm3::CompilerError( "Broadcast operands must all have the same width.", stmt->debugInfo); @@ -653,96 +648,98 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { broadcastWidth = 1; } - const auto dispIt = GATE_DISPATCH.find(resolvedId); - if (dispIt == GATE_DISPATCH.end()) { - throw qasm3::CompilerError("No MLIR mapping for gate '" + id + "'.", - stmt->debugInfo); - } - for (size_t b = 0; b < broadcastWidth; ++b) { - SmallVector iterQubits; - iterQubits.reserve(gateOperands.size()); - for (const auto& ops : gateOperands) { - iterQubits.push_back(ops.size() > 1 ? ops[b] : ops[0]); - } - - // Check that no qubit appears twice across targets and controls. - llvm::SmallDenseSet seen; - for (auto q : concat(iterQubits, posControls, negControls)) { - if (!seen.insert(q).second) { - throw qasm3::CompilerError("Duplicate qubit in gate '" + id + - "' operands.", - stmt->debugInfo); + SmallVector targets; + targets.reserve(gateOperands.size()); + for (const auto& operand : gateOperands) { + if (std::holds_alternative>(operand)) { + targets.push_back(std::get>(operand)[b]); + } else { + targets.push_back(std::get(operand)); } } - - emitGate(dispIt->second, iterQubits, params, posControls, negControls, + emitGate(dispIt->second, params, targets, posControls, negControls, invert); } } - /// Emit a single gate application, wrapping with ctrl/inv as needed. - void emitGate(const GateFn& gateFn, ArrayRef targets, - ArrayRef params, ArrayRef posControls, - ArrayRef negControls, bool invert) { - auto inner = [&](ValueRange qubits) { gateFn(builder, qubits, params); }; - - auto withInv = [&](ValueRange qubits) { + /// Helper function to build a gate with potential modifiers. + void buildModifiedGate(function_ref bodyFn, + ValueRange targets, ValueRange posControls, + ValueRange negControls, bool invert) { + auto wrappedBodyFn = [&](ValueRange qubits) { if (invert) { - builder.inv(qubits, function_ref(inner)); + builder.inv(qubits, function_ref(bodyFn)); } else { - inner(qubits); + bodyFn(qubits); } }; + if (posControls.empty() && negControls.empty()) { + wrappedBodyFn(targets); + return; + } + SmallVector controls; controls.append(posControls.begin(), posControls.end()); controls.append(negControls.begin(), negControls.end()); - if (controls.empty()) { - withInv(targets); - return; + for (auto control : negControls) { + builder.x(control); } - - for (auto q : negControls) { - builder.x(q); - } - builder.ctrl(controls, targets, function_ref(withInv)); - for (auto q : negControls) { - builder.x(q); + builder.ctrl(controls, targets, + function_ref(wrappedBodyFn)); + for (auto control : negControls) { + builder.x(control); } } - /// Inline-expand a compound (user-defined) gate. - void applyCompoundGate(const qasm3::CompoundGate& gate, - const std::vector>& gateOperands, - ArrayRef posControls, - ArrayRef negControls, ArrayRef params, - bool invert, - const std::shared_ptr& debugInfo) { - if (gate.targetNames.size() != gateOperands.size()) { - throw qasm3::CompilerError("Compound gate operand count mismatch.", - debugInfo); - } - if (gate.parameterNames.size() != params.size()) { - throw qasm3::CompilerError("Compound gate parameter count mismatch.", - debugInfo); - } + /// Emit a standard gate. + void emitGate(const GateFn& gateFn, const SmallVector& params, + ValueRange targets, ValueRange posControls, + ValueRange negControls, bool invert) { + auto bodyFn = [&](ValueRange qubits) { gateFn(builder, qubits, params); }; + buildModifiedGate(bodyFn, targets, posControls, negControls, invert); + } + + /// Inline a compound gate. + void applyCompoundGate( + const qasm3::CompoundGate& gate, const SmallVector& params, + const SmallVector>>& gateOperands, + ValueRange posControls, ValueRange negControls, bool invert, + const std::shared_ptr& debugInfo) { + assert(gate.parameterNames.size() == params.size()); + assert(gate.targetNames.size() == gateOperands.size()); - // Build local scope: argument name → Values + // Ordered list of unique qubits used by the compound gate llvm::SmallVector targets; + + // Map from internal target name to index in targets list. This map is + // needed because the qubits may be aliased if the CompoundGate is inlined + // within a modifier region. llvm::StringMap> targetsMap; - for (size_t i = 0; i < gate.targetNames.size(); ++i) { - for (auto target : gateOperands[i]) { - auto* it = llvm::find(targets, target); - size_t index = 0; - if (it == targets.end()) { - index = targets.size(); - targets.push_back(target); - } else { - index = static_cast(std::distance(targets.begin(), it)); + + // Helper function to populate targets and targetsMap + auto populate = [&](StringRef targetName, Value target) { + auto* const it = llvm::find(targets, target); + size_t index = 0; + if (it == targets.end()) { + index = targets.size(); + targets.push_back(target); + } else { + index = static_cast(std::distance(targets.begin(), it)); + } + targetsMap[targetName].push_back(index); + }; + + for (const auto& [targetName, operand] : + llvm::zip_equal(gate.targetNames, gateOperands)) { + if (std::holds_alternative(operand)) { + populate(targetName, std::get(operand)); + } else { + for (auto target : std::get>(operand)) { + populate(targetName, target); } - targetsMap[gate.targetNames[i]].push_back(index); } } @@ -762,60 +759,38 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } localScope[name] = std::move(args); } - for (const auto& statement : gate.body) { - const auto gateCall = - std::dynamic_pointer_cast(statement); - if (gateCall == nullptr) { - throw qasm3::CompilerError("Compound operations with non-quantum " - "statements are not supported.", - debugInfo); + for (const auto& stmt : gate.body) { + if (const auto gateCall = + std::dynamic_pointer_cast(stmt)) { + applyGateCallStatement(gateCall, localScope); + continue; } - applyGateCallStatement(gateCall, localScope); + throw qasm3::CompilerError("Compound operations with non-quantum " + "statements are not supported.", + debugInfo); } }; - auto withInv = [&](ValueRange qubits) { - if (invert) { - builder.inv(qubits, function_ref(bodyFn)); - } else { - bodyFn(qubits); - } - }; - - SmallVector controls; - controls.append(posControls.begin(), posControls.end()); - controls.append(negControls.begin(), negControls.end()); - - if (controls.empty()) { - withInv(targets); - } else { - for (auto q : negControls) { - builder.x(q); - } - builder.ctrl(controls, targets, function_ref(withInv)); - for (auto q : negControls) { - builder.x(q); - } - } + buildModifiedGate(bodyFn, targets, posControls, negControls, invert); constEvalPass.popEnv(); } - //===--- If/else helpers ------------------------------------------------===// + //===--- IfStatement helpers ------------------------------------------===// /// Emit quantum statements inside an if/else block. void emitBlockStatements( const std::vector>& statements, const std::shared_ptr& debugInfo) { - for (const auto& statement : statements) { - auto gateCall = - std::dynamic_pointer_cast(statement); - if (gateCall == nullptr) { - throw qasm3::CompilerError( - "If statements with non-quantum statements are not supported.", - debugInfo); + for (const auto& stmt : statements) { + if (const auto gateCall = + std::dynamic_pointer_cast(stmt)) { + applyGateCallStatement(gateCall, qubitRegisters); + continue; } - applyGateCallStatement(gateCall, qubitRegisters); + throw qasm3::CompilerError( + "If statements with non-quantum statements are not supported.", + debugInfo); } } @@ -907,55 +882,56 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { //===--- Operand resolution helpers ------------------------------------===// - /// Resolve a gate operand against the top-level qubit register map. - SmallVector + /// Resolve a gate operand against the top-level qubitRegisters map. + [[nodiscard]] std::variant> resolveGateOperand(const std::shared_ptr& operand, const std::shared_ptr& debugInfo) { return resolveGateOperandInScope(operand, qubitRegisters, debugInfo); } - /** - * @brief Resolve a gate operand against \p scope. - */ - SmallVector resolveGateOperandInScope( + /// Resolve a gate operand against @p scope. + [[nodiscard]] std::variant> + resolveGateOperandInScope( const std::shared_ptr& operand, const QubitScope& scope, const std::shared_ptr& debugInfo) { if (operand->isHardwareQubit()) { - return {builder.staticQubit(operand->getHardwareQubit())}; + return builder.staticQubit(operand->getHardwareQubit()); } - const auto idExpr = operand->getIdentifier(); - const auto& name = idExpr->identifier; - + const auto id = operand->getIdentifier(); + const auto& name = id->identifier; auto it = scope.find(name); if (it == scope.end()) { throw qasm3::CompilerError("Unknown qubit register '" + name + "'.", debugInfo); } + const auto& qubits = it->second; - if (idExpr->indices.empty()) { - return qubits; // full register + if (id->indices.empty()) { + if (qubits.size() == 1) { + return qubits[0]; + } + // Return full register + return qubits; } - if (idExpr->indices.size() > 1) { + if (id->indices.size() > 1) { throw qasm3::CompilerError("Only single-index expressions are supported.", debugInfo); } - const auto& indexExpression = idExpr->indices[0]->indexExpressions[0]; - const auto idx = evaluatePositiveConstant(indexExpression, debugInfo); - if (idx >= qubits.size()) { + const auto& indexExpression = id->indices[0]->indexExpressions[0]; + const auto index = evaluatePositiveConstant(indexExpression, debugInfo); + if (index >= qubits.size()) { throw qasm3::CompilerError("Qubit index out of bounds.", debugInfo); } - return {qubits[idx]}; + return qubits[index]; } - /** - * Resolve \p target to a list of classical bits in a known register. - * Returns all bits for an unindexed identifier, or a single bit otherwise. - */ - [[nodiscard]] std::vector resolveClassicalBits( + /// Resolve a classical bit operand to the corresponding measurement + /// result(s). + [[nodiscard]] SmallVector resolveClassicalBits( const std::shared_ptr& target, const std::shared_ptr& debugInfo) const { const auto& name = target->identifier; @@ -964,23 +940,28 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { throw qasm3::CompilerError("Unknown classical register '" + name + "'.", debugInfo); } + const auto& creg = it->second; + SmallVector bits; - std::vector bits; if (target->indices.empty()) { for (int64_t i = 0; i < creg.size; ++i) { bits.push_back(creg[i]); } return bits; } + + if (target->indices.size() > 1) { + throw qasm3::CompilerError("Only single-index expressions are supported.", + debugInfo); + } const auto& indexExpression = target->indices[0]->indexExpressions[0]; - const auto idx = evaluatePositiveConstant(indexExpression, debugInfo); - bits.push_back(creg[static_cast(idx)]); + const auto index = evaluatePositiveConstant(indexExpression, debugInfo); + bits.push_back(creg[static_cast(index)]); return bits; } - /// Evaluate \p expr as a non-negative integer constant. - /// Returns \p defaultValue if \p expr is null; throws on non-constant input. + /// Evaluate a constant expression to a positive integer. static size_t evaluatePositiveConstant(const std::shared_ptr& expr, const std::shared_ptr& debugInfo, From a6301338062df458b0c7b95c06ff73a873566288 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Fri, 12 Jun 2026 19:20:10 +0200 Subject: [PATCH 28/48] Test broadcasting --- .../Dialect/QC/Translation/test_qasm3_translation.cpp | 7 +++++++ mlir/unittests/programs/qasm_programs.cpp | 6 ++++++ mlir/unittests/programs/qasm_programs.h | 3 +++ 3 files changed, 16 insertions(+) diff --git a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp index e9b61cfb94..ffba1f3529 100644 --- a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp +++ b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp @@ -68,6 +68,12 @@ class QASM3TranslationTest } // namespace +static void twoX(qc::QCProgramBuilder& b) { + auto q = b.allocQubitRegister(2); + b.x(q[0]); + b.x(q[1]); +} + static void singleNegControlledX(qc::QCProgramBuilder& b) { auto q = b.allocQubitRegister(2); b.x(q[0]); @@ -160,6 +166,7 @@ INSTANTIATE_TEST_SUITE_P( "MultipleControlledIdentity", qasm::multipleControlledIdentity, MQT_NAMED_BUILDER(qc::multipleControlledIdentity)}, QASM3TranslationTestCase{"X", qasm::x, MQT_NAMED_BUILDER(qc::x)}, + QASM3TranslationTestCase{"TwoX", qasm::twoX, MQT_NAMED_BUILDER(twoX)}, QASM3TranslationTestCase{"SingleControlledX", qasm::singleControlledX, MQT_NAMED_BUILDER(qc::singleControlledX)}, QASM3TranslationTestCase{"SingleNegControlledX", diff --git a/mlir/unittests/programs/qasm_programs.cpp b/mlir/unittests/programs/qasm_programs.cpp index 8daa0ba1f2..0a3fae1fed 100644 --- a/mlir/unittests/programs/qasm_programs.cpp +++ b/mlir/unittests/programs/qasm_programs.cpp @@ -131,6 +131,12 @@ qubit[1] q; x q[0]; )qasm"; +const std::string twoX = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +x q; +)qasm"; + const std::string singleControlledX = R"qasm(OPENQASM 3.0; include "stdgates.inc"; qubit[2] q; diff --git a/mlir/unittests/programs/qasm_programs.h b/mlir/unittests/programs/qasm_programs.h index 66b6eac392..82818d2335 100644 --- a/mlir/unittests/programs/qasm_programs.h +++ b/mlir/unittests/programs/qasm_programs.h @@ -66,6 +66,9 @@ extern const std::string multipleControlledIdentity; /// Creates a circuit with just an X gate. extern const std::string x; +/// Creates a circuit with two X gates. +extern const std::string twoX; + /// Creates a circuit with a single controlled X gate. extern const std::string singleControlledX; From 301f23f84ecdc825f0e224253edd65860833e1bf Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Fri, 12 Jun 2026 19:27:58 +0200 Subject: [PATCH 29/48] Test translation of OpenQASM 2 program --- .../QC/Translation/test_qasm3_translation.cpp | 13 ++++++++++++- mlir/unittests/programs/qasm_programs.cpp | 10 ++++++++++ mlir/unittests/programs/qasm_programs.h | 3 +++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp index ffba1f3529..75daec15a3 100644 --- a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp +++ b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp @@ -88,6 +88,15 @@ static void mixedControlledX(qc::QCProgramBuilder& b) { b.x(q[1]); } +static void bell(qc::QCProgramBuilder& b) { + auto q = b.allocQubitRegister(2); + auto c = b.allocClassicalBitRegister(2); + b.h(q[0]); + b.cx(q[0], q[1]); + b.measure(q[0], c[0]); + b.measure(q[1], c[1]); +}; + TEST_P(QASM3TranslationTest, ProgramEquivalence) { const auto name = " (" + GetParam().name + ")"; const auto& source = GetParam().source; @@ -380,4 +389,6 @@ INSTANTIATE_TEST_SUITE_P( QASM3TranslationTestCase{"IfTwoQubits", qasm::ifTwoQubits, MQT_NAMED_BUILDER(qc::ifTwoQubits)}, QASM3TranslationTestCase{"IfElse", qasm::ifElse, - MQT_NAMED_BUILDER(qc::ifElse)})); + MQT_NAMED_BUILDER(qc::ifElse)}, + QASM3TranslationTestCase{"BellOpenQASM2", qasm::bellOpenQASM2, + MQT_NAMED_BUILDER(bell)})); diff --git a/mlir/unittests/programs/qasm_programs.cpp b/mlir/unittests/programs/qasm_programs.cpp index 0a3fae1fed..65e1db86a3 100644 --- a/mlir/unittests/programs/qasm_programs.cpp +++ b/mlir/unittests/programs/qasm_programs.cpp @@ -730,5 +730,15 @@ if (c) { } )qasm"; +const std::string bellOpenQASM2 = R"qasm(OPENQASM 2.0; +include "qelib1.inc"; +qreg q[2]; +creg c[2]; +h q[0]; +cx q[0],q[1]; +measure q[0] -> c[0]; +measure q[1] -> c[1]; +)qasm"; + } // namespace mlir::qasm // NOLINTEND(readability-identifier-naming) diff --git a/mlir/unittests/programs/qasm_programs.h b/mlir/unittests/programs/qasm_programs.h index 82818d2335..c69989746d 100644 --- a/mlir/unittests/programs/qasm_programs.h +++ b/mlir/unittests/programs/qasm_programs.h @@ -357,5 +357,8 @@ extern const std::string ifTwoQubits; /// Creates a circuit with an if operation with an else branch. extern const std::string ifElse; +/// Creates a Bell state circuit in OpenQASM 2. +extern const std::string bellOpenQASM2; + } // namespace mlir::qasm // NOLINTEND(readability-identifier-naming) From 29b7e0d9987cd0ab5dfa9a4d972007ddefc3222a Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Fri, 12 Jun 2026 19:44:50 +0200 Subject: [PATCH 30/48] Fix linter errors --- .../Dialect/QC/Translation/TranslateQASM3ToQC.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index b91eea9847..a472d06f70 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -25,8 +25,8 @@ #include "qasm3/passes/ConstEvalPass.hpp" #include "qasm3/passes/TypeCheckPass.hpp" -#include #include +#include #include #include #include @@ -51,6 +51,7 @@ #include #include #include +#include #include namespace mlir::qc { @@ -178,8 +179,8 @@ static llvm::StringMap buildGateDispatch() { static llvm::StringMap> convertToStringMap( const std::map>& sourceMap) { llvm::StringMap> targetMap; - for (auto& [key, value] : sourceMap) { - targetMap.insert(std::make_pair(key, std::move(value))); + for (const auto& [key, value] : sourceMap) { + targetMap.insert(std::make_pair(key, value)); } return targetMap; } @@ -301,8 +302,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { const auto& param = p->identifier; if (std::ranges::find(params, param) != params.end()) { throw qasm3::CompilerError( - "Parameter '" + param + "' already declared in gate '" + id + "'.", - stmt->debugInfo); + "Parameter is already declared in compound gate.", stmt->debugInfo); } params.push_back(param); } @@ -311,8 +311,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { const auto& target = t->identifier; if (std::ranges::find(targets, target) != targets.end()) { throw qasm3::CompilerError( - "Target '" + target + "' already declared in gate '" + id + "'.", - stmt->debugInfo); + "Target is already declared in compound gate.", stmt->debugInfo); } targets.push_back(target); } @@ -353,7 +352,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { switch (sizedType->type) { case qasm3::Qubit: { const auto& reg = builder.allocQubitRegister(size); - qubitRegisters[id] = std::move(reg.qubits); + qubitRegisters[id] = reg.qubits; break; } case qasm3::Bit: From ac413ba9f1a96fdacc2ec8689bddfdf64c6fc12e Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Fri, 12 Jun 2026 20:10:25 +0200 Subject: [PATCH 31/48] Address the Rabbit's comments --- .../QC/Translation/TranslateQASM3ToQC.cpp | 4 ++++ .../QC/Translation/test_qasm3_translation.cpp | 23 +++++++++---------- mlir/unittests/programs/qasm_programs.cpp | 16 +++++-------- mlir/unittests/programs/qasm_programs.h | 6 ++--- 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index a472d06f70..310d4e0cb1 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -956,6 +956,10 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } const auto& indexExpression = target->indices[0]->indexExpressions[0]; const auto index = evaluatePositiveConstant(indexExpression, debugInfo); + if (std::cmp_greater_equal(index, creg.size)) { + throw qasm3::CompilerError("Classical bit index out of bounds.", + debugInfo); + } bits.push_back(creg[static_cast(index)]); return bits; } diff --git a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp index 75daec15a3..c8f5869e78 100644 --- a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp +++ b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp @@ -81,6 +81,11 @@ static void singleNegControlledX(qc::QCProgramBuilder& b) { b.x(q[0]); } +static void tripleControlledX(qc::QCProgramBuilder& b) { + auto q = b.allocQubitRegister(4); + b.mcx({q[0], q[1], q[2]}, q[3]); +} + static void mixedControlledX(qc::QCProgramBuilder& b) { auto q = b.allocQubitRegister(3); b.x(q[1]); @@ -88,15 +93,6 @@ static void mixedControlledX(qc::QCProgramBuilder& b) { b.x(q[1]); } -static void bell(qc::QCProgramBuilder& b) { - auto q = b.allocQubitRegister(2); - auto c = b.allocClassicalBitRegister(2); - b.h(q[0]); - b.cx(q[0], q[1]); - b.measure(q[0], c[0]); - b.measure(q[1], c[1]); -}; - TEST_P(QASM3TranslationTest, ProgramEquivalence) { const auto name = " (" + GetParam().name + ")"; const auto& source = GetParam().source; @@ -166,6 +162,8 @@ INSTANTIATE_TEST_SUITE_P( MQT_NAMED_BUILDER(qc::repeatedResetAfterSingleOp)}, QASM3TranslationTestCase{"GlobalPhase", qasm::globalPhase, MQT_NAMED_BUILDER(qc::globalPhase)}, + QASM3TranslationTestCase{"InverseGlobalPhase", qasm::inverseGlobalPhase, + MQT_NAMED_BUILDER(qc::inverseGlobalPhase)}, QASM3TranslationTestCase{"Identity", qasm::identity, MQT_NAMED_BUILDER(qc::identity)}, QASM3TranslationTestCase{ @@ -184,6 +182,9 @@ INSTANTIATE_TEST_SUITE_P( QASM3TranslationTestCase{"MultipleControlledX", qasm::multipleControlledX, MQT_NAMED_BUILDER(qc::multipleControlledX)}, + QASM3TranslationTestCase{"TripleControlledXOpenQASM2", + qasm::tripleControlledXOpenQASM2, + MQT_NAMED_BUILDER(tripleControlledX)}, QASM3TranslationTestCase{"MixedControlledX", qasm::mixedControlledX, MQT_NAMED_BUILDER(mixedControlledX)}, QASM3TranslationTestCase{"InverseX", qasm::inverseX, @@ -389,6 +390,4 @@ INSTANTIATE_TEST_SUITE_P( QASM3TranslationTestCase{"IfTwoQubits", qasm::ifTwoQubits, MQT_NAMED_BUILDER(qc::ifTwoQubits)}, QASM3TranslationTestCase{"IfElse", qasm::ifElse, - MQT_NAMED_BUILDER(qc::ifElse)}, - QASM3TranslationTestCase{"BellOpenQASM2", qasm::bellOpenQASM2, - MQT_NAMED_BUILDER(bell)})); + MQT_NAMED_BUILDER(qc::ifElse)})); diff --git a/mlir/unittests/programs/qasm_programs.cpp b/mlir/unittests/programs/qasm_programs.cpp index 65e1db86a3..ae02199264 100644 --- a/mlir/unittests/programs/qasm_programs.cpp +++ b/mlir/unittests/programs/qasm_programs.cpp @@ -155,6 +155,12 @@ qubit[3] q; ctrl(2) @ x q[0], q[1], q[2]; )qasm"; +const std::string tripleControlledXOpenQASM2 = R"qasm(OPENQASM 2.0; +include "qelib1.inc"; +qreg q[4]; +cccx q[0], q[1], q[2], q[3]; +)qasm"; + const std::string mixedControlledX = R"qasm(OPENQASM 3.0; include "stdgates.inc"; qubit[3] q; @@ -730,15 +736,5 @@ if (c) { } )qasm"; -const std::string bellOpenQASM2 = R"qasm(OPENQASM 2.0; -include "qelib1.inc"; -qreg q[2]; -creg c[2]; -h q[0]; -cx q[0],q[1]; -measure q[0] -> c[0]; -measure q[1] -> c[1]; -)qasm"; - } // namespace mlir::qasm // NOLINTEND(readability-identifier-naming) diff --git a/mlir/unittests/programs/qasm_programs.h b/mlir/unittests/programs/qasm_programs.h index c69989746d..a15c85c500 100644 --- a/mlir/unittests/programs/qasm_programs.h +++ b/mlir/unittests/programs/qasm_programs.h @@ -78,6 +78,9 @@ extern const std::string singleNegControlledX; /// Creates a circuit with a multi-controlled X gate. extern const std::string multipleControlledX; +/// Creates a circuit with a triple-controlled X gate in OpenQASM 2. +extern const std::string tripleControlledXOpenQASM2; + /// Creates a circuit with an X gate that is positively and negatively /// controlled. extern const std::string mixedControlledX; @@ -357,8 +360,5 @@ extern const std::string ifTwoQubits; /// Creates a circuit with an if operation with an else branch. extern const std::string ifElse; -/// Creates a Bell state circuit in OpenQASM 2. -extern const std::string bellOpenQASM2; - } // namespace mlir::qasm // NOLINTEND(readability-identifier-naming) From e7ed9bda8c766e7c1a728354e214fb20ef4ae942 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Fri, 12 Jun 2026 21:31:43 +0200 Subject: [PATCH 32/48] Simplify IfStement helpers and improve coverage --- .../QC/Translation/TranslateQASM3ToQC.cpp | 110 ++++++++---------- .../QC/Translation/test_qasm3_translation.cpp | 11 ++ mlir/unittests/programs/qasm_programs.cpp | 10 ++ mlir/unittests/programs/qasm_programs.h | 3 + 4 files changed, 74 insertions(+), 60 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 310d4e0cb1..7982104ad3 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -777,7 +777,8 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { //===--- IfStatement helpers ------------------------------------------===// - /// Emit quantum statements inside an if/else block. + /// Helper function to emit quantum statements within an IfOp's then/else + /// regions. void emitBlockStatements( const std::vector>& statements, const std::shared_ptr& debugInfo) { @@ -793,102 +794,92 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } } - /// Translate a QASM3 condition expression to an i1 MLIR Value. - /// Supports: - /// - Single bit: `c[0]` or `!c[0]` / `~c[0]` + /// Translate a QASM3 condition to MLIR. [[nodiscard]] Value translateCondition(const std::shared_ptr& condition, const std::shared_ptr& debugInfo) { - // Case 1: Register comparison (creg == N, creg != N, etc.) - if (const auto binaryExpr = - std::dynamic_pointer_cast(condition)) { - throw qasm3::CompilerError( - "Register comparisons cannot be translated to QC at the moment.", - debugInfo); + // Single bit (c[0]) + if (const auto& id = + std::dynamic_pointer_cast(condition)) { + return lookupBitValue(id, debugInfo); } - // Case 2: Unary negation (!c[0] or ~c[0]) + // Unary negation (!c[0] or ~c[0]) if (const auto unaryExpr = std::dynamic_pointer_cast(condition)) { assert(unaryExpr->op == qasm3::UnaryExpression::LogicalNot || unaryExpr->op == qasm3::UnaryExpression::BitwiseNot); - const auto idExpr = std::dynamic_pointer_cast( + const auto& id = std::dynamic_pointer_cast( unaryExpr->operand); - if (!idExpr) { + if (!id) { throw qasm3::CompilerError("Unary expression has unsupported operand.", debugInfo); } - auto bitVal = lookupBitValue(idExpr, debugInfo); - // Negate: XOR with true - auto trueVal = + auto value = lookupBitValue(id, debugInfo); + auto trueValue = arith::ConstantOp::create( builder, builder.getIntegerAttr(builder.getI1Type(), 1)) .getResult(); - return arith::XOrIOp::create(builder, bitVal, trueVal).getResult(); + return arith::XOrIOp::create(builder, value, trueValue).getResult(); } - // Case 3: Single bit (c[0] — truthy) - if (const auto idExpr = - std::dynamic_pointer_cast(condition)) { - return lookupBitValue(idExpr, debugInfo); + // Register comparison (creg == N, creg != N, etc.) + if (const auto binaryExpr = + std::dynamic_pointer_cast(condition)) { + throw qasm3::CompilerError("Register comparisons are not supported.", + debugInfo); } throw qasm3::CompilerError( "Unsupported condition expression in if statement.", debugInfo); } - /// Look up the most recent measurement result for a single classical bit. + /// Look up the most recent measurement result for a classical bit. [[nodiscard]] Value - lookupBitValue(const std::shared_ptr& idExpr, + lookupBitValue(const std::shared_ptr& id, const std::shared_ptr& debugInfo) const { - const auto& regName = idExpr->identifier; + const auto& regName = id->identifier; auto it = bitValues.find(regName); if (it == bitValues.end()) { - throw qasm3::CompilerError( - "Classical register '" + regName + - "' has no measurement results to use in condition.", - debugInfo); + throw qasm3::CompilerError("No classical bit of register '" + regName + + "' has been measured yet.", + debugInfo); } const auto& regBits = it->second; - // Single bit — must be indexed - if (idExpr->indices.empty()) { - if (regBits.size() != 1) { - throw qasm3::CompilerError( - "Condition on full register '" + regName + - "' requires a comparison operator (e.g. creg == 0).", - debugInfo); - } - if (!regBits[0]) { - throw qasm3::CompilerError( - "Bit 0 of register '" + regName + - "' was not measured before use in condition.", - debugInfo); + if (id->indices.empty()) { + if (regBits.size() == 1) { + return regBits[0]; } - return regBits[0]; + throw qasm3::CompilerError("Cannot look up value of entire register.", + debugInfo); } - const auto idx = evaluatePositiveConstant( - idExpr->indices[0]->indexExpressions[0], debugInfo); - if (idx >= regBits.size() || !regBits[idx]) { - throw qasm3::CompilerError( - "Bit " + std::to_string(idx) + " of register '" + regName + - "' was not measured before use in condition.", - debugInfo); + if (id->indices.size() > 1) { + throw qasm3::CompilerError("Only single-index expressions are supported.", + debugInfo); + } + const auto& indexExpression = id->indices[0]->indexExpressions[0]; + const auto index = evaluatePositiveConstant(indexExpression, debugInfo); + if (index >= regBits.size() || !regBits[index]) { + throw qasm3::CompilerError("Bit " + std::to_string(index) + + " of register '" + regName + + "' has been not measured yet.", + debugInfo); } - return regBits[idx]; + return regBits[index]; } //===--- Operand resolution helpers ------------------------------------===// - /// Resolve a gate operand against the top-level qubitRegisters map. + /// Resolve a qubit operand against the top-level qubitRegisters map. [[nodiscard]] std::variant> resolveGateOperand(const std::shared_ptr& operand, const std::shared_ptr& debugInfo) { return resolveGateOperandInScope(operand, qubitRegisters, debugInfo); } - /// Resolve a gate operand against @p scope. + /// Resolve a qubit operand against @p scope. [[nodiscard]] std::variant> resolveGateOperandInScope( const std::shared_ptr& operand, @@ -898,7 +889,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { return builder.staticQubit(operand->getHardwareQubit()); } - const auto id = operand->getIdentifier(); + const auto& id = operand->getIdentifier(); const auto& name = id->identifier; auto it = scope.find(name); if (it == scope.end()) { @@ -928,12 +919,11 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { return qubits[index]; } - /// Resolve a classical bit operand to the corresponding measurement - /// result(s). + /// Resolve a classical bit operand. [[nodiscard]] SmallVector resolveClassicalBits( - const std::shared_ptr& target, + const std::shared_ptr& operand, const std::shared_ptr& debugInfo) const { - const auto& name = target->identifier; + const auto& name = operand->identifier; auto it = classicalRegisters.find(name); if (it == classicalRegisters.end()) { throw qasm3::CompilerError("Unknown classical register '" + name + "'.", @@ -943,18 +933,18 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { const auto& creg = it->second; SmallVector bits; - if (target->indices.empty()) { + if (operand->indices.empty()) { for (int64_t i = 0; i < creg.size; ++i) { bits.push_back(creg[i]); } return bits; } - if (target->indices.size() > 1) { + if (operand->indices.size() > 1) { throw qasm3::CompilerError("Only single-index expressions are supported.", debugInfo); } - const auto& indexExpression = target->indices[0]->indexExpressions[0]; + const auto& indexExpression = operand->indices[0]->indexExpressions[0]; const auto index = evaluatePositiveConstant(indexExpression, debugInfo); if (std::cmp_greater_equal(index, creg.size)) { throw qasm3::CompilerError("Classical bit index out of bounds.", diff --git a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp index c8f5869e78..b6b8d2f33e 100644 --- a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp +++ b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp @@ -93,6 +93,15 @@ static void mixedControlledX(qc::QCProgramBuilder& b) { b.x(q[1]); } +static void ifNot(qc::QCProgramBuilder& b) { + auto trueValue = b.boolConstant(true); + auto q = b.allocQubitRegister(1); + b.h(q[0]); + auto c = b.measure(q[0]); + auto cond = arith::XOrIOp::create(b, c, trueValue).getResult(); + b.scfIf(cond, [&] { b.x(q[0]); }); +} + TEST_P(QASM3TranslationTest, ProgramEquivalence) { const auto name = " (" + GetParam().name + ")"; const auto& source = GetParam().source; @@ -387,6 +396,8 @@ INSTANTIATE_TEST_SUITE_P( MQT_NAMED_BUILDER(qc::ctrlTwoMixed)}, QASM3TranslationTestCase{"SimpleIf", qasm::simpleIf, MQT_NAMED_BUILDER(qc::simpleIf)}, + QASM3TranslationTestCase{"IfNot", qasm::ifNot, + MQT_NAMED_BUILDER(ifNot)}, QASM3TranslationTestCase{"IfTwoQubits", qasm::ifTwoQubits, MQT_NAMED_BUILDER(qc::ifTwoQubits)}, QASM3TranslationTestCase{"IfElse", qasm::ifElse, diff --git a/mlir/unittests/programs/qasm_programs.cpp b/mlir/unittests/programs/qasm_programs.cpp index ae02199264..18be829e33 100644 --- a/mlir/unittests/programs/qasm_programs.cpp +++ b/mlir/unittests/programs/qasm_programs.cpp @@ -713,6 +713,16 @@ if (c) { } )qasm"; +const std::string ifNot = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +h q[0]; +bit c = measure q[0]; +if (!c) { + x q[0]; +} +)qasm"; + const std::string ifTwoQubits = R"qasm(OPENQASM 3.0; include "stdgates.inc"; qubit[2] q; diff --git a/mlir/unittests/programs/qasm_programs.h b/mlir/unittests/programs/qasm_programs.h index a15c85c500..a4a2615b31 100644 --- a/mlir/unittests/programs/qasm_programs.h +++ b/mlir/unittests/programs/qasm_programs.h @@ -354,6 +354,9 @@ extern const std::string ctrlTwoMixed; /// Creates a circuit with a simple if operation with one qubit. extern const std::string simpleIf; +/// Created a circuit with an if operation with a negated condition. +extern const std::string ifNot; + /// Creates a circuit with an if operation with two qubits. extern const std::string ifTwoQubits; From 6a11e8fa1977b3a4eaf5c33f98a957476a7b1b3d Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Fri, 12 Jun 2026 23:29:17 +0200 Subject: [PATCH 33/48] Improve documentation --- .../QC/Translation/TranslateQASM3ToQC.cpp | 52 +++++++++++++------ mlir/unittests/programs/qasm_programs.h | 2 +- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 7982104ad3..be7f799865 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -60,18 +60,18 @@ namespace { /// Signature: (builder, gate operands, evaluated parameters). /// For gates with implicit controls (cx, ccx, ...), all qubits including -/// the controls are part of the range, matching QASM3 operand order. +/// the controls are part of the range, matching OpenQASM 3 operand order. using GateFn = std::function)>; } // namespace /** - * @brief Build the table mapping QASM3 gate identifiers to QCProgramBuilder - * emitters. + * @brief Build the table mapping OpenQASM 3 gate identifiers to + * QCProgramBuilder emitters. * * @details - * Each entry maps a QASM3 gate identifier to a lambda that emits the + * Each entry maps an OpenQASM 3 gate identifier to a lambda that emits the * corresponding QC operation via the QCProgramBuilder. */ static llvm::StringMap buildGateDispatch() { @@ -187,14 +187,14 @@ static llvm::StringMap> convertToStringMap( namespace { -/// Map from QASM3 gate identifier to QCProgramBuilder emitter. +/// Map from OpenQASM 3 gate identifier to QCProgramBuilder emitter. const llvm::StringMap GATE_DISPATCH = buildGateDispatch(); /// Map of qubits in the current scope. using QubitScope = llvm::StringMap>; /** - * @brief AST visitor that translates a QASM3 program to a QC program. + * @brief AST visitor that translates an OpenQASM 3 program to a QC program. * * @details * Implements qasm3::InstVisitor to walk the AST produced by qasm3::Parser and @@ -236,7 +236,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { /// Map from classical-register name to measurement results. llvm::StringMap> bitValues; - /// Map from gate identifier to QASM3 definition. + /// Map from gate identifier to OpenQASM 3 definition. llvm::StringMap> gates; bool openQASM2CompatMode{false}; @@ -532,7 +532,9 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } if (it == gates.end()) { - throw qasm3::CompilerError("Unknown gate '" + id + "'.", stmt->debugInfo); + throw qasm3::CompilerError("No OpenQASM 3 definition found for gate '" + + id + "'.", + stmt->debugInfo); } // Evaluate parameters to doubles @@ -621,7 +623,8 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { // Emit standard gate const auto dispIt = GATE_DISPATCH.find(resolvedId); if (dispIt == GATE_DISPATCH.end()) { - throw qasm3::CompilerError("Unknown gate '" + id + "'.", stmt->debugInfo); + throw qasm3::CompilerError( + "No MLIR definition found for gate '" + id + "'.", stmt->debugInfo); } if (it->second->getNParameters() != params.size()) { @@ -794,7 +797,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } } - /// Translate a QASM3 condition to MLIR. + /// Translate an OpenQASM 3 condition to MLIR. [[nodiscard]] Value translateCondition(const std::shared_ptr& condition, const std::shared_ptr& debugInfo) { @@ -807,8 +810,11 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { // Unary negation (!c[0] or ~c[0]) if (const auto unaryExpr = std::dynamic_pointer_cast(condition)) { - assert(unaryExpr->op == qasm3::UnaryExpression::LogicalNot || - unaryExpr->op == qasm3::UnaryExpression::BitwiseNot); + if (unaryExpr->op != qasm3::UnaryExpression::LogicalNot && + unaryExpr->op != qasm3::UnaryExpression::BitwiseNot) { + throw qasm3::CompilerError( + "Only ! and ~ are supported in if statements.", debugInfo); + } const auto& id = std::dynamic_pointer_cast( unaryExpr->operand); if (!id) { @@ -872,14 +878,28 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { //===--- Operand resolution helpers ------------------------------------===// - /// Resolve a qubit operand against the top-level qubitRegisters map. + /** + * @brief Resolve a qubit operand against the top-level qubitRegisters map. + * + * @return A variant containing + * - a `Value` if the operand is, e.g., `q[0]`, + * - a `Value` if the operand `q` is a single-qubit register, or + * - a `SmallVector` if the operand `q` is a multi-qubit register. + */ [[nodiscard]] std::variant> resolveGateOperand(const std::shared_ptr& operand, const std::shared_ptr& debugInfo) { return resolveGateOperandInScope(operand, qubitRegisters, debugInfo); } - /// Resolve a qubit operand against @p scope. + /** + * @brief Resolve a qubit operand against @p scope. + * + * @return A variant containing + * - a `Value` if the operand is, e.g., `q[0]`, + * - a `Value` if the operand `q` is a single-qubit register, or + * - a `SmallVector` if the operand `q` is a multi-qubit register. + */ [[nodiscard]] std::variant> resolveGateOperandInScope( const std::shared_ptr& operand, @@ -986,10 +1006,10 @@ OwningOpRef translateQASM3ToQC(MLIRContext* context, importer.visitProgram(program); return importer.finalize(); } catch (const qasm3::CompilerError& e) { - llvm::errs() << "QASM3 import error: " << e.what() << "\n"; + llvm::errs() << "Import error: " << e.what() << "\n"; return nullptr; } catch (const std::exception& e) { - llvm::errs() << "QASM3 import error: " << e.what() << "\n"; + llvm::errs() << "Import error: " << e.what() << "\n"; return nullptr; } } diff --git a/mlir/unittests/programs/qasm_programs.h b/mlir/unittests/programs/qasm_programs.h index a4a2615b31..0cf1e3eee6 100644 --- a/mlir/unittests/programs/qasm_programs.h +++ b/mlir/unittests/programs/qasm_programs.h @@ -354,7 +354,7 @@ extern const std::string ctrlTwoMixed; /// Creates a circuit with a simple if operation with one qubit. extern const std::string simpleIf; -/// Created a circuit with an if operation with a negated condition. +/// Creates a circuit with an if operation with a negated condition. extern const std::string ifNot; /// Creates a circuit with an if operation with two qubits. From 198b77f8a563259bb0e429da665fdf907eb710b1 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Mon, 15 Jun 2026 00:04:38 +0200 Subject: [PATCH 34/48] Address the Rabbit's out-of-diff comments --- .../QC/Translation/TranslateQASM3ToQC.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index be7f799865..e36792341a 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -854,14 +854,12 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { const auto& regBits = it->second; if (id->indices.empty()) { - if (regBits.size() == 1) { - return regBits[0]; - } - throw qasm3::CompilerError("Cannot look up value of entire register.", - debugInfo); + assert(regBits.size() == 1); + return regBits[0]; } - if (id->indices.size() > 1) { + if (id->indices.size() != 1 || + id->indices[0]->indexExpressions.size() != 1) { throw qasm3::CompilerError("Only single-index expressions are supported.", debugInfo); } @@ -927,7 +925,8 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { return qubits; } - if (id->indices.size() > 1) { + if (id->indices.size() != 1 || + id->indices[0]->indexExpressions.size() != 1) { throw qasm3::CompilerError("Only single-index expressions are supported.", debugInfo); } @@ -960,7 +959,8 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { return bits; } - if (operand->indices.size() > 1) { + if (operand->indices.size() != 1 || + operand->indices[0]->indexExpressions.size() != 1) { throw qasm3::CompilerError("Only single-index expressions are supported.", debugInfo); } From 40e31f70098d63b9755c947e877c309cef0196ca Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Mon, 15 Jun 2026 01:22:07 +0200 Subject: [PATCH 35/48] Fix broadcasting --- .../QC/Translation/TranslateQASM3ToQC.cpp | 194 ++++++++++-------- .../QC/Translation/test_qasm3_translation.cpp | 15 ++ mlir/unittests/programs/qasm_programs.cpp | 8 + mlir/unittests/programs/qasm_programs.h | 4 + 4 files changed, 138 insertions(+), 83 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index e36792341a..35ef8de4f3 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -518,7 +518,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { auto it = gates.find(id); // OpenQASM 2 compatibility: - // Strip leading c characters and treat them as implicit controls + // Strip leading c characters and treat them as implicit control modifiers auto resolvedId = id; size_t numCompatControls = 0; if (openQASM2CompatMode && it == gates.end()) { @@ -550,17 +550,51 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } // Expand operands to MLIR values - SmallVector>> operands; - operands.reserve(stmt->operands.size()); + SmallVector operands; + SmallVector> operandsBroadcasting; + auto broadcasting = false; for (const auto& operand : stmt->operands) { - operands.push_back( - resolveGateOperandInScope(operand, scope, stmt->debugInfo)); + const auto& resolvedOperand = + resolveGateOperandInScope(operand, scope, stmt->debugInfo); + if (const auto* operand = std::get_if(&resolvedOperand)) { + operands.push_back(*operand); + } else if (const auto* operand = + std::get_if>(&resolvedOperand)) { + operandsBroadcasting.push_back(*operand); + broadcasting = true; + } + } + + if (broadcasting && !operands.empty()) { + throw qasm3::CompilerError("Gate operands must be single qubits or " + "quantum registers and not a mix of both.", + stmt->debugInfo); + } + + if (broadcasting && numCompatControls != 0) { + throw qasm3::CompilerError("OpenQASM 2 gates cannot be broadcasted.", + stmt->debugInfo); + } + + size_t broadcastWidth = 0; + if (broadcasting) { + for (const auto& operand : operandsBroadcasting) { + if (broadcastWidth == 0) { + broadcastWidth = operand.size(); + } else if (broadcastWidth != operand.size()) { + throw qasm3::CompilerError( + "All broadcasting operands must have the same width.", + stmt->debugInfo); + } + } } auto invert = false; size_t numControls = 0; SmallVector posControls; SmallVector negControls; + SmallVector> posControlsBroadcasting; + SmallVector> negControlsBroadcasting; // Parse modifiers for (const auto& mod : stmt->modifiers) { @@ -571,19 +605,29 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { const auto n = evaluatePositiveConstant(ctrlMod->expression, stmt->debugInfo, 1); for (size_t i = 0; i < n; ++i, ++numControls) { - if (numControls >= operands.size()) { - throw qasm3::CompilerError("Control index out of bounds.", - stmt->debugInfo); - } - const auto& qubit = operands[numControls]; - if (std::holds_alternative>(qubit)) { - throw qasm3::CompilerError("Control operand must be a qubit.", - stmt->debugInfo); - } - if (ctrlMod->ctrlType) { - posControls.push_back(std::get(qubit)); + const auto positive = ctrlMod->ctrlType; + if (!broadcasting) { + if (numControls >= operands.size()) { + throw qasm3::CompilerError("Control index out of bounds.", + stmt->debugInfo); + } + auto operand = operands[numControls]; + if (positive) { + posControls.push_back(operand); + } else { + negControls.push_back(operand); + } } else { - negControls.push_back(std::get(qubit)); + if (numControls >= operandsBroadcasting.size()) { + throw qasm3::CompilerError("Control index out of bounds.", + stmt->debugInfo); + } + const auto& operand = operandsBroadcasting[numControls]; + if (positive) { + posControlsBroadcasting.push_back(operand); + } else { + negControlsBroadcasting.push_back(operand); + } } } } else { @@ -594,29 +638,34 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } // OpenQASM 2 compatibility: - // Append implicit controls + // Append implicit control qubits for (size_t i = 0; i < numCompatControls; ++i, ++numControls) { if (numControls >= operands.size()) { throw qasm3::CompilerError("Control index out of bounds.", stmt->debugInfo); } - const auto& qubit = operands[numControls]; - if (std::holds_alternative>(qubit)) { - throw qasm3::CompilerError("Control operand must be a qubit.", - stmt->debugInfo); - } - posControls.push_back(std::get(qubit)); + posControls.push_back(operands[numControls]); } - // Remaining operands belong to the gate itself - auto gateOperands = - llvm::to_vector(llvm::drop_begin(operands, numControls)); + // Remaining operands are target qubits + SmallVector targets; + SmallVector> targetsBroadcasting; + if (!broadcasting) { + targets = llvm::to_vector(llvm::drop_begin(operands, numControls)); + } else { + targetsBroadcasting = + llvm::to_vector(llvm::drop_begin(operandsBroadcasting, numControls)); + } // Inline compound gate if (const auto* compound = dynamic_cast(it->second.get())) { - applyCompoundGate(*compound, params, gateOperands, posControls, - negControls, invert, stmt->debugInfo); + if (broadcasting) { + throw qasm3::CompilerError( + "Broadcasted compound gates are not supported.", stmt->debugInfo); + } + applyCompoundGate(*compound, params, targets, posControls, negControls, + invert, stmt->debugInfo); return; } @@ -633,35 +682,29 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { stmt->debugInfo); } - size_t broadcastWidth = 0; - for (const auto& operand : gateOperands) { - if (std::holds_alternative>(operand)) { - const auto& qubits = std::get>(operand); - if (broadcastWidth == 0) { - broadcastWidth = qubits.size(); - } else if (broadcastWidth != qubits.size()) { - throw qasm3::CompilerError( - "Broadcast operands must all have the same width.", - stmt->debugInfo); + if (!broadcasting) { + emitGate(dispIt->second, params, targets, posControls, negControls, + invert); + } else { + for (size_t b = 0; b < broadcastWidth; ++b) { + SmallVector bTargets; + bTargets.reserve(targetsBroadcasting.size()); + for (const auto& target : targetsBroadcasting) { + bTargets.push_back(target[b]); } - } - } - if (broadcastWidth == 0) { - broadcastWidth = 1; - } - - for (size_t b = 0; b < broadcastWidth; ++b) { - SmallVector targets; - targets.reserve(gateOperands.size()); - for (const auto& operand : gateOperands) { - if (std::holds_alternative>(operand)) { - targets.push_back(std::get>(operand)[b]); - } else { - targets.push_back(std::get(operand)); + SmallVector bPosControls; + bPosControls.reserve(posControlsBroadcasting.size()); + for (const auto& ctrl : posControlsBroadcasting) { + bPosControls.push_back(ctrl[b]); + } + SmallVector bNegControls; + bNegControls.reserve(negControlsBroadcasting.size()); + for (const auto& ctrl : negControlsBroadcasting) { + bNegControls.push_back(ctrl[b]); } + emitGate(dispIt->second, params, bTargets, bPosControls, bNegControls, + invert); } - emitGate(dispIt->second, params, targets, posControls, negControls, - invert); } } @@ -705,44 +748,29 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } /// Inline a compound gate. - void applyCompoundGate( - const qasm3::CompoundGate& gate, const SmallVector& params, - const SmallVector>>& gateOperands, - ValueRange posControls, ValueRange negControls, bool invert, - const std::shared_ptr& debugInfo) { + void applyCompoundGate(const qasm3::CompoundGate& gate, + const SmallVector& params, ValueRange targets, + ValueRange posControls, ValueRange negControls, + bool invert, + const std::shared_ptr& debugInfo) { assert(gate.parameterNames.size() == params.size()); - assert(gate.targetNames.size() == gateOperands.size()); - - // Ordered list of unique qubits used by the compound gate - llvm::SmallVector targets; + assert(gate.targetNames.size() == targets.size()); // Map from internal target name to index in targets list. This map is // needed because the qubits may be aliased if the CompoundGate is inlined // within a modifier region. llvm::StringMap> targetsMap; - // Helper function to populate targets and targetsMap - auto populate = [&](StringRef targetName, Value target) { - auto* const it = llvm::find(targets, target); - size_t index = 0; + for (const auto& [targetName, target] : + llvm::zip_equal(gate.targetNames, targets)) { + auto it = llvm::find(targets, target); if (it == targets.end()) { - index = targets.size(); - targets.push_back(target); - } else { - index = static_cast(std::distance(targets.begin(), it)); + throw qasm3::CompilerError( + "Target '" + targetName + "' not found in operands.", debugInfo); } + const auto index = + static_cast(std::distance(targets.begin(), it)); targetsMap[targetName].push_back(index); - }; - - for (const auto& [targetName, operand] : - llvm::zip_equal(gate.targetNames, gateOperands)) { - if (std::holds_alternative(operand)) { - populate(targetName, std::get(operand)); - } else { - for (auto target : std::get>(operand)) { - populate(targetName, target); - } - } } // Bind parameters as constants diff --git a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp index b6b8d2f33e..2dac69e2ce 100644 --- a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp +++ b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp @@ -93,6 +93,18 @@ static void mixedControlledX(qc::QCProgramBuilder& b) { b.x(q[1]); } +static void twoMixedControlledX(qc::QCProgramBuilder& b) { + auto q1 = b.allocQubitRegister(2); + auto q2 = b.allocQubitRegister(2); + auto q3 = b.allocQubitRegister(2); + b.x(q2[0]); + b.mcx({q1[0], q2[0]}, q3[0]); + b.x(q2[0]); + b.x(q2[1]); + b.mcx({q1[1], q2[1]}, q3[1]); + b.x(q2[1]); +} + static void ifNot(qc::QCProgramBuilder& b) { auto trueValue = b.boolConstant(true); auto q = b.allocQubitRegister(1); @@ -196,6 +208,9 @@ INSTANTIATE_TEST_SUITE_P( MQT_NAMED_BUILDER(tripleControlledX)}, QASM3TranslationTestCase{"MixedControlledX", qasm::mixedControlledX, MQT_NAMED_BUILDER(mixedControlledX)}, + QASM3TranslationTestCase{"TwoMixedControlledX", + qasm::twoMixedControlledX, + MQT_NAMED_BUILDER(twoMixedControlledX)}, QASM3TranslationTestCase{"InverseX", qasm::inverseX, MQT_NAMED_BUILDER(qc::inverseX)}, QASM3TranslationTestCase{ diff --git a/mlir/unittests/programs/qasm_programs.cpp b/mlir/unittests/programs/qasm_programs.cpp index 18be829e33..e58cc2b2b0 100644 --- a/mlir/unittests/programs/qasm_programs.cpp +++ b/mlir/unittests/programs/qasm_programs.cpp @@ -167,6 +167,14 @@ qubit[3] q; ctrl @ negctrl @ x q[0], q[1], q[2]; )qasm"; +const std::string twoMixedControlledX = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q1; +qubit[2] q2; +qubit[2] q3; +ctrl @ negctrl @ x q1, q2, q3; +)qasm"; + const std::string inverseX = R"qasm(OPENQASM 3.0; include "stdgates.inc"; qubit[1] q; diff --git a/mlir/unittests/programs/qasm_programs.h b/mlir/unittests/programs/qasm_programs.h index 0cf1e3eee6..0cfa923b23 100644 --- a/mlir/unittests/programs/qasm_programs.h +++ b/mlir/unittests/programs/qasm_programs.h @@ -85,6 +85,10 @@ extern const std::string tripleControlledXOpenQASM2; /// controlled. extern const std::string mixedControlledX; +/// Creates a circuit with two X gates that are positively and negatively +/// controlled. +extern const std::string twoMixedControlledX; + /// Creates a circuit with an inverse modifier applied to an X gate. extern const std::string inverseX; From e8133cedad91efb4fdfd69712ce95e1c046cf002 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 18 Jun 2026 01:05:55 +0200 Subject: [PATCH 36/48] Skip InitialLayout and OutputPermutation pragmas --- .../Dialect/QC/Translation/TranslateQASM3ToQC.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 35ef8de4f3..988e5d1494 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -380,16 +380,15 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } } - void - visitInitialLayout(std::shared_ptr layout) override { - throw qasm3::CompilerError("InitialLayout pragmas are not supported.", - layout->debugInfo); + void visitInitialLayout( + std::shared_ptr /*initialLayout*/) override { + return; } void visitOutputPermutation( - std::shared_ptr perm) override { - throw qasm3::CompilerError("OutputPermutation pragmas are not supported.", - perm->debugInfo); + std::shared_ptr /*outputPermutation*/) + override { + return; } void visitGateCallStatement( From a7a81b9b1f6b32bc52b974b986991abad2ea9e7e Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 18 Jun 2026 01:34:45 +0200 Subject: [PATCH 37/48] Use llvm::SourceMgr --- .../QC/Translation/TranslateQASM3ToQC.h | 19 ++++--------------- .../QC/Translation/TranslateQASM3ToQC.cpp | 19 ++++++++----------- .../QC/Translation/test_qasm3_translation.cpp | 9 +++++++-- 3 files changed, 19 insertions(+), 28 deletions(-) diff --git a/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h b/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h index c3cfc1c2b2..fdc778e6d7 100644 --- a/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h +++ b/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h @@ -10,30 +10,19 @@ #pragma once +#include #include #include -#include -#include - namespace mlir::qc { /** - * @brief Translate an OpenQASM3 program to the QC dialect. + * @brief Translate an OpenQASM 3 program to a QC program. * * @param context MLIRContext to create the module in. - * @param filename Path to the input OpenQASM3 file. + * @param sourceMgr Source manager containing the OpenQASM3 program. */ [[nodiscard]] OwningOpRef -translateQASM3ToQC(MLIRContext* context, const std::string& filename); - -/** - * @brief Translate an OpenQASM3 program to the QC dialect. - * - * @param context MLIRContext to create the module in. - * @param input Stream containing the OpenQASM3 program. - */ -[[nodiscard]] OwningOpRef translateQASM3ToQC(MLIRContext* context, - std::istream& input); +translateQASM3ToQC(MLIRContext* context, llvm::SourceMgr& sourceMgr); } // namespace mlir::qc diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 988e5d1494..6343ab75da 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -1025,10 +1026,16 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { //===----------------------------------------------------------------------===// OwningOpRef translateQASM3ToQC(MLIRContext* context, - std::istream& input) { + llvm::SourceMgr& sourceMgr) { try { + auto buffer = + sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID())->getBuffer(); + std::string_view view(buffer.data(), buffer.size()); + std::istringstream input((std::string(view))); + qasm3::Parser parser(input); const auto program = parser.parseProgram(); + MLIRQasmImporter importer(context); importer.visitProgram(program); return importer.finalize(); @@ -1041,14 +1048,4 @@ OwningOpRef translateQASM3ToQC(MLIRContext* context, } } -OwningOpRef translateQASM3ToQC(MLIRContext* context, - const std::string& filename) { - std::ifstream file(filename); - if (!file.good()) { - llvm::errs() << "Could not open file '" << filename << "'\n"; - return nullptr; - } - return translateQASM3ToQC(context, file); -} - } // namespace mlir::qc diff --git a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp index 2dac69e2ce..f7a97f1011 100644 --- a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp +++ b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp @@ -18,6 +18,8 @@ #include "qc_programs.h" #include +#include +#include #include #include #include @@ -120,8 +122,11 @@ TEST_P(QASM3TranslationTest, ProgramEquivalence) { const auto referenceBuilder = GetParam().referenceBuilder; mqt::test::DeferredPrinter printer; - std::istringstream input(source); - auto translated = qc::translateQASM3ToQC(context.get(), input); + llvm::SourceMgr sourceMgr; + auto buffer = llvm::MemoryBuffer::getMemBufferCopy(source); + sourceMgr.AddNewSourceBuffer(std::move(buffer), llvm::SMLoc()); + + auto translated = qc::translateQASM3ToQC(context.get(), sourceMgr); ASSERT_TRUE(translated); printer.record(translated.get(), "Translated QC IR" + name); EXPECT_TRUE(verify(*translated).succeeded()); From cce81349e4bbf62fd49ca6b735c53e9e457562a2 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 18 Jun 2026 01:49:44 +0200 Subject: [PATCH 38/48] Support if operations with empty then branches --- .../QC/Translation/TranslateQASM3ToQC.cpp | 24 ++++++++++++------- .../QC/Translation/test_qasm3_translation.cpp | 2 ++ mlir/unittests/programs/qasm_programs.cpp | 11 +++++++++ mlir/unittests/programs/qasm_programs.h | 3 +++ 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 6343ab75da..a48913d294 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -473,14 +473,25 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } void visitIfStatement(std::shared_ptr stmt) override { - if (stmt->thenStatements.empty()) { + if (stmt->thenStatements.empty() && stmt->elseStatements.empty()) { throw qasm3::CompilerError( - "If statements with empty then blocks are not supported.", + "If statements with empty then and else blocks are not supported.", stmt->debugInfo); } auto condition = translateCondition(stmt->condition, stmt->debugInfo); - const auto hasElse = !stmt->elseStatements.empty(); + auto hasElse = !stmt->elseStatements.empty(); + + std::vector> thenStatements; + if (stmt->thenStatements.empty()) { + thenStatements = stmt->elseStatements; + hasElse = false; + auto trueValue = builder.boolConstant(true); + condition = + arith::XOrIOp::create(builder, condition, trueValue).getResult(); + } else { + thenStatements = stmt->thenStatements; + } auto ifOp = scf::IfOp::create(builder, condition, /*withElseRegion=*/hasElse); @@ -490,7 +501,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { // Then block builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); - emitBlockStatements(stmt->thenStatements, stmt->debugInfo); + emitBlockStatements(thenStatements, stmt->debugInfo); // Else block if (hasElse) { @@ -850,10 +861,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { debugInfo); } auto value = lookupBitValue(id, debugInfo); - auto trueValue = - arith::ConstantOp::create( - builder, builder.getIntegerAttr(builder.getI1Type(), 1)) - .getResult(); + auto trueValue = builder.boolConstant(true); return arith::XOrIOp::create(builder, value, trueValue).getResult(); } diff --git a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp index f7a97f1011..d22235dde8 100644 --- a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp +++ b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp @@ -420,5 +420,7 @@ INSTANTIATE_TEST_SUITE_P( MQT_NAMED_BUILDER(ifNot)}, QASM3TranslationTestCase{"IfTwoQubits", qasm::ifTwoQubits, MQT_NAMED_BUILDER(qc::ifTwoQubits)}, + QASM3TranslationTestCase{"IfEmptyThen", qasm::ifEmptyThen, + MQT_NAMED_BUILDER(ifNot)}, QASM3TranslationTestCase{"IfElse", qasm::ifElse, MQT_NAMED_BUILDER(qc::ifElse)})); diff --git a/mlir/unittests/programs/qasm_programs.cpp b/mlir/unittests/programs/qasm_programs.cpp index e58cc2b2b0..2386d7e8c7 100644 --- a/mlir/unittests/programs/qasm_programs.cpp +++ b/mlir/unittests/programs/qasm_programs.cpp @@ -742,6 +742,17 @@ if (c) { } )qasm"; +const std::string ifEmptyThen = R"qasm(OPENQASM 3.0; +include "stdgates.inc"; +qubit[1] q; +h q[0]; +bit c = measure q[0]; +if (c) { +} else { + x q[0]; +} +)qasm"; + const std::string ifElse = R"qasm(OPENQASM 3.0; include "stdgates.inc"; qubit[1] q; diff --git a/mlir/unittests/programs/qasm_programs.h b/mlir/unittests/programs/qasm_programs.h index 0cfa923b23..5da45582c7 100644 --- a/mlir/unittests/programs/qasm_programs.h +++ b/mlir/unittests/programs/qasm_programs.h @@ -364,6 +364,9 @@ extern const std::string ifNot; /// Creates a circuit with an if operation with two qubits. extern const std::string ifTwoQubits; +/// Creates a circuit with an if operation with an empty then branch. +extern const std::string ifEmptyThen; + /// Creates a circuit with an if operation with an else branch. extern const std::string ifElse; From 77043ba95add0ef175f73b792436d47b1e287a36 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 18 Jun 2026 02:09:13 +0200 Subject: [PATCH 39/48] Fix linter errors --- .../QC/Translation/TranslateQASM3ToQC.cpp | 12 ++++-------- mlir/tools/mqt-cc/mqt-cc.cpp | 16 ++++++++++++---- .../QC/Translation/test_qasm3_translation.cpp | 4 ++-- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index a48913d294..5c546db5db 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -44,13 +44,13 @@ #include #include #include -#include #include -#include #include #include #include +#include #include +#include #include #include #include @@ -382,15 +382,11 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } void visitInitialLayout( - std::shared_ptr /*initialLayout*/) override { - return; - } + std::shared_ptr /*initialLayout*/) override {} void visitOutputPermutation( std::shared_ptr /*outputPermutation*/) - override { - return; - } + override {} void visitGateCallStatement( std::shared_ptr stmt) override { diff --git a/mlir/tools/mqt-cc/mqt-cc.cpp b/mlir/tools/mqt-cc/mqt-cc.cpp index 06eb93fddc..fbc8b1e5cd 100644 --- a/mlir/tools/mqt-cc/mqt-cc.cpp +++ b/mlir/tools/mqt-cc/mqt-cc.cpp @@ -89,11 +89,21 @@ static llvm::cl::opt enableHadamardLifting( llvm::cl::init(false)); /** - * @brief Load and parse a .qasm file, dispatching to the chosen import path. + * @brief Load and parse a .qasm file */ static OwningOpRef loadQASMFile(llvm::StringRef filename, MLIRContext* context) { - return qc::translateQASM3ToQC(context, filename.str()); + std::string errorMessage; + auto file = openInputFile(filename, &errorMessage); + if (!file) { + llvm::errs() << "Failed to load file '" << filename << "': '" + << errorMessage << "'\n"; + return nullptr; + } + + llvm::SourceMgr sourceMgr; + sourceMgr.AddNewSourceBuffer(std::move(file), SMLoc()); + return qc::translateQASM3ToQC(context, sourceMgr); } /** @@ -101,7 +111,6 @@ static OwningOpRef loadQASMFile(llvm::StringRef filename, */ static OwningOpRef loadMLIRFile(llvm::StringRef filename, MLIRContext* context) { - // Set up the input file std::string errorMessage; auto file = openInputFile(filename, &errorMessage); if (!file) { @@ -110,7 +119,6 @@ static OwningOpRef loadMLIRFile(llvm::StringRef filename, return nullptr; } - // Parse the input MLIR llvm::SourceMgr sourceMgr; sourceMgr.AddNewSourceBuffer(std::move(file), SMLoc()); return parseSourceFile(sourceMgr, context); diff --git a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp index d22235dde8..07ff264777 100644 --- a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp +++ b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp @@ -30,8 +30,8 @@ #include #include -#include #include +#include using namespace mlir; @@ -124,7 +124,7 @@ TEST_P(QASM3TranslationTest, ProgramEquivalence) { llvm::SourceMgr sourceMgr; auto buffer = llvm::MemoryBuffer::getMemBufferCopy(source); - sourceMgr.AddNewSourceBuffer(std::move(buffer), llvm::SMLoc()); + sourceMgr.AddNewSourceBuffer(std::move(buffer), SMLoc()); auto translated = qc::translateQASM3ToQC(context.get(), sourceMgr); ASSERT_TRUE(translated); From 86bbf4bfdc523b6649b572fccb7109b0778940f8 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 18 Jun 2026 02:15:16 +0200 Subject: [PATCH 40/48] Stop linking against MQT::CoreIR --- mlir/tools/mqt-cc/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/mlir/tools/mqt-cc/CMakeLists.txt b/mlir/tools/mqt-cc/CMakeLists.txt index adf0cd32d3..bc09039a35 100644 --- a/mlir/tools/mqt-cc/CMakeLists.txt +++ b/mlir/tools/mqt-cc/CMakeLists.txt @@ -17,7 +17,6 @@ target_link_libraries( MLIRSupport # Required for OpenQASM parsing MQT::CoreQASM - MQT::CoreIR MLIRQCTranslation) mqt_mlir_target_use_project_options(mqt-cc) From c06be11507c818f9f6a84bbcfd2053e3e79b6bf6 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 18 Jun 2026 02:36:21 +0200 Subject: [PATCH 41/48] Address the Rabbit's comment --- .../Dialect/QC/Translation/TranslateQASM3ToQC.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h b/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h index fdc778e6d7..9bbc13e5eb 100644 --- a/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h +++ b/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h @@ -11,10 +11,15 @@ #pragma once #include -#include -#include +#include -namespace mlir::qc { +namespace mlir { + +// Forward declarations +class MLIRContext; +class ModuleOp; + +namespace qc { /** * @brief Translate an OpenQASM 3 program to a QC program. @@ -25,4 +30,6 @@ namespace mlir::qc { [[nodiscard]] OwningOpRef translateQASM3ToQC(MLIRContext* context, llvm::SourceMgr& sourceMgr); -} // namespace mlir::qc +} // namespace qc + +} // namespace mlir From 8e6dd84f2dcc317663beca4e4ddeeae132566ccd Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 18 Jun 2026 10:45:08 +0200 Subject: [PATCH 42/48] Remove 3 --- mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index 5c546db5db..d265ffe18d 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -539,7 +539,7 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { } if (it == gates.end()) { - throw qasm3::CompilerError("No OpenQASM 3 definition found for gate '" + + throw qasm3::CompilerError("No OpenQASM definition found for gate '" + id + "'.", stmt->debugInfo); } From 05727e507d2a17661db3a80c315c9356988e2b20 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 18 Jun 2026 10:50:56 +0200 Subject: [PATCH 43/48] Simplify link libraries --- mlir/tools/mqt-cc/CMakeLists.txt | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/mlir/tools/mqt-cc/CMakeLists.txt b/mlir/tools/mqt-cc/CMakeLists.txt index bc09039a35..022aa279d8 100644 --- a/mlir/tools/mqt-cc/CMakeLists.txt +++ b/mlir/tools/mqt-cc/CMakeLists.txt @@ -8,16 +8,7 @@ # Build the compiler driver executable add_mlir_tool(mqt-cc mqt-cc.cpp DEPENDS MQTCompilerPipeline SUPPORT_PLUGINS) -target_link_libraries( - mqt-cc - PRIVATE MQTCompilerPipeline - # Required for parsing .mlir files - MLIRParser - # Required for file I/O - MLIRSupport - # Required for OpenQASM parsing - MQT::CoreQASM - MLIRQCTranslation) +target_link_libraries(mqt-cc PRIVATE MQTCompilerPipeline MLIRParser MLIRSupport MLIRQCTranslation) mqt_mlir_target_use_project_options(mqt-cc) llvm_update_compile_flags(mqt-cc) From 58829490418562006ef074845142ac25c92fac4c Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 18 Jun 2026 10:53:51 +0200 Subject: [PATCH 44/48] Update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3df6a465d6..3af7bf164d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,7 +42,7 @@ with the exception that minor releases may include breaking changes. [#1569], [#1570], [#1572], [#1573], [#1580], [#1602], [#1620], [#1623], [#1624], [#1626], [#1627], [#1635], [#1638], [#1673], [#1675], [#1700], [#1710], [#1717], [#1728], [#1730], [#1749], [#1751], [#1762], [#1765], - [#1774], [#1781], [#1782]) + [#1774], [#1780], [#1781], [#1782]) ([**@burgholzer**], [**@denialhaag**], [**@taminob**], [**@DRovara**], [**@li-mingbao**], [**@Ectras**], [**@MatthiasReumann**], [**@simon1hofmann**]) @@ -600,6 +600,7 @@ changelogs._ [#1782]: https://github.com/munich-quantum-toolkit/core/pull/1782 [#1781]: https://github.com/munich-quantum-toolkit/core/pull/1781 +[#1780]: https://github.com/munich-quantum-toolkit/core/pull/1780 [#1776]: https://github.com/munich-quantum-toolkit/core/pull/1776 [#1774]: https://github.com/munich-quantum-toolkit/core/pull/1774 [#1766]: https://github.com/munich-quantum-toolkit/core/pull/1766 From 19f5d957bfead6c4b0fd944c81330982443cfb4f Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 18 Jun 2026 12:17:52 +0200 Subject: [PATCH 45/48] Add overload that accepts a StringRef --- .../Dialect/QC/Translation/TranslateQASM3ToQC.h | 14 ++++++++++++-- .../Dialect/QC/Translation/TranslateQASM3ToQC.cpp | 13 +++++++++++-- mlir/tools/mqt-cc/mqt-cc.cpp | 9 ++++----- .../QC/Translation/test_qasm3_translation.cpp | 6 +----- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h b/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h index 9bbc13e5eb..165136a500 100644 --- a/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h +++ b/mlir/include/mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h @@ -12,6 +12,7 @@ #include #include +#include namespace mlir { @@ -24,11 +25,20 @@ namespace qc { /** * @brief Translate an OpenQASM 3 program to a QC program. * - * @param context MLIRContext to create the module in. * @param sourceMgr Source manager containing the OpenQASM3 program. + * @param context MLIRContext to create the module in. */ [[nodiscard]] OwningOpRef -translateQASM3ToQC(MLIRContext* context, llvm::SourceMgr& sourceMgr); +translateQASM3ToQC(llvm::SourceMgr& sourceMgr, MLIRContext* context); + +/** + * @brief Translate an OpenQASM 3 program to a QC program. + * + * @param source String containing the OpenQASM3 program. + * @param context MLIRContext to create the module in. + */ +[[nodiscard]] OwningOpRef translateQASM3ToQC(StringRef source, + MLIRContext* context); } // namespace qc diff --git a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp index d265ffe18d..bfc7bfe989 100644 --- a/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp +++ b/mlir/lib/Dialect/QC/Translation/TranslateQASM3ToQC.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -1029,8 +1030,8 @@ class MLIRQasmImporter final : public qasm3::InstVisitor { // Public API //===----------------------------------------------------------------------===// -OwningOpRef translateQASM3ToQC(MLIRContext* context, - llvm::SourceMgr& sourceMgr) { +OwningOpRef translateQASM3ToQC(llvm::SourceMgr& sourceMgr, + MLIRContext* context) { try { auto buffer = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID())->getBuffer(); @@ -1052,4 +1053,12 @@ OwningOpRef translateQASM3ToQC(MLIRContext* context, } } +OwningOpRef translateQASM3ToQC(StringRef source, + MLIRContext* context) { + llvm::SourceMgr sourceMgr; + auto buffer = llvm::MemoryBuffer::getMemBufferCopy(source); + sourceMgr.AddNewSourceBuffer(std::move(buffer), SMLoc()); + return translateQASM3ToQC(sourceMgr, context); +} + } // namespace mlir::qc diff --git a/mlir/tools/mqt-cc/mqt-cc.cpp b/mlir/tools/mqt-cc/mqt-cc.cpp index fbc8b1e5cd..ba652d1bf5 100644 --- a/mlir/tools/mqt-cc/mqt-cc.cpp +++ b/mlir/tools/mqt-cc/mqt-cc.cpp @@ -91,7 +91,7 @@ static llvm::cl::opt enableHadamardLifting( /** * @brief Load and parse a .qasm file */ -static OwningOpRef loadQASMFile(llvm::StringRef filename, +static OwningOpRef loadQASMFile(StringRef filename, MLIRContext* context) { std::string errorMessage; auto file = openInputFile(filename, &errorMessage); @@ -103,13 +103,13 @@ static OwningOpRef loadQASMFile(llvm::StringRef filename, llvm::SourceMgr sourceMgr; sourceMgr.AddNewSourceBuffer(std::move(file), SMLoc()); - return qc::translateQASM3ToQC(context, sourceMgr); + return qc::translateQASM3ToQC(sourceMgr, context); } /** * @brief Load and parse a .mlir file */ -static OwningOpRef loadMLIRFile(llvm::StringRef filename, +static OwningOpRef loadMLIRFile(StringRef filename, MLIRContext* context) { std::string errorMessage; auto file = openInputFile(filename, &errorMessage); @@ -127,8 +127,7 @@ static OwningOpRef loadMLIRFile(llvm::StringRef filename, /** * @brief Write the module to the output file */ -static mlir::LogicalResult writeOutput(ModuleOp module, - llvm::StringRef filename) { +static mlir::LogicalResult writeOutput(ModuleOp module, StringRef filename) { std::string errorMessage; const auto output = openOutputFile(filename, &errorMessage); if (!output) { diff --git a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp index 07ff264777..648c5b789d 100644 --- a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp +++ b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp @@ -122,11 +122,7 @@ TEST_P(QASM3TranslationTest, ProgramEquivalence) { const auto referenceBuilder = GetParam().referenceBuilder; mqt::test::DeferredPrinter printer; - llvm::SourceMgr sourceMgr; - auto buffer = llvm::MemoryBuffer::getMemBufferCopy(source); - sourceMgr.AddNewSourceBuffer(std::move(buffer), SMLoc()); - - auto translated = qc::translateQASM3ToQC(context.get(), sourceMgr); + auto translated = qc::translateQASM3ToQC(source, context.get()); ASSERT_TRUE(translated); printer.record(translated.get(), "Translated QC IR" + name); EXPECT_TRUE(verify(*translated).succeeded()); From 683f558bcde142a754e0770a39d5dd3c0cead3e2 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 18 Jun 2026 12:50:59 +0200 Subject: [PATCH 46/48] Add mqt-cc-translate tool --- mlir/include/mlir/Translation/Translation.h | 15 +++++++ mlir/lib/CMakeLists.txt | 1 + mlir/lib/Translation/CMakeLists.txt | 18 ++++++++ mlir/lib/Translation/Translation.cpp | 41 +++++++++++++++++++ mlir/tools/CMakeLists.txt | 1 + mlir/tools/mqt-cc-translate/CMakeLists.txt | 14 +++++++ .../mqt-cc-translate/mqt-cc-translate.cpp | 20 +++++++++ mlir/tools/mqt-cc/mqt-cc.cpp | 3 +- 8 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 mlir/include/mlir/Translation/Translation.h create mode 100644 mlir/lib/Translation/CMakeLists.txt create mode 100644 mlir/lib/Translation/Translation.cpp create mode 100644 mlir/tools/mqt-cc-translate/CMakeLists.txt create mode 100644 mlir/tools/mqt-cc-translate/mqt-cc-translate.cpp diff --git a/mlir/include/mlir/Translation/Translation.h b/mlir/include/mlir/Translation/Translation.h new file mode 100644 index 0000000000..e29f976bd9 --- /dev/null +++ b/mlir/include/mlir/Translation/Translation.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 - 2026 Chair for Design Automation, TUM + * Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH + * All rights reserved. + * + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License + */ + +namespace mlir { + +void registerQASM3ToQCTranslation(); + +} // namespace mlir diff --git a/mlir/lib/CMakeLists.txt b/mlir/lib/CMakeLists.txt index 959d80e2f1..ce73dbe174 100644 --- a/mlir/lib/CMakeLists.txt +++ b/mlir/lib/CMakeLists.txt @@ -10,3 +10,4 @@ add_subdirectory(Conversion) add_subdirectory(Compiler) add_subdirectory(Dialect) add_subdirectory(Support) +add_subdirectory(Translation) diff --git a/mlir/lib/Translation/CMakeLists.txt b/mlir/lib/Translation/CMakeLists.txt new file mode 100644 index 0000000000..7346fc5d23 --- /dev/null +++ b/mlir/lib/Translation/CMakeLists.txt @@ -0,0 +1,18 @@ +# Copyright (c) 2023 - 2026 Chair for Design Automation, TUM +# Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH +# All rights reserved. +# +# SPDX-License-Identifier: MIT +# +# Licensed under the MIT License + +add_mlir_library(MQTCCTranslation Translation.cpp LINK_LIBS MLIRQCTranslation) + +mqt_mlir_target_use_project_options(MQTCCTranslation) + +# collect header files +file(GLOB_RECURSE TRANSLATION_HEADERS_SOURCE ${MQT_MLIR_SOURCE_INCLUDE_DIR}/mlir/Translation/*.h) + +# add public headers using file sets +target_sources(MLIRQCTranslation PUBLIC FILE_SET HEADERS BASE_DIRS ${MQT_MLIR_SOURCE_INCLUDE_DIR} + FILES ${TRANSLATION_HEADERS_SOURCE}) diff --git a/mlir/lib/Translation/Translation.cpp b/mlir/lib/Translation/Translation.cpp new file mode 100644 index 0000000000..e457779e91 --- /dev/null +++ b/mlir/lib/Translation/Translation.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 - 2026 Chair for Design Automation, TUM + * Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH + * All rights reserved. + * + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License + */ + +#include "mlir/Translation/Translation.h" + +#include "mlir/Dialect/QC/IR/QCOps.h" +#include "mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mlir { + +void registerQASM3ToQCTranslation() { + static TranslateToMLIRRegistration registration( + "qasm3-to-qc", "translate an OpenQASM 3 program to a QC program", + [](llvm::SourceMgr& sourceMgr, + MLIRContext* context) -> OwningOpRef { + context->loadDialect(); + return OwningOpRef( + qc::translateQASM3ToQC(sourceMgr, context).release()); + }); +} + +} // namespace mlir diff --git a/mlir/tools/CMakeLists.txt b/mlir/tools/CMakeLists.txt index ea8dec04c0..a16e0ec5ae 100644 --- a/mlir/tools/CMakeLists.txt +++ b/mlir/tools/CMakeLists.txt @@ -7,3 +7,4 @@ # Licensed under the MIT License add_subdirectory(mqt-cc) +add_subdirectory(mqt-cc-translate) diff --git a/mlir/tools/mqt-cc-translate/CMakeLists.txt b/mlir/tools/mqt-cc-translate/CMakeLists.txt new file mode 100644 index 0000000000..1cc84d36de --- /dev/null +++ b/mlir/tools/mqt-cc-translate/CMakeLists.txt @@ -0,0 +1,14 @@ +# Copyright (c) 2023 - 2026 Chair for Design Automation, TUM +# Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH +# All rights reserved. +# +# SPDX-License-Identifier: MIT +# +# Licensed under the MIT License + +add_mlir_tool(mqt-cc-translate mqt-cc-translate.cpp DEPENDS MQTCCTranslation SUPPORT_PLUGINS) +target_link_libraries(mqt-cc-translate PRIVATE MQTCCTranslation) + +mqt_mlir_target_use_project_options(mqt-cc-translate) +llvm_update_compile_flags(mqt-cc-translate) +mlir_check_all_link_libraries(mqt-cc-translate) diff --git a/mlir/tools/mqt-cc-translate/mqt-cc-translate.cpp b/mlir/tools/mqt-cc-translate/mqt-cc-translate.cpp new file mode 100644 index 0000000000..20ac7b9d95 --- /dev/null +++ b/mlir/tools/mqt-cc-translate/mqt-cc-translate.cpp @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 - 2026 Chair for Design Automation, TUM + * Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH + * All rights reserved. + * + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License + */ + +#include "mlir/Translation/Translation.h" + +#include + +using namespace mlir; + +int main(int argc, char** argv) { + registerQASM3ToQCTranslation(); + return failed(mlirTranslateMain(argc, argv, "mqt-cc translation tool")); +} diff --git a/mlir/tools/mqt-cc/mqt-cc.cpp b/mlir/tools/mqt-cc/mqt-cc.cpp index ba652d1bf5..d8fb75daa4 100644 --- a/mlir/tools/mqt-cc/mqt-cc.cpp +++ b/mlir/tools/mqt-cc/mqt-cc.cpp @@ -144,7 +144,8 @@ int main(int argc, char** argv) { const llvm::InitLLVM y(argc, argv); // Parse command-line options; exit on error and print to stderr - llvm::cl::ParseCommandLineOptions(argc, argv, "MQT Core Compiler Driver\n"); + llvm::cl::ParseCommandLineOptions(argc, argv, + "MQT Compiler Collection Driver\n"); // Set up MLIR context with all required dialects DialectRegistry registry; From d0590fd2f4a51b701a0261e741bdff7903d05d1e Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 18 Jun 2026 15:59:03 +0200 Subject: [PATCH 47/48] Fix linter errors --- mlir/lib/Translation/CMakeLists.txt | 1 - mlir/lib/Translation/Translation.cpp | 8 ++++---- mlir/tools/mqt-cc-translate/CMakeLists.txt | 2 +- mlir/tools/mqt-cc-translate/mqt-cc-translate.cpp | 4 +++- .../Dialect/QC/Translation/test_qasm3_translation.cpp | 3 --- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/mlir/lib/Translation/CMakeLists.txt b/mlir/lib/Translation/CMakeLists.txt index 7346fc5d23..ab6ebe2c29 100644 --- a/mlir/lib/Translation/CMakeLists.txt +++ b/mlir/lib/Translation/CMakeLists.txt @@ -7,7 +7,6 @@ # Licensed under the MIT License add_mlir_library(MQTCCTranslation Translation.cpp LINK_LIBS MLIRQCTranslation) - mqt_mlir_target_use_project_options(MQTCCTranslation) # collect header files diff --git a/mlir/lib/Translation/Translation.cpp b/mlir/lib/Translation/Translation.cpp index e457779e91..401b267c62 100644 --- a/mlir/lib/Translation/Translation.cpp +++ b/mlir/lib/Translation/Translation.cpp @@ -10,16 +10,17 @@ #include "mlir/Translation/Translation.h" -#include "mlir/Dialect/QC/IR/QCOps.h" +#include "mlir/Dialect/QC/IR/QCDialect.h" #include "mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h" +#include #include #include #include #include #include -#include #include +#include #include #include @@ -33,8 +34,7 @@ void registerQASM3ToQCTranslation() { context->loadDialect(); - return OwningOpRef( - qc::translateQASM3ToQC(sourceMgr, context).release()); + return {qc::translateQASM3ToQC(sourceMgr, context).release()}; }); } diff --git a/mlir/tools/mqt-cc-translate/CMakeLists.txt b/mlir/tools/mqt-cc-translate/CMakeLists.txt index 1cc84d36de..4d5e3ed4de 100644 --- a/mlir/tools/mqt-cc-translate/CMakeLists.txt +++ b/mlir/tools/mqt-cc-translate/CMakeLists.txt @@ -7,7 +7,7 @@ # Licensed under the MIT License add_mlir_tool(mqt-cc-translate mqt-cc-translate.cpp DEPENDS MQTCCTranslation SUPPORT_PLUGINS) -target_link_libraries(mqt-cc-translate PRIVATE MQTCCTranslation) +target_link_libraries(mqt-cc-translate PRIVATE MQTCCTranslation MLIRTranslateLib) mqt_mlir_target_use_project_options(mqt-cc-translate) llvm_update_compile_flags(mqt-cc-translate) diff --git a/mlir/tools/mqt-cc-translate/mqt-cc-translate.cpp b/mlir/tools/mqt-cc-translate/mqt-cc-translate.cpp index 20ac7b9d95..b7e9e7a035 100644 --- a/mlir/tools/mqt-cc-translate/mqt-cc-translate.cpp +++ b/mlir/tools/mqt-cc-translate/mqt-cc-translate.cpp @@ -10,11 +10,13 @@ #include "mlir/Translation/Translation.h" +#include #include using namespace mlir; int main(int argc, char** argv) { registerQASM3ToQCTranslation(); - return failed(mlirTranslateMain(argc, argv, "mqt-cc translation tool")); + return static_cast( + failed(mlirTranslateMain(argc, argv, "mqt-cc translation tool"))); } diff --git a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp index 648c5b789d..b18c858b2d 100644 --- a/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp +++ b/mlir/unittests/Dialect/QC/Translation/test_qasm3_translation.cpp @@ -18,8 +18,6 @@ #include "qc_programs.h" #include -#include -#include #include #include #include @@ -31,7 +29,6 @@ #include #include #include -#include using namespace mlir; From 719764a7dd66ec5aeb77e1afe49d8e419a9d19b0 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Thu, 18 Jun 2026 17:45:17 +0200 Subject: [PATCH 48/48] Remove mqt-cc-translate tool again --- mlir/include/mlir/Translation/Translation.h | 15 ------- mlir/lib/CMakeLists.txt | 1 - mlir/lib/Translation/CMakeLists.txt | 17 -------- mlir/lib/Translation/Translation.cpp | 41 ------------------- mlir/tools/CMakeLists.txt | 1 - mlir/tools/mqt-cc-translate/CMakeLists.txt | 14 ------- .../mqt-cc-translate/mqt-cc-translate.cpp | 22 ---------- 7 files changed, 111 deletions(-) delete mode 100644 mlir/include/mlir/Translation/Translation.h delete mode 100644 mlir/lib/Translation/CMakeLists.txt delete mode 100644 mlir/lib/Translation/Translation.cpp delete mode 100644 mlir/tools/mqt-cc-translate/CMakeLists.txt delete mode 100644 mlir/tools/mqt-cc-translate/mqt-cc-translate.cpp diff --git a/mlir/include/mlir/Translation/Translation.h b/mlir/include/mlir/Translation/Translation.h deleted file mode 100644 index e29f976bd9..0000000000 --- a/mlir/include/mlir/Translation/Translation.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2023 - 2026 Chair for Design Automation, TUM - * Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH - * All rights reserved. - * - * SPDX-License-Identifier: MIT - * - * Licensed under the MIT License - */ - -namespace mlir { - -void registerQASM3ToQCTranslation(); - -} // namespace mlir diff --git a/mlir/lib/CMakeLists.txt b/mlir/lib/CMakeLists.txt index ce73dbe174..959d80e2f1 100644 --- a/mlir/lib/CMakeLists.txt +++ b/mlir/lib/CMakeLists.txt @@ -10,4 +10,3 @@ add_subdirectory(Conversion) add_subdirectory(Compiler) add_subdirectory(Dialect) add_subdirectory(Support) -add_subdirectory(Translation) diff --git a/mlir/lib/Translation/CMakeLists.txt b/mlir/lib/Translation/CMakeLists.txt deleted file mode 100644 index ab6ebe2c29..0000000000 --- a/mlir/lib/Translation/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2023 - 2026 Chair for Design Automation, TUM -# Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH -# All rights reserved. -# -# SPDX-License-Identifier: MIT -# -# Licensed under the MIT License - -add_mlir_library(MQTCCTranslation Translation.cpp LINK_LIBS MLIRQCTranslation) -mqt_mlir_target_use_project_options(MQTCCTranslation) - -# collect header files -file(GLOB_RECURSE TRANSLATION_HEADERS_SOURCE ${MQT_MLIR_SOURCE_INCLUDE_DIR}/mlir/Translation/*.h) - -# add public headers using file sets -target_sources(MLIRQCTranslation PUBLIC FILE_SET HEADERS BASE_DIRS ${MQT_MLIR_SOURCE_INCLUDE_DIR} - FILES ${TRANSLATION_HEADERS_SOURCE}) diff --git a/mlir/lib/Translation/Translation.cpp b/mlir/lib/Translation/Translation.cpp deleted file mode 100644 index 401b267c62..0000000000 --- a/mlir/lib/Translation/Translation.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2023 - 2026 Chair for Design Automation, TUM - * Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH - * All rights reserved. - * - * SPDX-License-Identifier: MIT - * - * Licensed under the MIT License - */ - -#include "mlir/Translation/Translation.h" - -#include "mlir/Dialect/QC/IR/QCDialect.h" -#include "mlir/Dialect/QC/Translation/TranslateQASM3ToQC.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mlir { - -void registerQASM3ToQCTranslation() { - static TranslateToMLIRRegistration registration( - "qasm3-to-qc", "translate an OpenQASM 3 program to a QC program", - [](llvm::SourceMgr& sourceMgr, - MLIRContext* context) -> OwningOpRef { - context->loadDialect(); - return {qc::translateQASM3ToQC(sourceMgr, context).release()}; - }); -} - -} // namespace mlir diff --git a/mlir/tools/CMakeLists.txt b/mlir/tools/CMakeLists.txt index a16e0ec5ae..ea8dec04c0 100644 --- a/mlir/tools/CMakeLists.txt +++ b/mlir/tools/CMakeLists.txt @@ -7,4 +7,3 @@ # Licensed under the MIT License add_subdirectory(mqt-cc) -add_subdirectory(mqt-cc-translate) diff --git a/mlir/tools/mqt-cc-translate/CMakeLists.txt b/mlir/tools/mqt-cc-translate/CMakeLists.txt deleted file mode 100644 index 4d5e3ed4de..0000000000 --- a/mlir/tools/mqt-cc-translate/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023 - 2026 Chair for Design Automation, TUM -# Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH -# All rights reserved. -# -# SPDX-License-Identifier: MIT -# -# Licensed under the MIT License - -add_mlir_tool(mqt-cc-translate mqt-cc-translate.cpp DEPENDS MQTCCTranslation SUPPORT_PLUGINS) -target_link_libraries(mqt-cc-translate PRIVATE MQTCCTranslation MLIRTranslateLib) - -mqt_mlir_target_use_project_options(mqt-cc-translate) -llvm_update_compile_flags(mqt-cc-translate) -mlir_check_all_link_libraries(mqt-cc-translate) diff --git a/mlir/tools/mqt-cc-translate/mqt-cc-translate.cpp b/mlir/tools/mqt-cc-translate/mqt-cc-translate.cpp deleted file mode 100644 index b7e9e7a035..0000000000 --- a/mlir/tools/mqt-cc-translate/mqt-cc-translate.cpp +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2023 - 2026 Chair for Design Automation, TUM - * Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH - * All rights reserved. - * - * SPDX-License-Identifier: MIT - * - * Licensed under the MIT License - */ - -#include "mlir/Translation/Translation.h" - -#include -#include - -using namespace mlir; - -int main(int argc, char** argv) { - registerQASM3ToQCTranslation(); - return static_cast( - failed(mlirTranslateMain(argc, argv, "mqt-cc translation tool"))); -}