Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new ops to quake. #109

Merged
merged 3 commits into from
Apr 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions include/cudaq/Optimizer/Dialect/Quake/QuakeOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,68 @@ def quake_ApplyOp : QuakeOp<"apply",
}];
}

//===----------------------------------------------------------------------===//
// Memory and register conversion instructions: These operations are useful for
// intermediate conversions between memory-SSA and value-SSA semantics and vice
// versa of the IR. They mainly exist during the conversion process.
//===----------------------------------------------------------------------===//

def quake_UnwrapOp : QuakeOp<"unwrap"> {
let summary = "Unwrap a reference to a wire and return the wire value.";
let description = [{
A quantum reference is an SSA-value that is associated with a volatile
quantum wire. The unwrap operation allows conversion from the reference
value semantics (memory SSA) to the volatile quantum wire value semantics
when/as desired. The binding of a reference value corresponds to a
particular data flow of volatile quantum wire values.

Unwrap and wrap operations should (typically) form pairs as in the following
example.

```mlir
%0 = ... : !quake.qref
%1 = quake.unwrap %0 : (!quake.qref) -> !quake.wire
%2 = quake.rx (%dbl) %1 : (f64, !quake.wire) -> !quake.wire
quake.wrap %2 to %0 : !quake.wire, !quake.qref
```
}];

let arguments = (ins Arg<QRefType,"",[MemRead]>:$ref_value);
let results = (outs WireType);
let assemblyFormat = [{
$ref_value `:` functional-type(operands, results) attr-dict
}];
}

def quake_WrapOp : QuakeOp<"wrap"> {
let summary = "Wrap a wire value with its reference.";
let description = [{
Each data flow of a volatile wire in a quantum circuit may be associated
and identified with an invariant and unique quantum reference value of type
`!qref`. The wrap operation provides a means of returning a quantum value,
a wire, back to the reference value domain.
}];

let arguments = (ins
WireType:$wire_value,
Arg<QRefType,"",[MemWrite]>:$ref_value
);
let assemblyFormat = [{
$wire_value `to` $ref_value `:` qualified(type(operands)) attr-dict
}];
}

def quake_NullWireOp : QuakeOp<"null_wire", [Pure]> {
let summary = "Initial state of a wire.";
let description = [{
|0> - the initial state of a wire when first constructed. A wire is assumed
to be defined in the |0> state as its initial state.
}];

let results = (outs WireType);
let assemblyFormat = "attr-dict";
}

//===----------------------------------------------------------------------===//
// Base quantum instructions
//===----------------------------------------------------------------------===//
Expand Down
15 changes: 15 additions & 0 deletions test/Quake/quake-ops.qke
Original file line number Diff line number Diff line change
Expand Up @@ -360,3 +360,18 @@ func.func @wire_type() -> !quake.wire {
%0 = cc.undef !quake.wire
return %0 : !quake.wire
}

// CHECK-LABEL: func.func @unwrap_wrap(
// CHECK-SAME: %[[VAL_0:.*]]: !quake.qref) {
// CHECK: %[[VAL_1:.*]] = quake.unwrap %[[VAL_0]] : (!quake.qref) -> !quake.wire
// CHECK: %[[VAL_2:.*]] = quake.null_wire
// CHECK: quake.wrap %[[VAL_2]] to %[[VAL_0]] : !quake.wire, !quake.qref
// CHECK: return
// CHECK: }

func.func @unwrap_wrap(%0 : !quake.qref) {
%1 = quake.unwrap %0 : (!quake.qref) -> !quake.wire
%2 = quake.null_wire
quake.wrap %2 to %0 : !quake.wire, !quake.qref
return
}