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

✨ Lower quantum-register functions to QIR Adaptive

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

Nobody has claimed this yet.

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

Description

🤖 AI text below 🤖

Problem Statement

QIR 2.1 Adaptive supports arrays and retained IR functions, but MQT Core assumes that helper calls have been inlined before QIR lowering. A retained qubit-register helper currently mixes the custom raw-pointer memref conversion with Func-to-LLVM descriptor promotion and can assert in MemRefDescriptor::unpack instead of producing QIR or a diagnostic.

The existing lowering also moves register releases to the entry point's output block, so preserving arbitrary allocating helpers would give invalid ownership and SSA behavior.

Proposed Solution

Lower a safe fixed-size borrowed-register subset to QIR Adaptive.

ABI and profile contract
  • Represent a fixed memref<Nx!qc.qubit> formal as a borrowed opaque pointer to caller-owned contiguous [N x ptr] storage.
  • Use MLIR's bare-pointer function calling convention consistently for function signatures and calls. Do not mix raw-pointer lowering with memref descriptor promotion.
  • The caller owns allocation and release. A callee may load and operate on register elements but must not allocate, release, or return the borrowed storage.
  • Preserve eligible helpers when existing no_inline policy requests it. Unmarked helpers may still inline.
  • Emit arrays=true and ir_functions=true when a helper remains.
  • Keep Base Profile behavior unchanged: inline helpers, or reject a retained no_inline helper with a diagnostic.

Initially reject dynamic register formals. They require a separate (ptr, i64 length) ABI and module-wide lifetime rules.

Pipeline and lowering
  • Make QIR preparation profile-aware in the shared pass builder and every library/CLI entry point.
  • Ensure fixed register allocations use a native LLVM array representation and type-correct GEP access.
  • Extend metadata analysis across every retained function. ir_functions already scans the module; dynamic-resource, array, type, and backward-branch capabilities must not inspect only the entry point.
  • Reject helper-local qubit/register/result allocation, measurement-result ownership, and deallocation until those lifetimes have a complete per-function lowering.
  • Replace the current assertion path with success for the supported subset and diagnostics for everything else.

Likely implementation areas:

  • mlir/lib/Support/Passes.cpp and its declaration/callers
  • mlir/lib/Compiler/Pipeline.cpp
  • mlir/tools/mqt-cc/mqt-cc.cpp
  • mlir/lib/Conversion/QCToQIR/QIRCommon/QIRCommon.cpp
  • mlir/lib/Conversion/QCToQIR/QIRAdaptive/QCToQIRAdaptive.cpp
  • mlir/lib/Dialect/QIR/Transforms/AttachQIRAttributes.cpp
  • Focused Adaptive/Base conversion and compiler-pipeline tests

Acceptance criteria

  • Adaptive output retains a no_inline fixed-register helper and a matching LLVM call.
  • The callee loads qubits from caller storage and never releases the register.
  • The LLVM/QIR output verifies and records arrays=true and ir_functions=true.
  • Capability metadata accounts for operations in retained helper bodies.
  • Base output contains no retained helper call; an impossible retained helper fails cleanly.
  • Dynamic register formals and unsafe helper-local resource operations receive diagnostics, never assertions or crashes.
  • Direct pass use, the C++ library pipeline, and mqt-cc produce the same profile behavior.

Dependencies and related work

Non-goals

Dynamic register formals; a new generic QIR ABI abstraction; Base Profile IR functions; helper-local quantum-resource ownership; register-return ABI; changing the default inlining policy for unrelated helpers.

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

Start with the shared pass-builder declaration and callers in mlir/lib/Support/Passes.cpp, then trace the profile handling through mlir/lib/Compiler/Pipeline.cpp and mqt-cc.cpp. Read the QIRCommon, QIRAdaptive, and AttachQIRAttributes implementations alongside the focused Adaptive/Base conversion and compiler-pipeline tests. Done means the supported fixed-register helper behavior, metadata, diagnostics, and profile consistency match the acceptance criteria without assertions.

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
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.