microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
copilot/fix-2145

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc/src/codegen/tests.rs

1630lines · 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
10fn compile_source_to_qir(source: &str, capabilities: TargetCapabilityFlags) -> String {
11 let sources = SourceMap::new([("test.qs".into(), source.into())], None);
12 let language_features = LanguageFeatures::default();
13
14 let (std_id, store) = crate::compile::package_store_with_stdlib(capabilities);
15 get_qir(
16 sources,
17 language_features,
18 capabilities,
19 store,
20 &[(std_id, None)],
21 )
22 .expect("Failed to generate QIR")
23}
24
25#[test]
26fn code_with_errors_returns_errors() {
27 let source = "namespace Test {
28 @EntryPoint()
29 operation Main() : Unit {
30 use q = Qubit()
31 let pi_over_two = 4.0 / 2.0;
32 }
33 }";
34 let sources = SourceMap::new([("test.qs".into(), source.into())], None);
35 let language_features = LanguageFeatures::default();
36 let capabilities = TargetCapabilityFlags::empty();
37 let (std_id, store) = crate::compile::package_store_with_stdlib(capabilities);
38
39 expect![[r#"
40 Err(
41 [
42 Compile(
43 WithSource {
44 sources: [
45 Source {
46 name: "test.qs",
47 contents: "namespace Test {\n @EntryPoint()\n operation Main() : Unit {\n use q = Qubit()\n let pi_over_two = 4.0 / 2.0;\n }\n }",
48 offset: 0,
49 },
50 ],
51 error: Frontend(
52 Error(
53 Parse(
54 Error(
55 Token(
56 Semi,
57 Keyword(
58 Let,
59 ),
60 Span {
61 lo: 129,
62 hi: 132,
63 },
64 ),
65 ),
66 ),
67 ),
68 ),
69 },
70 ),
71 ],
72 )
73 "#]]
74 .assert_debug_eq(&get_qir(sources, language_features, capabilities, store, &[(std_id, None)]));
75}
76
77mod base_profile {
78 use expect_test::expect;
79 use qsc_data_structures::target::TargetCapabilityFlags;
80
81 use super::compile_source_to_qir;
82 static CAPABILITIES: std::sync::LazyLock<TargetCapabilityFlags> =
83 std::sync::LazyLock::new(TargetCapabilityFlags::empty);
84
85 #[test]
86 fn simple() {
87 let source = "namespace Test {
88 import Std.Math.*;
89 open QIR.Intrinsic;
90 @EntryPoint()
91 operation Main() : Result {
92 use q = Qubit();
93 let pi_over_two = 4.0 / 2.0;
94 __quantum__qis__rz__body(pi_over_two, q);
95 mutable some_angle = ArcSin(0.0);
96 __quantum__qis__rz__body(some_angle, q);
97 set some_angle = ArcCos(-1.0) / PI();
98 __quantum__qis__rz__body(some_angle, q);
99 __quantum__qis__mresetz__body(q)
100 }
101 }";
102
103 let qir = compile_source_to_qir(source, *CAPABILITIES);
104 expect![[r#"
105 %Result = type opaque
106 %Qubit = type opaque
107
108 define void @ENTRYPOINT__main() #0 {
109 block_0:
110 call void @__quantum__qis__rz__body(double 2.0, %Qubit* inttoptr (i64 0 to %Qubit*))
111 call void @__quantum__qis__rz__body(double 0.0, %Qubit* inttoptr (i64 0 to %Qubit*))
112 call void @__quantum__qis__rz__body(double 1.0, %Qubit* inttoptr (i64 0 to %Qubit*))
113 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
114 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
115 ret void
116 }
117
118 declare void @__quantum__qis__rz__body(double, %Qubit*)
119
120 declare void @__quantum__rt__result_record_output(%Result*, i8*)
121
122 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
123
124 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="1" "required_num_results"="1" }
125 attributes #1 = { "irreversible" }
126
127 ; module flags
128
129 !llvm.module.flags = !{!0, !1, !2, !3}
130
131 !0 = !{i32 1, !"qir_major_version", i32 1}
132 !1 = !{i32 7, !"qir_minor_version", i32 0}
133 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
134 !3 = !{i32 1, !"dynamic_result_management", i1 false}
135 "#]]
136 .assert_eq(&qir);
137 }
138
139 #[test]
140 fn qubit_reuse_triggers_reindexing() {
141 let source = "namespace Test {
142 @EntryPoint()
143 operation Main() : (Result, Result) {
144 use q = Qubit();
145 (MResetZ(q), MResetZ(q))
146 }
147 }";
148 let qir = compile_source_to_qir(source, *CAPABILITIES);
149 expect![[r#"
150 %Result = type opaque
151 %Qubit = type opaque
152
153 define void @ENTRYPOINT__main() #0 {
154 block_0:
155 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
156 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
157 call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
158 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
159 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
160 ret void
161 }
162
163 declare void @__quantum__rt__tuple_record_output(i64, i8*)
164
165 declare void @__quantum__rt__result_record_output(%Result*, i8*)
166
167 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
168
169 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="2" }
170 attributes #1 = { "irreversible" }
171
172 ; module flags
173
174 !llvm.module.flags = !{!0, !1, !2, !3}
175
176 !0 = !{i32 1, !"qir_major_version", i32 1}
177 !1 = !{i32 7, !"qir_minor_version", i32 0}
178 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
179 !3 = !{i32 1, !"dynamic_result_management", i1 false}
180 "#]].assert_eq(&qir);
181 }
182
183 #[test]
184 fn qubit_measurements_get_deferred() {
185 let source = "namespace Test {
186 @EntryPoint()
187 operation Main() : Result[] {
188 use (q0, q1) = (Qubit(), Qubit());
189 X(q0);
190 let r0 = MResetZ(q0);
191 X(q1);
192 let r1 = MResetZ(q1);
193 [r0, r1]
194 }
195 }";
196 let qir = compile_source_to_qir(source, *CAPABILITIES);
197 expect![[r#"
198 %Result = type opaque
199 %Qubit = type opaque
200
201 define void @ENTRYPOINT__main() #0 {
202 block_0:
203 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
204 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 1 to %Qubit*))
205 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
206 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
207 call void @__quantum__rt__array_record_output(i64 2, i8* null)
208 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
209 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
210 ret void
211 }
212
213 declare void @__quantum__qis__x__body(%Qubit*)
214
215 declare void @__quantum__rt__array_record_output(i64, i8*)
216
217 declare void @__quantum__rt__result_record_output(%Result*, i8*)
218
219 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
220
221 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="2" }
222 attributes #1 = { "irreversible" }
223
224 ; module flags
225
226 !llvm.module.flags = !{!0, !1, !2, !3}
227
228 !0 = !{i32 1, !"qir_major_version", i32 1}
229 !1 = !{i32 7, !"qir_minor_version", i32 0}
230 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
231 !3 = !{i32 1, !"dynamic_result_management", i1 false}
232 "#]].assert_eq(&qir);
233 }
234
235 #[test]
236 fn qubit_id_swap_results_in_different_id_usage() {
237 let source = "namespace Test {
238 @EntryPoint()
239 operation Main() : (Result, Result) {
240 use (q0, q1) = (Qubit(), Qubit());
241 X(q0);
242 Relabel([q0, q1], [q1, q0]);
243 X(q1);
244 (MResetZ(q0), MResetZ(q1))
245 }
246 }";
247 let qir = compile_source_to_qir(source, *CAPABILITIES);
248 expect![[r#"
249 %Result = type opaque
250 %Qubit = type opaque
251
252 define void @ENTRYPOINT__main() #0 {
253 block_0:
254 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
255 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
256 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
257 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
258 call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
259 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
260 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
261 ret void
262 }
263
264 declare void @__quantum__qis__x__body(%Qubit*)
265
266 declare void @__quantum__rt__tuple_record_output(i64, i8*)
267
268 declare void @__quantum__rt__result_record_output(%Result*, i8*)
269
270 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
271
272 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="2" }
273 attributes #1 = { "irreversible" }
274
275 ; module flags
276
277 !llvm.module.flags = !{!0, !1, !2, !3}
278
279 !0 = !{i32 1, !"qir_major_version", i32 1}
280 !1 = !{i32 7, !"qir_minor_version", i32 0}
281 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
282 !3 = !{i32 1, !"dynamic_result_management", i1 false}
283 "#]].assert_eq(&qir);
284 }
285
286 #[test]
287 fn qubit_id_swap_across_reset_uses_updated_ids() {
288 let source = "namespace Test {
289 @EntryPoint()
290 operation Main() : (Result, Result) {
291 {
292 use (q0, q1) = (Qubit(), Qubit());
293 X(q0);
294 Relabel([q0, q1], [q1, q0]);
295 X(q1);
296 Reset(q0);
297 Reset(q1);
298 }
299 use (q0, q1) = (Qubit(), Qubit());
300 (MResetZ(q0), MResetZ(q1))
301 }
302 }";
303 let qir = compile_source_to_qir(source, *CAPABILITIES);
304 expect![[r#"
305 %Result = type opaque
306 %Qubit = type opaque
307
308 define void @ENTRYPOINT__main() #0 {
309 block_0:
310 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
311 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
312 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
313 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
314 call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
315 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
316 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
317 ret void
318 }
319
320 declare void @__quantum__qis__x__body(%Qubit*)
321
322 declare void @__quantum__rt__tuple_record_output(i64, i8*)
323
324 declare void @__quantum__rt__result_record_output(%Result*, i8*)
325
326 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
327
328 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="4" "required_num_results"="2" }
329 attributes #1 = { "irreversible" }
330
331 ; module flags
332
333 !llvm.module.flags = !{!0, !1, !2, !3}
334
335 !0 = !{i32 1, !"qir_major_version", i32 1}
336 !1 = !{i32 7, !"qir_minor_version", i32 0}
337 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
338 !3 = !{i32 1, !"dynamic_result_management", i1 false}
339 "#]].assert_eq(&qir);
340 }
341}
342
343mod adaptive_profile {
344 use super::compile_source_to_qir;
345 use expect_test::expect;
346 use qsc_data_structures::target::TargetCapabilityFlags;
347 static CAPABILITIES: std::sync::LazyLock<TargetCapabilityFlags> =
348 std::sync::LazyLock::new(|| TargetCapabilityFlags::Adaptive);
349
350 #[test]
351 fn simple() {
352 let source = "namespace Test {
353 import Std.Math.*;
354 open QIR.Intrinsic;
355 @EntryPoint()
356 operation Main() : Result {
357 use q = Qubit();
358 let pi_over_two = 4.0 / 2.0;
359 __quantum__qis__rz__body(pi_over_two, q);
360 mutable some_angle = ArcSin(0.0);
361 __quantum__qis__rz__body(some_angle, q);
362 set some_angle = ArcCos(-1.0) / PI();
363 __quantum__qis__rz__body(some_angle, q);
364 __quantum__qis__mresetz__body(q)
365 }
366 }";
367 let qir = compile_source_to_qir(source, *CAPABILITIES);
368 expect![[r#"
369 %Result = type opaque
370 %Qubit = type opaque
371
372 define void @ENTRYPOINT__main() #0 {
373 block_0:
374 call void @__quantum__qis__rz__body(double 2.0, %Qubit* inttoptr (i64 0 to %Qubit*))
375 call void @__quantum__qis__rz__body(double 0.0, %Qubit* inttoptr (i64 0 to %Qubit*))
376 call void @__quantum__qis__rz__body(double 1.0, %Qubit* inttoptr (i64 0 to %Qubit*))
377 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
378 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
379 ret void
380 }
381
382 declare void @__quantum__qis__rz__body(double, %Qubit*)
383
384 declare void @__quantum__rt__result_record_output(%Result*, i8*)
385
386 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
387
388 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="1" }
389 attributes #1 = { "irreversible" }
390
391 ; module flags
392
393 !llvm.module.flags = !{!0, !1, !2, !3}
394
395 !0 = !{i32 1, !"qir_major_version", i32 1}
396 !1 = !{i32 7, !"qir_minor_version", i32 0}
397 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
398 !3 = !{i32 1, !"dynamic_result_management", i1 false}
399 "#]]
400 .assert_eq(&qir);
401 }
402
403 #[test]
404 fn qubit_reuse_triggers_reindexing() {
405 let source = "namespace Test {
406 @EntryPoint()
407 operation Main() : (Result, Result) {
408 use q = Qubit();
409 (MResetZ(q), MResetZ(q))
410 }
411 }";
412 let qir = compile_source_to_qir(source, *CAPABILITIES);
413 expect![[r#"
414 %Result = type opaque
415 %Qubit = type opaque
416
417 define void @ENTRYPOINT__main() #0 {
418 block_0:
419 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
420 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
421 call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
422 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
423 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
424 ret void
425 }
426
427 declare void @__quantum__rt__tuple_record_output(i64, i8*)
428
429 declare void @__quantum__rt__result_record_output(%Result*, i8*)
430
431 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
432
433 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="2" "required_num_results"="2" }
434 attributes #1 = { "irreversible" }
435
436 ; module flags
437
438 !llvm.module.flags = !{!0, !1, !2, !3}
439
440 !0 = !{i32 1, !"qir_major_version", i32 1}
441 !1 = !{i32 7, !"qir_minor_version", i32 0}
442 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
443 !3 = !{i32 1, !"dynamic_result_management", i1 false}
444 "#]].assert_eq(&qir);
445 }
446
447 #[test]
448 fn custom_measurement_generates_correct_qir() {
449 let source = "namespace Test {
450 operation Main() : Result {
451 use q = Qubit();
452 H(q);
453 __quantum__qis__mx__body(q)
454 }
455
456 @Measurement()
457 operation __quantum__qis__mx__body(target: Qubit) : Result {
458 body intrinsic;
459 }
460 }";
461 let qir = compile_source_to_qir(source, *CAPABILITIES);
462 expect![[r#"
463 %Result = type opaque
464 %Qubit = type opaque
465
466 define void @ENTRYPOINT__main() #0 {
467 block_0:
468 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*))
469 call void @__quantum__qis__mx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
470 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
471 ret void
472 }
473
474 declare void @__quantum__qis__h__body(%Qubit*)
475
476 declare void @__quantum__qis__mx__body(%Qubit*, %Result*) #1
477
478 declare void @__quantum__rt__result_record_output(%Result*, i8*)
479
480 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="1" }
481 attributes #1 = { "irreversible" }
482
483 ; module flags
484
485 !llvm.module.flags = !{!0, !1, !2, !3}
486
487 !0 = !{i32 1, !"qir_major_version", i32 1}
488 !1 = !{i32 7, !"qir_minor_version", i32 0}
489 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
490 !3 = !{i32 1, !"dynamic_result_management", i1 false}
491 "#]].assert_eq(&qir);
492 }
493
494 #[test]
495 fn custom_joint_measurement_generates_correct_qir() {
496 let source = "namespace Test {
497 operation Main() : (Result, Result) {
498 use q1 = Qubit();
499 use q2 = Qubit();
500 H(q1);
501 H(q2);
502 __quantum__qis__mzz__body(q1, q2)
503 }
504
505 @Measurement()
506 operation __quantum__qis__mzz__body(q1: Qubit, q2: Qubit) : (Result, Result) {
507 body intrinsic;
508 }
509 }";
510 let qir = compile_source_to_qir(source, *CAPABILITIES);
511 expect![[r#"
512 %Result = type opaque
513 %Qubit = type opaque
514
515 define void @ENTRYPOINT__main() #0 {
516 block_0:
517 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*))
518 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
519 call void @__quantum__qis__mzz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*), %Result* inttoptr (i64 1 to %Result*))
520 call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
521 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
522 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
523 ret void
524 }
525
526 declare void @__quantum__qis__h__body(%Qubit*)
527
528 declare void @__quantum__qis__mzz__body(%Qubit*, %Qubit*, %Result*, %Result*) #1
529
530 declare void @__quantum__rt__tuple_record_output(i64, i8*)
531
532 declare void @__quantum__rt__result_record_output(%Result*, i8*)
533
534 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="2" "required_num_results"="2" }
535 attributes #1 = { "irreversible" }
536
537 ; module flags
538
539 !llvm.module.flags = !{!0, !1, !2, !3}
540
541 !0 = !{i32 1, !"qir_major_version", i32 1}
542 !1 = !{i32 7, !"qir_minor_version", i32 0}
543 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
544 !3 = !{i32 1, !"dynamic_result_management", i1 false}
545 "#]].assert_eq(&qir);
546 }
547
548 #[test]
549 fn qubit_measurements_not_deferred() {
550 let source = "namespace Test {
551 @EntryPoint()
552 operation Main() : Result[] {
553 use (q0, q1) = (Qubit(), Qubit());
554 X(q0);
555 let r0 = MResetZ(q0);
556 X(q1);
557 let r1 = MResetZ(q1);
558 [r0, r1]
559 }
560 }";
561 let qir = compile_source_to_qir(source, *CAPABILITIES);
562 expect![[r#"
563 %Result = type opaque
564 %Qubit = type opaque
565
566 define void @ENTRYPOINT__main() #0 {
567 block_0:
568 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
569 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
570 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 1 to %Qubit*))
571 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
572 call void @__quantum__rt__array_record_output(i64 2, i8* null)
573 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
574 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
575 ret void
576 }
577
578 declare void @__quantum__qis__x__body(%Qubit*)
579
580 declare void @__quantum__rt__array_record_output(i64, i8*)
581
582 declare void @__quantum__rt__result_record_output(%Result*, i8*)
583
584 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
585
586 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="2" "required_num_results"="2" }
587 attributes #1 = { "irreversible" }
588
589 ; module flags
590
591 !llvm.module.flags = !{!0, !1, !2, !3}
592
593 !0 = !{i32 1, !"qir_major_version", i32 1}
594 !1 = !{i32 7, !"qir_minor_version", i32 0}
595 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
596 !3 = !{i32 1, !"dynamic_result_management", i1 false}
597 "#]].assert_eq(&qir);
598 }
599}
600
601mod adaptive_ri_profile {
602
603 use expect_test::expect;
604 use qsc_data_structures::target::TargetCapabilityFlags;
605
606 use super::compile_source_to_qir;
607 static CAPABILITIES: std::sync::LazyLock<TargetCapabilityFlags> =
608 std::sync::LazyLock::new(|| {
609 TargetCapabilityFlags::Adaptive
610 | TargetCapabilityFlags::QubitReset
611 | TargetCapabilityFlags::IntegerComputations
612 });
613
614 #[test]
615 fn simple() {
616 let source = "namespace Test {
617 import Std.Math.*;
618 open QIR.Intrinsic;
619 @EntryPoint()
620 operation Main() : Result {
621 use q = Qubit();
622 let pi_over_two = 4.0 / 2.0;
623 __quantum__qis__rz__body(pi_over_two, q);
624 mutable some_angle = ArcSin(0.0);
625 __quantum__qis__rz__body(some_angle, q);
626 set some_angle = ArcCos(-1.0) / PI();
627 __quantum__qis__rz__body(some_angle, q);
628 __quantum__qis__mresetz__body(q)
629 }
630 }";
631 let qir = compile_source_to_qir(source, *CAPABILITIES);
632 expect![[r#"
633 %Result = type opaque
634 %Qubit = type opaque
635
636 define void @ENTRYPOINT__main() #0 {
637 block_0:
638 call void @__quantum__qis__rz__body(double 2.0, %Qubit* inttoptr (i64 0 to %Qubit*))
639 call void @__quantum__qis__rz__body(double 0.0, %Qubit* inttoptr (i64 0 to %Qubit*))
640 call void @__quantum__qis__rz__body(double 1.0, %Qubit* inttoptr (i64 0 to %Qubit*))
641 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
642 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
643 ret void
644 }
645
646 declare void @__quantum__qis__rz__body(double, %Qubit*)
647
648 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
649
650 declare void @__quantum__rt__result_record_output(%Result*, i8*)
651
652 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="1" }
653 attributes #1 = { "irreversible" }
654
655 ; module flags
656
657 !llvm.module.flags = !{!0, !1, !2, !3, !4}
658
659 !0 = !{i32 1, !"qir_major_version", i32 1}
660 !1 = !{i32 7, !"qir_minor_version", i32 0}
661 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
662 !3 = !{i32 1, !"dynamic_result_management", i1 false}
663 !4 = !{i32 1, !"int_computations", !"i64"}
664 "#]]
665 .assert_eq(&qir);
666 }
667
668 #[test]
669 fn qubit_reuse_allowed() {
670 let source = "namespace Test {
671 @EntryPoint()
672 operation Main() : (Result, Result) {
673 use q = Qubit();
674 (MResetZ(q), MResetZ(q))
675 }
676 }";
677 let qir = compile_source_to_qir(source, *CAPABILITIES);
678 expect![[r#"
679 %Result = type opaque
680 %Qubit = type opaque
681
682 define void @ENTRYPOINT__main() #0 {
683 block_0:
684 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
685 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
686 call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
687 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
688 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
689 ret void
690 }
691
692 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
693
694 declare void @__quantum__rt__tuple_record_output(i64, i8*)
695
696 declare void @__quantum__rt__result_record_output(%Result*, i8*)
697
698 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="2" }
699 attributes #1 = { "irreversible" }
700
701 ; module flags
702
703 !llvm.module.flags = !{!0, !1, !2, !3, !4}
704
705 !0 = !{i32 1, !"qir_major_version", i32 1}
706 !1 = !{i32 7, !"qir_minor_version", i32 0}
707 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
708 !3 = !{i32 1, !"dynamic_result_management", i1 false}
709 !4 = !{i32 1, !"int_computations", !"i64"}
710 "#]].assert_eq(&qir);
711 }
712
713 #[test]
714 fn qubit_measurements_not_deferred() {
715 let source = "namespace Test {
716 @EntryPoint()
717 operation Main() : Result[] {
718 use (q0, q1) = (Qubit(), Qubit());
719 X(q0);
720 let r0 = MResetZ(q0);
721 X(q1);
722 let r1 = MResetZ(q1);
723 [r0, r1]
724 }
725 }";
726 let qir = compile_source_to_qir(source, *CAPABILITIES);
727 expect![[r#"
728 %Result = type opaque
729 %Qubit = type opaque
730
731 define void @ENTRYPOINT__main() #0 {
732 block_0:
733 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
734 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
735 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 1 to %Qubit*))
736 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
737 call void @__quantum__rt__array_record_output(i64 2, i8* null)
738 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
739 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
740 ret void
741 }
742
743 declare void @__quantum__qis__x__body(%Qubit*)
744
745 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
746
747 declare void @__quantum__rt__array_record_output(i64, i8*)
748
749 declare void @__quantum__rt__result_record_output(%Result*, i8*)
750
751 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="2" "required_num_results"="2" }
752 attributes #1 = { "irreversible" }
753
754 ; module flags
755
756 !llvm.module.flags = !{!0, !1, !2, !3, !4}
757
758 !0 = !{i32 1, !"qir_major_version", i32 1}
759 !1 = !{i32 7, !"qir_minor_version", i32 0}
760 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
761 !3 = !{i32 1, !"dynamic_result_management", i1 false}
762 !4 = !{i32 1, !"int_computations", !"i64"}
763 "#]].assert_eq(&qir);
764 }
765
766 #[test]
767 fn qubit_id_swap_results_in_different_id_usage() {
768 let source = "namespace Test {
769 @EntryPoint()
770 operation Main() : (Result, Result) {
771 use (q0, q1) = (Qubit(), Qubit());
772 X(q0);
773 Relabel([q0, q1], [q1, q0]);
774 X(q1);
775 (MResetZ(q0), MResetZ(q1))
776 }
777 }";
778 let qir = compile_source_to_qir(source, *CAPABILITIES);
779 expect![[r#"
780 %Result = type opaque
781 %Qubit = type opaque
782
783 define void @ENTRYPOINT__main() #0 {
784 block_0:
785 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
786 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
787 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
788 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
789 call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
790 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
791 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
792 ret void
793 }
794
795 declare void @__quantum__qis__x__body(%Qubit*)
796
797 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
798
799 declare void @__quantum__rt__tuple_record_output(i64, i8*)
800
801 declare void @__quantum__rt__result_record_output(%Result*, i8*)
802
803 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="2" "required_num_results"="2" }
804 attributes #1 = { "irreversible" }
805
806 ; module flags
807
808 !llvm.module.flags = !{!0, !1, !2, !3, !4}
809
810 !0 = !{i32 1, !"qir_major_version", i32 1}
811 !1 = !{i32 7, !"qir_minor_version", i32 0}
812 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
813 !3 = !{i32 1, !"dynamic_result_management", i1 false}
814 !4 = !{i32 1, !"int_computations", !"i64"}
815 "#]].assert_eq(&qir);
816 }
817
818 #[test]
819 fn qubit_id_swap_across_reset_uses_updated_ids() {
820 let source = "namespace Test {
821 @EntryPoint()
822 operation Main() : (Result, Result) {
823 {
824 use (q0, q1) = (Qubit(), Qubit());
825 X(q0);
826 Relabel([q0, q1], [q1, q0]);
827 X(q1);
828 Reset(q0);
829 Reset(q1);
830 }
831 use (q0, q1) = (Qubit(), Qubit());
832 (MResetZ(q0), MResetZ(q1))
833 }
834 }";
835 let qir = compile_source_to_qir(source, *CAPABILITIES);
836 expect![[r#"
837 %Result = type opaque
838 %Qubit = type opaque
839
840 define void @ENTRYPOINT__main() #0 {
841 block_0:
842 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
843 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
844 call void @__quantum__qis__reset__body(%Qubit* inttoptr (i64 1 to %Qubit*))
845 call void @__quantum__qis__reset__body(%Qubit* inttoptr (i64 0 to %Qubit*))
846 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
847 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
848 call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
849 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
850 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
851 ret void
852 }
853
854 declare void @__quantum__qis__x__body(%Qubit*)
855
856 declare void @__quantum__qis__reset__body(%Qubit*) #1
857
858 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
859
860 declare void @__quantum__rt__tuple_record_output(i64, i8*)
861
862 declare void @__quantum__rt__result_record_output(%Result*, i8*)
863
864 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="2" "required_num_results"="2" }
865 attributes #1 = { "irreversible" }
866
867 ; module flags
868
869 !llvm.module.flags = !{!0, !1, !2, !3, !4}
870
871 !0 = !{i32 1, !"qir_major_version", i32 1}
872 !1 = !{i32 7, !"qir_minor_version", i32 0}
873 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
874 !3 = !{i32 1, !"dynamic_result_management", i1 false}
875 !4 = !{i32 1, !"int_computations", !"i64"}
876 "#]].assert_eq(&qir);
877 }
878
879 #[test]
880 fn qubit_id_swap_with_out_of_order_release_uses_correct_ids() {
881 let source = "namespace Test {
882 @EntryPoint()
883 operation Main() : (Result, Result) {
884 let q0 = QIR.Runtime.__quantum__rt__qubit_allocate();
885 let q1 = QIR.Runtime.__quantum__rt__qubit_allocate();
886 let q2 = QIR.Runtime.__quantum__rt__qubit_allocate();
887 X(q0);
888 X(q1);
889 X(q2);
890 Relabel([q0, q1], [q1, q0]);
891 QIR.Runtime.__quantum__rt__qubit_release(q0);
892 let q3 = QIR.Runtime.__quantum__rt__qubit_allocate();
893 X(q3);
894 (MResetZ(q3), MResetZ(q1))
895 }
896 }";
897 let qir = compile_source_to_qir(source, *CAPABILITIES);
898 expect![[r#"
899 %Result = type opaque
900 %Qubit = type opaque
901
902 define void @ENTRYPOINT__main() #0 {
903 block_0:
904 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
905 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 1 to %Qubit*))
906 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 2 to %Qubit*))
907 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 1 to %Qubit*))
908 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
909 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
910 call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
911 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
912 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
913 ret void
914 }
915
916 declare void @__quantum__qis__x__body(%Qubit*)
917
918 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
919
920 declare void @__quantum__rt__tuple_record_output(i64, i8*)
921
922 declare void @__quantum__rt__result_record_output(%Result*, i8*)
923
924 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="3" "required_num_results"="2" }
925 attributes #1 = { "irreversible" }
926
927 ; module flags
928
929 !llvm.module.flags = !{!0, !1, !2, !3, !4}
930
931 !0 = !{i32 1, !"qir_major_version", i32 1}
932 !1 = !{i32 7, !"qir_minor_version", i32 0}
933 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
934 !3 = !{i32 1, !"dynamic_result_management", i1 false}
935 !4 = !{i32 1, !"int_computations", !"i64"}
936 "#]].assert_eq(&qir);
937 }
938
939 #[test]
940 fn dynamic_integer_with_branch_and_phi_supported() {
941 let source = "namespace Test {
942 @EntryPoint()
943 operation Main() : Int {
944 use q = Qubit();
945 H(q);
946 MResetZ(q) == Zero ? 0 | 1
947 }
948 }";
949 let qir = compile_source_to_qir(source, *CAPABILITIES);
950 expect![[r#"
951 %Result = type opaque
952 %Qubit = type opaque
953
954 define void @ENTRYPOINT__main() #0 {
955 block_0:
956 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*))
957 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
958 %var_0 = call i1 @__quantum__qis__read_result__body(%Result* inttoptr (i64 0 to %Result*))
959 %var_1 = icmp eq i1 %var_0, false
960 br i1 %var_1, label %block_1, label %block_2
961 block_1:
962 br label %block_3
963 block_2:
964 br label %block_3
965 block_3:
966 %var_4 = phi i64 [0, %block_1], [1, %block_2]
967 call void @__quantum__rt__int_record_output(i64 %var_4, i8* null)
968 ret void
969 }
970
971 declare void @__quantum__qis__h__body(%Qubit*)
972
973 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
974
975 declare i1 @__quantum__qis__read_result__body(%Result*)
976
977 declare void @__quantum__rt__int_record_output(i64, i8*)
978
979 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="1" }
980 attributes #1 = { "irreversible" }
981
982 ; module flags
983
984 !llvm.module.flags = !{!0, !1, !2, !3, !4}
985
986 !0 = !{i32 1, !"qir_major_version", i32 1}
987 !1 = !{i32 7, !"qir_minor_version", i32 0}
988 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
989 !3 = !{i32 1, !"dynamic_result_management", i1 false}
990 !4 = !{i32 1, !"int_computations", !"i64"}
991 "#]].assert_eq(&qir);
992 }
993
994 #[test]
995 fn custom_reset_generates_correct_qir() {
996 let source = "namespace Test {
997 operation Main() : Result {
998 use q = Qubit();
999 __quantum__qis__custom_reset__body(q);
1000 M(q)
1001 }
1002
1003 @Reset()
1004 operation __quantum__qis__custom_reset__body(target: Qubit) : Unit {
1005 body intrinsic;
1006 }
1007 }";
1008 let qir = compile_source_to_qir(source, *CAPABILITIES);
1009 expect![[r#"
1010 %Result = type opaque
1011 %Qubit = type opaque
1012
1013 define void @ENTRYPOINT__main() #0 {
1014 block_0:
1015 call void @__quantum__qis__custom_reset__body(%Qubit* inttoptr (i64 0 to %Qubit*))
1016 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
1017 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
1018 ret void
1019 }
1020
1021 declare void @__quantum__qis__custom_reset__body(%Qubit*) #1
1022
1023 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
1024
1025 declare void @__quantum__rt__result_record_output(%Result*, i8*)
1026
1027 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="1" }
1028 attributes #1 = { "irreversible" }
1029
1030 ; module flags
1031
1032 !llvm.module.flags = !{!0, !1, !2, !3, !4}
1033
1034 !0 = !{i32 1, !"qir_major_version", i32 1}
1035 !1 = !{i32 7, !"qir_minor_version", i32 0}
1036 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1037 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1038 !4 = !{i32 1, !"int_computations", !"i64"}
1039 "#]]
1040 .assert_eq(&qir);
1041 }
1042}
1043
1044mod adaptive_rif_profile {
1045 use super::compile_source_to_qir;
1046 use expect_test::expect;
1047 use qsc_data_structures::target::TargetCapabilityFlags;
1048 static CAPABILITIES: std::sync::LazyLock<TargetCapabilityFlags> =
1049 std::sync::LazyLock::new(|| {
1050 TargetCapabilityFlags::Adaptive
1051 | TargetCapabilityFlags::QubitReset
1052 | TargetCapabilityFlags::IntegerComputations
1053 | TargetCapabilityFlags::FloatingPointComputations
1054 });
1055
1056 #[test]
1057 fn simple() {
1058 let source = "namespace Test {
1059 import Std.Math.*;
1060 open QIR.Intrinsic;
1061 @EntryPoint()
1062 operation Main() : Result {
1063 use q = Qubit();
1064 let pi_over_two = 4.0 / 2.0;
1065 __quantum__qis__rz__body(pi_over_two, q);
1066 mutable some_angle = ArcSin(0.0);
1067 __quantum__qis__rz__body(some_angle, q);
1068 set some_angle = ArcCos(-1.0) / PI();
1069 __quantum__qis__rz__body(some_angle, q);
1070 __quantum__qis__mresetz__body(q)
1071 }
1072 }";
1073 let qir = compile_source_to_qir(source, *CAPABILITIES);
1074 expect![[r#"
1075 %Result = type opaque
1076 %Qubit = type opaque
1077
1078 define void @ENTRYPOINT__main() #0 {
1079 block_0:
1080 call void @__quantum__qis__rz__body(double 2.0, %Qubit* inttoptr (i64 0 to %Qubit*))
1081 call void @__quantum__qis__rz__body(double 0.0, %Qubit* inttoptr (i64 0 to %Qubit*))
1082 call void @__quantum__qis__rz__body(double 1.0, %Qubit* inttoptr (i64 0 to %Qubit*))
1083 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
1084 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
1085 ret void
1086 }
1087
1088 declare void @__quantum__qis__rz__body(double, %Qubit*)
1089
1090 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
1091
1092 declare void @__quantum__rt__result_record_output(%Result*, i8*)
1093
1094 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="1" }
1095 attributes #1 = { "irreversible" }
1096
1097 ; module flags
1098
1099 !llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
1100
1101 !0 = !{i32 1, !"qir_major_version", i32 1}
1102 !1 = !{i32 7, !"qir_minor_version", i32 0}
1103 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1104 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1105 !4 = !{i32 1, !"int_computations", !"i64"}
1106 !5 = !{i32 1, !"float_computations", !"f64"}
1107 "#]]
1108 .assert_eq(&qir);
1109 }
1110
1111 #[test]
1112 fn qubit_reuse_allowed() {
1113 let source = "namespace Test {
1114 @EntryPoint()
1115 operation Main() : (Result, Result) {
1116 use q = Qubit();
1117 (MResetZ(q), MResetZ(q))
1118 }
1119 }";
1120 let qir = compile_source_to_qir(source, *CAPABILITIES);
1121 expect![[r#"
1122 %Result = type opaque
1123 %Qubit = type opaque
1124
1125 define void @ENTRYPOINT__main() #0 {
1126 block_0:
1127 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
1128 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
1129 call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
1130 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
1131 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
1132 ret void
1133 }
1134
1135 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
1136
1137 declare void @__quantum__rt__tuple_record_output(i64, i8*)
1138
1139 declare void @__quantum__rt__result_record_output(%Result*, i8*)
1140
1141 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="2" }
1142 attributes #1 = { "irreversible" }
1143
1144 ; module flags
1145
1146 !llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
1147
1148 !0 = !{i32 1, !"qir_major_version", i32 1}
1149 !1 = !{i32 7, !"qir_minor_version", i32 0}
1150 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1151 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1152 !4 = !{i32 1, !"int_computations", !"i64"}
1153 !5 = !{i32 1, !"float_computations", !"f64"}
1154 "#]].assert_eq(&qir);
1155 }
1156
1157 #[test]
1158 fn qubit_measurements_not_deferred() {
1159 let source = "namespace Test {
1160 @EntryPoint()
1161 operation Main() : Result[] {
1162 use (q0, q1) = (Qubit(), Qubit());
1163 X(q0);
1164 let r0 = MResetZ(q0);
1165 X(q1);
1166 let r1 = MResetZ(q1);
1167 [r0, r1]
1168 }
1169 }";
1170 let qir = compile_source_to_qir(source, *CAPABILITIES);
1171 expect![[r#"
1172 %Result = type opaque
1173 %Qubit = type opaque
1174
1175 define void @ENTRYPOINT__main() #0 {
1176 block_0:
1177 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
1178 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
1179 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 1 to %Qubit*))
1180 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
1181 call void @__quantum__rt__array_record_output(i64 2, i8* null)
1182 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
1183 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
1184 ret void
1185 }
1186
1187 declare void @__quantum__qis__x__body(%Qubit*)
1188
1189 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
1190
1191 declare void @__quantum__rt__array_record_output(i64, i8*)
1192
1193 declare void @__quantum__rt__result_record_output(%Result*, i8*)
1194
1195 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="2" "required_num_results"="2" }
1196 attributes #1 = { "irreversible" }
1197
1198 ; module flags
1199
1200 !llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
1201
1202 !0 = !{i32 1, !"qir_major_version", i32 1}
1203 !1 = !{i32 7, !"qir_minor_version", i32 0}
1204 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1205 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1206 !4 = !{i32 1, !"int_computations", !"i64"}
1207 !5 = !{i32 1, !"float_computations", !"f64"}
1208 "#]].assert_eq(&qir);
1209 }
1210
1211 #[test]
1212 fn qubit_id_swap_results_in_different_id_usage() {
1213 let source = "namespace Test {
1214 @EntryPoint()
1215 operation Main() : (Result, Result) {
1216 use (q0, q1) = (Qubit(), Qubit());
1217 X(q0);
1218 Relabel([q0, q1], [q1, q0]);
1219 X(q1);
1220 (MResetZ(q0), MResetZ(q1))
1221 }
1222 }";
1223 let qir = compile_source_to_qir(source, *CAPABILITIES);
1224 expect![[r#"
1225 %Result = type opaque
1226 %Qubit = type opaque
1227
1228 define void @ENTRYPOINT__main() #0 {
1229 block_0:
1230 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
1231 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
1232 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
1233 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
1234 call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
1235 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
1236 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
1237 ret void
1238 }
1239
1240 declare void @__quantum__qis__x__body(%Qubit*)
1241
1242 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
1243
1244 declare void @__quantum__rt__tuple_record_output(i64, i8*)
1245
1246 declare void @__quantum__rt__result_record_output(%Result*, i8*)
1247
1248 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="2" "required_num_results"="2" }
1249 attributes #1 = { "irreversible" }
1250
1251 ; module flags
1252
1253 !llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
1254
1255 !0 = !{i32 1, !"qir_major_version", i32 1}
1256 !1 = !{i32 7, !"qir_minor_version", i32 0}
1257 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1258 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1259 !4 = !{i32 1, !"int_computations", !"i64"}
1260 !5 = !{i32 1, !"float_computations", !"f64"}
1261 "#]].assert_eq(&qir);
1262 }
1263
1264 #[test]
1265 fn qubit_id_swap_across_reset_uses_updated_ids() {
1266 let source = "namespace Test {
1267 @EntryPoint()
1268 operation Main() : (Result, Result) {
1269 {
1270 use (q0, q1) = (Qubit(), Qubit());
1271 X(q0);
1272 Relabel([q0, q1], [q1, q0]);
1273 X(q1);
1274 Reset(q0);
1275 Reset(q1);
1276 }
1277 use (q0, q1) = (Qubit(), Qubit());
1278 (MResetZ(q0), MResetZ(q1))
1279 }
1280 }";
1281 let qir = compile_source_to_qir(source, *CAPABILITIES);
1282 expect![[r#"
1283 %Result = type opaque
1284 %Qubit = type opaque
1285
1286 define void @ENTRYPOINT__main() #0 {
1287 block_0:
1288 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
1289 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
1290 call void @__quantum__qis__reset__body(%Qubit* inttoptr (i64 1 to %Qubit*))
1291 call void @__quantum__qis__reset__body(%Qubit* inttoptr (i64 0 to %Qubit*))
1292 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
1293 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
1294 call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
1295 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
1296 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
1297 ret void
1298 }
1299
1300 declare void @__quantum__qis__x__body(%Qubit*)
1301
1302 declare void @__quantum__qis__reset__body(%Qubit*) #1
1303
1304 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
1305
1306 declare void @__quantum__rt__tuple_record_output(i64, i8*)
1307
1308 declare void @__quantum__rt__result_record_output(%Result*, i8*)
1309
1310 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="2" "required_num_results"="2" }
1311 attributes #1 = { "irreversible" }
1312
1313 ; module flags
1314
1315 !llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
1316
1317 !0 = !{i32 1, !"qir_major_version", i32 1}
1318 !1 = !{i32 7, !"qir_minor_version", i32 0}
1319 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1320 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1321 !4 = !{i32 1, !"int_computations", !"i64"}
1322 !5 = !{i32 1, !"float_computations", !"f64"}
1323 "#]].assert_eq(&qir);
1324 }
1325
1326 #[test]
1327 fn qubit_id_swap_with_out_of_order_release_uses_correct_ids() {
1328 let source = "namespace Test {
1329 @EntryPoint()
1330 operation Main() : (Result, Result) {
1331 let q0 = QIR.Runtime.__quantum__rt__qubit_allocate();
1332 let q1 = QIR.Runtime.__quantum__rt__qubit_allocate();
1333 let q2 = QIR.Runtime.__quantum__rt__qubit_allocate();
1334 X(q0);
1335 X(q1);
1336 X(q2);
1337 Relabel([q0, q1], [q1, q0]);
1338 QIR.Runtime.__quantum__rt__qubit_release(q0);
1339 let q3 = QIR.Runtime.__quantum__rt__qubit_allocate();
1340 X(q3);
1341 (MResetZ(q3), MResetZ(q1))
1342 }
1343 }";
1344 let qir = compile_source_to_qir(source, *CAPABILITIES);
1345 expect![[r#"
1346 %Result = type opaque
1347 %Qubit = type opaque
1348
1349 define void @ENTRYPOINT__main() #0 {
1350 block_0:
1351 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
1352 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 1 to %Qubit*))
1353 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 2 to %Qubit*))
1354 call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 1 to %Qubit*))
1355 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
1356 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
1357 call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
1358 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
1359 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
1360 ret void
1361 }
1362
1363 declare void @__quantum__qis__x__body(%Qubit*)
1364
1365 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
1366
1367 declare void @__quantum__rt__tuple_record_output(i64, i8*)
1368
1369 declare void @__quantum__rt__result_record_output(%Result*, i8*)
1370
1371 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="3" "required_num_results"="2" }
1372 attributes #1 = { "irreversible" }
1373
1374 ; module flags
1375
1376 !llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
1377
1378 !0 = !{i32 1, !"qir_major_version", i32 1}
1379 !1 = !{i32 7, !"qir_minor_version", i32 0}
1380 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1381 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1382 !4 = !{i32 1, !"int_computations", !"i64"}
1383 !5 = !{i32 1, !"float_computations", !"f64"}
1384 "#]].assert_eq(&qir);
1385 }
1386
1387 #[test]
1388 fn dynamic_integer_with_branch_and_phi_supported() {
1389 let source = "namespace Test {
1390 @EntryPoint()
1391 operation Main() : Int {
1392 use q = Qubit();
1393 H(q);
1394 MResetZ(q) == Zero ? 0 | 1
1395 }
1396 }";
1397 let qir = compile_source_to_qir(source, *CAPABILITIES);
1398 expect![[r#"
1399 %Result = type opaque
1400 %Qubit = type opaque
1401
1402 define void @ENTRYPOINT__main() #0 {
1403 block_0:
1404 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*))
1405 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
1406 %var_0 = call i1 @__quantum__qis__read_result__body(%Result* inttoptr (i64 0 to %Result*))
1407 %var_1 = icmp eq i1 %var_0, false
1408 br i1 %var_1, label %block_1, label %block_2
1409 block_1:
1410 br label %block_3
1411 block_2:
1412 br label %block_3
1413 block_3:
1414 %var_4 = phi i64 [0, %block_1], [1, %block_2]
1415 call void @__quantum__rt__int_record_output(i64 %var_4, i8* null)
1416 ret void
1417 }
1418
1419 declare void @__quantum__qis__h__body(%Qubit*)
1420
1421 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
1422
1423 declare i1 @__quantum__qis__read_result__body(%Result*)
1424
1425 declare void @__quantum__rt__int_record_output(i64, i8*)
1426
1427 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="1" }
1428 attributes #1 = { "irreversible" }
1429
1430 ; module flags
1431
1432 !llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
1433
1434 !0 = !{i32 1, !"qir_major_version", i32 1}
1435 !1 = !{i32 7, !"qir_minor_version", i32 0}
1436 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1437 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1438 !4 = !{i32 1, !"int_computations", !"i64"}
1439 !5 = !{i32 1, !"float_computations", !"f64"}
1440 "#]].assert_eq(&qir);
1441 }
1442
1443 #[test]
1444 fn dynamic_double_with_branch_and_phi_supported() {
1445 let source = "namespace Test {
1446 @EntryPoint()
1447 operation Main() : Double {
1448 use q = Qubit();
1449 H(q);
1450 MResetZ(q) == Zero ? 0.0 | 1.0
1451 }
1452 }";
1453 let qir = compile_source_to_qir(source, *CAPABILITIES);
1454 expect![[r#"
1455 %Result = type opaque
1456 %Qubit = type opaque
1457
1458 define void @ENTRYPOINT__main() #0 {
1459 block_0:
1460 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*))
1461 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
1462 %var_0 = call i1 @__quantum__qis__read_result__body(%Result* inttoptr (i64 0 to %Result*))
1463 %var_1 = icmp eq i1 %var_0, false
1464 br i1 %var_1, label %block_1, label %block_2
1465 block_1:
1466 br label %block_3
1467 block_2:
1468 br label %block_3
1469 block_3:
1470 %var_4 = phi double [0.0, %block_1], [1.0, %block_2]
1471 call void @__quantum__rt__double_record_output(double %var_4, i8* null)
1472 ret void
1473 }
1474
1475 declare void @__quantum__qis__h__body(%Qubit*)
1476
1477 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
1478
1479 declare i1 @__quantum__qis__read_result__body(%Result*)
1480
1481 declare void @__quantum__rt__double_record_output(double, i8*)
1482
1483 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="1" }
1484 attributes #1 = { "irreversible" }
1485
1486 ; module flags
1487
1488 !llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
1489
1490 !0 = !{i32 1, !"qir_major_version", i32 1}
1491 !1 = !{i32 7, !"qir_minor_version", i32 0}
1492 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1493 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1494 !4 = !{i32 1, !"int_computations", !"i64"}
1495 !5 = !{i32 1, !"float_computations", !"f64"}
1496 "#]].assert_eq(&qir);
1497 }
1498
1499 #[test]
1500 fn custom_reset_generates_correct_qir() {
1501 let source = "namespace Test {
1502 operation Main() : Result {
1503 use q = Qubit();
1504 __quantum__qis__custom_reset__body(q);
1505 M(q)
1506 }
1507
1508 @Reset()
1509 operation __quantum__qis__custom_reset__body(target: Qubit) : Unit {
1510 body intrinsic;
1511 }
1512 }";
1513 let qir = compile_source_to_qir(source, *CAPABILITIES);
1514 expect![[r#"
1515 %Result = type opaque
1516 %Qubit = type opaque
1517
1518 define void @ENTRYPOINT__main() #0 {
1519 block_0:
1520 call void @__quantum__qis__custom_reset__body(%Qubit* inttoptr (i64 0 to %Qubit*))
1521 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
1522 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
1523 ret void
1524 }
1525
1526 declare void @__quantum__qis__custom_reset__body(%Qubit*) #1
1527
1528 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
1529
1530 declare void @__quantum__rt__result_record_output(%Result*, i8*)
1531
1532 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="1" }
1533 attributes #1 = { "irreversible" }
1534
1535 ; module flags
1536
1537 !llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
1538
1539 !0 = !{i32 1, !"qir_major_version", i32 1}
1540 !1 = !{i32 7, !"qir_minor_version", i32 0}
1541 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1542 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1543 !4 = !{i32 1, !"int_computations", !"i64"}
1544 !5 = !{i32 1, !"float_computations", !"f64"}
1545 "#]]
1546 .assert_eq(&qir);
1547 }
1548
1549 #[test]
1550 fn dynamic_double_intrinsic() {
1551 let source = "namespace Test {
1552 operation OpA(theta: Double, q : Qubit) : Unit { body intrinsic; }
1553 @EntryPoint()
1554 operation Main() : Double {
1555 use q = Qubit();
1556 H(q);
1557 let theta = MResetZ(q) == Zero ? 0.0 | 1.0;
1558 OpA(1.0 + theta, q);
1559 Rx(2.0 * theta, q);
1560 Ry(theta / 3.0, q);
1561 Rz(theta - 4.0, q);
1562 OpA(theta, q);
1563 Rx(theta, q);
1564 theta
1565 }
1566 }";
1567 let qir = compile_source_to_qir(source, *CAPABILITIES);
1568 expect![[r#"
1569 %Result = type opaque
1570 %Qubit = type opaque
1571
1572 define void @ENTRYPOINT__main() #0 {
1573 block_0:
1574 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*))
1575 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
1576 %var_0 = call i1 @__quantum__qis__read_result__body(%Result* inttoptr (i64 0 to %Result*))
1577 %var_1 = icmp eq i1 %var_0, false
1578 br i1 %var_1, label %block_1, label %block_2
1579 block_1:
1580 br label %block_3
1581 block_2:
1582 br label %block_3
1583 block_3:
1584 %var_9 = phi double [0.0, %block_1], [1.0, %block_2]
1585 %var_4 = fadd double 1.0, %var_9
1586 call void @OpA(double %var_4, %Qubit* inttoptr (i64 0 to %Qubit*))
1587 %var_5 = fmul double 2.0, %var_9
1588 call void @__quantum__qis__rx__body(double %var_5, %Qubit* inttoptr (i64 0 to %Qubit*))
1589 %var_6 = fdiv double %var_9, 3.0
1590 call void @__quantum__qis__ry__body(double %var_6, %Qubit* inttoptr (i64 0 to %Qubit*))
1591 %var_7 = fsub double %var_9, 4.0
1592 call void @__quantum__qis__rz__body(double %var_7, %Qubit* inttoptr (i64 0 to %Qubit*))
1593 call void @OpA(double %var_9, %Qubit* inttoptr (i64 0 to %Qubit*))
1594 call void @__quantum__qis__rx__body(double %var_9, %Qubit* inttoptr (i64 0 to %Qubit*))
1595 call void @__quantum__rt__double_record_output(double %var_9, i8* null)
1596 ret void
1597 }
1598
1599 declare void @__quantum__qis__h__body(%Qubit*)
1600
1601 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
1602
1603 declare i1 @__quantum__qis__read_result__body(%Result*)
1604
1605 declare void @OpA(double, %Qubit*)
1606
1607 declare void @__quantum__qis__rx__body(double, %Qubit*)
1608
1609 declare void @__quantum__qis__ry__body(double, %Qubit*)
1610
1611 declare void @__quantum__qis__rz__body(double, %Qubit*)
1612
1613 declare void @__quantum__rt__double_record_output(double, i8*)
1614
1615 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="1" }
1616 attributes #1 = { "irreversible" }
1617
1618 ; module flags
1619
1620 !llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
1621
1622 !0 = !{i32 1, !"qir_major_version", i32 1}
1623 !1 = !{i32 7, !"qir_minor_version", i32 0}
1624 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1625 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1626 !4 = !{i32 1, !"int_computations", !"i64"}
1627 !5 = !{i32 1, !"float_computations", !"f64"}
1628 "#]].assert_eq(&qir);
1629 }
1630}
1631