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

Fleshing out some conceptual guidelines #25

Draft
wants to merge 67 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 65 commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
f7fd147
early outline for a Base Profile for the purpose of discussion
Jun 17, 2022
a4f09dd
Update specification/under_development/Base-Profile.md
bettinaheim Jun 30, 2022
f60a183
addressing some comments
Jun 30, 2022
745393e
Merge branch 'base-profile' of https://github.com/qir-alliance/qir-sp…
Jun 30, 2022
5977122
initial commit for the definition of known quantum instructions
Jun 30, 2022
3c1c44e
different version of the qis table
Jun 30, 2022
413788c
removing the address space 2
Jun 30, 2022
1d30c9b
revising output recording functions
Jun 30, 2022
6f399aa
some thoughts around output
Jun 30, 2022
1f5d4cd
more thoughts
Jun 30, 2022
a7e7132
minor edits
Jun 30, 2022
2959ffb
some more details on the output
Jun 30, 2022
8fa9d27
add output labels
Jul 1, 2022
07ad6bd
starting to flesh out more details about targeting and QIS resolution
Jul 7, 2022
66ab969
adding a couple of stages for clarity
Jul 7, 2022
bf90edf
adding bullet points with the three requirements we fleshed out in th…
Jul 7, 2022
542f2fd
just adding a small not so I don't forget
Jul 8, 2022
050dc86
minor updates to common instructions
Jul 12, 2022
b32b3d8
outlining some thoughts around the linking stage and qis resolution
Jul 12, 2022
56bf816
formatting
bettinaheim Aug 4, 2022
bdfc361
more formatting
bettinaheim Aug 4, 2022
74e8964
fleshing out the introduction and updating the example
bettinaheim Aug 4, 2022
a171784
finishing the profile section and updating the program structure section
bettinaheim Aug 5, 2022
6630e36
module flags seems like a good option for versioning and indicating q…
bettinaheim Aug 6, 2022
0c59756
let's make this two flags
bettinaheim Aug 6, 2022
b348dd8
almost done with the attributes, and started to write a section on mo…
bettinaheim Aug 6, 2022
2462e03
adding more details to the module flags section
bettinaheim Aug 6, 2022
8b348c5
finished the module flags section
bettinaheim Aug 7, 2022
67eefaa
finishing the attributes section
bettinaheim Aug 7, 2022
967087b
finished the sections on data types and values, as well as on the QIS
bettinaheim Aug 7, 2022
6e32f9e
finished the section on output recording
bettinaheim Aug 7, 2022
d09625b
that should clean up the last remaining section in the base profile s…
bettinaheim Aug 7, 2022
c11d719
overlooked a typo
bettinaheim Aug 7, 2022
7a2d7dd
spelling
bettinaheim Aug 7, 2022
0fd2c59
addressing some comments on the PR
bettinaheim Aug 7, 2022
2adae03
adressing more PR comments
bettinaheim Aug 7, 2022
6db8059
Merge branch 'main' into base-profile
bettinaheim Aug 7, 2022
757db22
addressing more review comments
bettinaheim Aug 8, 2022
e2dcc56
Merge branch 'base-profile' of https://github.com/qir-alliance/qir-sp…
bettinaheim Aug 8, 2022
6070ff6
removing some notes to avoid confusion
bettinaheim Aug 9, 2022
18bfc28
Update specification/under_development/profiles/Base_Profile.md
bettinaheim Aug 9, 2022
3518aa6
Update specification/under_development/profiles/Base_Profile.md
bettinaheim Aug 9, 2022
6185557
Update specification/under_development/profiles/Base_Profile.md
bettinaheim Aug 9, 2022
a3a779b
addressing comments
bettinaheim Aug 9, 2022
3b982f2
Update specification/under_development/profiles/Base_Profile.md
bettinaheim Aug 9, 2022
a2f4093
Update specification/under_development/profiles/Base_Profile.md
bettinaheim Aug 9, 2022
0ef8d5b
Update specification/under_development/profiles/Base_Profile.md
bettinaheim Aug 9, 2022
a84526b
Update specification/under_development/profiles/Base_Profile.md
bettinaheim Aug 9, 2022
be56184
Update specification/under_development/profiles/Base_Profile.md
bettinaheim Aug 9, 2022
666855f
Update specification/under_development/profiles/Base_Profile.md
bettinaheim Aug 9, 2022
110846a
addressing some comments
bettinaheim Aug 10, 2022
8fc659f
addressed most of the comments
bettinaheim Aug 10, 2022
0963ce4
Update specification/under_development/Compilation_And_Targeting.md
bettinaheim Aug 11, 2022
96b3685
addressing some of the remaining comments
bettinaheim Aug 16, 2022
468e60e
Merge branch 'base-profile' of https://github.com/qir-alliance/qir-sp…
bettinaheim Aug 16, 2022
7051641
now the only thing that isn't addressed is the question regarding spl…
bettinaheim Aug 18, 2022
88b8be0
forgot to update the block predecessors
bettinaheim Aug 18, 2022
719c61d
make the entry point have four blocks and require measurements to be …
bettinaheim Aug 18, 2022
1d7c4c9
minor rephrasing
bettinaheim Aug 18, 2022
52cbea1
minor edits
bettinaheim Aug 19, 2022
b173cc1
restructuring and some clean up
bettinaheim Aug 19, 2022
43abafc
Merge branch 'main' into conceptual
bettinaheim Sep 9, 2022
2f44980
Merge branch 'main' into conceptual
bettinaheim Sep 10, 2022
6410fc9
adding a note
bettinaheim Sep 26, 2022
007e98a
Adding output schemas (#32)
idavis Apr 6, 2023
57c1a18
Merge branch 'main' into spec_update
bettinaheim Sep 28, 2023
365efe3
removing outdated profile diff
Oct 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"cSpell.words": [
"argmemonly",
"getelementptr",
"inlinehint",
"inttoptr",
"nofree",
"norecurse",
"preds",
"readnone",
"readonly",
"writeonly"
]
}
130 changes: 130 additions & 0 deletions specification/under_development/Compilation_And_Targeting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Compilation Process and Toolchain

QIR serves as an integrating layer on top of which a shared compilation stage is
built to connect a variety of front- and backends. To accelerate progress,
quantum programming frameworks often choose to expose tools and APIs to
facilitate research and development efforts across the entire stack rather than
just at the application level. Efforts to develop and evaluate the performance
of different error correction schemes, for example, illustrate that compilation
logic may initially be expressed as application code before it is automated and
integrated into the compiler toolchain. A high degree of flexibility and
configurability is hence of great importance when conceptualizing different
compilation stages and how front- and backends integrate with the QIR toolchain
and ecosystem. At the same time, a clear understanding of the purpose and
functionality of subsequent stages in the compilation process is absolutely
vital to grow a robust and performant compiler infrastructure over time.

In addition to the [design goals of
QIR](https://github.com/qir-alliance/qir-spec/blob/main/Scope.md) itself, we
hence define the following goals for the compiler infrastructure around it:

- Unify the ecosystem when reasonable; <br/>
Certain design choices can easily and often unintentionally lead to a
fragmentation of the ecosystem of quantum application, libraries, and
compilation tools, making it harder to leverage existing work in a new
context. For example, requiring application code to be expressed in terms of a
backend-specific set of quantum instructions impedes portability of that code
and hampers the development of shared application libraries.

- Allow making use of backend-specific instructions at the application level;
<br /> Exposing access to backend-specific instructions is a valuable tool for
research purposes. While we encourage libraries to be built against a hardware
agnostic default set of instructions ([Default
QIS](./quantum_instruction_sets/Default_QIS.md)), we aim for a simple
mechanism for deviating from that default for the purpose of experimenting
with new hardware intrinsics and developing backend-specific compiler
optimizations. These developments, in turn, inform what abstractions are
beneficial to expose in the Default QIS, and ultimately permit incorporating
fruitful optimizations into a target specific compilation stage.

- Define (and follow clear) guidance for defining backend-specific instruction
sets; <br /> ...

TODO: the same as what is mentioned under bullet 1 applies to profiles

## Compilation Stages

- Language specific compilation: Compilation of source code to QIR bitcode
- General optimizations: Optimizations that map QIR -> QIR and that do not limit
compatibility in any way
- Linking of application code: Combines bitcode from different sources and
libraries; this stage also resolves the quantum instruction set - meaning the
QIS the application/library code uses will be replaced by a target specific
instruction set.
- Targeting and profile/qis specific optimization: maps QIR -> QIR profile
- Profile Validation: checks whether the compiled code is compliant with the
specified profile and fails compilation otherwise
- Backend-specific compilation and optimization, resolution of runtime functions
(possibly object level linking, standard LTO), possibly machine code
generation

### Linking

important to be able to use target specific instructions at the application
level without requiring frontends or other backends to add support on a
case-by-case basis.

QIS resolution can be done by having an optional attribute (one at most) on
function definitions in the program IR (i.e. the IR before our custom linking
stage) that indicates the target instruction name to check for. This means that
the program IR opts into using certain instructions (that should be listed under
naming conventions) if they are available on the targeted backend.

However, to enable research scenarios it needs to be possible, for example, to
easily prototype simulation specific optimizations that rely on direct access to
the quantum state, and leverage them to accelerate the simulation of quantum
subroutines defined in a library without modifying the source code of that
library.

This can be achieve by a custom compiler pass (QIR -> QIR) that takes a config
file of IR function names and the qis name as arguments and retroactively adds
this attribute. Note that this config file is frontend specific.

What we gain by adding a linking stage with some customizations, compared to
just use the standard llvm linker:

- It is still possible to have a simulator (or hardware for that matter) that
implements several gate sets but use a specific gate set, i.e. only a subset
of the implemented gates, during execution.
- It avoids forcing different front ends to effectively align on naming
convention at the IR level.
- It permits to check signatures and fail at compile time if they don't match.

### Targeting

The QIR specification defines which instructions, including runtime functions
and QIS functions, are sufficient to support arbitrary computations that make
use of both quantum and classical resources, and gives recommendations for how
to leverage and combine these building blocks in a way that ensures maximal
compatibility with different backends. Most or possibly all backends today do
not support arbitrary computations. For example, a common requirement for a program to be
executable on a quantum backend is the ability to ensure
during compilation that the quantum computation terminates. Such requirements
poses fundamental limitations for which programs can or cannot be executed on a
specific backend. Compiling a program in a way that maximizes compatibility with
different backends means that the program representation facilitates that
further compilation steps can largely eliminate constructs that are not
supported by the backend. This targeting process to meet backend requirements
compiles QIR into a form that is compatible with a QIR profile. It may result in
a compilation failure if certain constructs are not supported by the backend and
cannot reasonably be eliminated/replaced as part of targeting. For example,
suppose the targeted backend requires measurements to be performed only as a
final instruction on a QPU, i.e. all quantum resources are released after
measurement. If the program contains branching based on measurements, i.e.
subsequent quantum computations depend on a prior measurement result, then this
construct (meaning the branching) can be eliminate by replacing it with a
coherent version according to the [Deferred Measurement
Principle](https://en.wikipedia.org/wiki/Deferred_Measurement_Principle).
However, this may be impractical since it may require a (potentially
significantly) larger number of qubits to perform the computation, such that the
targeting stage may choose to fail compilation instead.

The QIR specification outlines how to ensure that certain data structures,
control flow structures, and classical computations can be eliminated during
targeting. It is up to each front end to determine the implications for when
source code can be successfully compiled and executed and whether or not to give
early feedback during development.

The profile validation stage ...

-> NOTE: Libraries are untargeted.
38 changes: 38 additions & 0 deletions specification/under_development/Execution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Execution

TODO: define terminology (e.g. QPU), and add some diagrams for how a quantum
backend conceptually looks like somewhere.

entry point should not call another entry point

## QPU Resources

The amount of available memory on a QPU is commonly still fairly limited, with
regards to qubits as well as with regards to classical memory for storing
measurement results before they are read out and transmitted to another
classical processor. Any memory - quantum or classical - that is used during
quantum execution is not usually managed dynamically. Instead, operations are
scheduled and resources are bound as part of compilation. How early in the
process this happens varies, and QIR permits to express programs in a form that
either defers allocation and management of such resources to later stages, or to
directly identify individual qubits and results by a constant integer value as
outlined above. This permits various frontends to accurately reflect application
intent.

Ultimately, it is up to the executing backend which data structure is associated
with a qubit or result value. This gives a backend the freedom to, e.g., process
measurement results asynchronously, or attach additional device data to qubits.
Qubits and result values are correspondingly represented as opaque pointers in
the bitcode, and a QIR program must not dereference such pointers, independent
on whether they are merely bitcasts of integer constants as they are in the Base
Profile program above, or whether they are created dynamically, meaning the
value is managed by the executing backend.

QIR does not make a type distinction for the two kinds of pointers, nor does it
use a different address space for them. This ensures that libraries and
optimization passes that map between different instruction sets do not need to
distinguish whether the compiled application code makes use of dynamic qubit and
result management or not. To execute a given bitcode file, the backend needs to
know how to process qubit and result pointers used by a program. This is
achieved by storing metadata in the form of [module
flags](https://llvm.org/docs/LangRef.html#module-flags-metadata) in the bitcode.
71 changes: 71 additions & 0 deletions specification/under_development/Instruction_Set.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Instruction Set

A backend that supports quantum computations is composed of multiple processing
units that include one or more quantum processors as well as classic computing
resources. A quantum program is a combination of instructions that execute on a
quantum processor, instructions that execute on an adjacent classical processor,
and data transfer between processors.

The QIR profile defines which instructions are used/supported for classical
computations and data transfer, while the Quantum Instruction Set (QIS) defines
which instructions are supported by the quantum processor. The profile and QIS
can be defined/chosen mostly independently, with the caveat that a profile
specification may contain restrictions that need to be satisfied for an QIS to
be compatible (compliant) with that profile. To target a program to a specific
backend hence requires selecting both a profiles and QIS that is supported by
that backend, see also [Compilation and
Targeting](Compilation_And_Targeting.md).

## Runtime Functions

Instructions that execute on a classical processor or serve data transfer are
expressed as LLVM instructions, including calls to `__quantum__rt__*` functions.
These functions are forward declared in the IR and defined by the executing
runtime. Which LLVM instructions and runtime functions are used/supported is
captured in the QIR profile specification. The complete list of all runtime
functions that are needed for executing QIR programs independent on which
profile they have been compiled for is given in the [Library_Reference.md]().
Most backends do not support the full set of runtime functions but merely a
subset that is sufficient for the supported QIR profile(s). The [Base
Profile](profiles/Base_Profile.md) defines the minimal set of runtime functions
that need to be supported for by a backend to permit computations that make use
of qubits and measurements of qubits. Additional functions may be needed to
support the use of data types beyond those for qubit and measurement result
values.

## Quantum Instruction Set (QIS)

The table below lists known quantum instructions along with their signatures and
a description of their functionality. Backends are **not** required to support
all of these. Instead, each backend will declare which of these instructions it
supports. We encourage to make instructions that are supported by a context
independent implementation in terms of other instructions as a library rather
than listing them as part of the backend specification. A library provided
either in the form of a bitcode file can be linked in as part of a QIR
compilation stage.

QIR does not specify the contents of the quantum instruction set. However, in
order to ensure some amount of uniformity, implementations that provide any of
the following quantum instructions must match the specified definition:

Who should add a function to the list of qis naming conventions and when?
-> backend providers, asap; meaning even speculative ones should be added.

| Operation Name | LLVM Function Declaration | Description | Matrix |
|----------------|----------------------------|-------------|--------|
| CCx, CCNOT, Toffoli | `__quantum__qis__ccx__body (%Qubit* control1, %Qubit* control1, %Qubit* target)` | Toffoli or doubly-controlled X | ![latex](https://render.githubusercontent.com/render/math?math=%5Cdisplaystyle+%5Cbegin%7Bbmatrix%7D+1+%26+0+%26+0+%26+0+%26+0+%26+0+%26+0+%26+0+%5C%5C+0+%26+1+%26+0+%26+0+%26+0+%26+0+%26+0+%26+0+%5C%5C+0+%26+0+%26+1+%26+0+%26+0+%26+0+%26+0+%26+0+%5C%5C+0+%26+0+%26+0+%26+1+%26+0+%26+0+%26+0+%26+0+%5C%5C+0+%26+0+%26+0+%26+0+%26+1+%26+0+%26+0+%26+0+%5C%5C+0+%26+0+%26+0+%26+0+%26+0+%26+1+%26+0+%26+0+%5C%5C+0+%26+0+%26+0+%26+0+%26+0+%26+0+%26+0+%26+1+%5C%5C+0+%26+0+%26+0+%26+0+%26+0+%26+0+%26+1+%26+0+%5C%5C+%5Cend%7Bbmatrix%7D) |
| Cx, CNOT | `__quantum__qis__cx__body (%Qubit* control, %Qubit* target)` | CNOT or singly-controlled X | ![latex](https://render.githubusercontent.com/render/math?math=%5Cdisplaystyle+%5Cbegin%7Bbmatrix%7D+1+%26+0+%26+0+%26+0+%5C%5C+0+%26+1+%26+0+%26+0+%5C%5C+0+%26+0+%26+0+%26+1+%5C%5C+0+%26+0+%26+1+%26+0+%5C%5C+%5Cend%7Bbmatrix%7D) |
| Cz | `__quantum__qis__cz__body (%Qubit* control, %Qubit* target)` | Singly-controlled Z | ![latex](https://render.githubusercontent.com/render/math?math=%5Cdisplaystyle+%5Cbegin%7Bbmatrix%7D+1+%26+0+%26+0+%26+0+%5C%5C+0+%26+1+%26+0+%26+0+%5C%5C+0+%26+0+%26+1+%26+0+%5C%5C+0+%26+0+%26+0+%26+-1+%5C%5C+%5Cend%7Bbmatrix%7D) |
| H | `__quantum__qis__h__body (%Qubit* target)` | Hadamard | ![latex](https://render.githubusercontent.com/render/math?math=%5Cdisplaystyle+%5Cfrac%7B1%7D%7B%5Csqrt%7B2%7D%7D%5Cbegin%7Bbmatrix%7D+1+%26+1+%5C%5C+1+%26+-1+%5C%5C+%5Cend%7Bbmatrix%7D) |
| Mz or Measure | `__quantum__qis__mz__body (%Qubit* target, %Result* result)` | Measure a qubit along the the Pauli Z axis |
| Reset | `__quantum__qis__reset__body (%Qubit* target)` | Prepare a qubit in the \|0⟩ state |
| Rx | `__quantum__qis__rx__body (%Qubit* target, double theta)` | Rotate a qubit around the Pauli X axis | ![latex](https://render.githubusercontent.com/render/math?math=%5Cdisplaystyle+%5Cbegin%7Bbmatrix%7D+%5Ccos+%5Cfrac+%7B%5Ctheta%7D+%7B2%7D+%26+-i%5Csin+%5Cfrac+%7B%5Ctheta%7D+%7B2%7D+%5C%5C+-i%5Csin+%5Cfrac+%7B%5Ctheta%7D+%7B2%7D+%26+%5Ccos+%5Cfrac+%7B%5Ctheta%7D+%7B2%7D+%5C%5C+%5Cend%7Bbmatrix%7D) |
| Ry | `__quantum__qis__ry__body (%Qubit* target, double theta)` | Rotate a qubit around the Pauli Y axis | ![latex](https://render.githubusercontent.com/render/math?math=%5Cdisplaystyle+%5Cbegin%7Bbmatrix%7D+%5Ccos+%5Cfrac+%7B%5Ctheta%7D+%7B2%7D+%26+-%5Csin+%5Cfrac+%7B%5Ctheta%7D+%7B2%7D+%5C%5C+%5Csin+%5Cfrac+%7B%5Ctheta%7D+%7B2%7D+%26+%5Ccos+%5Cfrac+%7B%5Ctheta%7D+%7B2%7D+%5C%5C+%5Cend%7Bbmatrix%7D) |
| Rz | `__quantum__qis__rz__body (%Qubit* target, double theta)` | Rotate a qubit around the Pauli Z axis | ![latex](https://render.githubusercontent.com/render/math?math=%5Cdisplaystyle+%5Cbegin%7Bbmatrix%7D+e%5E%7B-i+%5Ctheta%2F2%7D+%26+0+%5C%5C+0+%26+e%5E%7Bi+%5Ctheta%2F2%7D+%5C%5C+%5Cend%7Bbmatrix%7D) | |
| S | `__quantum__qis__s__body (%Qubit* target)` | S (phase gate) | ![latex](https://render.githubusercontent.com/render/math?math=%5Cdisplaystyle+%5Cbegin%7Bbmatrix%7D+1+%26+0+%5C%5C+0+%26+i+%5C%5C+%5Cend%7Bbmatrix%7D) |
| S&dagger; | `__quantum__qis__s_adj (%Qubit* target)` | The adjoint of S | ![latex](https://render.githubusercontent.com/render/math?math=%5Cdisplaystyle+%5Cbegin%7Bbmatrix%7D+1+%26+0+%5C%5C+0+%26+-i+%5C%5C+%5Cend%7Bbmatrix%7D) |
| T | `__quantum__qis__t__body (%Qubit* target)` | T | ![latex](https://render.githubusercontent.com/render/math?math=%5Cdisplaystyle+%5Cbegin%7Bbmatrix%7D+1+%26+0+%5C%5C+0+%26+e%5E%7Bi%5Cpi%2F4%7D+%5C%5C+%5Cend%7Bbmatrix%7D) |
| T&dagger; | `__quantum__qis__t__adj (%Qubit* target)` | The adjoint of T operation | ![latex](https://render.githubusercontent.com/render/math?math=%5Cdisplaystyle+%5Cbegin%7Bbmatrix%7D+1+%26+0+%5C%5C+0+%26+e%5E%7B-i%5Cpi%2F4%7D+%5C%5C+%5Cend%7Bbmatrix%7D) |
| X | `__quantum__qis__x__body (%Qubit* target)` | Pauli X | ![latex](https://render.githubusercontent.com/render/math?math=%5Cdisplaystyle+%5Cbegin%7Bbmatrix%7D+0+%26+1+%5C%5C+1+%26+0+%5C%5C+%5Cend%7Bbmatrix%7D) |
| Y | `__quantum__qis__y__body (%Qubit* target)` | Pauli Y | ![latex](https://render.githubusercontent.com/render/math?math=%5Cdisplaystyle+%5Cbegin%7Bbmatrix%7D+0+%26+-i+%5C%5C+i+%26+0+%5C%5C+%5Cend%7Bbmatrix%7D) |
| Z | `__quantum__qis__z__body (%Qubit* target)` | Pauli Z | ![latex](https://render.githubusercontent.com/render/math?math=%5Cdisplaystyle+%5Cbegin%7Bbmatrix%7D+1+%26+0+%5C%5C+0+%26+-1+%5C%5C+%5Cend%7Bbmatrix%7D) |
Loading