Here is the revised proposal for the LLVM/SPIR-V converter. Please comment.
Thanks.
Proposal of Adding SPIRV Target
Background
SPIR-V is a portable binary format for OpenCL kernels and GLSL shaders. A
typical use case of SPIR-V is as follows:
1. An application developer uses Clang to compile an OpenCL kernel
source code to a SPIR-V binary which is common for all OpenCL platforms.
2. The application developer ships the application containing the
SPIR-V binary to customers.
3. A customer runs the application on an OpenCL platform, which loads
the SPIR-V binary through an OpenCL API function.
4. The vendor-specific OpenCL runtime translates SPIR-V to LLVM IR,
changes the target triple and data layout to suit the device which will
execute the kernel, performs target specific optimizations, generates the
ISA and executes the ISA on the device.
For OpenCL kernels, there is implicit data layout dependence when compiling
the source to LLVM. Since SPIR-V is for common OpenCL platforms, a common
data layout accepted by different OpenCL vendors is required. We choose the
data layout which has been adopted by SPIR 1.2/2.0 for SPIR-V, since it has
been successfully used for supporting consumption of SPIR 1.2/2.0 on
various OpenCL platforms. For GLSL shaders, it is still under discussion
whether to choose the same data layout as OpenCL, or a different data
layout, or no data layout at all.
Location
From feedback of the previous version of the proposal, there are several
suggestions about the location for the LLVM/SPIR-V converter:
1. llvm/lib/SPIRV only, adding an option to Clang for outputting
SPIR-V. The advantage is ease of use for bi-way translation. However it
does not reflect the fact that only LLVM IR with specific target triple and
data layout can be translated to SPIR-V.
2. llvm/lib/SPIRV containing the main functionality of bi-way
translation between LLVM IR and SPIR-V, llvm/lib/Target/SPIRV containing a
thin wrapper as a target machine to allow Clang targeting SPIR-V. The
advantage compared with 1 is that it allows a more conventional way of
using Clang to produce SPIR-V. However it is subject to the same issue as 1
about not reflecting the requirement on the LLVM IR which can be translated
to SPIR-V.
3. llvm/lib/Target/SPIRV only. The advantage is that it reflects the
requirement on the target triple and data layout for LLVM IR which can be
translated to SPIR-V. However putting the SPIR-V to LLVM converter in the
same directory is unconventional. Leaving the SPIR-V to LLVM converter out
of LLVM source tree is also not desirable since OpenCL vendors need this
functionality.
Our proposal is to take approach 3 and keep the bi-way converter in
llvm/lib/Target/SPIRV. The functionality of the bi-way converter is exposed
through llvm/include/Support/SPIRV.h. A thin wrapper as a target machine is
also provided to allow Clang targeting SPIR-V. The rationale is that this
directory structure better reflects the nature of SPIR-V. SPIR-V is not an
alternative representation for arbitrary LLVM IR. Instead, it is an
alternative representation for LLVM IR targeting generic OpenCL or Vulkan
platforms. It has its own specific target triple and data layout. Therefore
it makes sense for the functionality to be put under llvm/lib/Target. Also,
as an alternative representation of LLVM IR, it makes sense to have a
bi-way convertor.
Implementation
About the implementation of the converter, although there are suggestions
to take the SelectionDAG/MC approach, it seems not a major concern in
general. The current implementation uses a shared in-memory representation
of SPIR-V, which facilitates supporting bi-way translation. The round-trip
translated LLVM IR by the current implementation has passed OpenCL SPIR 1.2
conformance test, which proves the current implementation works. On the
other hand, the SelectionDAG/MC approach would require significant tweaking
compared to a conventional backend, since SPIR-V is not a low level machine
ISA but a high level generic IR. Also, the SelectionDAG/MC approach only
supports one-way translation from LLVM to SPIR-V. Therefore unless major
concern arises, we will keep the current implementation approach.
Maintenance
The current implementation works by breaking down LLVM IR to instructions
and re-constructing them in SPIR-V, and vice versa. Therefore the
dependence of the current implementation on LLVM is mainly the C++ API in
llvm/include/IR. As such, its dependence on LLVM is similar to typical
module passes. Our experience with porting it among LLVM 3.2/3.4/3.6 is
that the porting effort is moderate.
Milestones
Currently Clang can compile OpenCL 1.2/2.0 C kernel source to LLVM IR with
spir/spir64 target triple, which is compatible with SPIR-V for the
supported instructions, data types and builtin functions. Therefore the
first milestone of the converter is to support compiling OpenCL 1.2/2.0
kernel to SPIR-V. This is also to lay the foundation for the upcoming
OpenCL 2.1 C++ frontend development in Clang. The next milestone would be
supporting OpenCL 2.1 C++, which hopefully would be in synch with the
frontend development work. In the meantime, as the SPIR-V target becomes
stable and is able to support the instructions common to OpenCL and GLSL,
hopefully the GLSL frontend work and support for GLSL specific instructions
would pick up and finally we would have a SPIR-V target supporting the
complete SPIR-V spec.
Testing
We will add lit tests for SPIR-V. Also the converter would be tested by
different OpenCL vendors for production quality through comprehensive
conformance tests, since SPIR-V is required by OpenCL 2.1.
Logistics
AMD, Intel and some other SPIR WG members would join force for the
development of the bi-way converter. Since supporting of SPIR-V is required
by OpenCL 2.1, it is expected that OpenCL vendors would continue the
maintenance efforts for supporting SPIRV target in LLVM.
Yaxun Liu
AMD