QIR Import and Export
QiliSDK can bridge Circuit and the
QIR Base Profile
via Microsoft’s pyqir library. Four
entry-points live in qilisdk.utils.qir:
from_qir()— parse a QIR textual LLVM IR string into a Circuit.from_qir_file()— read a.llor.bcfile (dispatched by extension).to_qir()— serialize a Circuit to QIR textual IR.to_qir_file()— write a.llor.bcfile (dispatched by extension).
The pyqir dependency is optional; install it with the qir extra:
pip install qilisdk[qir]
Quick start
from qilisdk.digital import CNOT, Circuit, H, M
from qilisdk.utils.qir import to_qir, from_qir
circuit = Circuit(2)
circuit.add(H(0))
circuit.add(CNOT(0, 1))
circuit.add(M(0, 1))
qir_text = to_qir(circuit, name="bell")
print(qir_text)
reparsed = from_qir(qir_text)
Reading and writing files dispatches on the extension — .ll is treated as
textual LLVM IR, .bc as LLVM bitcode:
from qilisdk.utils.qir import to_qir_file, from_qir_file
to_qir_file(circuit, "bell.ll") # textual
to_qir_file(circuit, "bell.bc") # bitcode
same_circuit = from_qir_file("bell.bc")
Supported features
QiliSDK targets the QIR Base Profile — a flat, statically-allocated subset of QIR with no classical control flow. The table below maps QIR features to their support status in QiliSDK:
✅: The feature is fully supported
🟡: The feature is partially supported, see the note for explanation
❌: The feature is not supported
QIR feature |
QiliSDK feature |
Supported |
Notes |
|---|---|---|---|
Base Profile module layout |
– |
✅ |
|
Entry-point function |
– |
✅ |
|
Static qubit allocation |
– |
✅ |
|
Static result allocation |
– |
✅ |
|
|
– |
✅ |
|
Textual LLVM IR ( |
– |
✅ |
|
LLVM bitcode ( |
– |
✅ |
|
Single-qubit QIS gates |
– |
✅ |
1 |
Two-qubit QIS gates |
– |
✅ |
1 |
Adjoint QIS gates ( |
– |
✅ |
|
Parameterized rotations |
– |
🟡 |
2 |
Measurement ( |
– |
🟡 |
3 |
Multi-qubit measurement grouping |
– |
🟡 |
4 |
|
– |
❌ |
|
|
– |
❌ |
5 |
Adaptive Profile / classical control |
– |
❌ |
|
Branching on measurement results |
– |
❌ |
|
Output recording calls ( |
– |
❌ |
|
Dynamic qubit / result management |
– |
❌ |
|
– |
|
❌ |
5 |
– |
Arbitrary |
❌ |
5 |
See the “Supported gates” table below for the exact intrinsic mapping.
Rotation angles are exported as their currently-resolved numeric values. Base Profile does not support symbolic parameters, so rebind any
Parametervalues to concrete numbers before callingto_qir().Only
mzis emitted; mid-circuit measurement followed by classical control is not supported (and is forbidden by the Base Profile).A multi-qubit
Mis serialized as onemzcall per target qubit. On reparse it comes back as oneMper measured qubit — the qubit set is preserved but the grouping is not.These must be decomposed into supported primitives before export, otherwise
to_qir()raisesNotImplementedError.
Supported gates
The exporter maps the following gates onto the standard __quantum__qis__*__body
intrinsics; everything else raises NotImplementedError to surface the
need for decomposition.
QiliSDK gate |
QIR intrinsic |
|---|---|
(no-op, emitted as nothing) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
one |
Gates outside this table (U1 / U2 / U3, three-qubit unitaries,
arbitrary Controlled /
Exponential wrappers) need to be decomposed
into the supported set before export.
Profile and round-trip notes
Modules are emitted with one entry-point function and statically allocated qubit and result registers (one result register per qubit), matching the Base Profile contract.
Round-tripping preserves gate types, qubit indices, and rotation angles. A multi-qubit
Minstance is serialized as onemzcall per target; on parse it comes back as oneMper measured qubit (i.e. the qubit set is preserved but the grouping is not).Parameterized rotations are exported with their currently-resolved numeric angles; Base Profile does not support symbolic parameters, so rebind any
Parametervalues to concrete numbers before callingto_qir().