munich-quantum-toolkit / munich-quantum-toolkit/core

✨ Support qubit-register arguments in reusable functions

Open
#2,427 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature MLIR
Dominant language
C++
Stars
133
Forks
73
Avg merge
17h 34m
Merged PRs (30d)
261

Description

🤖 AI text below 🤖

Problem Statement

MQT Core can represent qubit registers as memref values in QC and linear QTensor values in QCO, but reusable functions cannot carry those registers consistently across builders, QC↔QCO conversion, and compiler targets. The current paths either reject register operands, require direct allocations, flatten the function, or fail later in target conversion.

This blocks modular algorithms that operate on a complete register and makes each frontend or target solve the same ownership problem independently.

Proposed Solution

Define one shared register-call contract in QC and QCO, then implement only the target mappings that preserve it:

// QC borrows the register by reference.
func.func @f(%q: memref<4x!qc.qubit>)

// QCO transfers linear state through an explicit result.
func.func @f(%q: tensor<4x!qco.qubit>)
    -> tensor<4x!qco.qubit>
  • Use ordinary func.call. Do not extend the scalar-unitary qc.call or qco.call contract.
  • Support rank-one static and dynamic register types in the core IR contract.
  • In QCO, place ordinary results first, followed by one pass-through result for every scalar-qubit or qubit-register argument in argument order.
  • In QC, treat corresponding register arguments as borrowed references and erase only those pass-through results during QCO→QC conversion.
  • Reject unsupported declarations, recursion, views, casts, uncertain aliases, and incomplete quantum-result correspondence with diagnostics.

Delivery

Implement the feature as three dependent pull requests:

  1. #2428 defines the QC/QCO contract and proves it through a jeff round trip.
  2. #2429 imports and exports the supported OpenQASM 3 def subset.
  3. #2430 lowers retained fixed-size register functions to QIR Adaptive.

These implementation issues are also attached as native sub-issues.

Target decisions

jeff

jeff already has linear qureg values and typed function calls. Existing QCO↔jeff type and call conversion should need regression coverage, not a separate implementation layer.

OpenQASM 3

OpenQASM 3 subroutines accept typed qubit[N] arguments by reference and require distinct quantum operands. Preserve a deliberately small initial subset: fixed-size, defined, non-recursive, void subroutines with whole-register operands.

QIR

QIR 2.1 Adaptive supports arrays and IR functions. Preserve fixed-size borrowed register helpers with a caller-owned array ABI. Keep Base Profile inlining. Defer dynamic register formals until an explicit (ptr, length) ABI and lifetime contract are required.

Qiskit

Qiskit Gate and Instruction use a fixed flat sequence of qubit operands and do not preserve register-formal boundaries. Register-taking helpers must be inlined before Qiskit export. Qiskit import cannot reconstruct the boundary. Do not add private metadata or claim a lossless round trip. Add target-specific selective inlining only after a concrete export use case shows that callers cannot run the existing inliner themselves.

Completion criteria

  • The core contract is documented, verified, and tested for static and dynamic rank-one registers.
  • jeff serialization preserves register helper signatures and calls.
  • OpenQASM 3 round trips preserve supported fixed register boundaries.
  • QIR Adaptive emits valid retained helpers with arrays=true and ir_functions=true; Base Profile does not retain them.
  • Unsupported programs fail with diagnostics and never assert or crash.
  • Library and mqt-cc pipelines agree.

Related issues

  • #1733 tracks the broader OpenQASM frontend backlog.
  • #1734 tracks the broader QIR backlog.
  • #2109 tracks general OpenQASM classical arrays.
  • #2110 tracks OpenQASM register slices.
  • #2069 tracks Qiskit register aliases and layouts; it does not provide function-parameter semantics.

Non-goals

Register-valued unitary modifiers; arbitrary memref layouts or memory spaces; register views and slices; recursive register functions; Qiskit-specific boundary metadata; dynamic register parameters in OpenQASM or QIR.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Begin with dependent sub-issues #2428, #2429, and #2430, then inspect the existing QCO↔jeff type and call conversion. Use the stated completion criteria to verify static and dynamic register coverage, supported target round trips, and diagnostics for unsupported programs without crashes.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.