qir-alliance / qat

QIR compiler tools and optimization passes for targeting QIR to different hardware backends
https://qir-alliance.github.io/qat/
MIT License
26 stars 14 forks source link

Feature/results comparison #99

Closed troelsfr closed 2 years ago

troelsfr commented 2 years ago

This PR enables transformations of result with result comparison such that

entry:
  %q0 = call %Qubit* @__quantum__rt__qubit_allocate()
  %q1 = call %Qubit* @__quantum__rt__qubit_allocate()
  call void @__quantum__qis__h__body(%Qubit* %q0)
  call void @__quantum__qis__cnot__body(%Qubit* %q0, %Qubit* %q1)
  %result = call %Result* @__quantum__qis__m__body(%Qubit* %q0)
  %result__2 = call %Result* @__quantum__qis__m__body(%Qubit* %q1)
  %0 = call i1 @__quantum__rt__result_equal(%Result* %result, %Result* %result__2)
  call void @__quantum__rt__result_update_reference_count(%Result* %result, i32 -1)
  call void @__quantum__rt__result_update_reference_count(%Result* %result__2, i32 -1)
  br i1 %0, label %then0__1, label %continue__1
then0__1:                                         ; preds = %entry
  call void @__quantum__qis__x__body(%Qubit* %q0)
  call void @__quantum__qis__x__body(%Qubit* %q1)
  br label %continue__1
continue__1:                                      ; preds = %then0__1, %entry
  %result__4 = call %Result* @__quantum__qis__m__body(%Qubit* %q0)
  call void @__quantum__rt__result_update_reference_count(%Result* %result__4, i32 -1)
  call void @__quantum__rt__qubit_release(%Qubit* %q0)
  call void @__quantum__rt__qubit_release(%Qubit* %q1)
  call void @__quantum__rt__result_update_reference_count(%Result* %result__4, i32 1)
  call void @__quantum__rt__result_record_output(%Result* %result__4)
  call void @__quantum__rt__result_update_reference_count(%Result* %result__4, i32 -1)
  ret void

becomes

entry:
  call void @__quantum__qis__h__body(%Qubit* null)
  call void @__quantum__qis__cnot__body(%Qubit* null, %Qubit* nonnull inttoptr (i64 1 to %Qubit*))
  call void @__quantum__qis__mz__body(%Qubit* null, %Result* null)
  call void @__quantum__qis__mz__body(%Qubit* nonnull inttoptr (i64 1 to %Qubit*), %Result* nonnull inttoptr (i64 1 to %Result*))
  %0 = call i1 @__quantum__qis__read_result__body(%Result* null)
  %1 = call i1 @__quantum__qis__read_result__body(%Result* nonnull inttoptr (i64 1 to %Result*))
  %2 = xor i1 %0, %1
  br i1 %2, label %continue__1, label %then0__1

then0__1:                                         ; preds = %entry
  call void @__quantum__qis__x__body(%Qubit* null)
  call void @__quantum__qis__x__body(%Qubit* nonnull inttoptr (i64 1 to %Qubit*))
  br label %continue__1

continue__1:                                      ; preds = %then0__1, %entry
  call void @__quantum__qis__mz__body(%Qubit* null, %Result* nonnull inttoptr (i64 2 to %Result*))
  ret void
swernli commented 2 years ago

The pass itself looks good, and the transformation is exactly what we need. Just looks like it's not fully integrated yet, but once it is I'm ready to sign off!