QIR Generation with Q# Using Magic Commands
QIR Generation with Q# Using Magic Commands#
In this example, QIR is generated from Q# code for teleportation to transfer the binary representation of “hello world!”, followed with ASCII decoding. Teleportation technique contains heterogeneous instructions at the compilation time. The interdependent conditionals following the measurement of the source and the auxiliary qubits in teleportation determine the next quantum gate operations on the target qubit.
Computations involving heterogeneous instructions at compile time can benefit from QIR enabled compilers. QIR is generated in LLVM, which is backed by decades of classical compilation research and development. Hybrid quantum algorithms were defined to rely on both classical and quantum resources to fulfill the abstract computational model of the algorithm. In the next series of tutorials, a hybrid classical-quantum algorithm such as VQE or HHL (?) will be used to demonstrate further capabilities of QIR.
// Building on https://github.com/microsoft/Quantum/blob/main/samples/getting-started/teleportation/TeleportationSample.qs
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Measurement;
open Microsoft.Quantum.Core;
open Microsoft.Quantum.Arrays;
// Converts data type: int to bool
operation int2bool(bit: Int) : Bool {
if (bit == 1){return true;}
else {return false;}
}
// Converts data type: bool to int
operation bool2int(msg: Bool) : Int {
if (msg == true){return 1;}
else {return 0;}
}
// Pure quantum section of teleportation technique
operation Teleport (msg : Qubit, target : Qubit) : Unit {
use register = Qubit();
H(register);
CNOT(register, target);
CNOT(msg, register);
H(msg);
if (MResetZ(msg) == One) { Z(target); }
if (IsResultOne(MResetZ(register))) { X(target); }
}
// Interdependent conditional section of teleportation technique
operation TeleportClassicalMessage (message : Bool) : Bool {
use (msg, target) = (Qubit(), Qubit());
if (message) {
X(msg);
}
Teleport(msg, target);
return MResetZ(target) == One;
}
- int2bool
- bool2int
- Teleport
- TeleportClassicalMessage
// Runs teleporation with 2 loops: classical and hetrogenous
operation Greetings() : Unit {
mutable binary=[1, 0, 1, 0, 0];
let msg = ForEach(int2bool, binary);
let transferred= ForEach(TeleportClassicalMessage, msg);
for index in 0 .. Length(transferred)-1 {
Message($"{transferred[index]}");
}
}
- Greetings
%simulate Greetings
True
False
True
False
False
()
%qir Greetings
; ModuleID = '/tmp/tmpejydWC.bc'
%Tuple = type opaque
%Array = type opaque
%Callable = type opaque
%String = type opaque
%Qubit = type opaque
%Result = type opaque
@SNIPPET__int2bool__FunctionTable = internal constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @SNIPPET__int2bool__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null]
@SNIPPET__TeleportClassicalMessage__FunctionTable = internal constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @SNIPPET__TeleportClassicalMessage__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null]
@0 = internal constant [5 x i8] c"true\00"
@1 = internal constant [6 x i8] c"false\00"
@2 = internal constant [3 x i8] c"()\00"
define internal void @ENTRYPOINT__Greetings__body() {
entry:
call void @SNIPPET__Greetings__body()
ret void
}
define internal void @SNIPPET__Greetings__body() {
entry:
%binary = alloca %Array*, align 8
%0 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 5)
%1 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %0, i64 0)
%2 = bitcast i8* %1 to i64*
%3 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %0, i64 1)
%4 = bitcast i8* %3 to i64*
%5 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %0, i64 2)
%6 = bitcast i8* %5 to i64*
%7 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %0, i64 3)
%8 = bitcast i8* %7 to i64*
%9 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %0, i64 4)
%10 = bitcast i8* %9 to i64*
store i64 1, i64* %2, align 4
store i64 0, i64* %4, align 4
store i64 1, i64* %6, align 4
store i64 0, i64* %8, align 4
store i64 0, i64* %10, align 4
store %Array* %0, %Array** %binary, align 8
call void @__quantum__rt__array_update_alias_count(%Array* %0, i32 1)
%11 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @SNIPPET__int2bool__FunctionTable, [2 x void (%Tuple*, i32)*]* null, %Tuple* null)
%msg = call %Array* @Microsoft__Quantum__Arrays___35562116677345e0944256b6d342d497_ForEach__body(%Callable* %11, %Array* %0)
call void @__quantum__rt__array_update_alias_count(%Array* %msg, i32 1)
%12 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @SNIPPET__TeleportClassicalMessage__FunctionTable, [2 x void (%Tuple*, i32)*]* null, %Tuple* null)
%transferred = call %Array* @Microsoft__Quantum__Arrays___64c6375bfc954430924edecdbdf36db0_ForEach__body(%Callable* %12, %Array* %msg)
call void @__quantum__rt__array_update_alias_count(%Array* %transferred, i32 1)
%13 = call i64 @__quantum__rt__array_get_size_1d(%Array* %transferred)
%14 = sub i64 %13, 1
br label %header__1
header__1: ; preds = %exiting__1, %entry
%index = phi i64 [ 0, %entry ], [ %22, %exiting__1 ]
%15 = icmp sle i64 %index, %14
br i1 %15, label %body__1, label %exit__1
body__1: ; preds = %header__1
%16 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %transferred, i64 %index)
%17 = bitcast i8* %16 to i1*
%18 = load i1, i1* %17, align 1
br i1 %18, label %condTrue__1, label %condFalse__1
condTrue__1: ; preds = %body__1
%19 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @0, i32 0, i32 0))
br label %condContinue__1
condFalse__1: ; preds = %body__1
%20 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @1, i32 0, i32 0))
br label %condContinue__1
condContinue__1: ; preds = %condFalse__1, %condTrue__1
%21 = phi %String* [ %19, %condTrue__1 ], [ %20, %condFalse__1 ]
call void @__quantum__rt__message(%String* %21)
call void @__quantum__rt__string_update_reference_count(%String* %21, i32 -1)
br label %exiting__1
exiting__1: ; preds = %condContinue__1
%22 = add i64 %index, 1
br label %header__1
exit__1: ; preds = %header__1
call void @__quantum__rt__array_update_alias_count(%Array* %0, i32 -1)
call void @__quantum__rt__array_update_alias_count(%Array* %msg, i32 -1)
call void @__quantum__rt__array_update_alias_count(%Array* %transferred, i32 -1)
call void @__quantum__rt__capture_update_reference_count(%Callable* %11, i32 -1)
call void @__quantum__rt__callable_update_reference_count(%Callable* %11, i32 -1)
call void @__quantum__rt__array_update_reference_count(%Array* %msg, i32 -1)
call void @__quantum__rt__capture_update_reference_count(%Callable* %12, i32 -1)
call void @__quantum__rt__callable_update_reference_count(%Callable* %12, i32 -1)
call void @__quantum__rt__array_update_reference_count(%Array* %transferred, i32 -1)
call void @__quantum__rt__array_update_reference_count(%Array* %0, i32 -1)
ret void
}
define internal void @Microsoft__Quantum__Intrinsic__CNOT__body(%Qubit* %control, %Qubit* %target) {
entry:
%__controlQubits__ = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1)
%0 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %__controlQubits__, i64 0)
%1 = bitcast i8* %0 to %Qubit**
store %Qubit* %control, %Qubit** %1, align 8
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1)
call void @__quantum__qis__x__ctl(%Array* %__controlQubits__, %Qubit* %target)
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1)
call void @__quantum__rt__array_update_reference_count(%Array* %__controlQubits__, i32 -1)
ret void
}
declare %Array* @__quantum__rt__array_create_1d(i32, i64)
declare i8* @__quantum__rt__array_get_element_ptr_1d(%Array*, i64)
declare void @__quantum__rt__array_update_alias_count(%Array*, i32)
declare void @__quantum__qis__x__ctl(%Array*, %Qubit*)
declare void @__quantum__rt__array_update_reference_count(%Array*, i32)
define internal void @Microsoft__Quantum__Intrinsic__CNOT__adj(%Qubit* %control, %Qubit* %target) {
entry:
call void @Microsoft__Quantum__Intrinsic__CNOT__body(%Qubit* %control, %Qubit* %target)
ret void
}
define internal void @Microsoft__Quantum__Intrinsic__CNOT__ctl(%Array* %__controlQubits__, { %Qubit*, %Qubit* }* %0) {
entry:
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1)
%1 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 0
%control = load %Qubit*, %Qubit** %1, align 8
%2 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 1
%target = load %Qubit*, %Qubit** %2, align 8
%3 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1)
%4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %3, i64 0)
%5 = bitcast i8* %4 to %Qubit**
store %Qubit* %control, %Qubit** %5, align 8
%__controlQubits__1 = call %Array* @__quantum__rt__array_concatenate(%Array* %__controlQubits__, %Array* %3)
call void @__quantum__rt__array_update_reference_count(%Array* %__controlQubits__1, i32 1)
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__1, i32 1)
call void @__quantum__qis__x__ctl(%Array* %__controlQubits__1, %Qubit* %target)
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__1, i32 -1)
call void @__quantum__rt__array_update_reference_count(%Array* %3, i32 -1)
call void @__quantum__rt__array_update_reference_count(%Array* %__controlQubits__1, i32 -1)
call void @__quantum__rt__array_update_reference_count(%Array* %__controlQubits__1, i32 -1)
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1)
ret void
}
declare %Array* @__quantum__rt__array_concatenate(%Array*, %Array*)
define internal void @Microsoft__Quantum__Intrinsic__CNOT__ctladj(%Array* %__controlQubits__, { %Qubit*, %Qubit* }* %0) {
entry:
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1)
%1 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 0
%control = load %Qubit*, %Qubit** %1, align 8
%2 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 1
%target = load %Qubit*, %Qubit** %2, align 8
%3 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ %Qubit*, %Qubit* }* getelementptr ({ %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* null, i32 1) to i64))
%4 = bitcast %Tuple* %3 to { %Qubit*, %Qubit* }*
%5 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %4, i32 0, i32 0
%6 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %4, i32 0, i32 1
store %Qubit* %control, %Qubit** %5, align 8
store %Qubit* %target, %Qubit** %6, align 8
call void @Microsoft__Quantum__Intrinsic__CNOT__ctl(%Array* %__controlQubits__, { %Qubit*, %Qubit* }* %4)
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1)
call void @__quantum__rt__tuple_update_reference_count(%Tuple* %3, i32 -1)
ret void
}
declare %Tuple* @__quantum__rt__tuple_create(i64)
declare void @__quantum__rt__tuple_update_reference_count(%Tuple*, i32)
define internal void @Microsoft__Quantum__Intrinsic__H__body(%Qubit* %qubit) {
entry:
call void @__quantum__qis__h__body(%Qubit* %qubit)
ret void
}
declare void @__quantum__qis__h__body(%Qubit*)
define internal void @Microsoft__Quantum__Intrinsic__H__adj(%Qubit* %qubit) {
entry:
call void @__quantum__qis__h__body(%Qubit* %qubit)
ret void
}
define internal void @Microsoft__Quantum__Intrinsic__H__ctl(%Array* %__controlQubits__, %Qubit* %qubit) {
entry:
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1)
call void @__quantum__qis__h__ctl(%Array* %__controlQubits__, %Qubit* %qubit)
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1)
ret void
}
declare void @__quantum__qis__h__ctl(%Array*, %Qubit*)
define internal void @Microsoft__Quantum__Intrinsic__H__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) {
entry:
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1)
call void @__quantum__qis__h__ctl(%Array* %__controlQubits__, %Qubit* %qubit)
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1)
ret void
}
define internal %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %qubit) {
entry:
%bases = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 1)
%0 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %bases, i64 0)
%1 = bitcast i8* %0 to i2*
store i2 -2, i2* %1, align 1
call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 1)
%qubits = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1)
%2 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qubits, i64 0)
%3 = bitcast i8* %2 to %Qubit**
store %Qubit* %qubit, %Qubit** %3, align 8
call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1)
%4 = call %Result* @__quantum__qis__measure__body(%Array* %bases, %Array* %qubits)
call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 -1)
call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1)
call void @__quantum__rt__array_update_reference_count(%Array* %bases, i32 -1)
call void @__quantum__rt__array_update_reference_count(%Array* %qubits, i32 -1)
ret %Result* %4
}
declare %Result* @__quantum__qis__measure__body(%Array*, %Array*)
define internal %Result* @Microsoft__Quantum__Intrinsic__Measure__body(%Array* %bases, %Array* %qubits) {
entry:
call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 1)
call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1)
%0 = call %Result* @__quantum__qis__measure__body(%Array* %bases, %Array* %qubits)
call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 -1)
call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1)
ret %Result* %0
}
define internal void @Microsoft__Quantum__Intrinsic__X__body(%Qubit* %qubit) {
entry:
call void @__quantum__qis__x__body(%Qubit* %qubit)
ret void
}
declare void @__quantum__qis__x__body(%Qubit*)
define internal void @Microsoft__Quantum__Intrinsic__X__adj(%Qubit* %qubit) {
entry:
call void @__quantum__qis__x__body(%Qubit* %qubit)
ret void
}
define internal void @Microsoft__Quantum__Intrinsic__X__ctl(%Array* %__controlQubits__, %Qubit* %qubit) {
entry:
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1)
call void @__quantum__qis__x__ctl(%Array* %__controlQubits__, %Qubit* %qubit)
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1)
ret void
}
define internal void @Microsoft__Quantum__Intrinsic__X__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) {
entry:
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1)
call void @__quantum__qis__x__ctl(%Array* %__controlQubits__, %Qubit* %qubit)
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1)
ret void
}
define internal void @Microsoft__Quantum__Intrinsic__Z__body(%Qubit* %qubit) {
entry:
call void @__quantum__qis__z__body(%Qubit* %qubit)
ret void
}
declare void @__quantum__qis__z__body(%Qubit*)
define internal void @Microsoft__Quantum__Intrinsic__Z__adj(%Qubit* %qubit) {
entry:
call void @__quantum__qis__z__body(%Qubit* %qubit)
ret void
}
define internal void @Microsoft__Quantum__Intrinsic__Z__ctl(%Array* %__controlQubits__, %Qubit* %qubit) {
entry:
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1)
call void @__quantum__qis__z__ctl(%Array* %__controlQubits__, %Qubit* %qubit)
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1)
ret void
}
declare void @__quantum__qis__z__ctl(%Array*, %Qubit*)
define internal void @Microsoft__Quantum__Intrinsic__Z__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) {
entry:
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1)
call void @__quantum__qis__z__ctl(%Array* %__controlQubits__, %Qubit* %qubit)
call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1)
ret void
}
define internal %Result* @Microsoft__Quantum__Measurement__MResetZ__body(%Qubit* %target) {
entry:
%result = call %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %target)
%0 = call %Result* @__quantum__rt__result_get_one()
%1 = call i1 @__quantum__rt__result_equal(%Result* %result, %Result* %0)
br i1 %1, label %then0__1, label %continue__1
then0__1: ; preds = %entry
call void @__quantum__qis__x__body(%Qubit* %target)
br label %continue__1
continue__1: ; preds = %then0__1, %entry
ret %Result* %result
}
declare %Result* @__quantum__rt__result_get_one()
declare i1 @__quantum__rt__result_equal(%Result*, %Result*)
define internal %Array* @Microsoft__Quantum__Arrays___35562116677345e0944256b6d342d497_ForEach__body(%Callable* %action, %Array* %array) {
entry:
%retval = alloca %Array*, align 8
call void @__quantum__rt__capture_update_alias_count(%Callable* %action, i32 1)
call void @__quantum__rt__callable_update_alias_count(%Callable* %action, i32 1)
call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1)
%length = call i64 @__quantum__rt__array_get_size_1d(%Array* %array)
%0 = icmp eq i64 %length, 0
br i1 %0, label %then0__1, label %continue__1
then0__1: ; preds = %entry
%1 = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 0)
call void @__quantum__rt__capture_update_alias_count(%Callable* %action, i32 -1)
call void @__quantum__rt__callable_update_alias_count(%Callable* %action, i32 -1)
call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1)
ret %Array* %1
continue__1: ; preds = %entry
%2 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 0)
%3 = bitcast i8* %2 to i64*
%4 = load i64, i64* %3, align 4
%5 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i64 }* getelementptr ({ i64 }, { i64 }* null, i32 1) to i64))
%6 = bitcast %Tuple* %5 to { i64 }*
%7 = getelementptr inbounds { i64 }, { i64 }* %6, i32 0, i32 0
store i64 %4, i64* %7, align 4
%8 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i1 }* getelementptr ({ i1 }, { i1 }* null, i32 1) to i64))
call void @__quantum__rt__callable_invoke(%Callable* %action, %Tuple* %5, %Tuple* %8)
%9 = bitcast %Tuple* %8 to { i1 }*
%10 = getelementptr inbounds { i1 }, { i1 }* %9, i32 0, i32 0
%first = load i1, i1* %10, align 1
%11 = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 %length)
%12 = sub i64 %length, 1
br label %header__1
header__1: ; preds = %exiting__1, %continue__1
%13 = phi i64 [ 0, %continue__1 ], [ %17, %exiting__1 ]
%14 = icmp sle i64 %13, %12
br i1 %14, label %body__1, label %exit__1
body__1: ; preds = %header__1
%15 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %11, i64 %13)
%16 = bitcast i8* %15 to i1*
store i1 %first, i1* %16, align 1
br label %exiting__1
exiting__1: ; preds = %body__1
%17 = add i64 %13, 1
br label %header__1
exit__1: ; preds = %header__1
store %Array* %11, %Array** %retval, align 8
call void @__quantum__rt__array_update_alias_count(%Array* %11, i32 1)
%18 = sub i64 %length, 1
br label %header__2
header__2: ; preds = %exiting__2, %exit__1
%idx = phi i64 [ 1, %exit__1 ], [ %34, %exiting__2 ]
%19 = icmp sle i64 %idx, %18
br i1 %19, label %body__2, label %exit__2
body__2: ; preds = %header__2
%20 = load %Array*, %Array** %retval, align 8
call void @__quantum__rt__array_update_alias_count(%Array* %20, i32 -1)
%21 = call %Array* @__quantum__rt__array_copy(%Array* %20, i1 false)
%22 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %idx)
%23 = bitcast i8* %22 to i64*
%24 = load i64, i64* %23, align 4
%25 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i64 }* getelementptr ({ i64 }, { i64 }* null, i32 1) to i64))
%26 = bitcast %Tuple* %25 to { i64 }*
%27 = getelementptr inbounds { i64 }, { i64 }* %26, i32 0, i32 0
store i64 %24, i64* %27, align 4
%28 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i1 }* getelementptr ({ i1 }, { i1 }* null, i32 1) to i64))
call void @__quantum__rt__callable_invoke(%Callable* %action, %Tuple* %25, %Tuple* %28)
%29 = bitcast %Tuple* %28 to { i1 }*
%30 = getelementptr inbounds { i1 }, { i1 }* %29, i32 0, i32 0
%31 = load i1, i1* %30, align 1
%32 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %21, i64 %idx)
%33 = bitcast i8* %32 to i1*
store i1 %31, i1* %33, align 1
call void @__quantum__rt__array_update_alias_count(%Array* %21, i32 1)
store %Array* %21, %Array** %retval, align 8
call void @__quantum__rt__array_update_reference_count(%Array* %20, i32 -1)
call void @__quantum__rt__tuple_update_reference_count(%Tuple* %25, i32 -1)
call void @__quantum__rt__tuple_update_reference_count(%Tuple* %28, i32 -1)
br label %exiting__2
exiting__2: ; preds = %body__2
%34 = add i64 %idx, 1
br label %header__2
exit__2: ; preds = %header__2
%35 = load %Array*, %Array** %retval, align 8
call void @__quantum__rt__capture_update_alias_count(%Callable* %action, i32 -1)
call void @__quantum__rt__callable_update_alias_count(%Callable* %action, i32 -1)
call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1)
call void @__quantum__rt__array_update_alias_count(%Array* %35, i32 -1)
call void @__quantum__rt__tuple_update_reference_count(%Tuple* %5, i32 -1)
call void @__quantum__rt__tuple_update_reference_count(%Tuple* %8, i32 -1)
ret %Array* %35
}
declare void @__quantum__rt__capture_update_alias_count(%Callable*, i32)
declare void @__quantum__rt__callable_update_alias_count(%Callable*, i32)
declare i64 @__quantum__rt__array_get_size_1d(%Array*)
declare void @__quantum__rt__callable_invoke(%Callable*, %Tuple*, %Tuple*)
declare %Array* @__quantum__rt__array_copy(%Array*, i1)
define internal %Array* @Microsoft__Quantum__Arrays___64c6375bfc954430924edecdbdf36db0_ForEach__body(%Callable* %action, %Array* %array) {
entry:
%retval = alloca %Array*, align 8
call void @__quantum__rt__capture_update_alias_count(%Callable* %action, i32 1)
call void @__quantum__rt__callable_update_alias_count(%Callable* %action, i32 1)
call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1)
%length = call i64 @__quantum__rt__array_get_size_1d(%Array* %array)
%0 = icmp eq i64 %length, 0
br i1 %0, label %then0__1, label %continue__1
then0__1: ; preds = %entry
%1 = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 0)
call void @__quantum__rt__capture_update_alias_count(%Callable* %action, i32 -1)
call void @__quantum__rt__callable_update_alias_count(%Callable* %action, i32 -1)
call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1)
ret %Array* %1
continue__1: ; preds = %entry
%2 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 0)
%3 = bitcast i8* %2 to i1*
%4 = load i1, i1* %3, align 1
%5 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i1 }* getelementptr ({ i1 }, { i1 }* null, i32 1) to i64))
%6 = bitcast %Tuple* %5 to { i1 }*
%7 = getelementptr inbounds { i1 }, { i1 }* %6, i32 0, i32 0
store i1 %4, i1* %7, align 1
%8 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i1 }* getelementptr ({ i1 }, { i1 }* null, i32 1) to i64))
call void @__quantum__rt__callable_invoke(%Callable* %action, %Tuple* %5, %Tuple* %8)
%9 = bitcast %Tuple* %8 to { i1 }*
%10 = getelementptr inbounds { i1 }, { i1 }* %9, i32 0, i32 0
%first = load i1, i1* %10, align 1
%11 = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 %length)
%12 = sub i64 %length, 1
br label %header__1
header__1: ; preds = %exiting__1, %continue__1
%13 = phi i64 [ 0, %continue__1 ], [ %17, %exiting__1 ]
%14 = icmp sle i64 %13, %12
br i1 %14, label %body__1, label %exit__1
body__1: ; preds = %header__1
%15 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %11, i64 %13)
%16 = bitcast i8* %15 to i1*
store i1 %first, i1* %16, align 1
br label %exiting__1
exiting__1: ; preds = %body__1
%17 = add i64 %13, 1
br label %header__1
exit__1: ; preds = %header__1
store %Array* %11, %Array** %retval, align 8
call void @__quantum__rt__array_update_alias_count(%Array* %11, i32 1)
%18 = sub i64 %length, 1
br label %header__2
header__2: ; preds = %exiting__2, %exit__1
%idx = phi i64 [ 1, %exit__1 ], [ %34, %exiting__2 ]
%19 = icmp sle i64 %idx, %18
br i1 %19, label %body__2, label %exit__2
body__2: ; preds = %header__2
%20 = load %Array*, %Array** %retval, align 8
call void @__quantum__rt__array_update_alias_count(%Array* %20, i32 -1)
%21 = call %Array* @__quantum__rt__array_copy(%Array* %20, i1 false)
%22 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %idx)
%23 = bitcast i8* %22 to i1*
%24 = load i1, i1* %23, align 1
%25 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i1 }* getelementptr ({ i1 }, { i1 }* null, i32 1) to i64))
%26 = bitcast %Tuple* %25 to { i1 }*
%27 = getelementptr inbounds { i1 }, { i1 }* %26, i32 0, i32 0
store i1 %24, i1* %27, align 1
%28 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i1 }* getelementptr ({ i1 }, { i1 }* null, i32 1) to i64))
call void @__quantum__rt__callable_invoke(%Callable* %action, %Tuple* %25, %Tuple* %28)
%29 = bitcast %Tuple* %28 to { i1 }*
%30 = getelementptr inbounds { i1 }, { i1 }* %29, i32 0, i32 0
%31 = load i1, i1* %30, align 1
%32 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %21, i64 %idx)
%33 = bitcast i8* %32 to i1*
store i1 %31, i1* %33, align 1
call void @__quantum__rt__array_update_alias_count(%Array* %21, i32 1)
store %Array* %21, %Array** %retval, align 8
call void @__quantum__rt__array_update_reference_count(%Array* %20, i32 -1)
call void @__quantum__rt__tuple_update_reference_count(%Tuple* %25, i32 -1)
call void @__quantum__rt__tuple_update_reference_count(%Tuple* %28, i32 -1)
br label %exiting__2
exiting__2: ; preds = %body__2
%34 = add i64 %idx, 1
br label %header__2
exit__2: ; preds = %header__2
%35 = load %Array*, %Array** %retval, align 8
call void @__quantum__rt__capture_update_alias_count(%Callable* %action, i32 -1)
call void @__quantum__rt__callable_update_alias_count(%Callable* %action, i32 -1)
call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1)
call void @__quantum__rt__array_update_alias_count(%Array* %35, i32 -1)
call void @__quantum__rt__tuple_update_reference_count(%Tuple* %5, i32 -1)
call void @__quantum__rt__tuple_update_reference_count(%Tuple* %8, i32 -1)
ret %Array* %35
}
define internal i1 @Microsoft__Quantum__Canon__IsResultOne__body(%Result* %input) {
entry:
%0 = call %Result* @__quantum__rt__result_get_one()
%1 = call i1 @__quantum__rt__result_equal(%Result* %input, %Result* %0)
ret i1 %1
}
define internal void @SNIPPET__int2bool__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) {
entry:
%0 = bitcast %Tuple* %arg-tuple to { i64 }*
%1 = getelementptr inbounds { i64 }, { i64 }* %0, i32 0, i32 0
%2 = load i64, i64* %1, align 4
%3 = call i1 @SNIPPET__int2bool__body(i64 %2)
%4 = bitcast %Tuple* %result-tuple to { i1 }*
%5 = getelementptr inbounds { i1 }, { i1 }* %4, i32 0, i32 0
store i1 %3, i1* %5, align 1
ret void
}
declare %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]*, [2 x void (%Tuple*, i32)*]*, %Tuple*)
define internal void @SNIPPET__TeleportClassicalMessage__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) {
entry:
%0 = bitcast %Tuple* %arg-tuple to { i1 }*
%1 = getelementptr inbounds { i1 }, { i1 }* %0, i32 0, i32 0
%2 = load i1, i1* %1, align 1
%3 = call i1 @SNIPPET__TeleportClassicalMessage__body(i1 %2)
%4 = bitcast %Tuple* %result-tuple to { i1 }*
%5 = getelementptr inbounds { i1 }, { i1 }* %4, i32 0, i32 0
store i1 %3, i1* %5, align 1
ret void
}
declare %String* @__quantum__rt__string_create(i8*)
declare void @__quantum__rt__string_update_reference_count(%String*, i32)
declare void @__quantum__rt__message(%String*)
declare void @__quantum__rt__capture_update_reference_count(%Callable*, i32)
declare void @__quantum__rt__callable_update_reference_count(%Callable*, i32)
define internal i1 @SNIPPET__int2bool__body(i64 %bit) {
entry:
%0 = icmp eq i64 %bit, 1
br i1 %0, label %then0__1, label %else__1
then0__1: ; preds = %entry
ret i1 true
else__1: ; preds = %entry
ret i1 false
continue__1: ; No predecessors!
unreachable
}
define internal i1 @SNIPPET__TeleportClassicalMessage__body(i1 %message) {
entry:
%msg = call %Qubit* @__quantum__rt__qubit_allocate()
%target = call %Qubit* @__quantum__rt__qubit_allocate()
br i1 %message, label %then0__1, label %continue__1
then0__1: ; preds = %entry
call void @__quantum__qis__x__body(%Qubit* %msg)
br label %continue__1
continue__1: ; preds = %then0__1, %entry
call void @SNIPPET__Teleport__body(%Qubit* %msg, %Qubit* %target)
%0 = call %Result* @Microsoft__Quantum__Measurement__MResetZ__body(%Qubit* %target)
%1 = call %Result* @__quantum__rt__result_get_one()
%2 = call i1 @__quantum__rt__result_equal(%Result* %0, %Result* %1)
call void @__quantum__rt__result_update_reference_count(%Result* %0, i32 -1)
call void @__quantum__rt__qubit_release(%Qubit* %msg)
call void @__quantum__rt__qubit_release(%Qubit* %target)
ret i1 %2
}
define internal void @SNIPPET__Teleport__body(%Qubit* %msg, %Qubit* %target) {
entry:
%register = call %Qubit* @__quantum__rt__qubit_allocate()
call void @__quantum__qis__h__body(%Qubit* %register)
call void @Microsoft__Quantum__Intrinsic__CNOT__body(%Qubit* %register, %Qubit* %target)
call void @Microsoft__Quantum__Intrinsic__CNOT__body(%Qubit* %msg, %Qubit* %register)
call void @__quantum__qis__h__body(%Qubit* %msg)
%0 = call %Result* @Microsoft__Quantum__Measurement__MResetZ__body(%Qubit* %msg)
%1 = call %Result* @__quantum__rt__result_get_one()
%2 = call i1 @__quantum__rt__result_equal(%Result* %0, %Result* %1)
call void @__quantum__rt__result_update_reference_count(%Result* %0, i32 -1)
br i1 %2, label %then0__1, label %continue__1
then0__1: ; preds = %entry
call void @__quantum__qis__z__body(%Qubit* %target)
br label %continue__1
continue__1: ; preds = %then0__1, %entry
%3 = call %Result* @Microsoft__Quantum__Measurement__MResetZ__body(%Qubit* %register)
%4 = call i1 @Microsoft__Quantum__Canon__IsResultOne__body(%Result* %3)
call void @__quantum__rt__result_update_reference_count(%Result* %3, i32 -1)
br i1 %4, label %then0__2, label %continue__2
then0__2: ; preds = %continue__1
call void @__quantum__qis__x__body(%Qubit* %target)
br label %continue__2
continue__2: ; preds = %then0__2, %continue__1
call void @__quantum__rt__qubit_release(%Qubit* %register)
ret void
}
declare %Qubit* @__quantum__rt__qubit_allocate()
declare %Array* @__quantum__rt__qubit_allocate_array(i64)
declare void @__quantum__rt__qubit_release(%Qubit*)
declare void @__quantum__rt__result_update_reference_count(%Result*, i32)
define void @ENTRYPOINT__Greetings__Interop() #0 {
entry:
call void @ENTRYPOINT__Greetings__body()
ret void
}
define void @ENTRYPOINT__Greetings() #1 {
entry:
call void @ENTRYPOINT__Greetings__body()
%0 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @2, i32 0, i32 0))
call void @__quantum__rt__message(%String* %0)
call void @__quantum__rt__string_update_reference_count(%String* %0, i32 -1)
ret void
}
attributes #0 = { "InteropFriendly" }
attributes #1 = { "EntryPoint" }