microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
80434083bf8758d73a6cbfd98ba67a8d6ecbdc93

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc/src/codegen/tests.rs

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