Skip to content

Commit b80019a

Browse files
committed
Add measurement broadcast
1 parent f89ea75 commit b80019a

File tree

11 files changed

+231
-34
lines changed

11 files changed

+231
-34
lines changed

compiler/qsc_qasm/src/ast_builder.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -740,8 +740,24 @@ pub(crate) fn build_measure_call(
740740
stmt_span: Span,
741741
) -> ast::Expr {
742742
build_call_with_param(
743-
"__quantum__qis__m__body",
744-
&["QIR", "Intrinsic"],
743+
"M",
744+
&["Std", "Intrinsic"],
745+
expr,
746+
name_span,
747+
operand_span,
748+
stmt_span,
749+
)
750+
}
751+
752+
pub(crate) fn build_measureeachz_call(
753+
expr: ast::Expr,
754+
name_span: Span,
755+
operand_span: Span,
756+
stmt_span: Span,
757+
) -> ast::Expr {
758+
build_call_with_param(
759+
"MeasureEachZ",
760+
&["Std", "Measurement"],
745761
expr,
746762
name_span,
747763
operand_span,

compiler/qsc_qasm/src/compiler.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@ use crate::{
2626
build_lit_angle_expr, build_lit_bigint_expr, build_lit_bool_expr, build_lit_complex_expr,
2727
build_lit_double_expr, build_lit_int_expr, build_lit_result_array_expr_from_bitstring,
2828
build_lit_result_expr, build_managed_qubit_alloc, build_math_call_from_exprs,
29-
build_math_call_no_params, build_measure_call, build_operation_with_stmts,
30-
build_path_ident_expr, build_path_ident_ty, build_qasm_import_decl,
31-
build_qasm_import_items, build_qasmstd_convert_call_with_two_params, build_range_expr,
32-
build_reset_call, build_return_expr, build_return_unit, build_stmt_semi_from_expr,
29+
build_math_call_no_params, build_measure_call, build_measureeachz_call,
30+
build_operation_with_stmts, build_path_ident_expr, build_path_ident_ty,
31+
build_qasm_import_decl, build_qasm_import_items,
32+
build_qasmstd_convert_call_with_two_params, build_range_expr, build_reset_call,
33+
build_return_expr, build_return_unit, build_stmt_semi_from_expr,
3334
build_stmt_semi_from_expr_with_span, build_ternary_update_expr,
3435
build_top_level_ns_with_items, build_tuple_expr, build_unary_op_expr,
3536
build_unmanaged_qubit_alloc, build_unmanaged_qubit_alloc_array, build_while_stmt,
@@ -1158,7 +1159,7 @@ impl QasmCompiler {
11581159
semast::ExprKind::Cast(cast) => self.compile_cast_expr(cast),
11591160
semast::ExprKind::IndexExpr(index_expr) => self.compile_index_expr(index_expr),
11601161
semast::ExprKind::Paren(pexpr) => self.compile_paren_expr(pexpr, expr.span),
1161-
semast::ExprKind::Measure(expr) => self.compile_measure_expr(expr),
1162+
semast::ExprKind::Measure(mexpr) => self.compile_measure_expr(mexpr, &expr.ty),
11621163
}
11631164
}
11641165

@@ -1439,12 +1440,22 @@ impl QasmCompiler {
14391440
wrap_expr_in_parens(expr, span)
14401441
}
14411442

1442-
fn compile_measure_expr(&mut self, expr: &MeasureExpr) -> qsast::Expr {
1443+
fn compile_measure_expr(
1444+
&mut self,
1445+
expr: &MeasureExpr,
1446+
ty: &crate::semantic::types::Type,
1447+
) -> qsast::Expr {
1448+
assert!(matches!(ty, Type::BitArray(..) | Type::Bit(..)));
1449+
14431450
let call_span = expr.span;
14441451
let name_span = expr.measure_token_span;
14451452
let arg = self.compile_gate_operand(&expr.operand);
14461453
let operand_span = expr.operand.span;
1447-
build_measure_call(arg, name_span, operand_span, call_span)
1454+
if matches!(ty, Type::Bit(..)) {
1455+
build_measure_call(arg, name_span, operand_span, call_span)
1456+
} else {
1457+
build_measureeachz_call(arg, name_span, operand_span, call_span)
1458+
}
14481459
}
14491460

14501461
fn compile_gate_operand(&mut self, op: &GateOperand) -> qsast::Expr {

compiler/qsc_qasm/src/semantic/lowerer.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2640,15 +2640,19 @@ impl Lowerer {
26402640
}
26412641

26422642
fn lower_measure_expr(&mut self, expr: &syntax::MeasureExpr) -> semantic::Expr {
2643+
let operand = self.lower_gate_operand(&expr.operand);
2644+
let ty = get_measurement_ty_from_gate_operand(&operand);
2645+
26432646
let measurement = semantic::MeasureExpr {
26442647
span: expr.span,
26452648
measure_token_span: expr.measure_token_span,
26462649
operand: self.lower_gate_operand(&expr.operand),
26472650
};
2651+
26482652
semantic::Expr {
26492653
span: expr.span,
26502654
kind: Box::new(semantic::ExprKind::Measure(measurement)),
2651-
ty: Type::Bit(false),
2655+
ty,
26522656
}
26532657
}
26542658

@@ -3876,6 +3880,16 @@ fn wrap_expr_in_cast_expr(ty: Type, rhs: semantic::Expr) -> semantic::Expr {
38763880
}
38773881
}
38783882

3883+
fn get_measurement_ty_from_gate_operand(operand: &semantic::GateOperand) -> Type {
3884+
if let semantic::GateOperandKind::Expr(ref expr) = &operand.kind {
3885+
if let Type::QubitArray(size) = expr.ty {
3886+
return Type::BitArray(size, false);
3887+
}
3888+
}
3889+
3890+
Type::Bit(false)
3891+
}
3892+
38793893
/// +----------------+-------------------------------------------------------------+
38803894
/// | Allowed casts | Casting To |
38813895
/// +----------------+-------+-----+------+-------+-------+-----+----------+-------+

compiler/qsc_qasm/src/tests/expression/function_call.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ fn funcall_with_qubit_argument() -> miette::Result<(), Vec<Report>> {
101101
expect![[r#"
102102
import Std.OpenQASM.Intrinsic.*;
103103
operation parity(qs : Qubit[]) : Result {
104-
mutable a = QIR.Intrinsic.__quantum__qis__m__body(qs[0]);
105-
mutable b = QIR.Intrinsic.__quantum__qis__m__body(qs[1]);
104+
mutable a = Std.Intrinsic.M(qs[0]);
105+
mutable b = Std.Intrinsic.M(qs[1]);
106106
return if Std.OpenQASM.Convert.ResultAsInt(a) ^^^ Std.OpenQASM.Convert.ResultAsInt(b) == 0 {
107107
One
108108
} else {

compiler/qsc_qasm/src/tests/output.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ fn using_re_semantics_removes_output() -> miette::Result<(), Vec<Report>> {
4949
rz(Std.OpenQASM.Angle.DoubleAsAngle(theta, 53), q[0]);
5050
h(q[0]);
5151
cx(q[0], q[1]);
52-
set c w/= 0 <- QIR.Intrinsic.__quantum__qis__m__body(q[0]);
53-
set c w/= 1 <- QIR.Intrinsic.__quantum__qis__m__body(q[1]);
52+
set c w/= 0 <- Std.Intrinsic.M(q[0]);
53+
set c w/= 1 <- Std.Intrinsic.M(q[1]);
5454
}
5555
}"#]]
5656
.assert_eq(&qsharp);
@@ -98,8 +98,8 @@ fn using_qasm_semantics_captures_all_classical_decls_as_output() -> miette::Resu
9898
rz(Std.OpenQASM.Angle.DoubleAsAngle(theta, 53), q[0]);
9999
h(q[0]);
100100
cx(q[0], q[1]);
101-
set c w/= 0 <- QIR.Intrinsic.__quantum__qis__m__body(q[0]);
102-
set c w/= 1 <- QIR.Intrinsic.__quantum__qis__m__body(q[1]);
101+
set c w/= 0 <- Std.Intrinsic.M(q[0]);
102+
set c w/= 1 <- Std.Intrinsic.M(q[1]);
103103
(c, gamma, delta)
104104
}
105105
}"#]]
@@ -147,8 +147,8 @@ fn using_qiskit_semantics_only_bit_array_is_captured_and_reversed(
147147
rz(Std.OpenQASM.Angle.DoubleAsAngle(theta, 53), q[0]);
148148
h(q[0]);
149149
cx(q[0], q[1]);
150-
set c w/= 0 <- QIR.Intrinsic.__quantum__qis__m__body(q[0]);
151-
set c w/= 1 <- QIR.Intrinsic.__quantum__qis__m__body(q[1]);
150+
set c w/= 0 <- Std.Intrinsic.M(q[0]);
151+
set c w/= 1 <- Std.Intrinsic.M(q[1]);
152152
Std.Arrays.Reversed(c)
153153
}
154154
}"#]]
@@ -208,11 +208,11 @@ c2[2] = measure q[4];
208208
x(q[2]);
209209
id(q[3]);
210210
x(q[4]);
211-
set c w/= 0 <- QIR.Intrinsic.__quantum__qis__m__body(q[0]);
212-
set c w/= 1 <- QIR.Intrinsic.__quantum__qis__m__body(q[1]);
213-
set c2 w/= 0 <- QIR.Intrinsic.__quantum__qis__m__body(q[2]);
214-
set c2 w/= 1 <- QIR.Intrinsic.__quantum__qis__m__body(q[3]);
215-
set c2 w/= 2 <- QIR.Intrinsic.__quantum__qis__m__body(q[4]);
211+
set c w/= 0 <- Std.Intrinsic.M(q[0]);
212+
set c w/= 1 <- Std.Intrinsic.M(q[1]);
213+
set c2 w/= 0 <- Std.Intrinsic.M(q[2]);
214+
set c2 w/= 1 <- Std.Intrinsic.M(q[3]);
215+
set c2 w/= 2 <- Std.Intrinsic.M(q[4]);
216216
(Std.Arrays.Reversed(c2), Std.Arrays.Reversed(c))
217217
}
218218
}"#]]

compiler/qsc_qasm/src/tests/statement/if_stmt.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ fn can_use_cond_with_implicit_cast_to_bool() -> miette::Result<(), Vec<Report>>
2323
import Std.OpenQASM.Intrinsic.*;
2424
let q = QIR.Runtime.__quantum__rt__qubit_allocate();
2525
h(q);
26-
mutable result = QIR.Intrinsic.__quantum__qis__m__body(q);
26+
mutable result = Std.Intrinsic.M(q);
2727
if Std.OpenQASM.Convert.ResultAsBool(result) {
2828
Reset(q);
2929
};
@@ -50,7 +50,7 @@ fn can_use_negated_cond_with_implicit_cast_to_bool() -> miette::Result<(), Vec<R
5050
import Std.OpenQASM.Intrinsic.*;
5151
let q = QIR.Runtime.__quantum__rt__qubit_allocate();
5252
h(q);
53-
mutable result = QIR.Intrinsic.__quantum__qis__m__body(q);
53+
mutable result = Std.Intrinsic.M(q);
5454
if not Std.OpenQASM.Convert.ResultAsBool(result) {
5555
Reset(q);
5656
};

compiler/qsc_qasm/src/tests/statement/include.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ fn programs_with_includes_can_be_parsed() -> miette::Result<(), Vec<Report>> {
5050
mutable c = [Zero];
5151
let q = QIR.Runtime.AllocateQubitArray(1);
5252
my_gate(q[0]);
53-
set c w/= 0 <- QIR.Intrinsic.__quantum__qis__m__body(q[0]);
53+
set c w/= 0 <- Std.Intrinsic.M(q[0]);
5454
Std.Arrays.Reversed(c)
5555
}
5656
}"#]]

0 commit comments

Comments
 (0)