microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
cesarzc/try-rca-array-assign-improvement

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

compiler/qsc/src/codegen/tests.rs

763lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use expect_test::expect;
5use qsc_data_structures::{language_features::LanguageFeatures, target::TargetCapabilityFlags};
6use qsc_frontend::compile::SourceMap;
7
8use crate::codegen::qir::get_qir;
9
10#[test]
11fn code_with_errors_returns_errors() {
12 let source = "namespace Test {
13 @EntryPoint()
14 operation Main() : Unit {
15 use q = Qubit()
16 let pi_over_two = 4.0 / 2.0;
17 }
18 }";
19 let sources = SourceMap::new([("test.qs".into(), source.into())], None);
20 let language_features = LanguageFeatures::default();
21 let capabilities = TargetCapabilityFlags::empty();
22 let (std_id, store) = crate::compile::package_store_with_stdlib(capabilities);
23
24 expect![[r#"
25 Err(
26 [
27 Compile(
28 WithSource {
29 sources: [
30 Source {
31 name: "test.qs",
32 contents: "namespace Test {\n @EntryPoint()\n operation Main() : Unit {\n use q = Qubit()\n let pi_over_two = 4.0 / 2.0;\n }\n }",
33 offset: 0,
34 },
35 ],
36 error: Frontend(
37 Error(
38 Parse(
39 Error(
40 Token(
41 Semi,
42 Keyword(
43 Let,
44 ),
45 Span {
46 lo: 129,
47 hi: 132,
48 },
49 ),
50 ),
51 ),
52 ),
53 ),
54 },
55 ),
56 ],
57 )
58 "#]]
59 .assert_debug_eq(&get_qir(sources, language_features, capabilities, store, &[(std_id, None)]));
60}
61
62mod base_profile {
63 use expect_test::expect;
64 use qsc_data_structures::{language_features::LanguageFeatures, target::TargetCapabilityFlags};
65 use qsc_frontend::compile::SourceMap;
66
67 use crate::codegen::qir::get_qir;
68
69 #[test]
70 fn simple() {
71 let source = "namespace Test {
72 open Microsoft.Quantum.Math;
73 open QIR.Intrinsic;
74 @EntryPoint()
75 operation Main() : Result {
76 use q = Qubit();
77 let pi_over_two = 4.0 / 2.0;
78 __quantum__qis__rz__body(pi_over_two, q);
79 mutable some_angle = ArcSin(0.0);
80 __quantum__qis__rz__body(some_angle, q);
81 set some_angle = ArcCos(-1.0) / PI();
82 __quantum__qis__rz__body(some_angle, q);
83 __quantum__qis__mresetz__body(q)
84 }
85 }";
86 let sources = SourceMap::new([("test.qs".into(), source.into())], None);
87 let language_features = LanguageFeatures::default();
88 let capabilities = TargetCapabilityFlags::empty();
89
90 let (std_id, store) = crate::compile::package_store_with_stdlib(capabilities);
91 let qir = get_qir(
92 sources,
93 language_features,
94 capabilities,
95 store,
96 &[(std_id, None)],
97 )
98 .expect("Failed to generate QIR");
99 expect![[r#"
100 %Result = type opaque
101 %Qubit = type opaque
102
103 define void @ENTRYPOINT__main() #0 {
104 block_0:
105 call void @__quantum__qis__rz__body(double 2.0, %Qubit* inttoptr (i64 0 to %Qubit*))
106 call void @__quantum__qis__rz__body(double 0.0, %Qubit* inttoptr (i64 0 to %Qubit*))
107 call void @__quantum__qis__rz__body(double 1.0, %Qubit* inttoptr (i64 0 to %Qubit*))
108 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
109 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
110 ret void
111 }
112
113 declare void @__quantum__qis__rz__body(double, %Qubit*)
114
115 declare void @__quantum__rt__result_record_output(%Result*, i8*)
116
117 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
118
119 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="1" "required_num_results"="1" }
120 attributes #1 = { "irreversible" }
121
122 ; module flags
123
124 !llvm.module.flags = !{!0, !1, !2, !3}
125
126 !0 = !{i32 1, !"qir_major_version", i32 1}
127 !1 = !{i32 7, !"qir_minor_version", i32 0}
128 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
129 !3 = !{i32 1, !"dynamic_result_management", i1 false}
130 "#]]
131 .assert_eq(&qir);
132 }
133
134 #[test]
135 fn qubit_reuse_triggers_reindexing() {
136 let source = "namespace Test {
137 @EntryPoint()
138 operation Main() : (Result, Result) {
139 use q = Qubit();
140 (MResetZ(q), MResetZ(q))
141 }
142 }";
143 let sources = SourceMap::new([("test.qs".into(), source.into())], None);
144 let language_features = LanguageFeatures::default();
145 let capabilities = TargetCapabilityFlags::empty();
146
147 let (std_id, store) = crate::compile::package_store_with_stdlib(capabilities);
148 let qir = get_qir(
149 sources,
150 language_features,
151 capabilities,
152 store,
153 &[(std_id, None)],
154 )
155 .expect("Failed to generate QIR");
156 expect![[r#"
157 %Result = type opaque
158 %Qubit = type opaque
159
160 define void @ENTRYPOINT__main() #0 {
161 block_0:
162 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
163 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
164 call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
165 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
166 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
167 ret void
168 }
169
170 declare void @__quantum__rt__tuple_record_output(i64, i8*)
171
172 declare void @__quantum__rt__result_record_output(%Result*, i8*)
173
174 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
175
176 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="2" }
177 attributes #1 = { "irreversible" }
178
179 ; module flags
180
181 !llvm.module.flags = !{!0, !1, !2, !3}
182
183 !0 = !{i32 1, !"qir_major_version", i32 1}
184 !1 = !{i32 7, !"qir_minor_version", i32 0}
185 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
186 !3 = !{i32 1, !"dynamic_result_management", i1 false}
187 "#]].assert_eq(&qir);
188 }
189
190 #[test]
191 fn qubit_measurements_get_deferred() {
192 let source = "namespace Test {
193 @EntryPoint()
194 operation Main() : Result[] {
195 use (q0, q1) = (Qubit(), Qubit());
196 X(q0);
197 let r0 = MResetZ(q0);
198 X(q1);
199 let r1 = MResetZ(q1);
200 [r0, r1]
201 }
202 }";
203 let sources = SourceMap::new([("test.qs".into(), source.into())], None);
204 let language_features = LanguageFeatures::default();
205 let capabilities = TargetCapabilityFlags::empty();
206
207 let (std_id, store) = crate::compile::package_store_with_stdlib(capabilities);
208 let qir = get_qir(
209 sources,
210 language_features,
211 capabilities,
212 store,
213 &[(std_id, None)],
214 )
215 .expect("Failed to generate QIR");
216 expect![[r#"
217 %Result = type opaque
218 %Qubit = type opaque
219
220 define void @ENTRYPOINT__main() #0 {
221 block_0:
222 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
223 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 1 to %Qubit*))
224 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
225 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
226 call void @__quantum__rt__array_record_output(i64 2, i8* null)
227 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
228 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
229 ret void
230 }
231
232 declare void @__quantum__qis__x__body(%Qubit*)
233
234 declare void @__quantum__rt__array_record_output(i64, i8*)
235
236 declare void @__quantum__rt__result_record_output(%Result*, i8*)
237
238 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
239
240 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="2" }
241 attributes #1 = { "irreversible" }
242
243 ; module flags
244
245 !llvm.module.flags = !{!0, !1, !2, !3}
246
247 !0 = !{i32 1, !"qir_major_version", i32 1}
248 !1 = !{i32 7, !"qir_minor_version", i32 0}
249 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
250 !3 = !{i32 1, !"dynamic_result_management", i1 false}
251 "#]].assert_eq(&qir);
252 }
253}
254
255mod adaptive_profile {
256 use expect_test::expect;
257 use qsc_data_structures::{language_features::LanguageFeatures, target::TargetCapabilityFlags};
258 use qsc_frontend::compile::SourceMap;
259
260 use crate::codegen::qir::get_qir;
261
262 #[test]
263 fn simple() {
264 let source = "namespace Test {
265 open Microsoft.Quantum.Math;
266 open QIR.Intrinsic;
267 @EntryPoint()
268 operation Main() : Result {
269 use q = Qubit();
270 let pi_over_two = 4.0 / 2.0;
271 __quantum__qis__rz__body(pi_over_two, q);
272 mutable some_angle = ArcSin(0.0);
273 __quantum__qis__rz__body(some_angle, q);
274 set some_angle = ArcCos(-1.0) / PI();
275 __quantum__qis__rz__body(some_angle, q);
276 __quantum__qis__mresetz__body(q)
277 }
278 }";
279 let sources = SourceMap::new([("test.qs".into(), source.into())], None);
280 let language_features = LanguageFeatures::default();
281 let capabilities = TargetCapabilityFlags::Adaptive;
282
283 let (std_id, store) = crate::compile::package_store_with_stdlib(capabilities);
284 let qir = get_qir(
285 sources,
286 language_features,
287 capabilities,
288 store,
289 &[(std_id, None)],
290 )
291 .expect("Failed to generate QIR");
292 expect![[r#"
293 %Result = type opaque
294 %Qubit = type opaque
295
296 define void @ENTRYPOINT__main() #0 {
297 block_0:
298 call void @__quantum__qis__rz__body(double 2.0, %Qubit* inttoptr (i64 0 to %Qubit*))
299 call void @__quantum__qis__rz__body(double 0.0, %Qubit* inttoptr (i64 0 to %Qubit*))
300 call void @__quantum__qis__rz__body(double 1.0, %Qubit* inttoptr (i64 0 to %Qubit*))
301 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
302 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
303 ret void
304 }
305
306 declare void @__quantum__qis__rz__body(double, %Qubit*)
307
308 declare void @__quantum__rt__result_record_output(%Result*, i8*)
309
310 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
311
312 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="1" }
313 attributes #1 = { "irreversible" }
314
315 ; module flags
316
317 !llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10}
318
319 !0 = !{i32 1, !"qir_major_version", i32 1}
320 !1 = !{i32 7, !"qir_minor_version", i32 0}
321 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
322 !3 = !{i32 1, !"dynamic_result_management", i1 false}
323 !4 = !{i32 1, !"classical_ints", i1 false}
324 !5 = !{i32 1, !"classical_floats", i1 false}
325 !6 = !{i32 1, !"backwards_branching", i1 false}
326 !7 = !{i32 1, !"qubit_resetting", i1 false}
327 !8 = !{i32 1, !"classical_fixed_points", i1 false}
328 !9 = !{i32 1, !"user_functions", i1 false}
329 !10 = !{i32 1, !"multiple_target_branching", i1 false}
330 "#]]
331 .assert_eq(&qir);
332 }
333
334 #[test]
335 fn qubit_reuse_triggers_reindexing() {
336 let source = "namespace Test {
337 @EntryPoint()
338 operation Main() : (Result, Result) {
339 use q = Qubit();
340 (MResetZ(q), MResetZ(q))
341 }
342 }";
343 let sources = SourceMap::new([("test.qs".into(), source.into())], None);
344 let language_features = LanguageFeatures::default();
345 let capabilities = TargetCapabilityFlags::Adaptive;
346
347 let (std_id, store) = crate::compile::package_store_with_stdlib(capabilities);
348 let qir = get_qir(
349 sources,
350 language_features,
351 capabilities,
352 store,
353 &[(std_id, None)],
354 )
355 .expect("Failed to generate QIR");
356 expect![[r#"
357 %Result = type opaque
358 %Qubit = type opaque
359
360 define void @ENTRYPOINT__main() #0 {
361 block_0:
362 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
363 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
364 call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
365 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
366 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
367 ret void
368 }
369
370 declare void @__quantum__rt__tuple_record_output(i64, i8*)
371
372 declare void @__quantum__rt__result_record_output(%Result*, i8*)
373
374 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
375
376 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="2" "required_num_results"="2" }
377 attributes #1 = { "irreversible" }
378
379 ; module flags
380
381 !llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10}
382
383 !0 = !{i32 1, !"qir_major_version", i32 1}
384 !1 = !{i32 7, !"qir_minor_version", i32 0}
385 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
386 !3 = !{i32 1, !"dynamic_result_management", i1 false}
387 !4 = !{i32 1, !"classical_ints", i1 false}
388 !5 = !{i32 1, !"classical_floats", i1 false}
389 !6 = !{i32 1, !"backwards_branching", i1 false}
390 !7 = !{i32 1, !"qubit_resetting", i1 false}
391 !8 = !{i32 1, !"classical_fixed_points", i1 false}
392 !9 = !{i32 1, !"user_functions", i1 false}
393 !10 = !{i32 1, !"multiple_target_branching", i1 false}
394 "#]].assert_eq(&qir);
395 }
396
397 #[test]
398 fn qubit_measurements_not_deferred() {
399 let source = "namespace Test {
400 @EntryPoint()
401 operation Main() : Result[] {
402 use (q0, q1) = (Qubit(), Qubit());
403 X(q0);
404 let r0 = MResetZ(q0);
405 X(q1);
406 let r1 = MResetZ(q1);
407 [r0, r1]
408 }
409 }";
410 let sources = SourceMap::new([("test.qs".into(), source.into())], None);
411 let language_features = LanguageFeatures::default();
412 let capabilities = TargetCapabilityFlags::Adaptive;
413
414 let (std_id, store) = crate::compile::package_store_with_stdlib(capabilities);
415 let qir = get_qir(
416 sources,
417 language_features,
418 capabilities,
419 store,
420 &[(std_id, None)],
421 )
422 .expect("Failed to generate QIR");
423 expect![[r#"
424 %Result = type opaque
425 %Qubit = type opaque
426
427 define void @ENTRYPOINT__main() #0 {
428 block_0:
429 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
430 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
431 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 1 to %Qubit*))
432 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
433 call void @__quantum__rt__array_record_output(i64 2, i8* null)
434 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
435 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
436 ret void
437 }
438
439 declare void @__quantum__qis__x__body(%Qubit*)
440
441 declare void @__quantum__rt__array_record_output(i64, i8*)
442
443 declare void @__quantum__rt__result_record_output(%Result*, i8*)
444
445 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
446
447 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="2" "required_num_results"="2" }
448 attributes #1 = { "irreversible" }
449
450 ; module flags
451
452 !llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10}
453
454 !0 = !{i32 1, !"qir_major_version", i32 1}
455 !1 = !{i32 7, !"qir_minor_version", i32 0}
456 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
457 !3 = !{i32 1, !"dynamic_result_management", i1 false}
458 !4 = !{i32 1, !"classical_ints", i1 false}
459 !5 = !{i32 1, !"classical_floats", i1 false}
460 !6 = !{i32 1, !"backwards_branching", i1 false}
461 !7 = !{i32 1, !"qubit_resetting", i1 false}
462 !8 = !{i32 1, !"classical_fixed_points", i1 false}
463 !9 = !{i32 1, !"user_functions", i1 false}
464 !10 = !{i32 1, !"multiple_target_branching", i1 false}
465 "#]].assert_eq(&qir);
466 }
467}
468
469mod adaptive_ri_profile {
470
471 use expect_test::expect;
472 use qsc_data_structures::{language_features::LanguageFeatures, target::TargetCapabilityFlags};
473 use qsc_frontend::compile::SourceMap;
474
475 use crate::codegen::qir::get_qir;
476
477 #[test]
478 fn simple() {
479 let source = "namespace Test {
480 open Microsoft.Quantum.Math;
481 open QIR.Intrinsic;
482 @EntryPoint()
483 operation Main() : Result {
484 use q = Qubit();
485 let pi_over_two = 4.0 / 2.0;
486 __quantum__qis__rz__body(pi_over_two, q);
487 mutable some_angle = ArcSin(0.0);
488 __quantum__qis__rz__body(some_angle, q);
489 set some_angle = ArcCos(-1.0) / PI();
490 __quantum__qis__rz__body(some_angle, q);
491 __quantum__qis__mresetz__body(q)
492 }
493 }";
494 let sources = SourceMap::new([("test.qs".into(), source.into())], None);
495 let language_features = LanguageFeatures::default();
496 let capabilities = TargetCapabilityFlags::Adaptive
497 | TargetCapabilityFlags::QubitReset
498 | TargetCapabilityFlags::IntegerComputations;
499
500 let (std_id, store) = crate::compile::package_store_with_stdlib(capabilities);
501 let qir = get_qir(
502 sources,
503 language_features,
504 capabilities,
505 store,
506 &[(std_id, None)],
507 )
508 .expect("Failed to generate QIR");
509 expect![[r#"
510 %Result = type opaque
511 %Qubit = type opaque
512
513 define void @ENTRYPOINT__main() #0 {
514 block_0:
515 call void @__quantum__qis__rz__body(double 2.0, %Qubit* inttoptr (i64 0 to %Qubit*))
516 call void @__quantum__qis__rz__body(double 0.0, %Qubit* inttoptr (i64 0 to %Qubit*))
517 call void @__quantum__qis__rz__body(double 1.0, %Qubit* inttoptr (i64 0 to %Qubit*))
518 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
519 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
520 ret void
521 }
522
523 declare void @__quantum__qis__rz__body(double, %Qubit*)
524
525 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
526
527 declare void @__quantum__rt__result_record_output(%Result*, i8*)
528
529 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="1" }
530 attributes #1 = { "irreversible" }
531
532 ; module flags
533
534 !llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10}
535
536 !0 = !{i32 1, !"qir_major_version", i32 1}
537 !1 = !{i32 7, !"qir_minor_version", i32 0}
538 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
539 !3 = !{i32 1, !"dynamic_result_management", i1 false}
540 !4 = !{i32 1, !"classical_ints", i1 true}
541 !5 = !{i32 1, !"qubit_resetting", i1 true}
542 !6 = !{i32 1, !"classical_floats", i1 false}
543 !7 = !{i32 1, !"backwards_branching", i1 false}
544 !8 = !{i32 1, !"classical_fixed_points", i1 false}
545 !9 = !{i32 1, !"user_functions", i1 false}
546 !10 = !{i32 1, !"multiple_target_branching", i1 false}
547 "#]]
548 .assert_eq(&qir);
549 }
550
551 #[test]
552 fn qubit_reuse_allowed() {
553 let source = "namespace Test {
554 @EntryPoint()
555 operation Main() : (Result, Result) {
556 use q = Qubit();
557 (MResetZ(q), MResetZ(q))
558 }
559 }";
560 let sources = SourceMap::new([("test.qs".into(), source.into())], None);
561 let language_features = LanguageFeatures::default();
562 let capabilities = TargetCapabilityFlags::Adaptive
563 | TargetCapabilityFlags::QubitReset
564 | TargetCapabilityFlags::IntegerComputations;
565
566 let (std_id, store) = crate::compile::package_store_with_stdlib(capabilities);
567 let qir = get_qir(
568 sources,
569 language_features,
570 capabilities,
571 store,
572 &[(std_id, None)],
573 )
574 .expect("Failed to generate QIR");
575 expect![[r#"
576 %Result = type opaque
577 %Qubit = type opaque
578
579 define void @ENTRYPOINT__main() #0 {
580 block_0:
581 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
582 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
583 call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
584 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
585 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
586 ret void
587 }
588
589 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
590
591 declare void @__quantum__rt__tuple_record_output(i64, i8*)
592
593 declare void @__quantum__rt__result_record_output(%Result*, i8*)
594
595 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="2" }
596 attributes #1 = { "irreversible" }
597
598 ; module flags
599
600 !llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10}
601
602 !0 = !{i32 1, !"qir_major_version", i32 1}
603 !1 = !{i32 7, !"qir_minor_version", i32 0}
604 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
605 !3 = !{i32 1, !"dynamic_result_management", i1 false}
606 !4 = !{i32 1, !"classical_ints", i1 true}
607 !5 = !{i32 1, !"qubit_resetting", i1 true}
608 !6 = !{i32 1, !"classical_floats", i1 false}
609 !7 = !{i32 1, !"backwards_branching", i1 false}
610 !8 = !{i32 1, !"classical_fixed_points", i1 false}
611 !9 = !{i32 1, !"user_functions", i1 false}
612 !10 = !{i32 1, !"multiple_target_branching", i1 false}
613 "#]].assert_eq(&qir);
614 }
615
616 #[test]
617 fn qubit_measurements_not_deferred() {
618 let source = "namespace Test {
619 @EntryPoint()
620 operation Main() : Result[] {
621 use (q0, q1) = (Qubit(), Qubit());
622 X(q0);
623 let r0 = MResetZ(q0);
624 X(q1);
625 let r1 = MResetZ(q1);
626 [r0, r1]
627 }
628 }";
629 let sources = SourceMap::new([("test.qs".into(), source.into())], None);
630 let language_features = LanguageFeatures::default();
631 let capabilities = TargetCapabilityFlags::Adaptive
632 | TargetCapabilityFlags::QubitReset
633 | TargetCapabilityFlags::IntegerComputations;
634
635 let (std_id, store) = crate::compile::package_store_with_stdlib(capabilities);
636 let qir = get_qir(
637 sources,
638 language_features,
639 capabilities,
640 store,
641 &[(std_id, None)],
642 )
643 .expect("Failed to generate QIR");
644 expect![[r#"
645 %Result = type opaque
646 %Qubit = type opaque
647
648 define void @ENTRYPOINT__main() #0 {
649 block_0:
650 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
651 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
652 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 1 to %Qubit*))
653 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
654 call void @__quantum__rt__array_record_output(i64 2, i8* null)
655 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
656 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
657 ret void
658 }
659
660 declare void @__quantum__qis__x__body(%Qubit*)
661
662 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
663
664 declare void @__quantum__rt__array_record_output(i64, i8*)
665
666 declare void @__quantum__rt__result_record_output(%Result*, i8*)
667
668 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="2" "required_num_results"="2" }
669 attributes #1 = { "irreversible" }
670
671 ; module flags
672
673 !llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10}
674
675 !0 = !{i32 1, !"qir_major_version", i32 1}
676 !1 = !{i32 7, !"qir_minor_version", i32 0}
677 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
678 !3 = !{i32 1, !"dynamic_result_management", i1 false}
679 !4 = !{i32 1, !"classical_ints", i1 true}
680 !5 = !{i32 1, !"qubit_resetting", i1 true}
681 !6 = !{i32 1, !"classical_floats", i1 false}
682 !7 = !{i32 1, !"backwards_branching", i1 false}
683 !8 = !{i32 1, !"classical_fixed_points", i1 false}
684 !9 = !{i32 1, !"user_functions", i1 false}
685 !10 = !{i32 1, !"multiple_target_branching", i1 false}
686 "#]].assert_eq(&qir);
687 }
688
689 #[test]
690 fn dynamic_integer_with_branch_and_phi_supported() {
691 let source = "namespace Test {
692 @EntryPoint()
693 operation Main() : Int {
694 use q = Qubit();
695 H(q);
696 MResetZ(q) == Zero ? 0 | 1
697 }
698 }";
699 let sources = SourceMap::new([("test.qs".into(), source.into())], None);
700 let language_features = LanguageFeatures::default();
701 let capabilities = TargetCapabilityFlags::Adaptive
702 | TargetCapabilityFlags::QubitReset
703 | TargetCapabilityFlags::IntegerComputations;
704
705 let (std_id, store) = crate::compile::package_store_with_stdlib(capabilities);
706 let qir = get_qir(
707 sources,
708 language_features,
709 capabilities,
710 store,
711 &[(std_id, None)],
712 )
713 .expect("Failed to generate QIR");
714 expect![[r#"
715 %Result = type opaque
716 %Qubit = type opaque
717
718 define void @ENTRYPOINT__main() #0 {
719 block_0:
720 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*))
721 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
722 %var_0 = call i1 @__quantum__qis__read_result__body(%Result* inttoptr (i64 0 to %Result*))
723 %var_1 = icmp eq i1 %var_0, false
724 br i1 %var_1, label %block_1, label %block_2
725 block_1:
726 br label %block_3
727 block_2:
728 br label %block_3
729 block_3:
730 %var_3 = phi i64 [0, %block_1], [1, %block_2]
731 call void @__quantum__rt__int_record_output(i64 %var_3, i8* null)
732 ret void
733 }
734
735 declare void @__quantum__qis__h__body(%Qubit*)
736
737 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
738
739 declare i1 @__quantum__qis__read_result__body(%Result*)
740
741 declare void @__quantum__rt__int_record_output(i64, i8*)
742
743 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="1" }
744 attributes #1 = { "irreversible" }
745
746 ; module flags
747
748 !llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10}
749
750 !0 = !{i32 1, !"qir_major_version", i32 1}
751 !1 = !{i32 7, !"qir_minor_version", i32 0}
752 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
753 !3 = !{i32 1, !"dynamic_result_management", i1 false}
754 !4 = !{i32 1, !"classical_ints", i1 true}
755 !5 = !{i32 1, !"qubit_resetting", i1 true}
756 !6 = !{i32 1, !"classical_floats", i1 false}
757 !7 = !{i32 1, !"backwards_branching", i1 false}
758 !8 = !{i32 1, !"classical_fixed_points", i1 false}
759 !9 = !{i32 1, !"user_functions", i1 false}
760 !10 = !{i32 1, !"multiple_target_branching", i1 false}
761 "#]].assert_eq(&qir);
762 }
763}
764