qir-alliance / pyqir

PyQIR is a set of APIs for generating, parsing, and evaluating Quantum Intermediate Representation (QIR).
https://qir-alliance.github.io/pyqir
MIT License
57 stars 24 forks source link

Evaluator: Can't evaluate QIR file #121

Closed chemix-lunacy closed 2 years ago

chemix-lunacy commented 2 years ago

Using NonadaptiveEvaluator.eval crashes the process when given a QIR .ll file and fails with an encoding exception when given a bitcode version of the same file. Nothing custom was done to generate the QIR (straight from the Q# compiler) or bitcode (just passed directly to llvm::WriteBitcodeToFile). The code itself is very basic - just one of the many Q# examples floating around. pyqir was also installed from pip, not a local version.

Bitcode issue is likely due to us using LLVM 13 which I believe is a different version than the one you're using, so may not be an issue per-say, but attaching it if you want to look at it further. There might be a way to strip version/encoding from the bitcode, but haven't spent too much time digging as-of yet.

Just mention if you need any additional info.

QIR and bitcode files.

Versions/System Info

py-evaluator: 0.4.0-alpha.1 OS: Windows 10 Pro, 21H1 Python: 3.8 Rust: 1.60 Q# SDK: 0.24.208024

LaurentAjdnik commented 2 years ago

Hi @chemix-lunacy and thanks for your feedback!

Regarding the encoding error when evaluating the BasicExample.bc file:

Doing the test, I get the same LLVM ERROR: Invalid encoding problem as you do.

This is a very low-level fatal error thrown by the core LLVM itself.

Your file does not seem valid. Running llvm-bcanalyzer on it returns the same error with LLVM 11, 13 and even 14:

llvm-bcanalyzer: can't skip to bit 34931315776 from 864

Which llvm::WriteBitcodeToFile did you use?

When assembling from BasicExample.ll with llvm-as, the resulting bitcode can be analyzed properly with llvm-bcanalyzer.

And the encoding error disappears, yippee! 😄

Unfortunately, both bcand ll files still make pyqir-evaluator crash. 😢

I'll try to find some time to investigate further.

In particular, llvm-bcanalyzer itself is not able to parse a short piece of the file (details with --dump):

  <UnknownBlock26 NumWords=6 BlockCodeSize=2>
    <UnknownCode1 op0=115 op1=105 op2=110 op3=103 op4=108 op5=101 op6=116 op7=104 op8=114 op9=101 op10=97 op11=100/>
    <UnknownCode1/>
  </UnknownBlock26>
  Block ID #26:
      Num Instances: 1
         Total Size: 245b/30.62B/7W
    Percent of file: 0.2501%
      Num SubBlocks: 0
        Num Abbrevs: 0
        Num Records: 2
    Percent Abbrevs: 0.0000%

    Record Histogram:
          Count    # Bits     b/Rec   % Abv  Record Kind
              2       172      86.0          UnknownCode1
chemix-lunacy commented 2 years ago

@LaurentAjdnik Thanks for looking into it!

I'm using the same method that llvm-as uses but obviously with some required arguments missing or slightly different. It's not super import I get it working though as I don't need the bitcode right now, I was simply seeing if it worked where basic QIR didn't.

LaurentAjdnik commented 2 years ago

Hi again @chemix-lunacy! I think I got it!

I did many tries until I simplified your ll file to the extreme:

%String = type opaque

@0 = internal constant [3 x i8] c"()\00"

declare %String* @__quantum__rt__string_create(i8*)

define void @Microsoft__Quantum__OracleGenerator__RunProgram() #1 {
entry:
  %0 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @0, i32 0, i32 0))
  ret void
}

attributes #1 = { "EntryPoint" }

But it still failed...

On the other hand, replacing @__quantum__rt__string_create with any of the "well-known functions" (@__quantum__qis__h__body, @__quantum__qis__x__body...) works!

Looking into the code of the evaluator, it seems only a few functions are currently handled.

@__quantum__rt__string_create is simply unknown and cannot be evaluated. Hence the crash.

Well... It should rather return an error rather than crash... I'll file a separate issue...

idavis commented 2 years ago

Thanks @LaurentAjdnik - We should update the readme and code docs saying what bitcode is supported. Right now the evaluator can JIT QIR produced by the pyqir-generator, but cannot use any external function calls. The pyqir-evaluator does not have a full runtime environment and thus does not have a definition for __quantum__rt__string_create. We should also make better error messages as noted in #122 . We have another PR that is adding multiple LLVM version support (if manually building) and will be changing the default version to 13 after that PR is merged.

idavis commented 2 years ago

@chemix-lunacy I'm going to close this issue for now and use #122 to track a fix.