diff --git a/src/QirRuntime/lib/QIR/callables.cpp b/src/QirRuntime/lib/QIR/callables.cpp index b1fb38cc51c..e354d55e959 100644 --- a/src/QirRuntime/lib/QIR/callables.cpp +++ b/src/QirRuntime/lib/QIR/callables.cpp @@ -406,6 +406,14 @@ void QirCallable::Invoke(PTuple args, PTuple result) } } +void QirCallable::Invoke() +{ + assert((this->appliedFunctor & QirCallable::Controlled) == 0 && "Cannot invoke controlled callable without args"); + PTuple args = quantum__rt__tuple_create(0); + this->Invoke(args, nullptr); + quantum__rt__tuple_update_reference_count(args, -1); +} + // A + A = I; A + C = C + A = CA; C + C = C; CA + A = C; CA + C = CA void QirCallable::ApplyFunctor(int functor) { diff --git a/src/QirRuntime/lib/QIR/conditionals.cpp b/src/QirRuntime/lib/QIR/conditionals.cpp index 72c46e21db6..e9e0bb8d083 100644 --- a/src/QirRuntime/lib/QIR/conditionals.cpp +++ b/src/QirRuntime/lib/QIR/conditionals.cpp @@ -9,13 +9,6 @@ #include "QirTypes.hpp" #include "quantum__rt.hpp" -static void Apply(QirCallable* clb) -{ - PTuple argsTuple = quantum__rt__tuple_create(0); - quantum__rt__callable_invoke(clb, argsTuple /*args*/, nullptr /*result*/); - quantum__rt__tuple_update_reference_count(argsTuple, -1); -} - static bool ArraysContainEqualResults(QirArray* rs1, QirArray* rs2) { assert(rs1 != nullptr && rs2 != nullptr && rs1->count == rs2->count); @@ -38,8 +31,8 @@ extern "C" { void quantum__qis__applyifelseintrinsic__body(RESULT* r, QirCallable* clbOnZero, QirCallable* clbOnOne) { - QirCallable* clbApply = quantum__rt__result_equal(r, quantum__rt__result_zero()) ? clbOnZero : clbOnOne; - Apply(clbApply); + QirCallable* clb = quantum__rt__result_equal(r, quantum__rt__result_zero()) ? clbOnZero : clbOnOne; + clb->Invoke(); } void quantum__qis__applyconditionallyintrinsic__body( @@ -48,7 +41,7 @@ extern "C" QirCallable* clbOnAllEqual, QirCallable* clbOnSomeDifferent) { - QirCallable* clbApply = ArraysContainEqualResults(rs1, rs2) ? clbOnAllEqual : clbOnSomeDifferent; - Apply(clbApply); + QirCallable* clb = ArraysContainEqualResults(rs1, rs2) ? clbOnAllEqual : clbOnSomeDifferent; + clb->Invoke(); } } \ No newline at end of file diff --git a/src/QirRuntime/lib/Tracer/README.md b/src/QirRuntime/lib/Tracer/README.md index 3ba42c9ca35..43993131345 100644 --- a/src/QirRuntime/lib/Tracer/README.md +++ b/src/QirRuntime/lib/Tracer/README.md @@ -72,20 +72,24 @@ As the tracer is executing a sequential quantum program, it will compute a time using the _conceptual_ algorithm, described below (aka "tetris algorithm"). The actual implementation of layering might be done differently, as long as the resulting layering is the same as if running the conceptual algorithm. -A ___barrier___ is a layer that acts as if it was containing all currently allocated qubits and no operation can be added - into it. - -A user can inject _barriers_ by calling `__quantum__qis__global_barrier` function. The user can choose duration of - a barrier which would affect start time of the following layers but no operations will be added to a barrier, - independent of its duration. +A layer _L(T,N)_ acts as a ___fence___ if it does _not_ accepts any new operations, even if these operations don't + involve qubits from _Qubits(T,N)_. __Conditional execution on measurement results__: The Tracer will execute LLVM IR's branching structures "as is", depending on the values of the corresponding variables at runtime. To enable estimation of branches that depend on a - measurement result, the source Q# program will have to be authored in such a way that the Q# compiler will translate the - conditionals into corresponding callbacks to the tracer. The tracer will add operations from _both branches_ into the - layers it creates to compute the upper bound estimate. + measurement result, the source Q# program must be authored in such a way that the Q# compiler will translate the + conditionals into corresponding callbacks to the tracer (`__quantum__qis__apply_conditionally`). The tracer will + execute _both branches_ of the conditional statement to compute the upper bound estimate. The conditional callbacks + will mark the layers that contain measurements that produced the results used in conditionals as _fences_ for the + duration of the conditional callback. + +A user can create special layers that act as permanent _fences_ by calling `__quantum__qis__inject_barrier` function. The + user can choose duration of a barrier which would affect start time of the following layers but no operations will be + added to a barrier, independent of its duration. _Terminology note_: 'fence' is a role of layer, which might be assigned + to a layer temporarily or permanently; 'barrier' is a special layer the user can inject that has the role of a permanent + fence and contains no operations. -The following operations are _not_ supported inside conditional callbacks and would cause a runtime failure: +__TODO__: figure out which operations should or should _not_ be supported inside conditional callbacks. For example: - nested conditional callbacks; - measurements; @@ -201,7 +205,7 @@ TBD but lower priority. | `%Result* @__quantum__qis__single_qubit_measure(i32 %id, i32 %duration, %Qubit* %q)` | Function for counting measurements of a single qubit. The user can assign different operation ids for different measurement bases. | | `%Result* @__quantum__qis__joint_measure(i32 %id, i32 %duration, %Array* %qs)` | Function for counting joint-measurements of qubits. The user can assign different operation ids for different measurement bases. | | `void __quantum__qis__swap(%Qubit* %q1, %Qubit* %q2)` | See [Special handling of SWAP](#special-handling-of-swap) for details. | -| TODO: handling of conditionals on measurement results | | +| `void __quantum__qis__apply_conditionally(%Array* %.rs1, %Array* %.rs2, %Callable* %.clb_on_equal, %Callable* %.clb_on_different)` | The first two arguments contain arrays of results to be compared pairwise. The third argument is a callable that represents the branch that would be executed if all results compared equal and the forth argument is a callable that represents the branch that would be executed if any of the results compared different. The tracer executes _both_ branches.| _Note on operation ids_: The user is responsible for using operation ids in a consistent manner. Operations with the same id will be counted by the tracer as the _same_ operation, even accross invocations with different number of target diff --git a/src/QirRuntime/lib/Tracer/tracer-bridge.ll b/src/QirRuntime/lib/Tracer/tracer-bridge.ll index 1f0fa216c76..740ad7970f9 100644 --- a/src/QirRuntime/lib/Tracer/tracer-bridge.ll +++ b/src/QirRuntime/lib/Tracer/tracer-bridge.ll @@ -5,6 +5,7 @@ ; QIR types ; %Array = type opaque +%Callable = type opaque %Qubit = type opaque %Result = type opaque @@ -15,6 +16,7 @@ %class.QUBIT = type opaque %class.RESULT = type opaque %struct.QirArray = type opaque +%struct.QirCallable = type opaque ;=============================================================================== @@ -28,6 +30,8 @@ declare void @quantum__qis__multi_qubit_op_ctl(i32 %id, i32 %duration, %struct.Q declare void @quantum__qis__inject_barrier(i32 %id, i32 %duration) declare %class.RESULT* @quantum__qis__single_qubit_measure(i32 %id, i32 %duration, %class.QUBIT*) declare %class.RESULT* @quantum__qis__joint_measure(i32 %id, i32 %duration, %struct.QirArray*) +declare void @quantum__qis__apply_conditionally( + %struct.QirArray*, %struct.QirArray*, %struct.QirCallable*, %struct.QirCallable*) ;=============================================================================== ; quantum__trc namespace implementations @@ -82,4 +86,17 @@ define %Result* @__quantum__qis__joint_measure(i32 %id, i32 %duration, %Array* % %r = call %class.RESULT* @quantum__qis__joint_measure(i32 %id, i32 %duration, %struct.QirArray* %qs) %.r = bitcast %class.RESULT* %r to %Result* ret %Result* %.r +} + +define void @__quantum__qis__apply_conditionally( + %Array* %.rs1, %Array* %.rs2, %Callable* %.clb_on_equal, %Callable* %.clb_on_different) { + + %rs1 = bitcast %Array* %.rs1 to %struct.QirArray* + %rs2 = bitcast %Array* %.rs2 to %struct.QirArray* + %clb_on_equal = bitcast %Callable* %.clb_on_equal to %struct.QirCallable* + %clb_on_different = bitcast %Callable* %.clb_on_different to %struct.QirCallable* + call void @quantum__qis__apply_conditionally( + %struct.QirArray* %rs1, %struct.QirArray* %rs2, + %struct.QirCallable* %clb_on_equal, %struct.QirCallable* %clb_on_different) + ret void } \ No newline at end of file diff --git a/src/QirRuntime/lib/Tracer/tracer-qis.cpp b/src/QirRuntime/lib/Tracer/tracer-qis.cpp index ed7a5eeb370..dd608602215 100644 --- a/src/QirRuntime/lib/Tracer/tracer-qis.cpp +++ b/src/QirRuntime/lib/Tracer/tracer-qis.cpp @@ -63,4 +63,18 @@ extern "C" { return tracer->TraceMultiQubitMeasurement(id, duration, qs->count, reinterpret_cast(qs->buffer)); } + + void quantum__qis__apply_conditionally( // NOLINT + QirArray* rs1, + QirArray* rs2, + QirCallable* clbOnAllEqual, + QirCallable* clbOnSomeDifferent) + { + CTracer::FenceScope sf( + tracer.get(), rs1->count, reinterpret_cast(rs1->buffer), rs2->count, + reinterpret_cast(rs2->buffer)); + + clbOnAllEqual->Invoke(); + clbOnSomeDifferent->Invoke(); + } } \ No newline at end of file diff --git a/src/QirRuntime/lib/Tracer/tracer.cpp b/src/QirRuntime/lib/Tracer/tracer.cpp index c9e906f4a29..02afaeafb4d 100644 --- a/src/QirRuntime/lib/Tracer/tracer.cpp +++ b/src/QirRuntime/lib/Tracer/tracer.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#include #include #include #include @@ -19,12 +20,22 @@ namespace Quantum tracer = std::make_shared(preferredLayerDuration); return tracer; } - std::shared_ptr CreateTracer(int preferredLayerDuration, const std::unordered_map& opNames) + std::shared_ptr CreateTracer( + int preferredLayerDuration, + const std::unordered_map& opNames) { tracer = std::make_shared(preferredLayerDuration, opNames); return tracer; } + //------------------------------------------------------------------------------------------------------------------ + // CTracer::LaterLayerOf + //------------------------------------------------------------------------------------------------------------------ + /*static*/ LayerId CTracer::LaterLayerOf(LayerId l1, LayerId l2) + { + return std::max(l1, l2); + } + //------------------------------------------------------------------------------------------------------------------ // CTracer's ISimulator implementation //------------------------------------------------------------------------------------------------------------------ @@ -47,7 +58,8 @@ namespace Quantum const QubitState& qstate = this->UseQubit(q); stringstream str(std::to_string(qubitIndex)); - str << " last used in layer " << qstate.layer << "(pending zero ops: " << qstate.pendingZeroDurationOps.size() << ")"; + str << " last used in layer " << qstate.layer << "(pending zero ops: " << qstate.pendingZeroDurationOps.size() + << ")"; return str.str(); } @@ -81,11 +93,19 @@ namespace Quantum layerStartTime = lastLayer.startTime + lastLayer.duration; } this->metricsByLayer.emplace_back( - Layer {layerStartTime, max(this->preferredLayerDuration, minRequiredDuration)}); + Layer{layerStartTime, max(this->preferredLayerDuration, minRequiredDuration)}); return this->metricsByLayer.size() - 1; } + //------------------------------------------------------------------------------------------------------------------ + // CTracer::GetEffectiveFence + //------------------------------------------------------------------------------------------------------------------ + LayerId CTracer::GetEffectiveFence() const + { + return CTracer::LaterLayerOf(this->globalBarrier, this->latestConditionalFence); + } + //------------------------------------------------------------------------------------------------------------------ // CTracer::FindLayerToInsertOperationInto //------------------------------------------------------------------------------------------------------------------ @@ -93,16 +113,17 @@ namespace Quantum { const QubitState& qstate = this->UseQubit(q); - LayerId layerToInsertInto = INVALID; + LayerId layerToInsertInto = REQUESTNEW; + const LayerId barrier = this->GetEffectiveFence(); const LayerId firstLayerAfterBarrier = - this->globalBarrier == INVALID - ? this->metricsByLayer.empty() ? INVALID : 0 - : this->globalBarrier + 1 == this->metricsByLayer.size() ? INVALID : this->globalBarrier + 1; + (barrier == INVALID ? (this->metricsByLayer.empty() ? REQUESTNEW : 0) + : ((barrier + 1 == this->metricsByLayer.size()) ? REQUESTNEW : barrier + 1)); - LayerId candidate = max(qstate.layer, firstLayerAfterBarrier); + LayerId candidate = CTracer::LaterLayerOf(qstate.layer, firstLayerAfterBarrier); + assert(candidate != INVALID); - if (candidate != INVALID) + if (candidate != REQUESTNEW) { // Find the earliest layer that the operation fits in by duration const Layer& candidateLayer = this->metricsByLayer[candidate]; @@ -123,10 +144,6 @@ namespace Quantum } } } - else if (opDuration <= this->preferredLayerDuration) - { - layerToInsertInto = firstLayerAfterBarrier; - } return layerToInsertInto; } @@ -137,6 +154,8 @@ namespace Quantum void CTracer::AddOperationToLayer(OpId id, LayerId layer) { assert(layer < this->metricsByLayer.size()); + assert(this->metricsByLayer[layer].barrierId == -1 && "Should not add operations to barriers"); + this->metricsByLayer[layer].operations[id] += 1; } @@ -166,8 +185,8 @@ namespace Quantum this->seenOps.insert(id); QubitState& qstate = this->UseQubit(target); - if (opDuration == 0 && - (qstate.layer == INVALID || (this->globalBarrier != INVALID && qstate.layer < this->globalBarrier))) + const LayerId barrier = this->GetEffectiveFence(); + if (opDuration == 0 && (qstate.layer == INVALID || (barrier != INVALID && qstate.layer < barrier))) { qstate.pendingZeroDurationOps.push_back(id); return INVALID; @@ -175,7 +194,7 @@ namespace Quantum // Figure out the layer this operation should go into. LayerId layerToInsertInto = this->FindLayerToInsertOperationInto(target, opDuration); - if (layerToInsertInto == INVALID) + if (layerToInsertInto == REQUESTNEW) { layerToInsertInto = this->CreateNewLayer(opDuration); } @@ -188,7 +207,7 @@ namespace Quantum } //------------------------------------------------------------------------------------------------------------------ - // CTracer::TraceControlledSingleQubitOp + // CTracer::TraceMultiQubitOp //------------------------------------------------------------------------------------------------------------------ LayerId CTracer::TraceMultiQubitOp( OpId id, @@ -213,16 +232,16 @@ namespace Quantum // Figure out the layer this operation should go into. LayerId layerToInsertInto = this->FindLayerToInsertOperationInto(secondGroup[0], opDuration); - for (long i = 1; i < nSecondGroup && layerToInsertInto != INVALID; i++) + for (long i = 1; i < nSecondGroup && layerToInsertInto != REQUESTNEW; i++) { layerToInsertInto = max(layerToInsertInto, this->FindLayerToInsertOperationInto(secondGroup[i], opDuration)); } - for (long i = 0; i < nFirstGroup && layerToInsertInto != INVALID; i++) + for (long i = 0; i < nFirstGroup && layerToInsertInto != REQUESTNEW; i++) { layerToInsertInto = max(layerToInsertInto, this->FindLayerToInsertOperationInto(firstGroup[i], opDuration)); } - if (layerToInsertInto == INVALID) + if (layerToInsertInto == REQUESTNEW) { layerToInsertInto = this->CreateNewLayer(opDuration); } @@ -243,6 +262,9 @@ namespace Quantum return layerToInsertInto; } + //------------------------------------------------------------------------------------------------------------------ + // CTracer::InjectGlobalBarrier + //------------------------------------------------------------------------------------------------------------------ LayerId CTracer::InjectGlobalBarrier(OpId id, Duration duration) { LayerId layer = this->CreateNewLayer(duration); @@ -251,18 +273,76 @@ namespace Quantum return layer; } + //------------------------------------------------------------------------------------------------------------------ + // CTracer::TraceSingleQubitMeasurement + //------------------------------------------------------------------------------------------------------------------ Result CTracer::TraceSingleQubitMeasurement(OpId id, Duration duration, Qubit target) { LayerId layerId = this->TraceSingleQubitOp(id, duration, target); return reinterpret_cast(layerId); } + //------------------------------------------------------------------------------------------------------------------ + // CTracer::TraceMultiQubitMeasurement + //------------------------------------------------------------------------------------------------------------------ Result CTracer::TraceMultiQubitMeasurement(OpId id, Duration duration, long nTargets, Qubit* targets) { LayerId layerId = this->TraceMultiQubitOp(id, duration, 0, nullptr, nTargets, targets); return reinterpret_cast(layerId); } + //------------------------------------------------------------------------------------------------------------------ + // CTracer::FindLatestMeasurementLayer + //------------------------------------------------------------------------------------------------------------------ + LayerId CTracer::FindLatestMeasurementLayer(long count, Result* results) + { + LayerId latest = INVALID; + for (long i = 0; i < count; i++) + { + const LayerId id = this->GetLayerIdOfSourceMeasurement(results[i]); + latest = CTracer::LaterLayerOf(latest, id); + } + return latest; + } + + //------------------------------------------------------------------------------------------------------------------ + // CTracer::FenceScope + //------------------------------------------------------------------------------------------------------------------ + CTracer::FenceScope::FenceScope(CTracer* tracer, long count1, Result* rs1, long count2, Result* rs2) + : tracer(tracer) + { + const LayerId fence1 = + (rs1 != nullptr && count1 > 0) ? this->tracer->FindLatestMeasurementLayer(count1, rs1) : INVALID; + const LayerId fence2 = + (rs2 != nullptr && count2 > 0) ? this->tracer->FindLatestMeasurementLayer(count2, rs2) : INVALID; + + this->fence = CTracer::LaterLayerOf(fence1, fence2); + if (this->fence == INVALID) + { + return; + } + assert(this->fence < this->tracer->metricsByLayer.size()); + + this->tracer->conditionalFences.push_back(this->fence); + this->tracer->latestConditionalFence = CTracer::LaterLayerOf(this->tracer->latestConditionalFence, this->fence); + } + CTracer::FenceScope::~FenceScope() + { + if (this->fence == INVALID) + { + return; + } + + vector& fences = this->tracer->conditionalFences; + assert(!fences.empty()); + this->tracer->conditionalFences.pop_back(); + + // Update the latest layer (we expect the stack of fences to be shallow so a linear search through it + // should be OK). + this->tracer->latestConditionalFence = + fences.empty() ? INVALID : *std::max_element(fences.begin(), fences.end()); + } + //------------------------------------------------------------------------------------------------------------------ // CTracer::PrintLayerMetrics //------------------------------------------------------------------------------------------------------------------ diff --git a/src/QirRuntime/lib/Tracer/tracer.hpp b/src/QirRuntime/lib/Tracer/tracer.hpp index c5548e4bd18..508d525e68d 100644 --- a/src/QirRuntime/lib/Tracer/tracer.hpp +++ b/src/QirRuntime/lib/Tracer/tracer.hpp @@ -9,8 +9,8 @@ #include #include "CoreTypes.hpp" -#include "TracerTypes.hpp" #include "QuantumApi_I.hpp" +#include "TracerTypes.hpp" namespace Microsoft { @@ -71,10 +71,21 @@ namespace Quantum // The index into the vector is treated as implicit id of the layer. std::vector metricsByLayer; - // The last global barrier, injected by the user. No new operations can be added to the barrier or to any of the - // layer that preceeded it, even if the new operations involve completely new qubits. + // The last barrier, injected by the user. No new operations can be added to the barrier or to any of the + // layer that preceeded it, even if the new operations involve completely new qubits. Thus, the barriers act + // as permanent fences, that are activated at the moment the tracer executes the corresponding user code and are + // never removed. LayerId globalBarrier = INVALID; + // The conditional fences are layers that contain measurements for results used to guard conditional branches. + // The set of fences is a stack (for nested conditionals) but we use vector to store them so we can recalculate + // the latest (by time) fence when the stack is popped. + std::vector conditionalFences; + + // We don't expect the stack of conditional fences to be deep, so it's OK to recalculate the latest layer when + // the stack is modified. + LayerId latestConditionalFence = INVALID; + // Mapping of operation ids to user-chosen names, for operations that user didn't name, the output will use // operation ids. std::unordered_map opNames; @@ -96,7 +107,7 @@ namespace Quantum return this->qubits[qubitIndex]; } - // If no appropriate layer found, return `INVALID` + // If no appropriate layer found, returns `REQUESTNEW`. LayerId FindLayerToInsertOperationInto(Qubit q, Duration opDuration) const; // Returns the index of the created layer. @@ -105,10 +116,19 @@ namespace Quantum // Adds operation with given id into the given layer. Assumes that duration contraints have been satisfied. void AddOperationToLayer(OpId id, LayerId layer); - // Update the qubit state with the new layer information + // Update the qubit state with the new layer information. void UpdateQubitState(Qubit q, LayerId layer, Duration opDuration); + // Considers global barriers and conditional fences to find the fence currently in effect. + LayerId GetEffectiveFence() const; + + // For the given results finds the latest layer of the measurements that produced the results. + LayerId FindLatestMeasurementLayer(long count, Result* results); + public: + // Returns the later layer of the two. INVALID LayerId is treated as -Infinity, and REQUESTNEW -- as +Infinity. + static LayerId LaterLayerOf(LayerId l1, LayerId l2); + explicit CTracer(int preferredLayerDuration) : preferredLayerDuration(preferredLayerDuration) { @@ -184,6 +204,14 @@ namespace Quantum // ------------------------------------------------------------------------------------------------------------- LayerId InjectGlobalBarrier(OpId id, Duration duration); + struct FenceScope + { + CTracer* tracer = nullptr; + LayerId fence = INVALID; + explicit FenceScope(CTracer* tracer, long count1, Result* results1, long count2, Result* results2); + ~FenceScope(); + }; + // ------------------------------------------------------------------------------------------------------------- // Configuring the tracer and getting data back from it. // ------------------------------------------------------------------------------------------------------------- diff --git a/src/QirRuntime/public/QirTypes.hpp b/src/QirRuntime/public/QirTypes.hpp index a9ca03fa72f..dc0313995dc 100644 --- a/src/QirRuntime/public/QirTypes.hpp +++ b/src/QirRuntime/public/QirTypes.hpp @@ -166,6 +166,7 @@ struct QirCallable void UpdateAliasCount(int increment); void Invoke(PTuple args, PTuple result); + void Invoke(); // a shortcut to invoke a callable with no arguments and Unit result void ApplyFunctor(int functor); void InvokeCaptureCallback(int index, int64_t parameter); diff --git a/src/QirRuntime/public/TracerTypes.hpp b/src/QirRuntime/public/TracerTypes.hpp index 9b7d242f9f7..77e4565e974 100644 --- a/src/QirRuntime/public/TracerTypes.hpp +++ b/src/QirRuntime/public/TracerTypes.hpp @@ -10,8 +10,9 @@ namespace Quantum using OpId = int; using Time = int; using Duration = int; - using LayerId = size_t; + using LayerId = int64_t; - constexpr LayerId INVALID = std::numeric_limits::max(); + constexpr LayerId INVALID = std::numeric_limits::min(); + constexpr LayerId REQUESTNEW = std::numeric_limits::max(); } } \ No newline at end of file diff --git a/src/QirRuntime/test/QIR-tracer/qir-tracer-driver.cpp b/src/QirRuntime/test/QIR-tracer/qir-tracer-driver.cpp index ba2fd6e361a..09199fe5782 100644 --- a/src/QirRuntime/test/QIR-tracer/qir-tracer-driver.cpp +++ b/src/QirRuntime/test/QIR-tracer/qir-tracer-driver.cpp @@ -29,19 +29,21 @@ TEST_CASE("Invoke each intrinsic from Q# core once", "[qir-tracer]") tr->PrintLayerMetrics(out, ",", true /*printZeroMetrics*/); INFO(out.str()); - // TestCoreIntrinsics happens to produce 24 layers right now and we are not checking whether that's expected -- as + // TestCoreIntrinsics happens to produce 24 layers right now and we are not checking whether that's expected -- as // testing of layering logic is better done by unit tests. CHECK(layers.size() == 24); } -TEST_CASE("Measurements can be counted but cannot be compared", "[qir-tracer]") +TEST_CASE("Conditional execution on measurement result", "[qir-tracer]") { shared_ptr tr = CreateTracer(1 /*layer duration*/, g_operationNames); QirContextScope qirctx(tr.get(), false /*trackAllocatedObjects*/); - REQUIRE_NOTHROW(Microsoft__Quantum__Testing__Tracer__TestMeasurements__body(false /*compare*/)); - CHECK(tr->UseLayers().size() == 1); + REQUIRE_NOTHROW(Microsoft__Quantum__Testing__Tracer__TestMeasurements__body()); - REQUIRE_THROWS(Microsoft__Quantum__Testing__Tracer__TestMeasurements__body(true /*compare*/)); + std::stringstream out; + tr->PrintLayerMetrics(out, ",", true /*printZeroMetrics*/); + INFO(out.str()); + CHECK(tr->UseLayers().size() == 5); } -} \ No newline at end of file +} // namespace TracerUser \ No newline at end of file diff --git a/src/QirRuntime/test/QIR-tracer/tracer-conditionals.qs b/src/QirRuntime/test/QIR-tracer/tracer-conditionals.qs new file mode 100644 index 00000000000..e9c0c512421 --- /dev/null +++ b/src/QirRuntime/test/QIR-tracer/tracer-conditionals.qs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Testing.Tracer { + open Microsoft.Quantum.Intrinsic; + + // Private helper operations. + operation Delay(op : (Qubit => Unit), arg : Qubit, aux : Unit) : Unit { + op(arg); + } + + operation TestMeasurements() : Unit { + use qs = Qubit[6]; + T(qs[0]); // layer 0 + let r0 = M(qs[0]); // layer 1 + T(qs[1]); // layer 0 + CNOT(qs[1], qs[2]); // layer 1 + let qs12 = [qs[1], qs[2]]; + let r12 = Measure([PauliY, PauliX], qs12); // layer 2 + + ApplyIfElseIntrinsic(r0, Delay(X, qs[3], _), Delay(Y, qs[3], _)); // layers 2, 3 + ApplyIfElseIntrinsic(r12, Delay(Z, qs[4], _), Delay(S, qs[4], _)); // layer 3, 4 + Rx(4.2, qs[5]); // layer 0 + } +} \ No newline at end of file diff --git a/src/QirRuntime/test/QIR-tracer/tracer-config.cpp b/src/QirRuntime/test/QIR-tracer/tracer-config.cpp index eab02e878af..b47f1c70ba9 100644 --- a/src/QirRuntime/test/QIR-tracer/tracer-config.cpp +++ b/src/QirRuntime/test/QIR-tracer/tracer-config.cpp @@ -12,5 +12,7 @@ namespace TracerUser { const std::unordered_map g_operationNames = { - {0, "X"}, {1, "CX"}, {2, "MCX"}, {3, "Y"}, {4, "CY"}, {5, "MCY"} /*etc.*/}; + {0, "X"}, {1, "CX"}, {2, "MCX"}, {3, "Y"}, {4, "CY"}, {5, "MCY"}, {6, "Z"}, + {7, "CZ"}, {8, "MCZ"}, {19, "Rx"}, {20, "MCRx"}, {21, "Ry"}, {22, "MCRy"}, {23, "Rz"}, + {24, "MCRz"}, {9, "H"}, {10, "MCH"}, {11, "T"}, {12, "MCT"}, {15, "S"}, {16, "MCS"} /*etc.*/}; } diff --git a/src/QirRuntime/test/QIR-tracer/tracer-config.hpp b/src/QirRuntime/test/QIR-tracer/tracer-config.hpp index 8163231286d..ac7eef038d3 100644 --- a/src/QirRuntime/test/QIR-tracer/tracer-config.hpp +++ b/src/QirRuntime/test/QIR-tracer/tracer-config.hpp @@ -17,4 +17,4 @@ extern const std::unordered_map g_operati // Available function in generated QIR extern "C" void Microsoft__Quantum__Testing__Tracer__TestCoreIntrinsics__body(); // NOLINT -extern "C" void Microsoft__Quantum__Testing__Tracer__TestMeasurements__body(bool compare); // NOLINT +extern "C" void Microsoft__Quantum__Testing__Tracer__TestMeasurements__body(); // NOLINT diff --git a/src/QirRuntime/test/QIR-tracer/tracer-measurements.qs b/src/QirRuntime/test/QIR-tracer/tracer-measurements.qs deleted file mode 100644 index 7c4aab5eea1..00000000000 --- a/src/QirRuntime/test/QIR-tracer/tracer-measurements.qs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -namespace Microsoft.Quantum.Testing.Tracer { - open Microsoft.Quantum.Intrinsic; - - operation Fixup(qs : Qubit[]) : Unit { - for i in 0..Length(qs)-1 { - X(qs[i]); - } - } - - operation TestMeasurements(compare : Bool) : Unit { - use qs = Qubit[3]; - let r0 = M(qs[0]); - let qs12 = [qs[1], qs[2]]; - let r12 = Measure([PauliY, PauliX], qs12); - - if compare { - if r0 == Zero { - X(qs[1]); - } - - //ApplyIfOne(r12, (Fixup, qs12)); - } - } -} \ No newline at end of file diff --git a/src/QirRuntime/test/QIR-tracer/tracer-qir.ll b/src/QirRuntime/test/QIR-tracer/tracer-qir.ll index 3da1a0f7fa6..edf24b70e7c 100644 --- a/src/QirRuntime/test/QIR-tracer/tracer-qir.ll +++ b/src/QirRuntime/test/QIR-tracer/tracer-qir.ll @@ -1,13 +1,10 @@ -;This file was generated using: -;commit 722ec70a97b65f8d3ee1085368142a91183969db (HEAD, origin/swernli/standalone-llvm-2) -;Author: Stefan J. Wernli -;Date: Wed Feb 24 21:51:15 2021 -0800 %Result = type opaque %Range = type { i64, i64, i64 } +%Tuple = type opaque %Array = type opaque +%Callable = type opaque %Qubit = type opaque -%Tuple = type opaque %String = type opaque @ResultZero = external global %Result* @@ -17,476 +14,280 @@ @PauliY = constant i2 -1 @PauliZ = constant i2 -2 @EmptyRange = internal constant %Range { i64 0, i64 1, i64 -1 } +@Microsoft__Quantum__Testing__Tracer__Delay = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Testing__Tracer__Delay__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] +@Microsoft__Quantum__Intrinsic__X = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__ctladj__wrapper] +@PartialApplication__1 = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__1__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] +@MemoryManagement__1 = constant [2 x void (%Tuple*, i64)*] [void (%Tuple*, i64)* @MemoryManagement__1__RefCount, void (%Tuple*, i64)* @MemoryManagement__1__AliasCount] +@Microsoft__Quantum__Intrinsic__Y = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__ctladj__wrapper] +@PartialApplication__2 = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__2__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] +@Microsoft__Quantum__Intrinsic__Z = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__ctladj__wrapper] +@PartialApplication__3 = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__3__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] +@Microsoft__Quantum__Intrinsic__S = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__ctladj__wrapper] +@PartialApplication__4 = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__4__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] +@MemoryManagement__2 = constant [2 x void (%Tuple*, i64)*] [void (%Tuple*, i64)* @MemoryManagement__2__RefCount, void (%Tuple*, i64)* @MemoryManagement__2__AliasCount] + +define void @Microsoft__Quantum__Intrinsic__ApplyConditionallyIntrinsic__body(%Array* %measurementResults, %Array* %resultsValues, %Callable* %onEqualOp, %Callable* %onNonEqualOp) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %measurementResults, i64 1) + call void @__quantum__rt__array_update_alias_count(%Array* %resultsValues, i64 1) + call void @__quantum__rt__callable_memory_management(i32 1, %Callable* %onEqualOp, i64 1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %onEqualOp, i64 1) + call void @__quantum__rt__callable_memory_management(i32 1, %Callable* %onNonEqualOp, i64 1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %onNonEqualOp, i64 1) + call void @__quantum__qis__apply_conditionally(%Array* %measurementResults, %Array* %resultsValues, %Callable* %onEqualOp, %Callable* %onNonEqualOp) + call void @__quantum__rt__array_update_alias_count(%Array* %measurementResults, i64 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %resultsValues, i64 -1) + call void @__quantum__rt__callable_memory_management(i32 1, %Callable* %onEqualOp, i64 -1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %onEqualOp, i64 -1) + call void @__quantum__rt__callable_memory_management(i32 1, %Callable* %onNonEqualOp, i64 -1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %onNonEqualOp, i64 -1) + ret void +} + +declare void @__quantum__rt__array_update_alias_count(%Array*, i64) + +declare void @__quantum__rt__callable_memory_management(i32, %Callable*, i64) + +declare void @__quantum__rt__callable_update_alias_count(%Callable*, i64) -define void @Microsoft__Quantum__Testing__Tracer__Fixup__body(%Array* %qs) { +declare void @__quantum__qis__apply_conditionally(%Array*, %Array*, %Callable*, %Callable*) + +define void @Microsoft__Quantum__Intrinsic__ApplyIfElseIntrinsic__body(%Result* %measurementResult, %Callable* %onResultZeroOp, %Callable* %onResultOneOp) { entry: - call void @__quantum__rt__array_update_alias_count(%Array* %qs, i64 1) - %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %qs) - %1 = sub i64 %0, 1 + call void @__quantum__rt__callable_memory_management(i32 1, %Callable* %onResultZeroOp, i64 1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %onResultZeroOp, i64 1) + call void @__quantum__rt__callable_memory_management(i32 1, %Callable* %onResultOneOp, i64 1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %onResultOneOp, i64 1) + %0 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %1 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %0, i64 0) + %2 = bitcast i8* %1 to %Result** + store %Result* %measurementResult, %Result** %2 + %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 %Result** + %6 = load %Result*, %Result** @ResultZero + store %Result* %6, %Result** %5 + call void @__quantum__qis__apply_conditionally(%Array* %0, %Array* %3, %Callable* %onResultZeroOp, %Callable* %onResultOneOp) + call void @__quantum__rt__result_update_reference_count(%Result* %measurementResult, i64 1) + call void @__quantum__rt__result_update_reference_count(%Result* %6, i64 1) + call void @__quantum__rt__callable_memory_management(i32 1, %Callable* %onResultZeroOp, i64 -1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %onResultZeroOp, i64 -1) + call void @__quantum__rt__callable_memory_management(i32 1, %Callable* %onResultOneOp, i64 -1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %onResultOneOp, i64 -1) br label %header__1 header__1: ; preds = %exiting__1, %entry - %i = phi i64 [ 0, %entry ], [ %5, %exiting__1 ] - %2 = icmp sle i64 %i, %1 - br i1 %2, label %body__1, label %exit__1 + %7 = phi i64 [ 0, %entry ], [ %12, %exiting__1 ] + %8 = icmp sle i64 %7, 0 + br i1 %8, label %body__1, label %exit__1 body__1: ; preds = %header__1 - %3 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 %i) - %4 = bitcast i8* %3 to %Qubit** - %qb = load %Qubit*, %Qubit** %4 - call void @__quantum__qis__single_qubit_op(i64 0, i64 1, %Qubit* %qb) + %9 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %0, i64 %7) + %10 = bitcast i8* %9 to %Result** + %11 = load %Result*, %Result** %10 + call void @__quantum__rt__result_update_reference_count(%Result* %11, i64 -1) br label %exiting__1 exiting__1: ; preds = %body__1 - %5 = add i64 %i, 1 + %12 = add i64 %7, 1 br label %header__1 exit__1: ; preds = %header__1 - call void @__quantum__rt__array_update_alias_count(%Array* %qs, i64 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %0, i64 -1) + br label %header__2 + +header__2: ; preds = %exiting__2, %exit__1 + %13 = phi i64 [ 0, %exit__1 ], [ %18, %exiting__2 ] + %14 = icmp sle i64 %13, 0 + br i1 %14, label %body__2, label %exit__2 + +body__2: ; preds = %header__2 + %15 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %3, i64 %13) + %16 = bitcast i8* %15 to %Result** + %17 = load %Result*, %Result** %16 + call void @__quantum__rt__result_update_reference_count(%Result* %17, i64 -1) + br label %exiting__2 + +exiting__2: ; preds = %body__2 + %18 = add i64 %13, 1 + br label %header__2 + +exit__2: ; preds = %header__2 + call void @__quantum__rt__array_update_reference_count(%Array* %3, i64 -1) ret void } -declare void @__quantum__rt__array_update_alias_count(%Array*, i64) - -declare i64 @__quantum__rt__array_get_size_1d(%Array*) +declare %Array* @__quantum__rt__array_create_1d(i32, i64) declare i8* @__quantum__rt__array_get_element_ptr_1d(%Array*, i64) -declare void @__quantum__qis__single_qubit_op(i64, i64, %Qubit*) +declare void @__quantum__rt__result_update_reference_count(%Result*, i64) -define void @Microsoft__Quantum__Testing__Tracer__TestCoreIntrinsics__body() { +declare void @__quantum__rt__array_update_reference_count(%Array*, i64) + +define void @Microsoft__Quantum__Intrinsic__CNOT__body(%Qubit* %control, %Qubit* %target) { entry: - %qs = call %Array* @__quantum__rt__qubit_allocate_array(i64 3) - call void @__quantum__rt__array_update_alias_count(%Array* %qs, i64 1) - %0 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %1 = bitcast i8* %0 to %Qubit** - %qb = load %Qubit*, %Qubit** %1 - call void @__quantum__qis__single_qubit_op(i64 0, i64 1, %Qubit* %qb) - %2 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %3 = bitcast i8* %2 to %Qubit** - %qb__1 = load %Qubit*, %Qubit** %3 - call void @__quantum__qis__single_qubit_op(i64 3, i64 1, %Qubit* %qb__1) - %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %5 = bitcast i8* %4 to %Qubit** - %qb__2 = load %Qubit*, %Qubit** %5 - call void @__quantum__qis__single_qubit_op(i64 6, i64 1, %Qubit* %qb__2) - %6 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %7 = bitcast i8* %6 to %Qubit** - %qb__3 = load %Qubit*, %Qubit** %7 - call void @__quantum__qis__single_qubit_op(i64 9, i64 1, %Qubit* %qb__3) - %8 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %9 = bitcast i8* %8 to %Qubit** - %10 = load %Qubit*, %Qubit** %9 - %11 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %12 = bitcast i8* %11 to %Qubit** - %13 = load %Qubit*, %Qubit** %12 - call void @Microsoft__Quantum__Intrinsic__CNOT__body(%Qubit* %10, %Qubit* %13) - %14 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %15 = bitcast i8* %14 to %Qubit** - %qb__4 = load %Qubit*, %Qubit** %15 - call void @__quantum__qis__single_qubit_op(i64 19, i64 1, %Qubit* %qb__4) - %16 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %17 = bitcast i8* %16 to %Qubit** - %qb__5 = load %Qubit*, %Qubit** %17 - call void @__quantum__qis__single_qubit_op(i64 21, i64 1, %Qubit* %qb__5) - %18 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %19 = bitcast i8* %18 to %Qubit** - %qb__6 = load %Qubit*, %Qubit** %19 - call void @__quantum__qis__single_qubit_op(i64 23, i64 1, %Qubit* %qb__6) - %20 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %21 = bitcast i8* %20 to %Qubit** - %qb__7 = load %Qubit*, %Qubit** %21 - call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb__7) - %22 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %23 = bitcast i8* %22 to %Qubit** - %qb__9 = load %Qubit*, %Qubit** %23 - call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb__9) - call void @__quantum__qis__inject_barrier(i64 42, i64 0) - %24 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %25 = bitcast i8* %24 to %Qubit** - %qb__11 = load %Qubit*, %Qubit** %25 - call void @__quantum__qis__single_qubit_op(i64 0, i64 1, %Qubit* %qb__11) - %26 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %27 = bitcast i8* %26 to %Qubit** - %qb__13 = load %Qubit*, %Qubit** %27 - call void @__quantum__qis__single_qubit_op(i64 3, i64 1, %Qubit* %qb__13) - %28 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %29 = bitcast i8* %28 to %Qubit** - %qb__15 = load %Qubit*, %Qubit** %29 - call void @__quantum__qis__single_qubit_op(i64 6, i64 1, %Qubit* %qb__15) - %30 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %31 = bitcast i8* %30 to %Qubit** - %qb__17 = load %Qubit*, %Qubit** %31 - call void @__quantum__qis__single_qubit_op(i64 9, i64 1, %Qubit* %qb__17) - %32 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %33 = bitcast i8* %32 to %Qubit** - %34 = load %Qubit*, %Qubit** %33 - %35 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %36 = bitcast i8* %35 to %Qubit** - %37 = load %Qubit*, %Qubit** %36 - call void @Microsoft__Quantum__Intrinsic__CNOT__adj(%Qubit* %34, %Qubit* %37) - %38 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %39 = bitcast i8* %38 to %Qubit** - %qb__19 = load %Qubit*, %Qubit** %39 - call void @__quantum__qis__single_qubit_op(i64 19, i64 1, %Qubit* %qb__19) - %40 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %41 = bitcast i8* %40 to %Qubit** - %qb__20 = load %Qubit*, %Qubit** %41 - call void @__quantum__qis__single_qubit_op(i64 21, i64 1, %Qubit* %qb__20) - %42 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %43 = bitcast i8* %42 to %Qubit** - %qb__21 = load %Qubit*, %Qubit** %43 - call void @__quantum__qis__single_qubit_op(i64 24, i64 1, %Qubit* %qb__21) - %44 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %45 = bitcast i8* %44 to %Qubit** - %qb__22 = load %Qubit*, %Qubit** %45 - call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb__22) - %46 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %47 = bitcast i8* %46 to %Qubit** - %qb__24 = load %Qubit*, %Qubit** %47 - call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb__24) - %c = call %Qubit* @__quantum__rt__qubit_allocate() %ctls = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %48 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 0) - %49 = bitcast i8* %48 to %Qubit** - store %Qubit* %c, %Qubit** %49 + %0 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 0) + %1 = bitcast i8* %0 to %Qubit** + store %Qubit* %control, %Qubit** %1 call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) - %50 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %51 = bitcast i8* %50 to %Qubit** - %qb__26 = load %Qubit*, %Qubit** %51 br i1 true, label %then0__1, label %else__1 then0__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %ctls, %Qubit* %qb__26) + call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %ctls, %Qubit* %target) br label %continue__1 else__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %ctls, %Qubit* %qb__26) + call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %ctls, %Qubit* %target) br label %continue__1 continue__1: ; preds = %else__1, %then0__1 call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) call void @__quantum__rt__array_update_reference_count(%Array* %ctls, i64 -1) - %ctls__1 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %52 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__1, i64 0) - %53 = bitcast i8* %52 to %Qubit** - store %Qubit* %c, %Qubit** %53 + ret void +} + +declare void @__quantum__qis__single_qubit_op_ctl(i64, i64, %Array*, %Qubit*) + +define 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 void @Microsoft__Quantum__Intrinsic__CNOT__ctl(%Array* %ctls, { %Qubit*, %Qubit* }* %0) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) + %1 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 0 + %control = load %Qubit*, %Qubit** %1 + %2 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 1 + %target = load %Qubit*, %Qubit** %2 + %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 + %ctls__1 = call %Array* @__quantum__rt__array_concatenate(%Array* %ctls, %Array* %3) call void @__quantum__rt__array_update_alias_count(%Array* %ctls__1, i64 1) - %54 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %55 = bitcast i8* %54 to %Qubit** - %qb__27 = load %Qubit*, %Qubit** %55 - br i1 true, label %then0__2, label %else__2 + %6 = call i64 @__quantum__rt__array_get_size_1d(%Array* %ctls__1) + %7 = icmp eq i64 %6, 1 + br i1 %7, label %then0__1, label %else__1 -then0__2: ; preds = %continue__1 - call void @__quantum__qis__single_qubit_op_ctl(i64 4, i64 1, %Array* %ctls__1, %Qubit* %qb__27) - br label %continue__2 +then0__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %ctls__1, %Qubit* %target) + br label %continue__1 -else__2: ; preds = %continue__1 - call void @__quantum__qis__single_qubit_op_ctl(i64 5, i64 1, %Array* %ctls__1, %Qubit* %qb__27) - br label %continue__2 +else__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %ctls__1, %Qubit* %target) + br label %continue__1 -continue__2: ; preds = %else__2, %then0__2 +continue__1: ; preds = %else__1, %then0__1 call void @__quantum__rt__array_update_alias_count(%Array* %ctls__1, i64 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %3, i64 -1) call void @__quantum__rt__array_update_reference_count(%Array* %ctls__1, i64 -1) - %ctls__2 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %56 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__2, i64 0) - %57 = bitcast i8* %56 to %Qubit** - store %Qubit* %c, %Qubit** %57 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__2, i64 1) - %58 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %59 = bitcast i8* %58 to %Qubit** - %qb__28 = load %Qubit*, %Qubit** %59 - br i1 true, label %then0__3, label %else__3 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) + ret void +} -then0__3: ; preds = %continue__2 - call void @__quantum__qis__single_qubit_op_ctl(i64 7, i64 1, %Array* %ctls__2, %Qubit* %qb__28) - br label %continue__3 +declare %Array* @__quantum__rt__array_concatenate(%Array*, %Array*) -else__3: ; preds = %continue__2 - call void @__quantum__qis__single_qubit_op_ctl(i64 8, i64 1, %Array* %ctls__2, %Qubit* %qb__28) - br label %continue__3 +declare i64 @__quantum__rt__array_get_size_1d(%Array*) -continue__3: ; preds = %else__3, %then0__3 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__2, i64 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls__2, i64 -1) - %ctls__3 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %60 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__3, i64 0) - %61 = bitcast i8* %60 to %Qubit** - store %Qubit* %c, %Qubit** %61 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__3, i64 1) - %62 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %63 = bitcast i8* %62 to %Qubit** - %qb__29 = load %Qubit*, %Qubit** %63 - call void @__quantum__qis__single_qubit_op_ctl(i64 10, i64 1, %Array* %ctls__3, %Qubit* %qb__29) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__3, i64 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls__3, i64 -1) - %ctls__4 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %64 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__4, i64 0) - %65 = bitcast i8* %64 to %Qubit** - store %Qubit* %c, %Qubit** %65 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__4, i64 1) - %66 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %67 = bitcast i8* %66 to %Qubit** - %qb__30 = load %Qubit*, %Qubit** %67 - call void @__quantum__qis__single_qubit_op_ctl(i64 20, i64 1, %Array* %ctls__4, %Qubit* %qb__30) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__4, i64 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls__4, i64 -1) - %ctls__5 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %68 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__5, i64 0) - %69 = bitcast i8* %68 to %Qubit** - store %Qubit* %c, %Qubit** %69 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__5, i64 1) - %70 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %71 = bitcast i8* %70 to %Qubit** - %qb__31 = load %Qubit*, %Qubit** %71 - call void @__quantum__qis__single_qubit_op_ctl(i64 22, i64 1, %Array* %ctls__5, %Qubit* %qb__31) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__5, i64 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls__5, i64 -1) - %ctls__6 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %72 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__6, i64 0) - %73 = bitcast i8* %72 to %Qubit** - store %Qubit* %c, %Qubit** %73 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__6, i64 1) - %74 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %75 = bitcast i8* %74 to %Qubit** - %qb__32 = load %Qubit*, %Qubit** %75 - call void @__quantum__qis__single_qubit_op_ctl(i64 25, i64 1, %Array* %ctls__6, %Qubit* %qb__32) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__6, i64 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls__6, i64 -1) - %ctls__7 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %76 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__7, i64 0) - %77 = bitcast i8* %76 to %Qubit** - store %Qubit* %c, %Qubit** %77 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__7, i64 1) - %78 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %79 = bitcast i8* %78 to %Qubit** - %qb__33 = load %Qubit*, %Qubit** %79 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__7, i64 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %ctls__7, %Qubit* %qb__33) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__7, i64 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__7, i64 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls__7, i64 -1) - %ctls__9 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %80 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__9, i64 0) - %81 = bitcast i8* %80 to %Qubit** - store %Qubit* %c, %Qubit** %81 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__9, i64 1) - %82 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %83 = bitcast i8* %82 to %Qubit** - %qb__35 = load %Qubit*, %Qubit** %83 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__9, i64 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %ctls__9, %Qubit* %qb__35) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__9, i64 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__9, i64 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls__9, i64 -1) - call void @__quantum__rt__qubit_release(%Qubit* %c) - %cc = call %Array* @__quantum__rt__qubit_allocate_array(i64 2) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) - %84 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %85 = bitcast i8* %84 to %Qubit** - %qb__37 = load %Qubit*, %Qubit** %85 - %86 = call i64 @__quantum__rt__array_get_size_1d(%Array* %cc) - %87 = icmp eq i64 %86, 1 - br i1 %87, label %then0__4, label %else__4 - -then0__4: ; preds = %continue__3 - call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %cc, %Qubit* %qb__37) - br label %continue__4 - -else__4: ; preds = %continue__3 - call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %cc, %Qubit* %qb__37) - br label %continue__4 - -continue__4: ; preds = %else__4, %then0__4 - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) - %88 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %89 = bitcast i8* %88 to %Qubit** - %qb__38 = load %Qubit*, %Qubit** %89 - %90 = icmp eq i64 %86, 1 - br i1 %90, label %then0__5, label %else__5 - -then0__5: ; preds = %continue__4 - call void @__quantum__qis__single_qubit_op_ctl(i64 4, i64 1, %Array* %cc, %Qubit* %qb__38) - br label %continue__5 - -else__5: ; preds = %continue__4 - call void @__quantum__qis__single_qubit_op_ctl(i64 5, i64 1, %Array* %cc, %Qubit* %qb__38) - br label %continue__5 - -continue__5: ; preds = %else__5, %then0__5 - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) - %91 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %92 = bitcast i8* %91 to %Qubit** - %qb__39 = load %Qubit*, %Qubit** %92 - %93 = icmp eq i64 %86, 1 - br i1 %93, label %then0__6, label %else__6 +define void @Microsoft__Quantum__Intrinsic__CNOT__ctladj(%Array* %__controlQubits__, { %Qubit*, %Qubit* }* %0) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 1) + %1 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 0 + %control = load %Qubit*, %Qubit** %1 + %2 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 1 + %target = load %Qubit*, %Qubit** %2 + %3 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 2)) + %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 + store %Qubit* %target, %Qubit** %6 + call void @Microsoft__Quantum__Intrinsic__CNOT__ctl(%Array* %__controlQubits__, { %Qubit*, %Qubit* }* %4) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %3, i64 -1) + ret void +} -then0__6: ; preds = %continue__5 - call void @__quantum__qis__single_qubit_op_ctl(i64 7, i64 1, %Array* %cc, %Qubit* %qb__39) - br label %continue__6 +declare %Tuple* @__quantum__rt__tuple_create(i64) -else__6: ; preds = %continue__5 - call void @__quantum__qis__single_qubit_op_ctl(i64 8, i64 1, %Array* %cc, %Qubit* %qb__39) - br label %continue__6 +declare void @__quantum__rt__tuple_update_reference_count(%Tuple*, i64) -continue__6: ; preds = %else__6, %then0__6 - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) - %94 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %95 = bitcast i8* %94 to %Qubit** - %qb__40 = load %Qubit*, %Qubit** %95 - call void @__quantum__qis__single_qubit_op_ctl(i64 10, i64 1, %Array* %cc, %Qubit* %qb__40) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) - %96 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %97 = bitcast i8* %96 to %Qubit** - %qb__41 = load %Qubit*, %Qubit** %97 - call void @__quantum__qis__single_qubit_op_ctl(i64 20, i64 1, %Array* %cc, %Qubit* %qb__41) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) - %98 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %99 = bitcast i8* %98 to %Qubit** - %qb__42 = load %Qubit*, %Qubit** %99 - call void @__quantum__qis__single_qubit_op_ctl(i64 22, i64 1, %Array* %cc, %Qubit* %qb__42) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) - %100 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %101 = bitcast i8* %100 to %Qubit** - %qb__43 = load %Qubit*, %Qubit** %101 - call void @__quantum__qis__single_qubit_op_ctl(i64 25, i64 1, %Array* %cc, %Qubit* %qb__43) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) - %102 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %103 = bitcast i8* %102 to %Qubit** - %qb__44 = load %Qubit*, %Qubit** %103 - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %cc, %Qubit* %qb__44) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) - %104 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %105 = bitcast i8* %104 to %Qubit** - %qb__46 = load %Qubit*, %Qubit** %105 - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %cc, %Qubit* %qb__46) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) - call void @__quantum__rt__qubit_release_array(%Array* %cc) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %cc, i64 -1) - call void @__quantum__rt__qubit_release_array(%Array* %qs) - call void @__quantum__rt__array_update_alias_count(%Array* %qs, i64 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %qs, i64 -1) +define void @Microsoft__Quantum__Intrinsic__H__body(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 9, i64 1, %Qubit* %qb) ret void } -declare %Qubit* @__quantum__rt__qubit_allocate() +declare void @__quantum__qis__single_qubit_op(i64, i64, %Qubit*) -declare %Array* @__quantum__rt__qubit_allocate_array(i64) +define void @Microsoft__Quantum__Intrinsic__H__adj(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 9, i64 1, %Qubit* %qb) + ret void +} -define void @Microsoft__Quantum__Intrinsic__CNOT__body(%Qubit* %control, %Qubit* %target) { +define void @Microsoft__Quantum__Intrinsic__H__ctl(%Array* %ctls, %Qubit* %qb) { entry: - %ctls = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %0 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 0) - %1 = bitcast i8* %0 to %Qubit** - store %Qubit* %control, %Qubit** %1 call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) - br i1 true, label %then0__1, label %else__1 - -then0__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %ctls, %Qubit* %target) - br label %continue__1 - -else__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %ctls, %Qubit* %target) - br label %continue__1 - -continue__1: ; preds = %else__1, %then0__1 + call void @__quantum__qis__single_qubit_op_ctl(i64 10, i64 1, %Array* %ctls, %Qubit* %qb) call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls, i64 -1) ret void } -declare void @__quantum__qis__inject_barrier(i64, i64) - -define void @Microsoft__Quantum__Intrinsic__CNOT__adj(%Qubit* %control, %Qubit* %target) { +define void @Microsoft__Quantum__Intrinsic__H__ctladj(%Array* %__controlQubits__, %Qubit* %qb) { entry: - call void @Microsoft__Quantum__Intrinsic__CNOT__body(%Qubit* %control, %Qubit* %target) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 1) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 10, i64 1, %Array* %__controlQubits__, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 -1) ret void } -declare %Array* @__quantum__rt__array_create_1d(i32, i64) - -declare void @__quantum__qis__single_qubit_op_ctl(i64, i64, %Array*, %Qubit*) - -declare void @__quantum__rt__array_update_reference_count(%Array*, i64) - -declare void @__quantum__rt__qubit_release(%Qubit*) +define %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %qb) { +entry: + %0 = call %Result* @__quantum__qis__single_qubit_measure(i64 100, i64 1, %Qubit* %qb) + ret %Result* %0 +} -declare void @__quantum__rt__qubit_release_array(%Array*) +declare %Result* @__quantum__qis__single_qubit_measure(i64, i64, %Qubit*) -define void @Microsoft__Quantum__Testing__Tracer__TestMeasurements__body(i1 %compare) { +define %Result* @Microsoft__Quantum__Intrinsic__Measure__body(%Array* %paulis, %Array* %qubits) { entry: - %qs = call %Array* @__quantum__rt__qubit_allocate_array(i64 3) - call void @__quantum__rt__array_update_alias_count(%Array* %qs, i64 1) - %0 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %1 = bitcast i8* %0 to %Qubit** - %qb = load %Qubit*, %Qubit** %1 - %r0 = call %Result* @__quantum__qis__single_qubit_measure(i64 100, i64 1, %Qubit* %qb) - %qs12 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 2) - %2 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs12, i64 0) - %3 = bitcast i8* %2 to %Qubit** - %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs12, i64 1) - %5 = bitcast i8* %4 to %Qubit** - %6 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %7 = bitcast i8* %6 to %Qubit** - %8 = load %Qubit*, %Qubit** %7 - %9 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %10 = bitcast i8* %9 to %Qubit** - %11 = load %Qubit*, %Qubit** %10 - store %Qubit* %8, %Qubit** %3 - store %Qubit* %11, %Qubit** %5 - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 1) - %paulis = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 2) - %12 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) - %13 = bitcast i8* %12 to i2* - %14 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) - %15 = bitcast i8* %14 to i2* - %16 = load i2, i2* @PauliY - %17 = load i2, i2* @PauliX - store i2 %16, i2* %13 - store i2 %17, i2* %15 call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i64 1) - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 1) - %18 = load %Result*, %Result** @ResultOne + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i64 1) + %0 = load %Result*, %Result** @ResultOne %res = alloca %Result* - store %Result* %18, %Result** %res - call void @__quantum__rt__result_update_reference_count(%Result* %18, i64 1) + store %Result* %0, %Result** %res + call void @__quantum__rt__result_update_reference_count(%Result* %0, i64 1) %haveY = alloca i1 store i1 false, i1* %haveY + %1 = call i64 @__quantum__rt__array_get_size_1d(%Array* %paulis) + %2 = sub i64 %1, 1 br label %header__1 header__1: ; preds = %exiting__1, %entry - %i = phi i64 [ 0, %entry ], [ %31, %exiting__1 ] - %19 = icmp sle i64 %i, 1 - br i1 %19, label %body__1, label %exit__1 + %i = phi i64 [ 0, %entry ], [ %15, %exiting__1 ] + %3 = icmp sle i64 %i, %2 + br i1 %3, label %body__1, label %exit__1 body__1: ; preds = %header__1 - %20 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 %i) - %21 = bitcast i8* %20 to i2* - %22 = load i2, i2* %21 - %23 = load i2, i2* @PauliY - %24 = icmp eq i2 %22, %23 - %25 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 %i) - %26 = bitcast i8* %25 to i2* - %27 = load i2, i2* %26 - %28 = load i2, i2* @PauliI - %29 = icmp eq i2 %27, %28 - %30 = or i1 %24, %29 - br i1 %30, label %then0__1, label %continue__1 + %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 %i) + %5 = bitcast i8* %4 to i2* + %6 = load i2, i2* %5 + %7 = load i2, i2* @PauliY + %8 = icmp eq i2 %6, %7 + %9 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 %i) + %10 = bitcast i8* %9 to i2* + %11 = load i2, i2* %10 + %12 = load i2, i2* @PauliI + %13 = icmp eq i2 %11, %12 + %14 = or i1 %8, %13 + br i1 %14, label %then0__1, label %continue__1 then0__1: ; preds = %body__1 store i1 true, i1* %haveY @@ -496,386 +297,45 @@ continue__1: ; preds = %then0__1, %body__1 br label %exiting__1 exiting__1: ; preds = %continue__1 - %31 = add i64 %i, 1 + %15 = add i64 %i, 1 br label %header__1 exit__1: ; preds = %header__1 - %32 = load i1, i1* %haveY - br i1 %32, label %then0__2, label %test1__1 + %16 = load i1, i1* %haveY + br i1 %16, label %then0__2, label %test1__1 then0__2: ; preds = %exit__1 - %33 = call %Result* @__quantum__qis__joint_measure(i64 106, i64 1, %Array* %qs12) - call void @__quantum__rt__result_update_reference_count(%Result* %33, i64 1) - store %Result* %33, %Result** %res - call void @__quantum__rt__result_update_reference_count(%Result* %33, i64 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %18, i64 -1) + %17 = call %Result* @__quantum__qis__joint_measure(i64 106, i64 1, %Array* %qubits) + call void @__quantum__rt__result_update_reference_count(%Result* %17, i64 1) + store %Result* %17, %Result** %res + call void @__quantum__rt__result_update_reference_count(%Result* %17, i64 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %0, i64 -1) br label %continue__2 test1__1: ; preds = %exit__1 - br i1 false, label %then1__1, label %test2__1 + %18 = icmp sgt i64 %1, 2 + br i1 %18, label %then1__1, label %test2__1 then1__1: ; preds = %test1__1 - %34 = call %Result* @__quantum__qis__joint_measure(i64 107, i64 1, %Array* %qs12) - call void @__quantum__rt__result_update_reference_count(%Result* %34, i64 1) - %35 = load %Result*, %Result** %res - store %Result* %34, %Result** %res - call void @__quantum__rt__result_update_reference_count(%Result* %34, i64 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %35, i64 -1) + %19 = call %Result* @__quantum__qis__joint_measure(i64 107, i64 1, %Array* %qubits) + call void @__quantum__rt__result_update_reference_count(%Result* %19, i64 1) + %20 = load %Result*, %Result** %res + store %Result* %19, %Result** %res + call void @__quantum__rt__result_update_reference_count(%Result* %19, i64 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %20, i64 -1) br label %continue__2 test2__1: ; preds = %test1__1 - br i1 false, label %then2__1, label %test3__1 + %21 = icmp eq i64 %1, 1 + br i1 %21, label %then2__1, label %test3__1 then2__1: ; preds = %test2__1 - %36 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) - %37 = bitcast i8* %36 to i2* - %38 = load i2, i2* %37 - %39 = load i2, i2* @PauliX - %40 = icmp eq i2 %38, %39 - br i1 %40, label %then0__3, label %else__1 - -then0__3: ; preds = %then2__1 - %41 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs12, i64 0) - %42 = bitcast i8* %41 to %Qubit** - %qb__2 = load %Qubit*, %Qubit** %42 - %43 = call %Result* @__quantum__qis__single_qubit_measure(i64 101, i64 1, %Qubit* %qb__2) - call void @__quantum__rt__result_update_reference_count(%Result* %43, i64 1) - %44 = load %Result*, %Result** %res - store %Result* %43, %Result** %res - call void @__quantum__rt__result_update_reference_count(%Result* %43, i64 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %44, i64 -1) - br label %continue__3 - -else__1: ; preds = %then2__1 - %45 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs12, i64 0) - %46 = bitcast i8* %45 to %Qubit** - %qb__3 = load %Qubit*, %Qubit** %46 - %47 = call %Result* @__quantum__qis__single_qubit_measure(i64 100, i64 1, %Qubit* %qb__3) - call void @__quantum__rt__result_update_reference_count(%Result* %47, i64 1) - %48 = load %Result*, %Result** %res - store %Result* %47, %Result** %res - call void @__quantum__rt__result_update_reference_count(%Result* %47, i64 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %48, i64 -1) - br label %continue__3 - -continue__3: ; preds = %else__1, %then0__3 - br label %continue__2 - -test3__1: ; preds = %test2__1 - %49 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) - %50 = bitcast i8* %49 to i2* - %51 = load i2, i2* %50 - %52 = load i2, i2* @PauliX - %53 = icmp eq i2 %51, %52 - %54 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) - %55 = bitcast i8* %54 to i2* - %56 = load i2, i2* %55 - %57 = load i2, i2* @PauliX - %58 = icmp eq i2 %56, %57 - %59 = and i1 %53, %58 - br i1 %59, label %then3__1, label %test4__1 - -then3__1: ; preds = %test3__1 - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 1) - %60 = call %Result* @__quantum__qis__joint_measure(i64 105, i64 1, %Array* %qs12) - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %60, i64 1) - %61 = load %Result*, %Result** %res - store %Result* %60, %Result** %res - call void @__quantum__rt__result_update_reference_count(%Result* %60, i64 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %61, i64 -1) - br label %continue__2 - -test4__1: ; preds = %test3__1 - %62 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) - %63 = bitcast i8* %62 to i2* - %64 = load i2, i2* %63 - %65 = load i2, i2* @PauliX - %66 = icmp eq i2 %64, %65 - %67 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) - %68 = bitcast i8* %67 to i2* - %69 = load i2, i2* %68 - %70 = load i2, i2* @PauliZ - %71 = icmp eq i2 %69, %70 - %72 = and i1 %66, %71 - br i1 %72, label %then4__1, label %test5__1 - -then4__1: ; preds = %test4__1 - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 1) - %73 = call %Result* @__quantum__qis__joint_measure(i64 103, i64 1, %Array* %qs12) - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %73, i64 1) - %74 = load %Result*, %Result** %res - store %Result* %73, %Result** %res - call void @__quantum__rt__result_update_reference_count(%Result* %73, i64 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %74, i64 -1) - br label %continue__2 - -test5__1: ; preds = %test4__1 - %75 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) - %76 = bitcast i8* %75 to i2* - %77 = load i2, i2* %76 - %78 = load i2, i2* @PauliZ - %79 = icmp eq i2 %77, %78 - %80 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) - %81 = bitcast i8* %80 to i2* - %82 = load i2, i2* %81 - %83 = load i2, i2* @PauliX - %84 = icmp eq i2 %82, %83 - %85 = and i1 %79, %84 - br i1 %85, label %then5__1, label %test6__1 - -then5__1: ; preds = %test5__1 - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 1) - %86 = call %Result* @__quantum__qis__joint_measure(i64 104, i64 1, %Array* %qs12) - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %86, i64 1) - %87 = load %Result*, %Result** %res - store %Result* %86, %Result** %res - call void @__quantum__rt__result_update_reference_count(%Result* %86, i64 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %87, i64 -1) - br label %continue__2 - -test6__1: ; preds = %test5__1 - %88 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) - %89 = bitcast i8* %88 to i2* - %90 = load i2, i2* %89 - %91 = load i2, i2* @PauliZ - %92 = icmp eq i2 %90, %91 - %93 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) - %94 = bitcast i8* %93 to i2* - %95 = load i2, i2* %94 - %96 = load i2, i2* @PauliZ - %97 = icmp eq i2 %95, %96 - %98 = and i1 %92, %97 - br i1 %98, label %then6__1, label %continue__2 - -then6__1: ; preds = %test6__1 - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 1) - %99 = call %Result* @__quantum__qis__joint_measure(i64 102, i64 1, %Array* %qs12) - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %99, i64 1) - %100 = load %Result*, %Result** %res - store %Result* %99, %Result** %res - call void @__quantum__rt__result_update_reference_count(%Result* %99, i64 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %100, i64 -1) - br label %continue__2 - -continue__2: ; preds = %then6__1, %test6__1, %then5__1, %then4__1, %then3__1, %continue__3, %then1__1, %then0__2 - %r12 = load %Result*, %Result** %res - call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i64 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %paulis, i64 -1) - br i1 %compare, label %then0__4, label %continue__4 - -then0__4: ; preds = %continue__2 - %101 = load %Result*, %Result** @ResultZero - %102 = call i1 @__quantum__rt__result_equal(%Result* %r0, %Result* %101) - br i1 %102, label %then0__5, label %continue__5 - -then0__5: ; preds = %then0__4 - %103 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %104 = bitcast i8* %103 to %Qubit** - %qb__4 = load %Qubit*, %Qubit** %104 - call void @__quantum__qis__single_qubit_op(i64 0, i64 1, %Qubit* %qb__4) - br label %continue__5 - -continue__5: ; preds = %then0__5, %then0__4 - br label %continue__4 - -continue__4: ; preds = %continue__5, %continue__2 - call void @__quantum__rt__qubit_release_array(%Array* %qs) - call void @__quantum__rt__array_update_alias_count(%Array* %qs, i64 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %qs, i64 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %r0, i64 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %qs12, i64 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %r12, i64 -1) - ret void -} - -declare %Result* @__quantum__qis__single_qubit_measure(i64, i64, %Qubit*) - -declare void @__quantum__rt__result_update_reference_count(%Result*, i64) - -declare %Result* @__quantum__qis__joint_measure(i64, i64, %Array*) - -declare i1 @__quantum__rt__result_equal(%Result*, %Result*) - -define void @Microsoft__Quantum__Intrinsic__CNOT__ctl(%Array* %ctls, { %Qubit*, %Qubit* }* %0) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) - %1 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 0 - %control = load %Qubit*, %Qubit** %1 - %2 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 1 - %target = load %Qubit*, %Qubit** %2 - %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 - %ctls__1 = call %Array* @__quantum__rt__array_concatenate(%Array* %ctls, %Array* %3) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__1, i64 1) - %6 = call i64 @__quantum__rt__array_get_size_1d(%Array* %ctls__1) - %7 = icmp eq i64 %6, 1 - br i1 %7, label %then0__1, label %else__1 - -then0__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %ctls__1, %Qubit* %target) - br label %continue__1 - -else__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %ctls__1, %Qubit* %target) - br label %continue__1 - -continue__1: ; preds = %else__1, %then0__1 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__1, i64 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %3, i64 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls__1, i64 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) - ret void -} - -declare %Array* @__quantum__rt__array_concatenate(%Array*, %Array*) - -define void @Microsoft__Quantum__Intrinsic__CNOT__ctladj(%Array* %__controlQubits__, { %Qubit*, %Qubit* }* %0) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 1) - %1 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 0 - %control = load %Qubit*, %Qubit** %1 - %2 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 1 - %target = load %Qubit*, %Qubit** %2 - %3 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 2)) - %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 - store %Qubit* %target, %Qubit** %6 - call void @Microsoft__Quantum__Intrinsic__CNOT__ctl(%Array* %__controlQubits__, { %Qubit*, %Qubit* }* %4) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %3, i64 -1) - ret void -} - -declare %Tuple* @__quantum__rt__tuple_create(i64) - -declare void @__quantum__rt__tuple_update_reference_count(%Tuple*, i64) - -define void @Microsoft__Quantum__Intrinsic__H__body(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 9, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__H__adj(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 9, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__H__ctl(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 10, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__H__ctladj(%Array* %__controlQubits__, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 1) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 10, i64 1, %Array* %__controlQubits__, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 -1) - ret void -} - -define %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %qb) { -entry: - %0 = call %Result* @__quantum__qis__single_qubit_measure(i64 100, i64 1, %Qubit* %qb) - ret %Result* %0 -} - -define %Result* @Microsoft__Quantum__Intrinsic__Measure__body(%Array* %paulis, %Array* %qubits) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i64 1) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i64 1) - %0 = load %Result*, %Result** @ResultOne - %res = alloca %Result* - store %Result* %0, %Result** %res - call void @__quantum__rt__result_update_reference_count(%Result* %0, i64 1) - %haveY = alloca i1 - store i1 false, i1* %haveY - %1 = call i64 @__quantum__rt__array_get_size_1d(%Array* %paulis) - %2 = sub i64 %1, 1 - br label %header__1 - -header__1: ; preds = %exiting__1, %entry - %i = phi i64 [ 0, %entry ], [ %15, %exiting__1 ] - %3 = icmp sle i64 %i, %2 - br i1 %3, label %body__1, label %exit__1 - -body__1: ; preds = %header__1 - %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 %i) - %5 = bitcast i8* %4 to i2* - %6 = load i2, i2* %5 - %7 = load i2, i2* @PauliY - %8 = icmp eq i2 %6, %7 - %9 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 %i) - %10 = bitcast i8* %9 to i2* - %11 = load i2, i2* %10 - %12 = load i2, i2* @PauliI - %13 = icmp eq i2 %11, %12 - %14 = or i1 %8, %13 - br i1 %14, label %then0__1, label %continue__1 - -then0__1: ; preds = %body__1 - store i1 true, i1* %haveY - br label %continue__1 - -continue__1: ; preds = %then0__1, %body__1 - br label %exiting__1 - -exiting__1: ; preds = %continue__1 - %15 = add i64 %i, 1 - br label %header__1 - -exit__1: ; preds = %header__1 - %16 = load i1, i1* %haveY - br i1 %16, label %then0__2, label %test1__1 - -then0__2: ; preds = %exit__1 - %17 = call %Result* @__quantum__qis__joint_measure(i64 106, i64 1, %Array* %qubits) - call void @__quantum__rt__result_update_reference_count(%Result* %17, i64 1) - store %Result* %17, %Result** %res - call void @__quantum__rt__result_update_reference_count(%Result* %17, i64 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %0, i64 -1) - br label %continue__2 - -test1__1: ; preds = %exit__1 - %18 = icmp sgt i64 %1, 2 - br i1 %18, label %then1__1, label %test2__1 - -then1__1: ; preds = %test1__1 - %19 = call %Result* @__quantum__qis__joint_measure(i64 107, i64 1, %Array* %qubits) - call void @__quantum__rt__result_update_reference_count(%Result* %19, i64 1) - %20 = load %Result*, %Result** %res - store %Result* %19, %Result** %res - call void @__quantum__rt__result_update_reference_count(%Result* %19, i64 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %20, i64 -1) - br label %continue__2 - -test2__1: ; preds = %test1__1 - %21 = icmp eq i64 %1, 1 - br i1 %21, label %then2__1, label %test3__1 - -then2__1: ; preds = %test2__1 - %22 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) - %23 = bitcast i8* %22 to i2* - %24 = load i2, i2* %23 - %25 = load i2, i2* @PauliX - %26 = icmp eq i2 %24, %25 - br i1 %26, label %then0__3, label %else__1 + %22 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) + %23 = bitcast i8* %22 to i2* + %24 = load i2, i2* %23 + %25 = load i2, i2* @PauliX + %26 = icmp eq i2 %24, %25 + br i1 %26, label %then0__3, label %else__1 then0__3: ; preds = %then2__1 %27 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qubits, i64 0) @@ -1011,6 +471,8 @@ continue__2: ; preds = %then6__1, %test6__1 ret %Result* %87 } +declare %Result* @__quantum__qis__joint_measure(i64, i64, %Array*) + define void @Microsoft__Quantum__Intrinsic__Rx__body(double %theta, %Qubit* %qb) { entry: call void @__quantum__qis__single_qubit_op(i64 19, i64 1, %Qubit* %qb) @@ -1091,7 +553,7 @@ entry: define void @Microsoft__Quantum__Intrinsic__Rz__adj(double %theta, %Qubit* %qb) { entry: - call void @__quantum__qis__single_qubit_op(i64 24, i64 1, %Qubit* %qb) + call void @__quantum__qis__single_qubit_op(i64 23, i64 1, %Qubit* %qb) ret void } @@ -1102,7 +564,7 @@ entry: %theta = load double, double* %1 %2 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 1 %qb = load %Qubit*, %Qubit** %2 - call void @__quantum__qis__single_qubit_op_ctl(i64 25, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__qis__single_qubit_op_ctl(i64 24, i64 1, %Array* %ctls, %Qubit* %qb) call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) ret void } @@ -1114,7 +576,7 @@ entry: %theta = load double, double* %1 %2 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 1 %qb = load %Qubit*, %Qubit** %2 - call void @__quantum__qis__single_qubit_op_ctl(i64 25, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__qis__single_qubit_op_ctl(i64 24, i64 1, %Array* %ctls, %Qubit* %qb) call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) ret void } @@ -1223,299 +685,1325 @@ entry: %1 = icmp eq i64 %0, 1 br i1 %1, label %then0__1, label %else__1 -then0__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %__controlQubits__, %Qubit* %qb) - br label %continue__1 +then0__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %__controlQubits__, %Qubit* %qb) + br label %continue__1 + +else__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %__controlQubits__, %Qubit* %qb) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Y__body(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 3, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Y__adj(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 3, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Y__ctl(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) + %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %ctls) + %1 = icmp eq i64 %0, 1 + br i1 %1, label %then0__1, label %else__1 + +then0__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 4, i64 1, %Array* %ctls, %Qubit* %qb) + br label %continue__1 + +else__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 5, i64 1, %Array* %ctls, %Qubit* %qb) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Y__ctladj(%Array* %__controlQubits__, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 1) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 1) + %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %__controlQubits__) + %1 = icmp eq i64 %0, 1 + br i1 %1, label %then0__1, label %else__1 + +then0__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 4, i64 1, %Array* %__controlQubits__, %Qubit* %qb) + br label %continue__1 + +else__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 5, i64 1, %Array* %__controlQubits__, %Qubit* %qb) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Z__body(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 6, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Z__adj(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 6, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Z__ctl(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) + %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %ctls) + %1 = icmp eq i64 %0, 1 + br i1 %1, label %then0__1, label %else__1 + +then0__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 7, i64 1, %Array* %ctls, %Qubit* %qb) + br label %continue__1 + +else__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 8, i64 1, %Array* %ctls, %Qubit* %qb) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Z__ctladj(%Array* %__controlQubits__, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 1) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 1) + %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %__controlQubits__) + %1 = icmp eq i64 %0, 1 + br i1 %1, label %then0__1, label %else__1 + +then0__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 7, i64 1, %Array* %__controlQubits__, %Qubit* %qb) + br label %continue__1 + +else__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 8, i64 1, %Array* %__controlQubits__, %Qubit* %qb) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 -1) + ret void +} + +define %Tuple* @Microsoft__Quantum__Core__Attribute__body() { +entry: + ret %Tuple* null +} + +define %Tuple* @Microsoft__Quantum__Core__EntryPoint__body() { +entry: + ret %Tuple* null +} + +define %Tuple* @Microsoft__Quantum__Core__Inline__body() { +entry: + ret %Tuple* null +} + +define %Result* @Microsoft__Quantum__Instructions__Mx__body(%Qubit* %qb) { +entry: + %0 = call %Result* @__quantum__qis__single_qubit_measure(i64 101, i64 1, %Qubit* %qb) + ret %Result* %0 +} + +define %Result* @Microsoft__Quantum__Instructions__Mxx__body(%Array* %qubits) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i64 1) + %0 = call %Result* @__quantum__qis__joint_measure(i64 105, i64 1, %Array* %qubits) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i64 -1) + ret %Result* %0 +} + +define %Result* @Microsoft__Quantum__Instructions__Mxz__body(%Array* %qubits) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i64 1) + %0 = call %Result* @__quantum__qis__joint_measure(i64 103, i64 1, %Array* %qubits) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i64 -1) + ret %Result* %0 +} + +define %Result* @Microsoft__Quantum__Instructions__Mz__body(%Qubit* %qb) { +entry: + %0 = call %Result* @__quantum__qis__single_qubit_measure(i64 100, i64 1, %Qubit* %qb) + ret %Result* %0 +} + +define %Result* @Microsoft__Quantum__Instructions__Mzx__body(%Array* %qubits) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i64 1) + %0 = call %Result* @__quantum__qis__joint_measure(i64 104, i64 1, %Array* %qubits) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i64 -1) + ret %Result* %0 +} + +define %Result* @Microsoft__Quantum__Instructions__Mzz__body(%Array* %qubits) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i64 1) + %0 = call %Result* @__quantum__qis__joint_measure(i64 102, i64 1, %Array* %qubits) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i64 -1) + ret %Result* %0 +} + +define void @Microsoft__Quantum__Instructions__Sx__body(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 17, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Instructions__Sx__adj(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 17, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Instructions__Sx__ctl(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 18, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) + ret void +} + +define void @Microsoft__Quantum__Instructions__Sx__ctladj(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 18, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) + ret void +} + +define void @Microsoft__Quantum__Instructions__Sz__body(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Instructions__Sz__adj(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Instructions__Sz__ctl(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) + ret void +} + +define void @Microsoft__Quantum__Instructions__Sz__ctladj(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) + ret void +} + +define void @Microsoft__Quantum__Instructions__Tx__body(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 13, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Instructions__Tx__adj(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 13, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Instructions__Tx__ctl(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 14, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) + ret void +} + +define void @Microsoft__Quantum__Instructions__Tx__ctladj(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 14, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) + ret void +} + +define void @Microsoft__Quantum__Instructions__Tz__body(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Instructions__Tz__adj(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Instructions__Tz__ctl(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) + ret void +} + +define void @Microsoft__Quantum__Instructions__Tz__ctladj(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) + ret void +} + +define void @Microsoft__Quantum__Testing__Tracer__Delay__body(%Callable* %op, %Qubit* %arg, %Tuple* %aux) { +entry: + call void @__quantum__rt__callable_memory_management(i32 1, %Callable* %op, i64 1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %op, i64 1) + %0 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64)) + %1 = bitcast %Tuple* %0 to { %Qubit* }* + %2 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %1, i32 0, i32 0 + store %Qubit* %arg, %Qubit** %2 + call void @__quantum__rt__callable_invoke(%Callable* %op, %Tuple* %0, %Tuple* null) + call void @__quantum__rt__callable_memory_management(i32 1, %Callable* %op, i64 -1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %op, i64 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %0, i64 -1) + ret void +} + +declare void @__quantum__rt__callable_invoke(%Callable*, %Tuple*, %Tuple*) + +define void @Microsoft__Quantum__Testing__Tracer__TestCoreIntrinsics__body() { +entry: + %qs = call %Array* @__quantum__rt__qubit_allocate_array(i64 3) + call void @__quantum__rt__array_update_alias_count(%Array* %qs, i64 1) + %0 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %1 = bitcast i8* %0 to %Qubit** + %qb = load %Qubit*, %Qubit** %1 + call void @__quantum__qis__single_qubit_op(i64 0, i64 1, %Qubit* %qb) + %2 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %3 = bitcast i8* %2 to %Qubit** + %qb__1 = load %Qubit*, %Qubit** %3 + call void @__quantum__qis__single_qubit_op(i64 3, i64 1, %Qubit* %qb__1) + %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %5 = bitcast i8* %4 to %Qubit** + %qb__2 = load %Qubit*, %Qubit** %5 + call void @__quantum__qis__single_qubit_op(i64 6, i64 1, %Qubit* %qb__2) + %6 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %7 = bitcast i8* %6 to %Qubit** + %qb__3 = load %Qubit*, %Qubit** %7 + call void @__quantum__qis__single_qubit_op(i64 9, i64 1, %Qubit* %qb__3) + %8 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %9 = bitcast i8* %8 to %Qubit** + %10 = load %Qubit*, %Qubit** %9 + %11 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %12 = bitcast i8* %11 to %Qubit** + %13 = load %Qubit*, %Qubit** %12 + call void @Microsoft__Quantum__Intrinsic__CNOT__body(%Qubit* %10, %Qubit* %13) + %14 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %15 = bitcast i8* %14 to %Qubit** + %qb__4 = load %Qubit*, %Qubit** %15 + call void @__quantum__qis__single_qubit_op(i64 19, i64 1, %Qubit* %qb__4) + %16 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %17 = bitcast i8* %16 to %Qubit** + %qb__5 = load %Qubit*, %Qubit** %17 + call void @__quantum__qis__single_qubit_op(i64 21, i64 1, %Qubit* %qb__5) + %18 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %19 = bitcast i8* %18 to %Qubit** + %qb__6 = load %Qubit*, %Qubit** %19 + call void @__quantum__qis__single_qubit_op(i64 23, i64 1, %Qubit* %qb__6) + %20 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %21 = bitcast i8* %20 to %Qubit** + %qb__7 = load %Qubit*, %Qubit** %21 + call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb__7) + %22 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %23 = bitcast i8* %22 to %Qubit** + %qb__9 = load %Qubit*, %Qubit** %23 + call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb__9) + call void @__quantum__qis__inject_barrier(i64 42, i64 0) + %24 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %25 = bitcast i8* %24 to %Qubit** + %qb__11 = load %Qubit*, %Qubit** %25 + call void @__quantum__qis__single_qubit_op(i64 0, i64 1, %Qubit* %qb__11) + %26 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %27 = bitcast i8* %26 to %Qubit** + %qb__13 = load %Qubit*, %Qubit** %27 + call void @__quantum__qis__single_qubit_op(i64 3, i64 1, %Qubit* %qb__13) + %28 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %29 = bitcast i8* %28 to %Qubit** + %qb__15 = load %Qubit*, %Qubit** %29 + call void @__quantum__qis__single_qubit_op(i64 6, i64 1, %Qubit* %qb__15) + %30 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %31 = bitcast i8* %30 to %Qubit** + %qb__17 = load %Qubit*, %Qubit** %31 + call void @__quantum__qis__single_qubit_op(i64 9, i64 1, %Qubit* %qb__17) + %32 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %33 = bitcast i8* %32 to %Qubit** + %34 = load %Qubit*, %Qubit** %33 + %35 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %36 = bitcast i8* %35 to %Qubit** + %37 = load %Qubit*, %Qubit** %36 + call void @Microsoft__Quantum__Intrinsic__CNOT__adj(%Qubit* %34, %Qubit* %37) + %38 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %39 = bitcast i8* %38 to %Qubit** + %qb__19 = load %Qubit*, %Qubit** %39 + call void @__quantum__qis__single_qubit_op(i64 19, i64 1, %Qubit* %qb__19) + %40 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %41 = bitcast i8* %40 to %Qubit** + %qb__20 = load %Qubit*, %Qubit** %41 + call void @__quantum__qis__single_qubit_op(i64 21, i64 1, %Qubit* %qb__20) + %42 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %43 = bitcast i8* %42 to %Qubit** + %qb__21 = load %Qubit*, %Qubit** %43 + call void @__quantum__qis__single_qubit_op(i64 23, i64 1, %Qubit* %qb__21) + %44 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %45 = bitcast i8* %44 to %Qubit** + %qb__22 = load %Qubit*, %Qubit** %45 + call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb__22) + %46 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %47 = bitcast i8* %46 to %Qubit** + %qb__24 = load %Qubit*, %Qubit** %47 + call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb__24) + %c = call %Qubit* @__quantum__rt__qubit_allocate() + %ctls = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %48 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 0) + %49 = bitcast i8* %48 to %Qubit** + store %Qubit* %c, %Qubit** %49 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) + %50 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %51 = bitcast i8* %50 to %Qubit** + %qb__26 = load %Qubit*, %Qubit** %51 + br i1 true, label %then0__1, label %else__1 + +then0__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %ctls, %Qubit* %qb__26) + br label %continue__1 + +else__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %ctls, %Qubit* %qb__26) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls, i64 -1) + %ctls__1 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %52 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__1, i64 0) + %53 = bitcast i8* %52 to %Qubit** + store %Qubit* %c, %Qubit** %53 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__1, i64 1) + %54 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %55 = bitcast i8* %54 to %Qubit** + %qb__27 = load %Qubit*, %Qubit** %55 + br i1 true, label %then0__2, label %else__2 + +then0__2: ; preds = %continue__1 + call void @__quantum__qis__single_qubit_op_ctl(i64 4, i64 1, %Array* %ctls__1, %Qubit* %qb__27) + br label %continue__2 + +else__2: ; preds = %continue__1 + call void @__quantum__qis__single_qubit_op_ctl(i64 5, i64 1, %Array* %ctls__1, %Qubit* %qb__27) + br label %continue__2 + +continue__2: ; preds = %else__2, %then0__2 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__1, i64 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls__1, i64 -1) + %ctls__2 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %56 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__2, i64 0) + %57 = bitcast i8* %56 to %Qubit** + store %Qubit* %c, %Qubit** %57 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__2, i64 1) + %58 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %59 = bitcast i8* %58 to %Qubit** + %qb__28 = load %Qubit*, %Qubit** %59 + br i1 true, label %then0__3, label %else__3 + +then0__3: ; preds = %continue__2 + call void @__quantum__qis__single_qubit_op_ctl(i64 7, i64 1, %Array* %ctls__2, %Qubit* %qb__28) + br label %continue__3 + +else__3: ; preds = %continue__2 + call void @__quantum__qis__single_qubit_op_ctl(i64 8, i64 1, %Array* %ctls__2, %Qubit* %qb__28) + br label %continue__3 + +continue__3: ; preds = %else__3, %then0__3 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__2, i64 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls__2, i64 -1) + %ctls__3 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %60 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__3, i64 0) + %61 = bitcast i8* %60 to %Qubit** + store %Qubit* %c, %Qubit** %61 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__3, i64 1) + %62 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %63 = bitcast i8* %62 to %Qubit** + %qb__29 = load %Qubit*, %Qubit** %63 + call void @__quantum__qis__single_qubit_op_ctl(i64 10, i64 1, %Array* %ctls__3, %Qubit* %qb__29) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__3, i64 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls__3, i64 -1) + %ctls__4 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %64 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__4, i64 0) + %65 = bitcast i8* %64 to %Qubit** + store %Qubit* %c, %Qubit** %65 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__4, i64 1) + %66 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %67 = bitcast i8* %66 to %Qubit** + %qb__30 = load %Qubit*, %Qubit** %67 + call void @__quantum__qis__single_qubit_op_ctl(i64 20, i64 1, %Array* %ctls__4, %Qubit* %qb__30) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__4, i64 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls__4, i64 -1) + %ctls__5 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %68 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__5, i64 0) + %69 = bitcast i8* %68 to %Qubit** + store %Qubit* %c, %Qubit** %69 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__5, i64 1) + %70 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %71 = bitcast i8* %70 to %Qubit** + %qb__31 = load %Qubit*, %Qubit** %71 + call void @__quantum__qis__single_qubit_op_ctl(i64 22, i64 1, %Array* %ctls__5, %Qubit* %qb__31) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__5, i64 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls__5, i64 -1) + %ctls__6 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %72 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__6, i64 0) + %73 = bitcast i8* %72 to %Qubit** + store %Qubit* %c, %Qubit** %73 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__6, i64 1) + %74 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %75 = bitcast i8* %74 to %Qubit** + %qb__32 = load %Qubit*, %Qubit** %75 + call void @__quantum__qis__single_qubit_op_ctl(i64 24, i64 1, %Array* %ctls__6, %Qubit* %qb__32) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__6, i64 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls__6, i64 -1) + %ctls__7 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %76 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__7, i64 0) + %77 = bitcast i8* %76 to %Qubit** + store %Qubit* %c, %Qubit** %77 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__7, i64 1) + %78 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %79 = bitcast i8* %78 to %Qubit** + %qb__33 = load %Qubit*, %Qubit** %79 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__7, i64 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %ctls__7, %Qubit* %qb__33) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__7, i64 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__7, i64 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls__7, i64 -1) + %ctls__9 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %80 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__9, i64 0) + %81 = bitcast i8* %80 to %Qubit** + store %Qubit* %c, %Qubit** %81 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__9, i64 1) + %82 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %83 = bitcast i8* %82 to %Qubit** + %qb__35 = load %Qubit*, %Qubit** %83 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__9, i64 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %ctls__9, %Qubit* %qb__35) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__9, i64 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__9, i64 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls__9, i64 -1) + call void @__quantum__rt__qubit_release(%Qubit* %c) + %cc = call %Array* @__quantum__rt__qubit_allocate_array(i64 2) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) + %84 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %85 = bitcast i8* %84 to %Qubit** + %qb__37 = load %Qubit*, %Qubit** %85 + %86 = call i64 @__quantum__rt__array_get_size_1d(%Array* %cc) + %87 = icmp eq i64 %86, 1 + br i1 %87, label %then0__4, label %else__4 + +then0__4: ; preds = %continue__3 + call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %cc, %Qubit* %qb__37) + br label %continue__4 + +else__4: ; preds = %continue__3 + call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %cc, %Qubit* %qb__37) + br label %continue__4 + +continue__4: ; preds = %else__4, %then0__4 + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) + %88 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %89 = bitcast i8* %88 to %Qubit** + %qb__38 = load %Qubit*, %Qubit** %89 + %90 = icmp eq i64 %86, 1 + br i1 %90, label %then0__5, label %else__5 + +then0__5: ; preds = %continue__4 + call void @__quantum__qis__single_qubit_op_ctl(i64 4, i64 1, %Array* %cc, %Qubit* %qb__38) + br label %continue__5 + +else__5: ; preds = %continue__4 + call void @__quantum__qis__single_qubit_op_ctl(i64 5, i64 1, %Array* %cc, %Qubit* %qb__38) + br label %continue__5 + +continue__5: ; preds = %else__5, %then0__5 + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) + %91 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %92 = bitcast i8* %91 to %Qubit** + %qb__39 = load %Qubit*, %Qubit** %92 + %93 = icmp eq i64 %86, 1 + br i1 %93, label %then0__6, label %else__6 + +then0__6: ; preds = %continue__5 + call void @__quantum__qis__single_qubit_op_ctl(i64 7, i64 1, %Array* %cc, %Qubit* %qb__39) + br label %continue__6 + +else__6: ; preds = %continue__5 + call void @__quantum__qis__single_qubit_op_ctl(i64 8, i64 1, %Array* %cc, %Qubit* %qb__39) + br label %continue__6 + +continue__6: ; preds = %else__6, %then0__6 + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) + %94 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %95 = bitcast i8* %94 to %Qubit** + %qb__40 = load %Qubit*, %Qubit** %95 + call void @__quantum__qis__single_qubit_op_ctl(i64 10, i64 1, %Array* %cc, %Qubit* %qb__40) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) + %96 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %97 = bitcast i8* %96 to %Qubit** + %qb__41 = load %Qubit*, %Qubit** %97 + call void @__quantum__qis__single_qubit_op_ctl(i64 20, i64 1, %Array* %cc, %Qubit* %qb__41) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) + %98 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %99 = bitcast i8* %98 to %Qubit** + %qb__42 = load %Qubit*, %Qubit** %99 + call void @__quantum__qis__single_qubit_op_ctl(i64 22, i64 1, %Array* %cc, %Qubit* %qb__42) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) + %100 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %101 = bitcast i8* %100 to %Qubit** + %qb__43 = load %Qubit*, %Qubit** %101 + call void @__quantum__qis__single_qubit_op_ctl(i64 24, i64 1, %Array* %cc, %Qubit* %qb__43) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) + %102 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %103 = bitcast i8* %102 to %Qubit** + %qb__44 = load %Qubit*, %Qubit** %103 + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %cc, %Qubit* %qb__44) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) + %104 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %105 = bitcast i8* %104 to %Qubit** + %qb__46 = load %Qubit*, %Qubit** %105 + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %cc, %Qubit* %qb__46) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) + call void @__quantum__rt__qubit_release_array(%Array* %cc) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i64 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %cc, i64 -1) + call void @__quantum__rt__qubit_release_array(%Array* %qs) + call void @__quantum__rt__array_update_alias_count(%Array* %qs, i64 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %qs, i64 -1) + ret void +} + +declare %Qubit* @__quantum__rt__qubit_allocate() + +declare %Array* @__quantum__rt__qubit_allocate_array(i64) + +declare void @__quantum__qis__inject_barrier(i64, i64) + +declare void @__quantum__rt__qubit_release(%Qubit*) + +declare void @__quantum__rt__qubit_release_array(%Array*) + +define void @Microsoft__Quantum__Testing__Tracer__TestMeasurements__body() { +entry: + %qs = call %Array* @__quantum__rt__qubit_allocate_array(i64 6) + call void @__quantum__rt__array_update_alias_count(%Array* %qs, i64 1) + %0 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %1 = bitcast i8* %0 to %Qubit** + %qb = load %Qubit*, %Qubit** %1 + call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb) + %2 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %3 = bitcast i8* %2 to %Qubit** + %qb__2 = load %Qubit*, %Qubit** %3 + %r0 = call %Result* @__quantum__qis__single_qubit_measure(i64 100, i64 1, %Qubit* %qb__2) + %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %5 = bitcast i8* %4 to %Qubit** + %qb__4 = load %Qubit*, %Qubit** %5 + call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb__4) + %6 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %7 = bitcast i8* %6 to %Qubit** + %8 = load %Qubit*, %Qubit** %7 + %9 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %10 = bitcast i8* %9 to %Qubit** + %11 = load %Qubit*, %Qubit** %10 + call void @Microsoft__Quantum__Intrinsic__CNOT__body(%Qubit* %8, %Qubit* %11) + %qs12 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 2) + %12 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs12, i64 0) + %13 = bitcast i8* %12 to %Qubit** + %14 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs12, i64 1) + %15 = bitcast i8* %14 to %Qubit** + %16 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %17 = bitcast i8* %16 to %Qubit** + %18 = load %Qubit*, %Qubit** %17 + %19 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %20 = bitcast i8* %19 to %Qubit** + %21 = load %Qubit*, %Qubit** %20 + store %Qubit* %18, %Qubit** %13 + store %Qubit* %21, %Qubit** %15 + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 1) + %paulis = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 2) + %22 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) + %23 = bitcast i8* %22 to i2* + %24 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) + %25 = bitcast i8* %24 to i2* + %26 = load i2, i2* @PauliY + %27 = load i2, i2* @PauliX + store i2 %26, i2* %23 + store i2 %27, i2* %25 + call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i64 1) + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 1) + %28 = load %Result*, %Result** @ResultOne + %res = alloca %Result* + store %Result* %28, %Result** %res + call void @__quantum__rt__result_update_reference_count(%Result* %28, i64 1) + %haveY = alloca i1 + store i1 false, i1* %haveY + br label %header__1 + +header__1: ; preds = %exiting__1, %entry + %i = phi i64 [ 0, %entry ], [ %41, %exiting__1 ] + %29 = icmp sle i64 %i, 1 + br i1 %29, label %body__1, label %exit__1 + +body__1: ; preds = %header__1 + %30 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 %i) + %31 = bitcast i8* %30 to i2* + %32 = load i2, i2* %31 + %33 = load i2, i2* @PauliY + %34 = icmp eq i2 %32, %33 + %35 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 %i) + %36 = bitcast i8* %35 to i2* + %37 = load i2, i2* %36 + %38 = load i2, i2* @PauliI + %39 = icmp eq i2 %37, %38 + %40 = or i1 %34, %39 + br i1 %40, label %then0__1, label %continue__1 -else__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %__controlQubits__, %Qubit* %qb) +then0__1: ; preds = %body__1 + store i1 true, i1* %haveY br label %continue__1 -continue__1: ; preds = %else__1, %then0__1 - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Y__body(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 3, i64 1, %Qubit* %qb) - ret void -} +continue__1: ; preds = %then0__1, %body__1 + br label %exiting__1 -define void @Microsoft__Quantum__Intrinsic__Y__adj(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 3, i64 1, %Qubit* %qb) - ret void -} +exiting__1: ; preds = %continue__1 + %41 = add i64 %i, 1 + br label %header__1 -define void @Microsoft__Quantum__Intrinsic__Y__ctl(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) - %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %ctls) - %1 = icmp eq i64 %0, 1 - br i1 %1, label %then0__1, label %else__1 +exit__1: ; preds = %header__1 + %42 = load i1, i1* %haveY + br i1 %42, label %then0__2, label %test1__1 -then0__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 4, i64 1, %Array* %ctls, %Qubit* %qb) - br label %continue__1 +then0__2: ; preds = %exit__1 + %43 = call %Result* @__quantum__qis__joint_measure(i64 106, i64 1, %Array* %qs12) + call void @__quantum__rt__result_update_reference_count(%Result* %43, i64 1) + store %Result* %43, %Result** %res + call void @__quantum__rt__result_update_reference_count(%Result* %43, i64 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %28, i64 -1) + br label %continue__2 -else__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 5, i64 1, %Array* %ctls, %Qubit* %qb) - br label %continue__1 +test1__1: ; preds = %exit__1 + br i1 false, label %then1__1, label %test2__1 -continue__1: ; preds = %else__1, %then0__1 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) - ret void -} +then1__1: ; preds = %test1__1 + %44 = call %Result* @__quantum__qis__joint_measure(i64 107, i64 1, %Array* %qs12) + call void @__quantum__rt__result_update_reference_count(%Result* %44, i64 1) + %45 = load %Result*, %Result** %res + store %Result* %44, %Result** %res + call void @__quantum__rt__result_update_reference_count(%Result* %44, i64 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %45, i64 -1) + br label %continue__2 -define void @Microsoft__Quantum__Intrinsic__Y__ctladj(%Array* %__controlQubits__, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 1) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 1) - %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %__controlQubits__) - %1 = icmp eq i64 %0, 1 - br i1 %1, label %then0__1, label %else__1 +test2__1: ; preds = %test1__1 + br i1 false, label %then2__1, label %test3__1 -then0__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 4, i64 1, %Array* %__controlQubits__, %Qubit* %qb) - br label %continue__1 +then2__1: ; preds = %test2__1 + %46 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) + %47 = bitcast i8* %46 to i2* + %48 = load i2, i2* %47 + %49 = load i2, i2* @PauliX + %50 = icmp eq i2 %48, %49 + br i1 %50, label %then0__3, label %else__1 -else__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 5, i64 1, %Array* %__controlQubits__, %Qubit* %qb) - br label %continue__1 +then0__3: ; preds = %then2__1 + %51 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs12, i64 0) + %52 = bitcast i8* %51 to %Qubit** + %qb__6 = load %Qubit*, %Qubit** %52 + %53 = call %Result* @__quantum__qis__single_qubit_measure(i64 101, i64 1, %Qubit* %qb__6) + call void @__quantum__rt__result_update_reference_count(%Result* %53, i64 1) + %54 = load %Result*, %Result** %res + store %Result* %53, %Result** %res + call void @__quantum__rt__result_update_reference_count(%Result* %53, i64 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %54, i64 -1) + br label %continue__3 -continue__1: ; preds = %else__1, %then0__1 - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 -1) - ret void -} +else__1: ; preds = %then2__1 + %55 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs12, i64 0) + %56 = bitcast i8* %55 to %Qubit** + %qb__7 = load %Qubit*, %Qubit** %56 + %57 = call %Result* @__quantum__qis__single_qubit_measure(i64 100, i64 1, %Qubit* %qb__7) + call void @__quantum__rt__result_update_reference_count(%Result* %57, i64 1) + %58 = load %Result*, %Result** %res + store %Result* %57, %Result** %res + call void @__quantum__rt__result_update_reference_count(%Result* %57, i64 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %58, i64 -1) + br label %continue__3 -define void @Microsoft__Quantum__Intrinsic__Z__body(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 6, i64 1, %Qubit* %qb) - ret void -} +continue__3: ; preds = %else__1, %then0__3 + br label %continue__2 -define void @Microsoft__Quantum__Intrinsic__Z__adj(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 6, i64 1, %Qubit* %qb) - ret void -} +test3__1: ; preds = %test2__1 + %59 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) + %60 = bitcast i8* %59 to i2* + %61 = load i2, i2* %60 + %62 = load i2, i2* @PauliX + %63 = icmp eq i2 %61, %62 + %64 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) + %65 = bitcast i8* %64 to i2* + %66 = load i2, i2* %65 + %67 = load i2, i2* @PauliX + %68 = icmp eq i2 %66, %67 + %69 = and i1 %63, %68 + br i1 %69, label %then3__1, label %test4__1 -define void @Microsoft__Quantum__Intrinsic__Z__ctl(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) - %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %ctls) - %1 = icmp eq i64 %0, 1 - br i1 %1, label %then0__1, label %else__1 +then3__1: ; preds = %test3__1 + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 1) + %70 = call %Result* @__quantum__qis__joint_measure(i64 105, i64 1, %Array* %qs12) + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %70, i64 1) + %71 = load %Result*, %Result** %res + store %Result* %70, %Result** %res + call void @__quantum__rt__result_update_reference_count(%Result* %70, i64 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %71, i64 -1) + br label %continue__2 -then0__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 7, i64 1, %Array* %ctls, %Qubit* %qb) - br label %continue__1 +test4__1: ; preds = %test3__1 + %72 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) + %73 = bitcast i8* %72 to i2* + %74 = load i2, i2* %73 + %75 = load i2, i2* @PauliX + %76 = icmp eq i2 %74, %75 + %77 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) + %78 = bitcast i8* %77 to i2* + %79 = load i2, i2* %78 + %80 = load i2, i2* @PauliZ + %81 = icmp eq i2 %79, %80 + %82 = and i1 %76, %81 + br i1 %82, label %then4__1, label %test5__1 -else__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 8, i64 1, %Array* %ctls, %Qubit* %qb) - br label %continue__1 +then4__1: ; preds = %test4__1 + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 1) + %83 = call %Result* @__quantum__qis__joint_measure(i64 103, i64 1, %Array* %qs12) + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %83, i64 1) + %84 = load %Result*, %Result** %res + store %Result* %83, %Result** %res + call void @__quantum__rt__result_update_reference_count(%Result* %83, i64 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %84, i64 -1) + br label %continue__2 -continue__1: ; preds = %else__1, %then0__1 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) - ret void -} +test5__1: ; preds = %test4__1 + %85 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) + %86 = bitcast i8* %85 to i2* + %87 = load i2, i2* %86 + %88 = load i2, i2* @PauliZ + %89 = icmp eq i2 %87, %88 + %90 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) + %91 = bitcast i8* %90 to i2* + %92 = load i2, i2* %91 + %93 = load i2, i2* @PauliX + %94 = icmp eq i2 %92, %93 + %95 = and i1 %89, %94 + br i1 %95, label %then5__1, label %test6__1 -define void @Microsoft__Quantum__Intrinsic__Z__ctladj(%Array* %__controlQubits__, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 1) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 1) - %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %__controlQubits__) - %1 = icmp eq i64 %0, 1 - br i1 %1, label %then0__1, label %else__1 +then5__1: ; preds = %test5__1 + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 1) + %96 = call %Result* @__quantum__qis__joint_measure(i64 104, i64 1, %Array* %qs12) + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %96, i64 1) + %97 = load %Result*, %Result** %res + store %Result* %96, %Result** %res + call void @__quantum__rt__result_update_reference_count(%Result* %96, i64 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %97, i64 -1) + br label %continue__2 -then0__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 7, i64 1, %Array* %__controlQubits__, %Qubit* %qb) - br label %continue__1 +test6__1: ; preds = %test5__1 + %98 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) + %99 = bitcast i8* %98 to i2* + %100 = load i2, i2* %99 + %101 = load i2, i2* @PauliZ + %102 = icmp eq i2 %100, %101 + %103 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) + %104 = bitcast i8* %103 to i2* + %105 = load i2, i2* %104 + %106 = load i2, i2* @PauliZ + %107 = icmp eq i2 %105, %106 + %108 = and i1 %102, %107 + br i1 %108, label %then6__1, label %continue__2 -else__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 8, i64 1, %Array* %__controlQubits__, %Qubit* %qb) - br label %continue__1 +then6__1: ; preds = %test6__1 + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 1) + %109 = call %Result* @__quantum__qis__joint_measure(i64 102, i64 1, %Array* %qs12) + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %109, i64 1) + %110 = load %Result*, %Result** %res + store %Result* %109, %Result** %res + call void @__quantum__rt__result_update_reference_count(%Result* %109, i64 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %110, i64 -1) + br label %continue__2 -continue__1: ; preds = %else__1, %then0__1 - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i64 -1) +continue__2: ; preds = %then6__1, %test6__1, %then5__1, %then4__1, %then3__1, %continue__3, %then1__1, %then0__2 + %r12 = load %Result*, %Result** %res + call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i64 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %paulis, i64 -1) + %111 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) + %112 = bitcast %Tuple* %111 to { %Callable*, %Callable*, %Qubit* }* + %113 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %112, i32 0, i32 0 + %114 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %112, i32 0, i32 1 + %115 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %112, i32 0, i32 2 + %116 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Testing__Tracer__Delay, [2 x void (%Tuple*, i64)*]* null, %Tuple* null) + %117 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__X, [2 x void (%Tuple*, i64)*]* null, %Tuple* null) + %118 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 3) + %119 = bitcast i8* %118 to %Qubit** + %120 = load %Qubit*, %Qubit** %119 + store %Callable* %116, %Callable** %113 + store %Callable* %117, %Callable** %114 + store %Qubit* %120, %Qubit** %115 + %121 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @PartialApplication__1, [2 x void (%Tuple*, i64)*]* @MemoryManagement__1, %Tuple* %111) + %122 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) + %123 = bitcast %Tuple* %122 to { %Callable*, %Callable*, %Qubit* }* + %124 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %123, i32 0, i32 0 + %125 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %123, i32 0, i32 1 + %126 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %123, i32 0, i32 2 + %127 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Testing__Tracer__Delay, [2 x void (%Tuple*, i64)*]* null, %Tuple* null) + %128 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__Y, [2 x void (%Tuple*, i64)*]* null, %Tuple* null) + %129 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 3) + %130 = bitcast i8* %129 to %Qubit** + %131 = load %Qubit*, %Qubit** %130 + store %Callable* %127, %Callable** %124 + store %Callable* %128, %Callable** %125 + store %Qubit* %131, %Qubit** %126 + %132 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @PartialApplication__2, [2 x void (%Tuple*, i64)*]* @MemoryManagement__1, %Tuple* %122) + call void @Microsoft__Quantum__Intrinsic__ApplyIfElseIntrinsic__body(%Result* %r0, %Callable* %121, %Callable* %132) + %133 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) + %134 = bitcast %Tuple* %133 to { %Callable*, %Callable*, %Qubit* }* + %135 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %134, i32 0, i32 0 + %136 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %134, i32 0, i32 1 + %137 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %134, i32 0, i32 2 + %138 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Testing__Tracer__Delay, [2 x void (%Tuple*, i64)*]* null, %Tuple* null) + %139 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__Z, [2 x void (%Tuple*, i64)*]* null, %Tuple* null) + %140 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 4) + %141 = bitcast i8* %140 to %Qubit** + %142 = load %Qubit*, %Qubit** %141 + store %Callable* %138, %Callable** %135 + store %Callable* %139, %Callable** %136 + store %Qubit* %142, %Qubit** %137 + %143 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @PartialApplication__3, [2 x void (%Tuple*, i64)*]* @MemoryManagement__1, %Tuple* %133) + %144 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) + %145 = bitcast %Tuple* %144 to { %Callable*, %Callable*, %Qubit* }* + %146 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %145, i32 0, i32 0 + %147 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %145, i32 0, i32 1 + %148 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %145, i32 0, i32 2 + %149 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Testing__Tracer__Delay, [2 x void (%Tuple*, i64)*]* null, %Tuple* null) + %150 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__S, [2 x void (%Tuple*, i64)*]* null, %Tuple* null) + %151 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 4) + %152 = bitcast i8* %151 to %Qubit** + %153 = load %Qubit*, %Qubit** %152 + store %Callable* %149, %Callable** %146 + store %Callable* %150, %Callable** %147 + store %Qubit* %153, %Qubit** %148 + %154 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @PartialApplication__4, [2 x void (%Tuple*, i64)*]* @MemoryManagement__2, %Tuple* %144) + call void @Microsoft__Quantum__Intrinsic__ApplyIfElseIntrinsic__body(%Result* %r12, %Callable* %143, %Callable* %154) + %155 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 5) + %156 = bitcast i8* %155 to %Qubit** + %qb__8 = load %Qubit*, %Qubit** %156 + call void @__quantum__qis__single_qubit_op(i64 19, i64 1, %Qubit* %qb__8) + call void @__quantum__rt__qubit_release_array(%Array* %qs) + call void @__quantum__rt__array_update_alias_count(%Array* %qs, i64 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i64 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %qs, i64 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %r0, i64 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %qs12, i64 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %r12, i64 -1) + call void @__quantum__rt__callable_memory_management(i32 0, %Callable* %121, i64 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %121, i64 -1) + call void @__quantum__rt__callable_memory_management(i32 0, %Callable* %132, i64 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %132, i64 -1) + call void @__quantum__rt__callable_memory_management(i32 0, %Callable* %143, i64 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %143, i64 -1) + call void @__quantum__rt__callable_memory_management(i32 0, %Callable* %154, i64 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %154, i64 -1) ret void } -define %Tuple* @Microsoft__Quantum__Core__Attribute__body() { +define void @Microsoft__Quantum__Testing__Tracer__Delay__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { entry: - ret %Tuple* null + %0 = bitcast %Tuple* %arg-tuple to { %Callable*, %Qubit*, %Tuple* }* + %1 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %0, i32 0, i32 1 + %3 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %0, i32 0, i32 2 + %4 = load %Callable*, %Callable** %1 + %5 = load %Qubit*, %Qubit** %2 + %6 = load %Tuple*, %Tuple** %3 + call void @Microsoft__Quantum__Testing__Tracer__Delay__body(%Callable* %4, %Qubit* %5, %Tuple* %6) + ret void } -define %Tuple* @Microsoft__Quantum__Core__EntryPoint__body() { +declare %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]*, [2 x void (%Tuple*, i64)*]*, %Tuple*) + +define void @Microsoft__Quantum__Intrinsic__X__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { entry: - ret %Tuple* null + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1 + call void @Microsoft__Quantum__Intrinsic__X__body(%Qubit* %2) + ret void } -define %Tuple* @Microsoft__Quantum__Core__Inline__body() { +define void @Microsoft__Quantum__Intrinsic__X__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { entry: - ret %Tuple* null + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1 + call void @Microsoft__Quantum__Intrinsic__X__adj(%Qubit* %2) + ret void } -define %Result* @Microsoft__Quantum__Instructions__Mx__body(%Qubit* %qb) { +define void @Microsoft__Quantum__Intrinsic__X__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { entry: - %0 = call %Result* @__quantum__qis__single_qubit_measure(i64 101, i64 1, %Qubit* %qb) - ret %Result* %0 + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1 + %4 = load %Qubit*, %Qubit** %2 + call void @Microsoft__Quantum__Intrinsic__X__ctl(%Array* %3, %Qubit* %4) + ret void } -define %Result* @Microsoft__Quantum__Instructions__Mxx__body(%Array* %qubits) { +define void @Microsoft__Quantum__Intrinsic__X__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { entry: - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i64 1) - %0 = call %Result* @__quantum__qis__joint_measure(i64 105, i64 1, %Array* %qubits) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i64 -1) - ret %Result* %0 + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1 + %4 = load %Qubit*, %Qubit** %2 + call void @Microsoft__Quantum__Intrinsic__X__ctladj(%Array* %3, %Qubit* %4) + ret void } -define %Result* @Microsoft__Quantum__Instructions__Mxz__body(%Array* %qubits) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i64 1) - %0 = call %Result* @__quantum__qis__joint_measure(i64 103, i64 1, %Array* %qubits) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i64 -1) - ret %Result* %0 +define void @Lifted__PartialApplication__1__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* + %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 + %2 = load %Callable*, %Callable** %1 + %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 2 + %4 = load %Qubit*, %Qubit** %3 + %5 = bitcast %Tuple* %arg-tuple to { %Tuple* }* + %6 = getelementptr inbounds { %Tuple* }, { %Tuple* }* %5, i32 0, i32 0 + %7 = load %Tuple*, %Tuple** %6 + %8 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) + %9 = bitcast %Tuple* %8 to { %Callable*, %Qubit*, %Tuple* }* + %10 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 0 + %11 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 1 + %12 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 2 + store %Callable* %2, %Callable** %10 + store %Qubit* %4, %Qubit** %11 + store %Tuple* %7, %Tuple** %12 + %13 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 + %14 = load %Callable*, %Callable** %13 + call void @__quantum__rt__callable_invoke(%Callable* %14, %Tuple* %8, %Tuple* %result-tuple) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %8, i64 -1) + ret void } -define %Result* @Microsoft__Quantum__Instructions__Mz__body(%Qubit* %qb) { +define void @MemoryManagement__1__RefCount(%Tuple* %capture-tuple, i64 %count-change) { entry: - %0 = call %Result* @__quantum__qis__single_qubit_measure(i64 100, i64 1, %Qubit* %qb) - ret %Result* %0 + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* + %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 + %2 = load %Callable*, %Callable** %1 + call void @__quantum__rt__callable_memory_management(i32 0, %Callable* %2, i64 %count-change) + call void @__quantum__rt__callable_update_reference_count(%Callable* %2, i64 %count-change) + %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 + %4 = load %Callable*, %Callable** %3 + call void @__quantum__rt__callable_memory_management(i32 0, %Callable* %4, i64 %count-change) + call void @__quantum__rt__callable_update_reference_count(%Callable* %4, i64 %count-change) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %capture-tuple, i64 %count-change) + ret void } -define %Result* @Microsoft__Quantum__Instructions__Mzx__body(%Array* %qubits) { +define void @MemoryManagement__1__AliasCount(%Tuple* %capture-tuple, i64 %count-change) { entry: - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i64 1) - %0 = call %Result* @__quantum__qis__joint_measure(i64 104, i64 1, %Array* %qubits) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i64 -1) - ret %Result* %0 + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* + %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 + %2 = load %Callable*, %Callable** %1 + call void @__quantum__rt__callable_memory_management(i32 1, %Callable* %2, i64 %count-change) + call void @__quantum__rt__callable_update_alias_count(%Callable* %2, i64 %count-change) + %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 + %4 = load %Callable*, %Callable** %3 + call void @__quantum__rt__callable_memory_management(i32 1, %Callable* %4, i64 %count-change) + call void @__quantum__rt__callable_update_alias_count(%Callable* %4, i64 %count-change) + call void @__quantum__rt__tuple_update_alias_count(%Tuple* %capture-tuple, i64 %count-change) + ret void } -define %Result* @Microsoft__Quantum__Instructions__Mzz__body(%Array* %qubits) { +define void @Microsoft__Quantum__Intrinsic__Y__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { entry: - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i64 1) - %0 = call %Result* @__quantum__qis__joint_measure(i64 102, i64 1, %Array* %qubits) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i64 -1) - ret %Result* %0 + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1 + call void @Microsoft__Quantum__Intrinsic__Y__body(%Qubit* %2) + ret void } -define void @Microsoft__Quantum__Instructions__Sx__body(%Qubit* %qb) { +define void @Microsoft__Quantum__Intrinsic__Y__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { entry: - call void @__quantum__qis__single_qubit_op(i64 17, i64 1, %Qubit* %qb) + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1 + call void @Microsoft__Quantum__Intrinsic__Y__adj(%Qubit* %2) ret void } -define void @Microsoft__Quantum__Instructions__Sx__adj(%Qubit* %qb) { +define void @Microsoft__Quantum__Intrinsic__Y__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { entry: - call void @__quantum__qis__single_qubit_op(i64 17, i64 1, %Qubit* %qb) + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1 + %4 = load %Qubit*, %Qubit** %2 + call void @Microsoft__Quantum__Intrinsic__Y__ctl(%Array* %3, %Qubit* %4) ret void } -define void @Microsoft__Quantum__Instructions__Sx__ctl(%Array* %ctls, %Qubit* %qb) { +define void @Microsoft__Quantum__Intrinsic__Y__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 18, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1 + %4 = load %Qubit*, %Qubit** %2 + call void @Microsoft__Quantum__Intrinsic__Y__ctladj(%Array* %3, %Qubit* %4) ret void } -define void @Microsoft__Quantum__Instructions__Sx__ctladj(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 18, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) +define void @Lifted__PartialApplication__2__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* + %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 + %2 = load %Callable*, %Callable** %1 + %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 2 + %4 = load %Qubit*, %Qubit** %3 + %5 = bitcast %Tuple* %arg-tuple to { %Tuple* }* + %6 = getelementptr inbounds { %Tuple* }, { %Tuple* }* %5, i32 0, i32 0 + %7 = load %Tuple*, %Tuple** %6 + %8 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) + %9 = bitcast %Tuple* %8 to { %Callable*, %Qubit*, %Tuple* }* + %10 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 0 + %11 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 1 + %12 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 2 + store %Callable* %2, %Callable** %10 + store %Qubit* %4, %Qubit** %11 + store %Tuple* %7, %Tuple** %12 + %13 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 + %14 = load %Callable*, %Callable** %13 + call void @__quantum__rt__callable_invoke(%Callable* %14, %Tuple* %8, %Tuple* %result-tuple) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %8, i64 -1) ret void } -define void @Microsoft__Quantum__Instructions__Sz__body(%Qubit* %qb) { +define void @Microsoft__Quantum__Intrinsic__Z__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { entry: - call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb) + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1 + call void @Microsoft__Quantum__Intrinsic__Z__body(%Qubit* %2) ret void } -define void @Microsoft__Quantum__Instructions__Sz__adj(%Qubit* %qb) { +define void @Microsoft__Quantum__Intrinsic__Z__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { entry: - call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb) + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1 + call void @Microsoft__Quantum__Intrinsic__Z__adj(%Qubit* %2) ret void } -define void @Microsoft__Quantum__Instructions__Sz__ctl(%Array* %ctls, %Qubit* %qb) { +define void @Microsoft__Quantum__Intrinsic__Z__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1 + %4 = load %Qubit*, %Qubit** %2 + call void @Microsoft__Quantum__Intrinsic__Z__ctl(%Array* %3, %Qubit* %4) ret void } -define void @Microsoft__Quantum__Instructions__Sz__ctladj(%Array* %ctls, %Qubit* %qb) { +define void @Microsoft__Quantum__Intrinsic__Z__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1 + %4 = load %Qubit*, %Qubit** %2 + call void @Microsoft__Quantum__Intrinsic__Z__ctladj(%Array* %3, %Qubit* %4) ret void } -define void @Microsoft__Quantum__Instructions__Tx__body(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 13, i64 1, %Qubit* %qb) +define void @Lifted__PartialApplication__3__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* + %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 + %2 = load %Callable*, %Callable** %1 + %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 2 + %4 = load %Qubit*, %Qubit** %3 + %5 = bitcast %Tuple* %arg-tuple to { %Tuple* }* + %6 = getelementptr inbounds { %Tuple* }, { %Tuple* }* %5, i32 0, i32 0 + %7 = load %Tuple*, %Tuple** %6 + %8 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) + %9 = bitcast %Tuple* %8 to { %Callable*, %Qubit*, %Tuple* }* + %10 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 0 + %11 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 1 + %12 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 2 + store %Callable* %2, %Callable** %10 + store %Qubit* %4, %Qubit** %11 + store %Tuple* %7, %Tuple** %12 + %13 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 + %14 = load %Callable*, %Callable** %13 + call void @__quantum__rt__callable_invoke(%Callable* %14, %Tuple* %8, %Tuple* %result-tuple) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %8, i64 -1) ret void } -define void @Microsoft__Quantum__Instructions__Tx__adj(%Qubit* %qb) { +define void @Microsoft__Quantum__Intrinsic__S__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { entry: - call void @__quantum__qis__single_qubit_op(i64 13, i64 1, %Qubit* %qb) + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1 + call void @Microsoft__Quantum__Intrinsic__S__body(%Qubit* %2) ret void } -define void @Microsoft__Quantum__Instructions__Tx__ctl(%Array* %ctls, %Qubit* %qb) { +define void @Microsoft__Quantum__Intrinsic__S__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 14, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1 + call void @Microsoft__Quantum__Intrinsic__S__adj(%Qubit* %2) ret void } -define void @Microsoft__Quantum__Instructions__Tx__ctladj(%Array* %ctls, %Qubit* %qb) { +define void @Microsoft__Quantum__Intrinsic__S__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 14, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1 + %4 = load %Qubit*, %Qubit** %2 + call void @Microsoft__Quantum__Intrinsic__S__ctl(%Array* %3, %Qubit* %4) ret void } -define void @Microsoft__Quantum__Instructions__Tz__body(%Qubit* %qb) { +define void @Microsoft__Quantum__Intrinsic__S__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { entry: - call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb) + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1 + %4 = load %Qubit*, %Qubit** %2 + call void @Microsoft__Quantum__Intrinsic__S__ctladj(%Array* %3, %Qubit* %4) ret void } -define void @Microsoft__Quantum__Instructions__Tz__adj(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb) +define void @Lifted__PartialApplication__4__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* + %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 + %2 = load %Callable*, %Callable** %1 + %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 2 + %4 = load %Qubit*, %Qubit** %3 + %5 = bitcast %Tuple* %arg-tuple to { %Tuple* }* + %6 = getelementptr inbounds { %Tuple* }, { %Tuple* }* %5, i32 0, i32 0 + %7 = load %Tuple*, %Tuple** %6 + %8 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) + %9 = bitcast %Tuple* %8 to { %Callable*, %Qubit*, %Tuple* }* + %10 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 0 + %11 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 1 + %12 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 2 + store %Callable* %2, %Callable** %10 + store %Qubit* %4, %Qubit** %11 + store %Tuple* %7, %Tuple** %12 + %13 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 + %14 = load %Callable*, %Callable** %13 + call void @__quantum__rt__callable_invoke(%Callable* %14, %Tuple* %8, %Tuple* %result-tuple) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %8, i64 -1) ret void } -define void @Microsoft__Quantum__Instructions__Tz__ctl(%Array* %ctls, %Qubit* %qb) { +define void @MemoryManagement__2__RefCount(%Tuple* %capture-tuple, i64 %count-change) { entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* + %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 + %2 = load %Callable*, %Callable** %1 + call void @__quantum__rt__callable_memory_management(i32 0, %Callable* %2, i64 %count-change) + call void @__quantum__rt__callable_update_reference_count(%Callable* %2, i64 %count-change) + %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 + %4 = load %Callable*, %Callable** %3 + call void @__quantum__rt__callable_memory_management(i32 0, %Callable* %4, i64 %count-change) + call void @__quantum__rt__callable_update_reference_count(%Callable* %4, i64 %count-change) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %capture-tuple, i64 %count-change) ret void } -define void @Microsoft__Quantum__Instructions__Tz__ctladj(%Array* %ctls, %Qubit* %qb) { +define void @MemoryManagement__2__AliasCount(%Tuple* %capture-tuple, i64 %count-change) { entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i64 -1) + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* + %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 + %2 = load %Callable*, %Callable** %1 + call void @__quantum__rt__callable_memory_management(i32 1, %Callable* %2, i64 %count-change) + call void @__quantum__rt__callable_update_alias_count(%Callable* %2, i64 %count-change) + %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 + %4 = load %Callable*, %Callable** %3 + call void @__quantum__rt__callable_memory_management(i32 1, %Callable* %4, i64 %count-change) + call void @__quantum__rt__callable_update_alias_count(%Callable* %4, i64 %count-change) + call void @__quantum__rt__tuple_update_alias_count(%Tuple* %capture-tuple, i64 %count-change) ret void } +declare void @__quantum__rt__callable_update_reference_count(%Callable*, i64) + define { %String* }* @Microsoft__Quantum__Targeting__TargetInstruction__body(%String* %__Item1__) { entry: %0 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64)) @@ -1527,3 +2015,5 @@ entry: } declare void @__quantum__rt__string_update_reference_count(%String*, i64) + +declare void @__quantum__rt__tuple_update_alias_count(%Tuple*, i64) diff --git a/src/QirRuntime/test/QIR-tracer/tracer-target.qs b/src/QirRuntime/test/QIR-tracer/tracer-target.qs index f40b8f9aa4d..f07b57c4304 100644 --- a/src/QirRuntime/test/QIR-tracer/tracer-target.qs +++ b/src/QirRuntime/test/QIR-tracer/tracer-target.qs @@ -36,6 +36,13 @@ namespace Microsoft.Quantum.Instructions { body intrinsic; } + @TargetInstruction("apply_conditionally") + operation apply_conditionally( + measurementResults : Result[], resultsValues : Result[], + onEqualOp : (Unit => Unit) , onNonEqualOp : (Unit => Unit)) : Unit { + body intrinsic; + } + // Operations, used in Hadamard frame tracking @Inline() operation Tz(qb : Qubit) : Unit @@ -209,9 +216,9 @@ namespace Microsoft.Quantum.Intrinsic { operation Rz(theta : Double, qb : Qubit) : Unit is Adj + Ctl { body (...) { Phys.single_qubit_op(23, 1, qb); } - adjoint (...) { Phys.single_qubit_op(24, 1, qb); } - controlled (ctls, ...) { Phys.single_qubit_op_ctl(25, 1, ctls, qb); } - controlled adjoint (ctls, ...) { Phys.single_qubit_op_ctl(25, 1, ctls, qb); } + adjoint (...) { Phys.single_qubit_op(23, 1, qb); } + controlled (ctls, ...) { Phys.single_qubit_op_ctl(24, 1, ctls, qb); } + controlled adjoint (ctls, ...) { Phys.single_qubit_op_ctl(24, 1, ctls, qb); } } @Inline() @@ -252,6 +259,17 @@ namespace Microsoft.Quantum.Intrinsic { } } + operation ApplyConditionallyIntrinsic( + measurementResults : Result[], resultsValues : Result[], + onEqualOp : (Unit => Unit) , onNonEqualOp : (Unit => Unit)) : Unit { + body (...) { return Phys.apply_conditionally(measurementResults, resultsValues, onEqualOp, onNonEqualOp); } + } + + operation ApplyIfElseIntrinsic( + measurementResult : Result, onResultZeroOp : (Unit => Unit) , onResultOneOp : (Unit => Unit)) : Unit { + body (...) { return Phys.apply_conditionally([measurementResult], [Zero], onResultZeroOp, onResultOneOp); } + } + // operation SWAP(a : Qubit, b : Qubit) : Unit // is Adj { // body intrinsic; diff --git a/src/QirRuntime/test/unittests/TracerTests.cpp b/src/QirRuntime/test/unittests/TracerTests.cpp index 37f8bc57ad1..d1ff4711036 100644 --- a/src/QirRuntime/test/unittests/TracerTests.cpp +++ b/src/QirRuntime/test/unittests/TracerTests.cpp @@ -2,8 +2,8 @@ // Licensed under the MIT License. #include -#include #include +#include #include "catch.hpp" @@ -213,12 +213,190 @@ TEST_CASE("Layering measurements", "[tracer]") Qubit qs23[2] = {q2, q3}; CHECK(2 == tr->GetLayerIdOfSourceMeasurement(tr->TraceMultiQubitMeasurement(5, 1, 2, qs23))); CHECK(1 == tr->TraceSingleQubitOp(3, 1, q4)); +} - const vector& layers = tr->UseLayers(); - REQUIRE(layers.size() == 3); - CHECK(layers[0].operations.size() == 3); - CHECK(layers[1].operations.size() == 2); - CHECK(layers[2].operations.size() == 1); +TEST_CASE("Conditionals: noops", "[tracer][tracer.conditionals]") +{ + shared_ptr tr = CreateTracer(3 /*layer duration*/); + + Qubit q1 = tr->AllocateQubit(); + Qubit q2 = tr->AllocateQubit(); + + CHECK(0 == tr->TraceSingleQubitOp(1, 3, q1)); + CHECK(1 == tr->TraceSingleQubitOp(1, 3, q1)); + Result one = tr->UseOne(); + { + CTracer::FenceScope fs(tr.get(), 1, &one, 0, nullptr); + CHECK(0 == tr->TraceSingleQubitOp(1, 1, q2)); + } + { + CTracer::FenceScope fs(tr.get(), 0, nullptr, 1, &one); + CHECK(0 == tr->TraceSingleQubitOp(1, 1, q2)); + } + { + CTracer::FenceScope fs(tr.get(), 0, nullptr, 0, nullptr); + CHECK(0 == tr->TraceSingleQubitOp(1, 1, q2)); + } +} + +TEST_CASE("Conditionals: a new layer because of the fence", "[tracer][tracer.conditionals]") +{ + shared_ptr tr = CreateTracer(1 /*layer duration*/); + + Qubit q1 = tr->AllocateQubit(); + Qubit q2 = tr->AllocateQubit(); + Qubit q3 = tr->AllocateQubit(); + + CHECK(0 == tr->TraceSingleQubitOp(1, 1, q1)); + Result r = tr->TraceSingleQubitMeasurement(1, 1, q1); + CHECK(1 == tr->GetLayerIdOfSourceMeasurement(r)); + + { + CTracer::FenceScope fs(tr.get(), 1, &r, 0, nullptr); + CHECK(2 == tr->TraceSingleQubitOp(1, 1, q2)); + } + + CHECK(0 == tr->TraceSingleQubitOp(1, 1, q3)); +} + +TEST_CASE("Conditionals: single fence", "[tracer][tracer.conditionals]") +{ + shared_ptr tr = CreateTracer(1 /*layer duration*/); + + Qubit q1 = tr->AllocateQubit(); + Qubit q2 = tr->AllocateQubit(); + Qubit q3 = tr->AllocateQubit(); + + CHECK(0 == tr->TraceSingleQubitOp(1, 1, q1)); + Result r = tr->TraceSingleQubitMeasurement(1, 1, q1); + CHECK(1 == tr->GetLayerIdOfSourceMeasurement(r)); + CHECK(2 == tr->TraceSingleQubitOp(1, 1, q1)); + + { + CTracer::FenceScope fs(tr.get(), 1, &r, 0, nullptr); + CHECK(2 == tr->TraceSingleQubitOp(1, 1, q2)); + } + + CHECK(3 == tr->TraceSingleQubitOp(1, 1, q1)); + CHECK(3 == tr->TraceSingleQubitOp(1, 1, q2)); + CHECK(0 == tr->TraceSingleQubitOp(1, 1, q3)); + CHECK(1 == tr->TraceSingleQubitOp(1, 1, q3)); + CHECK(2 == tr->TraceSingleQubitOp(1, 1, q3)); +} + +TEST_CASE("Conditionals: fence from two result arrays", "[tracer][tracer.conditionals]") +{ + shared_ptr tr = CreateTracer(1 /*layer duration*/); + + Qubit q1 = tr->AllocateQubit(); + Qubit q2 = tr->AllocateQubit(); + Qubit q3 = tr->AllocateQubit(); + + CHECK(0 == tr->TraceSingleQubitOp(1, 1, q1)); + Result r1 = tr->TraceSingleQubitMeasurement(1, 1, q1); + CHECK(1 == tr->GetLayerIdOfSourceMeasurement(r1)); + CHECK(0 == tr->TraceSingleQubitOp(1, 1, q2)); + CHECK(1 == tr->TraceSingleQubitOp(1, 1, q2)); + Result r2 = tr->TraceSingleQubitMeasurement(1, 1, q2); + CHECK(2 == tr->GetLayerIdOfSourceMeasurement(r2)); + + { + CTracer::FenceScope fs(tr.get(), 1, &r1, 1, &r2); + CHECK(3 == tr->TraceSingleQubitOp(1, 1, q3)); + } + + CHECK(2 == tr->TraceSingleQubitOp(1, 1, q1)); +} + +TEST_CASE("Conditionals: nested fence is later than parent", "[tracer][tracer.conditionals]") +{ + shared_ptr tr = CreateTracer(1 /*layer duration*/); + + Qubit q1 = tr->AllocateQubit(); + Qubit q2 = tr->AllocateQubit(); + Qubit q3 = tr->AllocateQubit(); + Qubit q4 = tr->AllocateQubit(); + Qubit q5 = tr->AllocateQubit(); + + CHECK(0 == tr->TraceSingleQubitOp(1, 1, q1)); + Result r1 = tr->TraceSingleQubitMeasurement(1, 1, q1); + CHECK(1 == tr->GetLayerIdOfSourceMeasurement(r1)); + CHECK(0 == tr->TraceSingleQubitOp(1, 1, q2)); + CHECK(1 == tr->TraceSingleQubitOp(1, 1, q2)); + Result r2 = tr->TraceSingleQubitMeasurement(1, 1, q2); + CHECK(2 == tr->GetLayerIdOfSourceMeasurement(r2)); + + { + CTracer::FenceScope fs(tr.get(), 1, &r1, 0, nullptr); + CHECK(2 == tr->TraceSingleQubitOp(1, 1, q3)); + { + CTracer::FenceScope fs(tr.get(), 0, nullptr, 1, &r2); + CHECK(3 == tr->TraceSingleQubitOp(1, 1, q4)); + } + CHECK(2 == tr->TraceSingleQubitOp(1, 1, q5)); + } + + CHECK(2 == tr->TraceSingleQubitOp(1, 1, q1)); +} + +TEST_CASE("Conditionals: nested fence is earlier than parent", "[tracer][tracer.conditionals]") +{ + shared_ptr tr = CreateTracer(1 /*layer duration*/); + + Qubit q1 = tr->AllocateQubit(); + Qubit q2 = tr->AllocateQubit(); + Qubit q3 = tr->AllocateQubit(); + Qubit q4 = tr->AllocateQubit(); + Qubit q5 = tr->AllocateQubit(); + + CHECK(0 == tr->TraceSingleQubitOp(1, 1, q1)); + Result r1 = tr->TraceSingleQubitMeasurement(1, 1, q1); + CHECK(1 == tr->GetLayerIdOfSourceMeasurement(r1)); + CHECK(0 == tr->TraceSingleQubitOp(1, 1, q2)); + CHECK(1 == tr->TraceSingleQubitOp(1, 1, q2)); + Result r2 = tr->TraceSingleQubitMeasurement(1, 1, q2); + CHECK(2 == tr->GetLayerIdOfSourceMeasurement(r2)); + + { + CTracer::FenceScope fs(tr.get(), 1, &r2, 0, nullptr); + CHECK(3 == tr->TraceSingleQubitOp(1, 1, q3)); + { + CTracer::FenceScope fs(tr.get(), 0, nullptr, 1, &r1); + CHECK(3 == tr->TraceSingleQubitOp(1, 1, q4)); + } + CHECK(3 == tr->TraceSingleQubitOp(1, 1, q5)); + } + CHECK(2 == tr->TraceSingleQubitOp(1, 1, q1)); +} + +TEST_CASE("Conditionals: fences and barriers", "[tracer][tracer.conditionals]") +{ + shared_ptr tr = CreateTracer(1 /*layer duration*/); + + Qubit q1 = tr->AllocateQubit(); + Qubit q2 = tr->AllocateQubit(); + Qubit q3 = tr->AllocateQubit(); + Qubit q4 = tr->AllocateQubit(); + Qubit q5 = tr->AllocateQubit(); + + CHECK(0 == tr->TraceSingleQubitOp(1, 1, q1)); + Result r1 = tr->TraceSingleQubitMeasurement(1, 1, q1); + CHECK(1 == tr->GetLayerIdOfSourceMeasurement(r1)); + + CHECK(2 == tr->InjectGlobalBarrier(42, 1)); + + Result r2 = tr->TraceSingleQubitMeasurement(1, 1, q2); + CHECK(3 == tr->GetLayerIdOfSourceMeasurement(r2)); + + { + CTracer::FenceScope fs(tr.get(), 1, &r1, 0, nullptr); + CHECK(3 == tr->TraceSingleQubitOp(1, 1, q3)); + } + { + CTracer::FenceScope fs(tr.get(), 0, nullptr, 1, &r2); + CHECK(4 == tr->TraceSingleQubitOp(1, 1, q4)); + } + CHECK(3 == tr->TraceSingleQubitOp(1, 1, q5)); } TEST_CASE("Output: to string", "[tracer]")