What is SPIR?
The Standard Portable Intermediate Representation (SPIR) is a portable encoding of device programs. SPIR 1.2 is an encoding of OpenCL C device programs in LLVM IR.
SPIR 1.2 defines how any OpenCL C (version 1.2) device program can be encoded in LLVM (version 3.2).
What set of problems is SPIR supposed to solve?
Enable third-party code generation targeting OpenCL platforms without going through OpenCL C:
For example, a compiler for an alternative device language (not OpenCL C) can generate SPIR and have it run on any OpenCL backend that supports the cl_khr_spir extension. There is no need to generate OpenCL C as an intermediate. The alternative language could be many things, such as an established language (like FORTRAN), an exotic domain specific language, or a single source programming environment with automatic code partitioning. However, the language semantics must be mappable to SPIR and satisfy the constraints of OpenCL target systems.
A developer can ship an OpenCL application without exposing their device program source at any point in the flow.
The standard OpenCL compilation model provides device program source text to the clCreateProgramWithSource API.
Shipping a SPIR IR instance in bitcode format gives them legal protections they would otherwise not have. (This is not cryptographically strong protection, but instead it is similar to DMCA style protection whereby obfuscation is enough to prove intent if IP reverse engineering is discovered.)
The alternative is to ship device-specific (and sometimes driver-specific) binaries. This can imply a combinatorial explosion in the number of device binaries an application developer would have to prepare and ship.
Compatibility across vendors, and forward compatibility to newer devices:
An application that uses a valid SPIR IR instance should be runnable on any OpenCL platform supporting the cl_khr_spir extension and the matching SPIR version. (A single platform/device combination could support more than one version of SPIR IR; see the CL_DEVICE_SPIR_VERSIONS device query.) The SPIR IR instance could have been generated by any tool, provided it is valid SPIR IR.
How does SPIR fit in? (Reference flow)
The reference SPIR flow is as follows:
At development time:
- A developer writes a device program is some programming language (such as OpenCL C).
- The developer translates the device program into a SPIR IR instance.
- An application queries the OpenCL platform to ensure that the cl_khr_spir extension is supported.
- The application queries the OpenCL CL_DEVICE_SPIR_VERSIONS to ensure the correct version of SPIR is supported.
- The application calls clCreateProgramWithBinary and then clBuildProgram or clCompileProgram to create a standard platform-specific device binary that can then be used to execute code on the device.
The development time activities in the above flow are called SPIR Generation, and the runtime activities are called SPIR consumption.
What does Khronos standardize?
Khronos standardizes (provides specifications and conformance tests for) two things:
- SPIR IR. This defines how an OpenCL device program can be expressed in LLVM IR:
- Some LLVM features are forbidden, e.g. unusual integer data types, forbidden instructions
- OpenCL C specific information must be encoded in a specific way, e.g. which functions are kernel functions, how are attributes encoded, what extensions are used by the program, etc.
- SPIR consumption: the cl_khr_spir extension to the OpenCL platform and runtime APIs.
Khronos does not define the process for translating a program from any source language into SPIR.
What open source is related to SPIR?
- Patched Clang 3.2 that can translate OpenCL C (version 1.2) into SPIR IR 1.2. See the Khronos Github account. See the SPIR repository under the Khronos Group Github account.
- Clang trunk. Patches are being contributed to Clang trunk to enable it to generate valid SPIR 1.2 IR. See below.
- There is no known open source implementation of SPIR consumption.
Can I use SPIR? (Licensing)
Khronos specifications themselves are copyrighted by The Khronos Group Inc., and are restrictively licensed. (See the specification document preamble for details.)
You may use or implement the functionality in the SPIR IR or OpenCL specifications, free of charge.
To claim conformance to the specifications, you must follow the process defined in the Khronos Adopters program.
As always, check the full legal terms and conditions for any Khronos specification, Adopters Agreement, or any software or hardware implementations you plan to use.
How can I generate a SPIR IR instance from OpenCL C?
Use the patched Clang 3.2 from the Khronos Github account to translate valid OpenCL C (version 1.2) into SPIR 1.2.
Khronos group members are contributing all patches to Clang trunk. As of January 2014, most of the support is already included in Clang trunk, but there are some pieces missing.
When will Clang trunk support OpenCL C 1.2 to SPIR 1.2 generation?
See previous answer. The only holdup is review of the remaining patches.
Where can I ask about Clang support for SPIR?
Ask on the Clang developer email list.
Can I generate SPIR IR from language XYZ?
Yes. It's very likely (but not required) that you will want to base your work on a recent version of LLVM and perhaps Clang.
How do I know if something is valid SPIR IR?
Use the Verifier module. It is an LLVM pass that checks validity with respect to the SPIR IR specification.
As of January 2014, it is known to be incomplete. The intent is to continue to improve it.
Can I optimize SPIR IR?
Optimization or transformation of an LLVM module that is also a valid SPIR IR instance is beyond the scope of any Khronos specfication.
However, it is the responsibility of the transformation to (a) preserve program semantics according to LLVM rules, (b) preserve OpenCL semantics as expressed in SPIR IR, and (c) result in valid SPIR IR; if these are also goals of the transform.
What will run a SPIR IR instance?
A conformant OpenCL implementation that supports standard extension cl_khr_spir can load and run a SPIR IR instance. See the OpenCL extension specification for version 1.2, 2.0 or later for details on the runtime APIs for doing so.
In particular, an OpenCL platform would list cl_khr_spir in its response to the CL_PLATFORM_EXTENSIONS query. Also, the CL_DEVICE_SPIR_VERSIONS lists which versions of SPIR IR are supported by a particular device, e.g. 1.2 2.0.
What OpenCL implementations support SPIR consumption?
It is up to vendors to describe what extensions their OpenCL implementations support. Khronos does not maintain a list. (Yet...?)
Can a non-OpenCL implementation execute a SPIR instance?
Khronos does not control what you do with a SPIR instance.
However, the Khronos Adopters Program defines the conformance process and criteria for SPIR consumption (the cl_khr_spir extension to OpenCL).
Ecosystem and miscellaneous
Why is the first version of SPIR called 1.2?
SPIR 1.2 supports all features of OpenCL 1.2 device programs.
Secondarily, OpenCL 1.2 is the first version of OpenCL to define the cl_khr_spir runtime API to load SPIR instances.
Who is using SPIR?
The following projects are known to use SPIR:
|Clang 3.2 patched||OpenCL C 1.2 to SPIR compiler||Khronos Group Inc|
|SPIR Tools||SPIR module verifier, etc.||Khronos Group Inc|
|PGI OpenACC||OpenACC to SPIR compiler||Portland Group Inc|
|C++AMP compiler||Multicoreware Inc|
SPIR portability and versioning
Can I generate a SPIR instance with compiler X and run it on platform Y?
The OpenCL cl_khr_spir runtime API extension assumes you can deliver a binary SPIR IR instance to the clCreateProgramWithBinary API.
The target environment may impose additional requirements before such an application can execute. For example, a target environment may require application pre-verification and cryptographically strong application signing. See the definition of Deployment Ecosystem in the Glossary below.
Can a SPIR 1.2 instance be processed by an LLVM 3.4+ system?
For OpenCL targets, the conformance process ensures that SPIR 1.2 instances can be loaded and executed by an OpenCL platform which supports the cl_khr_spir extension and which includes "1.2" in its reply to the CL_DEVICE_SPIR_VERSIONS device query. (The target platform might not even include any part of LLVM in its tool flow, let alone a specific version.)
The broader question is whether an LLVM 3.2 IR bitcode can be loaded and processed by an LLVM toolchain that is much newer than LLVM 3.2. For example, LLVM 3.4 encodes function attributes differently than LLVM 3.2 does. Khronos members (such as Intel) are contributing tests and fixes to the LLVM trunk to attempt to preserve the ability for newer LLVM versions to load LLVM 3.2 bitcodes. This is an ongoing process, and at some point the LLVM community may decide to break backward compatibility in a fundamental and hard-to-fix way.
- Clang Clang is an open source language parser (or front-end) for compiling C, C++ and related languages into LLVM IR. Development of Clang is tightly integrated with the development of LLVM.
- Container A data object designed to deliver a program to be executed in a target environment. A container may include a SPIR instance, a different program representation, or other data items used to validate, authenticate or otherwise annotate the program.
- Deployment Ecosystem A universe of target machine environments defined by policies for preparing and encoding a program for execution. Example ecosystem policies may include:
- That a particular toolchain must be used to process programs.
- That all programs be signed by their authors.
- The container to be used.
- Backward compatibility A property of a system whereby newer versions of the system accept data generated for use with an older version of the system.
- Intermediate Representation (IR) An encoding for computer programs. An IR is typically designed to for ease of generation by a language parser (or compiler front-end), for ease of optimization (where both the input to and the output of an optimization transformation are valid IR), and for ease of generating a target machine specific representation of the program.
- ISV Independent Software Vendor. A person or organization which publishes an application, in particular one designed to run on an OpenCL platform and device.
- LLVM The LLVM Project is an open source compiler infrastructure software project. It comprises:
- A language definition for a compiler intermediate representation (IR) for programs.
- A set of software tools for creating and manipulating LLVM IR.
- LLVM bitcode A binary format for encoding an LLVM IR instance.
- LLVM IR instance A program expressed in LLVM Intermediate Representation. An LLVM IR instance typically requires further processing before it is executed by a machine.
- Materialization A processing step where a program is transformed from one form into another. In the SPIR context, this typically means translation of a program from SPIR into a target machine specific representation.
- SPIR consumer A runtime which can load and run a SPIR instance. For SPIR 1.2 this process is defined by the cl_khr_spir extension to OpenCL 1.2 and OpenCL 2.0.
- SPIR generator A software tool which can create a SPIR instance. Typically this is a language parser (front-end) such as Clang which can translate a OpenCL C program into a SPIR instance. However, the source language is not limited to OpenCL C.
- SPIR instance An LLVM IR instance which satisfies the SPIR specification.
- SPIR TSG The SPIR Technical Subgroup of the Khronos OpenCL working group.