Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: support ~ operation, close #278 #303

Merged
merged 5 commits into from
Mar 27, 2024
Merged

Conversation

Zhaoyilunnn
Copy link
Contributor

Hi Team,

I've added rules to parse "~" symbol in qe-qasm: openqasm/qe-qasm#29, at the side of qe-compiler, we need to generate a MLIR op for ASTOpTypeBitNot in lib/Frontend/OpenQASM3/QUIRGenQASM3Visitor.cpp.

After searching, I find that MLIR does not have arith operations directly related to "BitNot". In the context of OQ3, I believe "~cbit" and "!cbit" are equivalent in a "if" condition? So I just simply reused the processing logic of ASTOpTypeLogicalNot, which checks whether the target is a I1Type and also works for ASTOpTypeBitNot operation. It will also create an CmpIPredicate::ne operation.

Willing to update my pr if you have better solutions

Thanks,
Yilun

Changes

  1. Update the commit id of qe-qasm project
  2. Reuse the processing logic of ASTOpTypeLogicalNot for ASTOpTypeBitNot.

Sample

Given the following source file

OPENQASM 3.0;

qubit $0;

gate x q {}

bit[4] qc0_c0;

if ((qc0_c0[0] & qc0_c0[1] | qc0_c0[0] & qc0_c0[2] | qc0_c0[1] & qc0_c0[2]) & ~(qc0_c0[0] & qc0_c0[1] & qc0_c0[2])) {
    x $0;
}
qc0_c0[3] = measure $0;

The compiler generates following MLIR

module {
  oq3.declare_variable @qc0_c0 : !quir.cbit<4>
  func.func @x(%arg0: !quir.qubit<1>) {
    return
  }
  func.func @main() -> i32 {
    qcs.init
    %c0 = arith.constant 0 : index
    %c1000 = arith.constant 1000 : index
    %c1 = arith.constant 1 : index
    scf.for %arg0 = %c0 to %c1000 step %c1 {
      %dur = quir.constant #quir.duration<1.000000e+00> : !quir.duration<ms>
      quir.delay %dur, () : !quir.duration<ms>, () -> ()
      qcs.shot_init {qcs.num_shots = 1000 : i32}
      %0 = quir.declare_qubit {id = 0 : i32} : !quir.qubit<1>
      %c0_i4 = arith.constant 0 : i4
      %1 = "oq3.cast"(%c0_i4) : (i4) -> !quir.cbit<4>
      oq3.variable_assign @qc0_c0 : !quir.cbit<4> = %1
      %2 = oq3.variable_load @qc0_c0 : !quir.cbit<4>
      %3 = oq3.cbit_extractbit(%2 : !quir.cbit<4>) [0] : i1
      %4 = oq3.variable_load @qc0_c0 : !quir.cbit<4>
      %5 = oq3.cbit_extractbit(%4 : !quir.cbit<4>) [1] : i1
      %6 = oq3.cbit_and %3, %5 : i1
      %7 = oq3.variable_load @qc0_c0 : !quir.cbit<4>
      %8 = oq3.cbit_extractbit(%7 : !quir.cbit<4>) [0] : i1
      %9 = oq3.variable_load @qc0_c0 : !quir.cbit<4>
      %10 = oq3.cbit_extractbit(%9 : !quir.cbit<4>) [2] : i1
      %11 = oq3.cbit_and %8, %10 : i1
      %12 = oq3.cbit_or %6, %11 : i1
      %13 = oq3.variable_load @qc0_c0 : !quir.cbit<4>
      %14 = oq3.cbit_extractbit(%13 : !quir.cbit<4>) [1] : i1
      %15 = oq3.variable_load @qc0_c0 : !quir.cbit<4>
      %16 = oq3.cbit_extractbit(%15 : !quir.cbit<4>) [2] : i1
      %17 = oq3.cbit_and %14, %16 : i1
      %18 = oq3.cbit_or %12, %17 : i1
      %19 = oq3.variable_load @qc0_c0 : !quir.cbit<4>
      %20 = oq3.cbit_extractbit(%19 : !quir.cbit<4>) [0] : i1
      %21 = oq3.variable_load @qc0_c0 : !quir.cbit<4>
      %22 = oq3.cbit_extractbit(%21 : !quir.cbit<4>) [1] : i1
      %23 = oq3.cbit_and %20, %22 : i1
      %24 = oq3.variable_load @qc0_c0 : !quir.cbit<4>
      %25 = oq3.cbit_extractbit(%24 : !quir.cbit<4>) [2] : i1
      %26 = oq3.cbit_and %23, %25 : i1
      %true = arith.constant true
      %27 = arith.cmpi ne, %26, %true : i1
      %28 = oq3.cbit_and %18, %27 : i1
      scf.if %28 {
        quir.call_gate @x(%0) : (!quir.qubit<1>) -> ()
        %false = arith.constant false
      }
      %29 = quir.measure(%0) : (!quir.qubit<1>) -> i1
      oq3.cbit_assign_bit @qc0_c0<4> [3] : i1 = %29
    } {qcs.shot_loop}
    qcs.finalize
    %c0_i32 = arith.constant 0 : i32
    return %c0_i32 : i32
  }
}
```

@Zhaoyilunnn Zhaoyilunnn requested a review from a team as a code owner March 24, 2024 07:41
Copy link
Collaborator

@taalexander taalexander left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Zhaoyilunnn, thank you very much for this follow up PR! Do you think you could create a reproducer test here to https://github.com/openqasm/qe-compiler/blob/main/test/Frontend/OpenQASM3/bitops.qasm

Could you please bump the version here to 0.3.1 -

version = "0.3.0"
and correspondingly here -
- qasm/0.3.0@qss/stable

I think you'll also need to add a short reno to get the static checks to pass.

@@ -1,5 +1,5 @@
sources:
hash: "d59248cbb4cf8840c9720462f2569907b9506323"
hash: "d42bca2c2b7a8e2543462cceea178240709b6fa2"
Copy link
Collaborator

@taalexander taalexander Mar 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind updating this to openqasm/qe-qasm@a9cf9fa?

Copy link
Collaborator

@taalexander taalexander left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost, there - just a couple small changes please

test/Frontend/OpenQASM3/bitops.qasm Show resolved Hide resolved
conan/qasm/conandata.yml Outdated Show resolved Hide resolved
Copy link
Collaborator

@taalexander taalexander left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, pending CI passes. Thank you!

@taalexander taalexander merged commit d09f48c into openqasm:main Mar 27, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants