Skip to main content
This module enables conversion from Quantum Intermediate Representation (PyQIR) to Squin kernels, allowing you to execute QIR circuits using the Bloqade SDK’s Squin execution engine. Squin provides a high-performance quantum circuit execution environment, and this conversion opens the door to running QIR circuits on Bloqade simulators and hardware backends.

Installation

pip install 'qbraid-qir[squin]'

Conversions

This section highlights the different ways in which the converter load() can be used with various formats and input types. Each conversion method is demonstrated with practical examples below.

PyQIR String to Squin kernel

Convert PyQIR IR string to a Squin kernel:
from qbraid_qir.squin import load

qir_str = """
; ModuleID = 'bell'
source_filename = "bell"

%Qubit = type opaque

define void @main() #0 {
entry:
  call void @__quantum__qis__h__body(%Qubit* null)
  call void @__quantum__qis__cnot__body(%Qubit* null, %Qubit* inttoptr (i64 1 to %Qubit*))
  ret void
}

declare void @__quantum__qis__h__body(%Qubit*)

declare void @__quantum__qis__cnot__body(%Qubit*, %Qubit*)

attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="custom" "required_num_qubits"="2" "required_num_results"="2" }

!llvm.module.flags = !{!0, !1, !2, !3}

!0 = !{i32 1, !"qir_major_version", i32 1}
!1 = !{i32 7, !"qir_minor_version", i32 0}
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
!3 = !{i32 1, !"dynamic_result_management", i1 false}
"""

squin_kernel = load(qir_str, kernel_name="bell")
squin_kernel.print()

PyQIR Module to Squin kernel

Convert a PyQIR Module object to a Squin kernel:
from qbraid_qir.squin import load
from pyqir import BasicQisBuilder, SimpleModule

mod = SimpleModule("ghz", num_qubits=3, num_results=3)
qis = BasicQisBuilder(mod.builder)

qis.h(mod.qubits[0])
qis.cx(mod.qubits[0], mod.qubits[1])
qis.cx(mod.qubits[1], mod.qubits[2])

squin_kernel = load(mod._module)
squin_kernel.print()

Conversion from File

Load PyQIR IR from a file (.ll for LLVM IR text or .bc for LLVM bitcode):
Code
from qbraid_qir.squin import load

# Load from .ll file (LLVM IR text)
kernel = load("path/to/circuit.ll", kernel_name="my_circuit")

# Load from .bc file (LLVM bitcode)
kernel = load("path/to/circuit.bc", kernel_name="my_circuit")

Integration with OpenQASM 3

Convert OpenQASM3 programs to Squin kernels using qbraid-qir:
from qbraid_qir.qasm3 import qasm3_to_qir
from qbraid_qir.squin import load

program = """
OPENQASM 3;
include "stdgates.inc";
qubit[2] q;
bit[2] c;
h q[0];
x q[0], q[1];
rx(pi/2) q[0];
"""

module = qasm3_to_qir(program, name="my_program")

squin_kernel = load(str(module))

squin_kernel.print()

Integration with CUDA-Q

Convert CUDA-Q kernels to Squin kernels
Code
import cudaq
from qbraid_qir.squin import load

@cudaq.kernel
def bell():
    q = cudaq.qvector(2)
    h(q[0])
    cx(q[0], q[1])

# Generate QIR from kernel
qir_str = cudaq.translate(bell, format="qir-base")

squin_kernel = load(qir_str, kernel_name="bell")
squin_kernel.print()
CUDA-Q is capable of exporting QIR using multiple profiles (such asqir-base, qir-adaptive, etc.). Currently, the qbraid-qir Squin integration supports only QIR generated with the qir-base profile. Ensure that when using cudaq.translate, you specify format=“qir-base” for compatibility.

Using Qubit Register as Argument

Create a kernel that accepts a qubit register as an argument, enabling composition of kernel functions:
from qbraid_qir.squin import load
from pyqir import BasicQisBuilder, SimpleModule

mod = SimpleModule("main", num_qubits=3, num_results=3)
qis = BasicQisBuilder(mod.builder)
qis.h(mod.qubits[0])
qis.cx(mod.qubits[0], mod.qubits[1])

squin_kernel = load(
module=mod._module,
kernel_name="bell",
register_as_argument=True,
register_argument_name="qreg"
)
squin_kernel.print()

Supported Gates

The following gates are currently supported for conversion from PyQIR to Squin kernels:
QIR GateSquin GateDescription
__quantum__qis__h__bodysquin.hHadamard gate
__quantum__qis__x__bodysquin.xPauli-X gate
__quantum__qis__y__bodysquin.yPauli-Y gate
__quantum__qis__z__bodysquin.zPauli-Z gate
__quantum__qis__s__bodysquin.sS gate (π/2 phase)
__quantum__qis__t__bodysquin.tT gate (π/4 phase)
__quantum__qis__s__adjsquin.s_adjS† gate (adjoint S)
__quantum__qis__t__adjsquin.t_adjT† gate (adjoint T)
__quantum__qis__rx__bodysquin.rxRotation around X-axis
__quantum__qis__ry__bodysquin.ryRotation around Y-axis
__quantum__qis__rz__bodysquin.rzRotation around Z-axis
__quantum__qis__cnot__bodysquin.cxControlled-NOT gate
__quantum__qis__cz__bodysquin.czControlled-Z gate

Next Steps

Our current implementation provides comprehensive support for standard QIR gates and circuit conversion. We are actively working on expanding functionality in the following areas:
  • Measurement operations: Support for measurement operations is planned for a future release.
  • Classical control flow: Conditional gates and classical control flow are on our roadmap.
  • Custom gates: We currently support all standard QIR gates listed in the Supported Gates table, with plans to extend support for custom gate definitions.