Conversions¶
Classical Register Conversion¶
-convert-cbit-to-memref¶
Lower CBit registers to memrefs
This pass explicitly lowers CBit register types and operations to memrefs. A zero-initialized register becomes an allocation followed by a loop that stores false to each element. An undefined register becomes an allocation only. The pass also converts function signatures, calls, returns, branches, and structural SCF operation types. It does not infer CBit registers from existing memrefs.
Internal Conversions¶
-qc-to-qco¶
Convert QC dialect to QCO dialect.
This pass converts all operations from the QC dialect to their equivalent operations in the QCO dialect.
It handles the transformation of qubit references in QC to qubit values in QCO, ensuring that the semantics of quantum operations are preserved during the conversion process.
Control flow must use structured SCF operations. Operations with block
successors, including cf.br, cf.cond_br, and cf.switch, are diagnosed
before conversion.
Private helpers may borrow fixed-size rank-one qubit memrefs with identity
layout and default memory space. They become qubit tensors. Updated scalar
qubits and complete tensors are appended to ordinary results in argument
order. Duplicate register operands, register/element aliases, and consumption
or explicit returns of borrowed registers are diagnosed before conversion.
Register slots retain their qubit identities. Loads refer to stable slots;
identity stores are erased. Entry-block physical reference buffers may be
initialized once with distinct static qubits and become tensors of those
qubits. Other reference stores are unsupported. Loaded references remain
valid across helper calls. Bounds, disjoint runtime operands, and matching
dynamic store indices are program preconditions; this pass diagnoses known
violations without inserting runtime checks. See the shared
quantum resource contract.
Static qubit references are hoisted and coalesced when needed. General
classical folding and common subexpression elimination are not guaranteed
by this conversion; use the corresponding simplification passes when needed.
-qco-to-qc¶
Convert QCO dialect to QC dialect.
Convert QCO qubit values to QC references and QTensor registers to memrefs. Scalar qubits and fixed-size rank-one qubit-tensor arguments become in-place references; each function must return its quantum arguments as a positional suffix. Register helpers must be private. Registers must be complete when passed through calls or structured regions, returned, or dynamically freed. Extracted qubits may be passed to scalar helpers while their remaining tensor stays in the caller. Transferring the register itself is unsupported. Other results remain explicit, including qubits created by a function.
Before rewriting, prove that quantum values yielded by modifiers, branches,
and loops correspond positionally to their region arguments. Reject wire
permutations and changes to quantum loop-state counts or types. Classical
loop state can change type in scf.while. Extraction becomes memref.load;
reinsertion preserves the same slot and needs no store. Known slot changes
are rejected; equality of dynamic extraction and insertion indices is a
program precondition. See the shared
quantum resource contract.
Determine the module’s allocation mode before converting any function. Dynamic qubit sinks become deallocations; static qubit sinks are removed. Mixing static and dynamic allocation roots is unsupported. Tensors of existing qubits must contain static qubits, assigned by placement, and use local reference buffers. Static tensor release does not release physical qubits. Dynamic tensors must restore every extracted slot before region exit or deallocation. Unsupported lifetimes fail before rewriting.
jeff Conversions¶
-qco-to-jeff¶
Convert QCO operations to jeff operations
This pass converts all operations from the QCO dialect to their equivalent operations in the jeff dialect.
It ensures that the returned module is a valid jeff module that can be serialized.
Defined single-block functions and their calls are preserved. Mutable
classical-register arguments in helpers are not supported. Unitary calls
inside quantum modifiers must be expanded with unroll-modifiers first.
Each remaining modifier must contain one unitary using all body arguments
in order. Canonicalize or unroll modifiers outside this normal form before
conversion.
qco.static exports as jeff.qubit_alloc; static site indices are not
preserved. Exchange logical programs before device mapping.
-jeff-to-qco¶
Convert jeff operations to QCO operations
This pass converts all operations from the jeff dialect to their equivalent operations in the QCO dialect.
It ensures that the returned module is a valid QCO module.
Note that this pass is still in development as QCO and jeff do not have full feature parity yet.
Known limitations:
Only specific
CustomOps are currently supportedOnly specific
PPROps are currently supportedMutable classical-register arguments in helper functions are not supported
Function definitions and calls are preserved. Only the designated entry
point remains public; helper functions become private. Calls remain generic
func.call operations because jeff does not specify function unitarity.
QIR Conversions¶
-qc-to-qir-base¶
Lower the QC dialect to the LLVM dialect compliant with the QIR Base Profile 2.1
Lower supported QC operations to QIR Base Profile runtime calls and
LLVM dialect operations. Run set-qir-attributes-and-metadata separately
to attach QIR attributes and module flags.
Requirements:
Stores to returned CBit registers must write measurement results at indices defined by constant operations. Constant expressions must be folded before conversion; constant operations may move before the measurement. The store and measurement must share a block. Intervening effects must be limited to quantum resources or stores to distinct constant indices of the same register.
Input is a valid module in the QC dialect.
The entry function must be marked with
mqt.entry_point.The input entry function must consist of a single block. Multi-block input functions are currently not supported.
The program must have straight-line control flow (i.e., Base Profile QIR).
A measured qubit must not be used by another quantum instruction, including another measurement. Gates on independent qubits may follow measurements in the input.
Explicit static qubit IDs cannot be mixed with qubit allocations.
Qubit-register loads require constant, in-bounds indices into statically sized allocations. Register aliases must be resolved before conversion.
Behavior:
Constant classical tensors and element reads are lowered to constant LLVM arrays and loads. Other classical tensor operations must be lowered before this pass.
Each QC quantum operation is replaced in place by its QIR call. After validating qubit usage in instruction order, the pass moves terminal measurements to the irreversible operations block.
The pass transforms the single-block entry function into four blocks to satisfy QIR Base Profile constraints: 0. Initialization block: Sets up the execution environment and performs required runtime initialization.
Reversible operations block: Contains only void-returning calls to reversible quantum operations.
Irreversible operations block: Contains terminal measurement calls (
__quantum__qis__mz__body). Reset operations are not supported.Epilogue block: Records measurement results and returns from the entry function.
Blocks are connected via unconditional branches in the order listed above.
Non-quantum dialects are lowered via MLIR’s built-in conversions.
-qc-to-qir-adaptive¶
Lower the QC dialect to the LLVM dialect compliant with the QIR Adaptive Profile 2.1
Lower supported QC operations to QIR Adaptive Profile runtime calls and
LLVM dialect operations. Run set-qir-attributes-and-metadata separately
to attach QIR attributes and module flags.
Requirements:
Input is a valid module in the QC dialect.
The entry function must be marked with
mqt.entry_pointand have a single return.Measurement-only returned CBit registers require stores in the same block as their measurements and indices that are available or safely computable before measurement. Intervening effects must be limited to quantum resources or stores to distinct constant indices of the same register.
Behavior:
Each QC quantum operation is replaced by a call to the corresponding QIR function in the LLVM dialect.
Operations from the scf dialect are lowered into the cf dialect before they are lowered to the LLVM dialect.
The pass extends the existing block structure of the entry function with an entry block and an epilogue block: 0. Initialization block: Sets up the execution environment and performs required runtime initialization.
Epilogue block: Records measurement results and returns from the entry function. Any blocks in-between have no restrictions regarding their operations as long as they are supported.
Quantum releases retain their original control-flow positions.
Local qubit-reference buffers support loads, stores, and shape casts without allocating qubits.
Scalar and register results are dynamically allocated and released after output recording.
Measurement results may be used as classical values to drive conditional branches.
Non-quantum dialects are lowered via MLIR’s built-in conversions.
Constant classical tensors and element reads are lowered to constant LLVM arrays and loads, including reads with runtime indices. Other classical tensor operations must be lowered before this pass.