‘qco’ Dialect¶
The QCO (value semantics) dialect for quantum computing.
The QCO dialect uses value semantics where quantum operations consume input qubits and produce new output values, following the functional programming and SSA paradigm. This model enables:
Powerful compiler optimizations through clear dataflow
Safe reordering and parallelization analysis
Advanced transformation passes
Explicit dependency tracking
The name “QCO” stands for “Quantum Circuit Optimization.”
Example:
%q_out = qco.h %q_in // Consumes %q_in, produces %q_out
%q0_out, %q1_out = qco.swap %q0_in, %q1_in // Consumes inputs, produces outputs
Operations¶
qco.alloc (qco::AllocOp)¶
Allocate a qubit dynamically
Syntax:
operation ::= `qco.alloc` attr-dict `:` type($result)
Allocates a new qubit dynamically and returns an SSA value representing it. The qubit is initialized to the |0⟩ state.
Example:
%q = qco.alloc : !qco.qubit
Interfaces: InferTypeOpInterface, MemoryEffectOpInterface (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{MemoryEffects::Allocate on ::mlir::SideEffects::DefaultResource}
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.barrier (qco::BarrierOp)¶
Apply a barrier gate to a set of qubits
Syntax:
operation ::= `qco.barrier` $qubits_in attr-dict `:` type($qubits_in) `->` type($qubits_out)
Applies a barrier gate to a set of qubits and returns the transformed qubits.
Example:
%q_out = qco.barrier %q_in : !qco.qubit -> !qco.qubit
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
variadic of QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
variadic of QCO qubit value type |
qco.ctrl (qco::CtrlOp)¶
Add control qubits to a unitary operation
Syntax:
operation ::= `qco.ctrl` `(` $controls_in `)`
`targets`
custom<TargetAliasing>($region, $targets_in)
attr-dict `:`
`(` `{` type($controls_in) `}` ( `,` `{` type($targets_in)^ `}` )? `)`
`->`
`(` `{` type($controls_out) `}` ( `,` `{` type($targets_out)^ `}` )? `)`
A modifier operation that adds control qubits to the unitary operation defined in its body region. The controlled operation applies the underlying unitary only when all control qubits are in the \(|1\rangle\) state.
The operation takes a variadic number of control and target qubits as inputs and produces corresponding output qubits. Control qubits are not modified by the operation and simply pass through to the outputs.
The body region may contain an arbitrary amount of unitary and classical operations.
Non-unitary operations, such as AllocOp and MeasureOp, are not allowed.
Example:
%res_ctrl, %res_tgt:2 = qco.ctrl(%ctrl) targets(%a0 = %q0, %a1 = %q1) {
%a0_1, %a1_1 = qco.swap %a0, %a1 : !qco.qubit, !qco.qubit -> !qco.qubit, !qco.qubit
qco.yield %a0_1, %a1_1 : !qco.qubit, !qco.qubit
} : ({!qco.qubit}, {!qco.qubit, !qco.qubit}) -> ({!qco.qubit}, {!qco.qubit, !qco.qubit})
Traits: AttrSizedOperandSegments, AttrSizedResultSegments, RecursiveMemoryEffects, SameOperandsAndResultShape, SameOperandsAndResultType, SingleBlockImplicitTerminator<YieldOp>, SingleBlock
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
variadic of QCO qubit value type |
|
variadic of QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
variadic of QCO qubit value type |
|
variadic of QCO qubit value type |
qco.dcx (qco::DCXOp)¶
Apply a DCX gate to two qubits
Syntax:
operation ::= `qco.dcx` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in) `->` type($qubit0_out) `,` type($qubit1_out)
Applies a DCX gate to two qubits and returns the transformed qubits.
Example:
%q0_out, %q1_out = qco.dcx %q0_in, %q1_in : !qco.qubit, !qco.qubit -> !qco.qubit, !qco.qubit
Traits: TwoTargetZeroParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
qco.ecr (qco::ECROp)¶
Apply an ECR gate to two qubits
Syntax:
operation ::= `qco.ecr` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in) `->` type($qubit0_out) `,` type($qubit1_out)
Applies an ECR gate to two qubits and returns the transformed qubits.
Example:
%q0_out, %q1_out = qco.ecr %q0_in, %q1_in : !qco.qubit, !qco.qubit -> !qco.qubit, !qco.qubit
Traits: TwoTargetZeroParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
qco.gphase (qco::GPhaseOp)¶
Apply a global phase to the state
Syntax:
operation ::= `qco.gphase` `(` $theta `)` attr-dict
Applies a global phase to the state.
Example:
qco.gphase(%theta)
Traits: ZeroTargetOneParameter
Interfaces: MemoryEffectOpInterface (MemoryEffectOpInterface), UnitaryOpInterface
Effects: MemoryEffects::Effect{MemoryEffects::Write on ::mlir::SideEffects::DefaultResource}
Operands:¶
Operand |
Description |
|---|---|
|
64-bit float |
qco.h (qco::HOp)¶
Apply a H gate to a qubit
Syntax:
operation ::= `qco.h` $qubit_in attr-dict `:` type($qubit_in) `->` type($qubit_out)
Applies a H gate to a qubit and returns the transformed qubit.
Example:
%q_out = qco.h %q_in : !qco.qubit -> !qco.qubit
Traits: OneTargetZeroParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.id (qco::IdOp)¶
Apply an Id gate to a qubit
Syntax:
operation ::= `qco.id` $qubit_in attr-dict `:` type($qubit_in) `->` type($qubit_out)
Applies an Id gate to a qubit and returns the transformed qubit.
Example:
%q_out = qco.id %q_in : !qco.qubit -> !qco.qubit
Traits: OneTargetZeroParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.if (qco::IfOp)¶
If-then-else operation for linear (qubit) types
The qco.if operation is an if-then-else construct similar to the standard scf.if operation.
In addition to the condition, the operation takes a variadic number of qubits and qtensors as inputs that are
required in the bodies of both branches. These values are passed down to the individual regions
as block arguments. The number of results and the type of the results must be equivalent to the
number and types of the input qubit and qtensor values.
Example:
%result = qco.if %condition args(%arg0 = %q0) {
%q1 = qco.h %arg0 : !qco.qubit -> !qco.qubit
qco.yield %q1 : !qco.qubit
} else args(%arg0 = %q0) {
qco.yield %arg0 : !qco.qubit
} : {i1, !qco.qubit} -> {!qco.qubit}
Traits: RecursiveMemoryEffects, SingleBlockImplicitTerminator<YieldOp>, SingleBlock
Interfaces: RegionBranchOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
1-bit signless integer |
|
variadic of QCO qubit value type or 1D tensor of QCO qubit value type values |
Results:¶
Result |
Description |
|---|---|
|
variadic of QCO qubit value type or 1D tensor of QCO qubit value type values |
qco.inv (qco::InvOp)¶
Invert a unitary operation
Syntax:
operation ::= `qco.inv` custom<TargetAliasing>($region, $qubits_in)
attr-dict `:`
`{` type($qubits_in) `}`
`->`
`{` type($qubits_out) `}`
A modifier operation that inverts the unitary operation defined in its body region.
The operation takes a variadic number of qubits as inputs and produces corresponding output qubits.
The body region may contain an arbitrary amount of unitary and classical operations.
Non-unitary operations, such as AllocOp and MeasureOp, are not allowed.
Example:
%q_out = qco.inv (%q = %q_in) {
%q_1 = qco.s %q : !qco.qubit -> !qco.qubit
qco.yield %q_1 : !qco.qubit
} : {!qco.qubit} -> {!qco.qubit}
Traits: RecursiveMemoryEffects, SingleBlockImplicitTerminator<YieldOp>, SingleBlock
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
variadic of QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
variadic of QCO qubit value type |
qco.iswap (qco::iSWAPOp)¶
Apply a iSWAP gate to two qubits
Syntax:
operation ::= `qco.iswap` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in) `->` type($qubit0_out) `,` type($qubit1_out)
Applies a iSWAP gate to two qubits and returns the transformed qubits.
Example:
%q0_out, %q1_out = qco.iswap %q0_in, %q1_in : !qco.qubit, !qco.qubit -> !qco.qubit, !qco.qubit
Traits: TwoTargetZeroParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
qco.measure (qco::MeasureOp)¶
Measure a qubit in the computational basis
Syntax:
operation ::= `qco.measure` (`(` $register_name^ `,` $register_size `,` $register_index `)`)?
$qubit_in `:` type($qubit_in) attr-dict
Measures a qubit in the computational (Z) basis, collapsing the state and returning both the output qubit and a classical bit result.
Optionally, the measurement can be recorded to an output register by specifying:
register_name: Name of the classical register (e.g., “c”)register_size: Total size of the registerregister_index: Index within the register for this measurement
Example (simple measurement):
%q_out, %result = qco.measure %q_in : !qco.qubit
Example (measurement with output recording):
%q_out, %result = qco.measure("c", 2, 0) %q_in : !qco.qubit
Interfaces: InferTypeOpInterface
Attributes:¶
| Attribute | MLIR Type | Description |
|---|---|---|
register_name | ::mlir::StringAttr | string attribute |
register_size | ::mlir::IntegerAttr | 64-bit signless integer attribute whose value is positive |
register_index | ::mlir::IntegerAttr | 64-bit signless integer attribute whose value is non-negative |
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
|
1-bit signless integer |
qco.p (qco::POp)¶
Apply a P gate to a qubit
Syntax:
operation ::= `qco.p` `(` $theta `)` $qubit_in attr-dict `:` type($qubit_in) `->` type($qubit_out)
Applies a P gate to a qubit and returns the transformed qubit.
Example:
%q_out = qco.p(%theta) %q_in : !qco.qubit -> !qco.qubit
Traits: OneTargetOneParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
|
64-bit float |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.r (qco::ROp)¶
Apply an R gate to a qubit
Syntax:
operation ::= `qco.r` `(` $theta `,` $phi `)` $qubit_in attr-dict `:` type($qubit_in) `->` type($qubit_out)
Applies an R gate to a qubit and returns the transformed qubit.
Example:
%q_out = qco.r(%theta, %phi) %q_in : !qco.qubit -> !qco.qubit
Traits: OneTargetTwoParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
|
64-bit float |
|
64-bit float |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.reset (qco::ResetOp)¶
Reset a qubit to |0⟩ state
Syntax:
operation ::= `qco.reset` $qubit_in attr-dict `:` type($qubit_in) `->` type($qubit_out)
Resets a qubit to the |0⟩ state, regardless of its current state, and returns the reset qubit.
Example:
%q_out = qco.reset %q_in : !qco.qubit -> !qco.qubit
Traits: Idempotent, SameOperandsAndResultType
Interfaces: InferTypeOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.rx (qco::RXOp)¶
Apply an RX gate to a qubit
Syntax:
operation ::= `qco.rx` `(` $theta `)` $qubit_in attr-dict `:` type($qubit_in) `->` type($qubit_out)
Applies an RX gate to a qubit and returns the transformed qubit.
Example:
%q_out = qco.rx(%theta) %q_in : !qco.qubit -> !qco.qubit
Traits: OneTargetOneParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
|
64-bit float |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.rxx (qco::RXXOp)¶
Apply an RXX gate to two qubits
Syntax:
operation ::= `qco.rxx` `(` $theta `)` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in) `->` type($qubit0_out) `,` type($qubit1_out)
Applies an RXX gate to two qubits and returns the transformed qubits.
Example:
%q0_out, %q1_out = qco.rxx(%theta) %q0_in, %q1_in : !qco.qubit, !qco.qubit -> !qco.qubit, !qco.qubit
Traits: TwoTargetOneParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
|
64-bit float |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
qco.ry (qco::RYOp)¶
Apply an RY gate to a qubit
Syntax:
operation ::= `qco.ry` `(` $theta `)` $qubit_in attr-dict `:` type($qubit_in) `->` type($qubit_out)
Applies an RY gate to a qubit and returns the transformed qubit.
Example:
%q_out = qco.ry(%theta) %q_in : !qco.qubit -> !qco.qubit
Traits: OneTargetOneParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
|
64-bit float |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.ryy (qco::RYYOp)¶
Apply an RYY gate to two qubits
Syntax:
operation ::= `qco.ryy` `(` $theta `)` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in) `->` type($qubit0_out) `,` type($qubit1_out)
Applies an RYY gate to two qubits and returns the transformed qubits.
Example:
%q0_out, %q1_out = qco.ryy(%theta) %q0_in, %q1_in : !qco.qubit, !qco.qubit -> !qco.qubit, !qco.qubit
Traits: TwoTargetOneParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
|
64-bit float |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
qco.rz (qco::RZOp)¶
Apply an RZ gate to a qubit
Syntax:
operation ::= `qco.rz` `(` $theta `)` $qubit_in attr-dict `:` type($qubit_in) `->` type($qubit_out)
Applies an RZ gate to a qubit and returns the transformed qubit.
Example:
%q_out = qco.rz(%theta) %q_in : !qco.qubit -> !qco.qubit
Traits: OneTargetOneParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
|
64-bit float |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.rzx (qco::RZXOp)¶
Apply an RZX gate to two qubits
Syntax:
operation ::= `qco.rzx` `(` $theta `)` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in) `->` type($qubit0_out) `,` type($qubit1_out)
Applies an RZX gate to two qubits and returns the transformed qubits.
Example:
%q0_out, %q1_out = qco.rzx(%theta) %q0_in, %q1_in : !qco.qubit, !qco.qubit -> !qco.qubit, !qco.qubit
Traits: TwoTargetOneParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
|
64-bit float |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
qco.rzz (qco::RZZOp)¶
Apply an RZZ gate to two qubits
Syntax:
operation ::= `qco.rzz` `(` $theta `)` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in) `->` type($qubit0_out) `,` type($qubit1_out)
Applies an RZZ gate to two qubits and returns the transformed qubits.
Example:
%q0_out, %q1_out = qco.rzz(%theta) %q0_in, %q1_in : !qco.qubit, !qco.qubit -> !qco.qubit, !qco.qubit
Traits: TwoTargetOneParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
|
64-bit float |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
qco.s (qco::SOp)¶
Apply an S gate to a qubit
Syntax:
operation ::= `qco.s` $qubit_in attr-dict `:` type($qubit_in) `->` type($qubit_out)
Applies an S gate to a qubit and returns the transformed qubit.
Example:
%q_out = qco.s %q_in : !qco.qubit -> !qco.qubit
Traits: OneTargetZeroParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.sdg (qco::SdgOp)¶
Apply an Sdg gate to a qubit
Syntax:
operation ::= `qco.sdg` $qubit_in attr-dict `:` type($qubit_in) `->` type($qubit_out)
Applies an Sdg gate to a qubit and returns the transformed qubit.
Example:
%q_out = qco.sdg %q_in : !qco.qubit -> !qco.qubit
Traits: OneTargetZeroParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.sink (qco::SinkOp)¶
Consume a qubit value (end of lifetime)
Syntax:
operation ::= `qco.sink` $qubit attr-dict `:` type($qubit)
Consumes a qubit SSA value and marks the end of its lifetime.
This operation is the canonical “sink” for QCO’s linear/value semantics: every qubit value must be consumed exactly once on all paths.
When converting back to QC (reference semantics), sinks corresponding to static qubits may be erased.
Example:
qco.sink %q : !qco.qubit
Interfaces: MemoryEffectOpInterface (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{MemoryEffects::Free on ::mlir::SideEffects::DefaultResource}
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
qco.static (qco::StaticOp)¶
Retrieve a static qubit by index
Syntax:
operation ::= `qco.static` $index attr-dict `:` type($qubit)
The qco.static operation produces an SSA value representing a qubit
identified by a static index. This is useful for referring to fixed
qubits in a quantum program or to hardware-mapped qubits.
Example:
%q = qco.static 0 : !qco.qubit
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:¶
| Attribute | MLIR Type | Description |
|---|---|---|
index | ::mlir::IntegerAttr | 64-bit signless integer attribute whose value is non-negative |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.swap (qco::SWAPOp)¶
Apply a SWAP gate to two qubits
Syntax:
operation ::= `qco.swap` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in) `->` type($qubit0_out) `,` type($qubit1_out)
Applies a SWAP gate to two qubits and returns the transformed qubits.
Example:
%q0_out, %q1_out = qco.swap %q0_in, %q1_in : !qco.qubit, !qco.qubit -> !qco.qubit, !qco.qubit
Traits: TwoTargetZeroParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
qco.sx (qco::SXOp)¶
Apply an SX gate to a qubit
Syntax:
operation ::= `qco.sx` $qubit_in attr-dict `:` type($qubit_in) `->` type($qubit_out)
Applies an SX gate to a qubit and returns the transformed qubit.
Example:
%q_out = qco.sx %q_in : !qco.qubit -> !qco.qubit
Traits: OneTargetZeroParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.sxdg (qco::SXdgOp)¶
Apply an SXdg gate to a qubit
Syntax:
operation ::= `qco.sxdg` $qubit_in attr-dict `:` type($qubit_in) `->` type($qubit_out)
Applies an SXdg gate to a qubit and returns the transformed qubit.
Example:
%q_out = qco.sxdg %q_in : !qco.qubit -> !qco.qubit
Traits: OneTargetZeroParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.t (qco::TOp)¶
Apply a T gate to a qubit
Syntax:
operation ::= `qco.t` $qubit_in attr-dict `:` type($qubit_in) `->` type($qubit_out)
Applies a T gate to a qubit and returns the transformed qubit.
Example:
%q_out = qco.t %q_in : !qco.qubit -> !qco.qubit
Traits: OneTargetZeroParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.tdg (qco::TdgOp)¶
Apply a Tdg gate to a qubit
Syntax:
operation ::= `qco.tdg` $qubit_in attr-dict `:` type($qubit_in) `->` type($qubit_out)
Applies a Tdg gate to a qubit and returns the transformed qubit.
Example:
%q_out = qco.tdg %q_in : !qco.qubit -> !qco.qubit
Traits: OneTargetZeroParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.u (qco::UOp)¶
Apply a U gate to a qubit
Syntax:
operation ::= `qco.u` `(` $theta `,` $phi `,` $lambda `)` $qubit_in attr-dict `:` type($qubit_in) `->` type($qubit_out)
Applies a U gate to a qubit and returns the transformed qubit.
Example:
%q_out = qco.u(%theta, %phi, %lambda) %q_in : !qco.qubit -> !qco.qubit
Traits: OneTargetThreeParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
|
64-bit float |
|
64-bit float |
|
64-bit float |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.u2 (qco::U2Op)¶
Apply a U2 gate to a qubit
Syntax:
operation ::= `qco.u2` `(` $phi `,` $lambda `)` $qubit_in attr-dict `:` type($qubit_in) `->` type($qubit_out)
Applies a U2 gate to a qubit and returns the transformed qubit.
Example:
%q_out = qco.u2(%phi, %lambda) %q_in : !qco.qubit -> !qco.qubit
Traits: OneTargetTwoParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
|
64-bit float |
|
64-bit float |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.x (qco::XOp)¶
Apply an X gate to a qubit
Syntax:
operation ::= `qco.x` $qubit_in attr-dict `:` type($qubit_in) `->` type($qubit_out)
Applies an X gate to a qubit and returns the transformed qubit.
Example:
%q_out = qco.x %q_in : !qco.qubit -> !qco.qubit
Traits: OneTargetZeroParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.xx_minus_yy (qco::XXMinusYYOp)¶
Apply an XX-YY gate to two qubits
Syntax:
operation ::= `qco.xx_minus_yy` `(` $theta `,` $beta `)` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in) `->` type($qubit0_out) `,` type($qubit1_out)
Applies an XX-YY gate to two qubits and returns the transformed qubits.
Example:
%q0_out, %q1_out = qco.xx_minus_yy(%theta, %beta) %q0_in, %q1_in : !qco.qubit, !qco.qubit -> !qco.qubit, !qco.qubit
Traits: TwoTargetTwoParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
|
64-bit float |
|
64-bit float |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
qco.xx_plus_yy (qco::XXPlusYYOp)¶
Apply an XX+YY gate to two qubits
Syntax:
operation ::= `qco.xx_plus_yy` `(` $theta `,` $beta `)` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in) `->` type($qubit0_out) `,` type($qubit1_out)
Applies an XX+YY gate to two qubits and returns the transformed qubits.
Example:
%q0_out, %q1_out = qco.xx_plus_yy(%theta, %beta) %q0_in, %q1_in : !qco.qubit, !qco.qubit -> !qco.qubit, !qco.qubit
Traits: TwoTargetTwoParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
|
64-bit float |
|
64-bit float |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
|
QCO qubit value type |
qco.y (qco::YOp)¶
Apply a Y gate to a qubit
Syntax:
operation ::= `qco.y` $qubit_in attr-dict `:` type($qubit_in) `->` type($qubit_out)
Applies a Y gate to a qubit and returns the transformed qubit.
Example:
%q_out = qco.y %q_in : !qco.qubit -> !qco.qubit
Traits: OneTargetZeroParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
qco.yield (qco::YieldOp)¶
Yield from a modifier region
Syntax:
operation ::= `qco.yield` attr-dict ($targets^ `:` type($targets))?
Terminates a modifier region, yielding the transformed target qubit and qtensor values back to the enclosing modifier operation. The targets must match the expected output signature of the modifier region.
Example:
%res_ctrl, %res_tgt:2 = qco.ctrl(%ctrl) targets(%a0 = %q0, %a1 = %q1) {
%a0_1, %a1_1 = qco.swap %a0, %a1 : !qco.qubit, !qco.qubit -> !qco.qubit, !qco.qubit
qco.yield %a0_1, %a1_1 : !qco.qubit, !qco.qubit
} : ({!qco.qubit}, {!qco.qubit, !qco.qubit}) -> ({!qco.qubit}, {!qco.qubit, !qco.qubit})
Traits: ReturnLike, Terminator
Interfaces: RegionBranchTerminatorOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
variadic of QCO qubit value type or 1D tensor of QCO qubit value type values |
qco.z (qco::ZOp)¶
Apply a Z gate to a qubit
Syntax:
operation ::= `qco.z` $qubit_in attr-dict `:` type($qubit_in) `->` type($qubit_out)
Applies a Z gate to a qubit and returns the transformed qubit.
Example:
%q_out = qco.z %q_in : !qco.qubit -> !qco.qubit
Traits: OneTargetZeroParameter
Interfaces: InferTypeOpInterface, UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QCO qubit value type |
Results:¶
Result |
Description |
|---|---|
|
QCO qubit value type |
Types¶
QubitType¶
QCO qubit value type
Syntax: !qco.qubit
The !qco.qubit type represents an SSA value holding a quantum bit
in the QCO dialect. Operations using this type consume input qubits
and produce new output qubits following value semantics and the SSA
paradigm, enabling powerful dataflow analysis and optimization.
Example:
%q0 = qco.alloc : !qco.qubit
%q1 = qco.h %q0 : !qco.qubit -> !qco.qubit
%q2 = qco.x %q1 : !qco.qubit -> !qco.qubit
OpInterface definitions¶
UnitaryOpInterface (UnitaryOpInterface)¶
This interface provides a unified API for all operations that apply or produce a unitary transformation in the QCO dialect. This includes base gates, user-defined gates, modifier operations (control, inverse, power), and sequences.
The interface enables uniform introspection and composition capabilities across all unitary operations with value semantics.
Methods:¶
getNumQubits¶
size_t getNumQubits();
Returns the number of qubits acted on by the unitary operation.
NOTE: This method must be implemented by the user.
getNumTargets¶
size_t getNumTargets();
Returns the number of target qubits (excluding control qubits).
NOTE: This method must be implemented by the user.
getNumControls¶
size_t getNumControls();
Returns the number of control qubits (both positive and negative).
NOTE: This method must be implemented by the user.
getInputQubit¶
Value getInputQubit(size_t i);
Returns the i-th input qubit (targets + controls combined).
NOTE: This method must be implemented by the user.
getInputQubits¶
OperandRange getInputQubits();
Returns a range of all input qubits (targets + controls combined).
NOTE: This method must be implemented by the user.
getOutputQubit¶
Value getOutputQubit(size_t i);
Returns the i-th output qubit (targets + controls combined).
NOTE: This method must be implemented by the user.
getOutputQubits¶
ResultRange getOutputQubits();
Returns a range of all output qubits (targets + controls combined).
NOTE: This method must be implemented by the user.
getInputTarget¶
Value getInputTarget(size_t i);
Returns the i-th target input qubit.
NOTE: This method must be implemented by the user.
getInputTargets¶
OperandRange getInputTargets();
Returns a range of all target input qubits.
NOTE: This method must be implemented by the user.
getOutputTarget¶
Value getOutputTarget(size_t i);
Returns the i-th target output qubit.
NOTE: This method must be implemented by the user.
getOutputTargets¶
ResultRange getOutputTargets();
Returns a range of all target output qubits.
NOTE: This method must be implemented by the user.
getInputControl¶
Value getInputControl(size_t i);
Returns the i-th control input qubit.
NOTE: This method must be implemented by the user.
getInputControls¶
OperandRange getInputControls();
Returns a range of all control input qubits.
NOTE: This method must be implemented by the user.
getOutputControl¶
Value getOutputControl(size_t i);
Returns the i-th control output qubit.
NOTE: This method must be implemented by the user.
getOutputControls¶
ResultRange getOutputControls();
Returns a range of all control output qubits.
NOTE: This method must be implemented by the user.
getInputForOutput¶
Value getInputForOutput(Value output);
Returns the input qubit corresponding to the given output qubit.
NOTE: This method must be implemented by the user.
getOutputForInput¶
Value getOutputForInput(Value input);
Returns the output qubit corresponding to the given input qubit.
NOTE: This method must be implemented by the user.
getNumParams¶
size_t getNumParams();
Returns the number of parameters.
NOTE: This method must be implemented by the user.
getParameter¶
Value getParameter(size_t i);
Returns the i-th parameter.
NOTE: This method must be implemented by the user.
getParameters¶
OperandRange getParameters();
Returns a range of all parameters.
NOTE: This method must be implemented by the user.
isControlled¶
bool isControlled();
Returns true if the operation has any control qubits, otherwise false.
isSingleQubit¶
bool isSingleQubit();
Returns true if the operation only acts on a single qubit.
isTwoQubit¶
bool isTwoQubit();
Returns true if the operation acts on two qubits.
getBaseSymbol¶
StringRef getBaseSymbol();
Returns the base symbol/mnemonic of the operation.
NOTE: This method must be implemented by the user.
hasCompileTimeKnownUnitaryMatrix¶
bool hasCompileTimeKnownUnitaryMatrix();
Returns true if the operation has a compile-time known unitary matrix representation, false otherwise.
NOTE: This method must be implemented by the user.
getUnitaryMatrix1x1¶
bool getUnitaryMatrix1x1(Matrix1x1&out);
Populates the given 1x1 unitary matrix if possible.
getUnitaryMatrix2x2¶
bool getUnitaryMatrix2x2(Matrix2x2&out);
Populates the given 2x2 unitary matrix if possible.
getUnitaryMatrix4x4¶
bool getUnitaryMatrix4x4(Matrix4x4&out);
Populates the given 4x4 unitary matrix if possible.
getUnitaryMatrixDynamic¶
bool getUnitaryMatrixDynamic(DynamicMatrix&out);
Populates the given dynamic unitary matrix.
Passes¶
-fuse-single-qubit-unitary-runs¶
Fuse single-qubit unitary runs using Euler resynthesis
Matches maximal runs of consecutive single-qubit unitary operations on the
same qubit wire (anchored at each run head), composes their constant unitary
matrices, and replaces a run with an equivalent sequence of basis gates when
beneficial: when the run contains a gate outside the target basis, or when
Euler resynthesis would shorten it (synthesizeUnitary1QEuler). Runs that are
already in the target basis and no shorter than the canonical synthesis
length are left unchanged.
The emitted basis is controlled via the basis option (e.g. zyz, zsxx).
A gphase correction is inserted when needed so the rewritten sequence
matches the composed matrix exactly (not only up to global phase).
Currently, only operations whose unitary matrix can be obtained at compile time are fused.
Options¶
-basis : Target Euler basis (zyz, zxz, xzx, xyx, u, zsxx).
-hadamard-lifting¶
This pass attempts to move Hadamard gates as far away from measurements as possible by commuting them with Pauli gates. This is done in order to apply measurement lifting more efficiently, which is a sub-routine of qubit reuse. Additionally, it can change target and control qubits from Pauli-Z gates to make Hadamard lifting applicable. It also lifts Hadamard gates over CNOT gates if that moves a measurement directly after a control.
This pass lifts Hadamard gates away from the measurements in order to apply measurement lifting more effectively. Measurement lifting is a subroutine of the qubit reuse routine. The goal is to measure qubits earlier in the circuit to reuse them and to potentially remove some quantum gates.
Measurement lifting commutes measurements with Pauli and phase gates. However, the routine stops if a Hadamard gate is applied before the measurement takes place. Hadamard lifting attempts to move Hadamards further in front of the circuit, in order to improve the results provided by measurement lifting.
Hadamard lifting uses the following commutation rules: ┌───┐ ┌───┐ ┌───┐ ┌───┐ ─┤ X ├─┤ H ├─ => ─┤ H ├─┤ Z ├─ └───┘ └───┘ └───┘ └───┘ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ─┤ Z ├─┤ H ├─ => ─┤ H ├─┤ X ├─ └───┘ └───┘ └───┘ └───┘ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───────┐ ─┤ Y ├─┤ H ├─ => ─┤ H ├─┤ Y ├─, while adding a global phase: │ G(pi) │ └───┘ └───┘ └───┘ └───┘ └───────┘ Hadamard lifting is only applied to commute Hadamard gates further in front in the circuit, not the other way around. A global phase is added if the Hadamard gate is commuted with a Pauli-Y gate, as YH = -HY.
The routine is only applied to non-controlled Pauli and Hadamard gates.
In order to reduce multi-qubit gates, a second transformation routine is applied. Using the commutation rule ┌───┐┌───┐┌───┐ ──■── ┤ H ├┤ X ├┤ H ├ ┌─┴─┐ => │───│└─┬─┘│───│ ┤ X ├ ┤ H ├──■──┤ H ├ └───┘ └───┘ └───┘ the following transformation is applied to circuits where a Hadamard gate follows a target gate of a controlled Pauli-X gate, which is followed by a measurement: ┌───┐┌───┐┌───┐ ──■───────────── ┤ H ├┤ X ├┤ H ├── ┌─┴─┐┌───┐┌──────┐ => │───│└─┬─┘│───┘──┐ ┤ X ├┤ H ├┤ Meas │ ┤ H ├──■──┤ Meas │ └───┘└───┘└──────┘ └───┘ └──────┘
Afterward the measurement lifting routine could transform the CNOT into a classically controlled Pauli-X.
-merge-single-qubit-rotation-gates¶
Merge rotation gates using quaternion-based fusion
Merges consecutive single-qubit rotation gates acting on the same qubit into a single equivalent U gate, reducing circuit depth and gate count.
Supported gate types: rx, ry, rz, p, r, u2, u.
The pass greedily collects the longest possible chain of consecutive mergeable gates. Each gate is converted to a unit quaternion:
rx,ry,rz,p: single-axis rotations via half-angle formulas.r(theta, phi): rotation bythetaaround axis(cos(phi), sin(phi), 0).u2(phi, lambda) = u(pi / 2, phi, lambda).u(theta, phi, lambda): ZYZ decompositionrz(phi) * ry(theta) * rz(lambda), each factor converted to a quaternion and merged via the Hamilton product.
The gates are then folded one by one via the Hamilton product into a single quaternion, which is decomposed back into ZYZ Euler angles and emitted as a single UOp, representing the same rotation as the chain of single gates.
The global phase of each gate is tracked alongside and combined together.
The emitted UOp is defined by \(U = \exp [i (\phi + \lambda) / 2] R_z (\phi) R_y (\theta) R_z (\lambda)\).
Each merge emits a GPhaseOp carrying the accumulated input phase of the chain.
Because the synthesized UOp introduces an additional intrinsic phase of \((\phi + \lambda) / 2\), the GPhaseOp must compensate for it.
This applies even to chains composed entirely of \(\mathrm{SU} (2)\) gates (rx, ry, rz, r) because the synthesis into a UOp still produces the intrinsic phase term.
-place-and-route¶
This pass ensures that a program meets the connectivity constraints of a target architecture.
This pass maps the dynamically allocated qubits in a quantum program to the static qubits of a target architecture. The pass performs both placement and routing of the qubits to ensure that all two-qubit operations in the program can be executed on the target architecture.
First, the pass assigns static qubits to the dynamically allocated ones by creating an initial dynamic-to-static
mapping, which is referred to as the initial layout. Then, it traverses the circuit and inserts SWAP operations to
ensure that all two-qubit operations are executable on the target architecture, a process known as routing.
For routing, the pass first divides the circuit into layers. A layer is a set of independently executable (sequences
or blocks of) two-qubit operations. Subsequently, the pass performs an A* search for each layer to find and insert a
sequence of SWAP operations that makes these two-qubit operations executable. The A* search also considers
subsequent layers, which are determined by the nlookahead parameter.
The cost function of the A* search is defined as follows:
f(n) = g(n) + h(n)g(n) = alpha * depth(n)h(n) = sum(pow(lambda, i) * h(L, p) for [i, L] in enumerate(layers))
Where:
pis the dynamic-to-static mapping associated with search noden.layersis an array of layers with size1 + nlookahead.depth(n)returns the distance from the nodento the root node.dist(i, j)returns the distance between the qubitsiandjon the target’s coupling graph.h(L, p) := sum(dist(p[gate.first], p[gate.second]) for gate in L)
To iteratively refine the mapping, the pass performs multiple forward and backward traversals of the circuit. In
each traversal, the pass routes the circuit and updates the dynamic-to-static mapping based on the routing decisions
made during that traversal. By performing multiple traversals, the pass can iteratively refine the mapping and
potentially find a more optimal solution. This is behavior is controlled by the niterations parameter.
The pass option ntrials determines how many random initial layouts the pass explores. If compiled with multi-threading on, these trials will be executed in parallel.
Options¶
-nlookahead : The number of lookahead steps.
-alpha : The alpha factor in the cost function. Must be > 0.
-lambda : The lambda factor in the cost function.
-niterations : The number of forwards and backwards traversal to improve the initial layout. Must be > 0.
-ntrials : The number of (possibly parallel) random trials of the forwards and backwards mechanism. Must be > 0.
-seed : A seed used for randomization.
Statistics¶
num-inserted-swaps : The number of inserted SWAPs
-quantum-loop-unroll¶
Unroll bounded loops containing quantum operations
This pass unrolls scf.for operations which contain quantum operations. Classical loops are not unrolled.
Because the pass uses the mlir::loopUnrollByFactor utility internally, the same assumptions and restrictions hold for both.
See the MLIR documentation for more information.
Options¶
-unroll-factor : Use this unroll factor for all loops being unrolled, set it to -1, and it will fully unroll.