Microsoft Introduces Its Quantum Intermediate Representation

Based on LLVM, Microsoft Quantum Intermediate Representation (QIR) extends LLVM IR to better suit the representation of quantum constructs.

Coming from Microsoft, QIR specifically supports Q# but it is not by any means limited to it, says Microsoft software architect for quantum software and applications Alan Geller.

Any programming language for gate-based quantum computing can be represented in QIR. Similarly, QIR is hardware-agnostic: it does not specify a quantum instruction or gate set, leaving that to the target computing environment.

According to Geller, QIR is suitable to represent programs integrating both a classical and a quantum computation, a trend, he says, that will become ever more important as quantum hardware advances.

Geller also provides an example of what QIR looks like for a very simple quantum function written in Q#:

 // Assumes that qb1 and qb2 are already in the |0> state  operation BellPair(qb1 : Qubit, qb2 : Qubit) : Unit  {      H(qb1);      CNOT(qb1, qb2);  }  

Each Q# operation is represented through an LLVM function starting with the prefix __quantum__qis__, while qubits are represented using a pointer to a named opaque type called `%Qubit. With this in mind, this is how the previous snippet's QIR looks like:

 define void @BellPair__body(%Qubit* %qb1, %Qubit* %qb2) {  entry:    call void @__quantum__qis__h(%Qubit* %qb1)    call void @__quantum__qis__cnot(%Qubit* %qb1, %Qubit* %qb2)    ret void  }  

When applied to quantum computations, in particular, an intermediate representation opens up a number of interesting possibilities. For example, using clang, LLVM C front-end, it would be possible to compile QIR into executable code for classical hardware, which could simplify the creation of quantum simulators. In addition, it would be possible to create quantum optimizers to transform the intermediate representation in a language- and hardware-independent way, which would enable reusing those optimizers for different languages and computing platforms with almost no effort.

The idea of a language-independent intermediate representation for programs is at the very heart of LLVM and other compilers and is key to enable them to support many different programming languages. In short, an intermediate representation acts as an abstract representation of a program. All programs, irrespective of the language they are written in, are translated into this intermediate representation by a so-called front-end compiler, while a back-end component is responsible for translating that intermediate representation into a machine representation. The intermediate representation allows thus to decouple source languages from hardware platforms and makes it possible to build a compiler in a modular way, where each new language only requires a new front-end to be supported on all platforms for which a back-end is available.