munich-quantum-toolkit / munich-quantum-toolkit/core
✨ Lower quantum-register functions to QIR Adaptive
Nobody has claimed this yet.
- 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_inlinepolicy requests it. Unmarked helpers may still inline. - Emit
arrays=trueandir_functions=truewhen a helper remains. - Keep Base Profile behavior unchanged: inline helpers, or reject a retained
no_inlinehelper 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_functionsalready 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.cppand its declaration/callersmlir/lib/Compiler/Pipeline.cppmlir/tools/mqt-cc/mqt-cc.cppmlir/lib/Conversion/QCToQIR/QIRCommon/QIRCommon.cppmlir/lib/Conversion/QCToQIR/QIRAdaptive/QCToQIRAdaptive.cppmlir/lib/Dialect/QIR/Transforms/AttachQIRAttributes.cpp- Focused Adaptive/Base conversion and compiler-pipeline tests
Acceptance criteria
- Adaptive output retains a
no_inlinefixed-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=trueandir_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-ccproduce the same profile behavior.
Dependencies and related work
- Parent feature: #2427
- Depends on: #2428
- Related broader backlog: #1734
- QIR array contract: https://github.com/qir-alliance/qir-spec/blob/main/specification/Memory_Management.md
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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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