NVIDIA/cuda-quantum

issue with if condition after mid circuit measurement

Closed this issue · 1 comments

Required prerequisites

  • Consult the security policy. If reporting a security vulnerability, do not report the bug using this form. Use the process described in the policy to report the issue.
  • Make sure you've read the documentation. Your issue may be addressed there.
  • Search the issue tracker to verify that this hasn't already been reported. +1 or comment there if it has.
  • If possible, make a PR with a failing test to give us a starting point to work on!

Describe the bug

If I run example 1, it will work and print the register a. However, if I run example 2, it will not print the register a

Steps to reproduce the bug

Example 1:

import cudaq

@cudaq.kernel
def kernel_break():
    ancilla_a=cudaq.qubit()
    ancilla_b=cudaq.qubit()
    q=cudaq.qubit()
    
    
    
    h(ancilla_a)
    h(ancilla_b)
    x(q)
        
    aux_1=mz(ancilla_a)
    aux_2=mz(ancilla_b)
    if aux_1==0:
        if aux_2==0:
            x.ctrl(ancilla_a,q)
            a=mz(q)
         
            


count=cudaq.sample(kernel_break,shots_count=1000)
print(count)

Example 2:

import cudaq

@cudaq.kernel
def kernel_break():
    ancilla_a=cudaq.qubit()
    ancilla_b=cudaq.qubit()
    q=cudaq.qubit()
    
    
    
    h(ancilla_a)
    h(ancilla_b)
    x(q)
        
    aux_1=mz(ancilla_a)
    aux_2=mz(ancilla_b)
    if aux_1==0 and aux_2==0:
        #if aux_2==0:
        x.ctrl(ancilla_a,q)
        a=mz(q)
         
            


count=cudaq.sample(kernel_break,shots_count=1000)
print(count)

Expected behavior

if aux_1==0:
   if aux_2==0:
      ......

and

if aux_1==0 and axu_2==0:
   ....

I expect the two if statement should work.

Is this a regression? If it is, put the last known working version (or commit) here.

Not a regression

Environment

  • CUDA Quantum version: latest
  • Python version: 3.10
  • C++ compiler:
  • Operating system: linux

Suggestions

No response

Doing some triage, it looks like the and operator is lowering to correct code initially. But something is going sideways after that.

  func.func @__nvqpp__mlirgen__kernel_break() attributes {"cudaq-entrypoint"} {
    %false = arith.constant false
    %c0_i64 = arith.constant 0 : i64
    %0 = quake.alloca !quake.ref
    %1 = quake.alloca !quake.ref
    %2 = quake.alloca !quake.ref
    quake.h %0 : (!quake.ref) -> ()
    quake.h %1 : (!quake.ref) -> ()
    quake.x %2 : (!quake.ref) -> ()
    %measOut = quake.mz %0 name "aux_1" : (!quake.ref) -> !quake.measure
    %3 = quake.discriminate %measOut : (!quake.measure) -> i1
    %measOut_0 = quake.mz %1 name "aux_2" : (!quake.ref) -> !quake.measure
    %4 = quake.discriminate %measOut_0 : (!quake.measure) -> i1
    %5 = cc.cast unsigned %3 : (i1) -> i64
    %6 = arith.cmpi eq, %5, %c0_i64 : i64
    %7 = arith.cmpi eq, %6, %false : i1
    %8 = cc.if(%7) -> i1 {
      cc.continue %false : i1
    } else {
      %9 = cc.cast unsigned %4 : (i1) -> i64
      %10 = arith.cmpi eq, %9, %c0_i64 : i64
      cc.continue %10 : i1
    }
    cc.if(%8) {
      quake.x [%0] %2 : (!quake.ref, !quake.ref) -> ()
      %measOut_1 = quake.mz %2 name "a" : (!quake.ref) -> !quake.measure
    }
    return
  }