SPIRV-LLVM as an external tool

Hi,

for a few months already I have been asking around for opinions on how
people could best work together on Khronos' SPIR-V <-> LLVM-IR converter
and some consensus seems to have formed.

Most of the people I talked to favored having the converter become an
external tool within the LLVM project, similar to libclc. I think that
the LLVM project's processes, infrastructure and community form the best
place for this collaboration to happen.

I hope that having the converter as part of LLVM can help expand LLVM's
value proposition in heterogeneous computing, in part by complementing
the OpenCL C backend in clang.

Thus I would like to ask what the LLVM community needs to see from us
before SPIRV-LLVM can be accepted as an external tool, if at all.

Thanks,

Tomeu

I agree that having the conversion live as part of LLVM is the best option going forward.

libclc is an library implementation of the OpenCL builtins and I think its fine for that aspect of the converter,
i.e. consumption of SPIR-V into LLVM IR in preparation for code generation by LLVM by its various backends as a library
to link the generated code to, to live in an external repo.

This is fine because SPIR<->LLVM IR is trivial, SPIR-V<->LLVM is not.

Having the SPIR-V <-> LLVM-IR conversion part of the tool as an external repo as opposed to the llvm would
make it very difficult to use as a fontend:

First the changes to the build pipeline are a hinderance. In my fork of SPIRV-LLVM the backend is a target
because I couldn’t get CMake to link the libraries to LDC as a support library. This would be made even more
complicated with at external project. I would probably resort to invoking an external program despite integrated
conversion being the best solution.

Secondly (unless you've changed things) all of the builtins are not intrinsics, but C++ Itanium with extensions mangled.
This makes it so that anyone not implementing a C++ frontend has to deal with it, presumably by hardcoding the
names since C++ is very non-trivial. Even for projects like LDC (the LLVM based D compiler) which have a C++ mangler,
we still have to hardcode the names because Windows does not use Itanium and the compiler is not set up to do two
different forms of C++ mangling, and even if that were possible the non-standard extensions make it infeasible.
Whereas any LLVM frontend worth is salt has a way of exposing intrinsics.

The backend as it currently stands is not based on tablegen and that is required AFAIU to support intrinsics.
I have tablegen descriptions of the SPIR-V format mostly complete (all core instruction relevant to OpenCL +
most of the ones for Vulkan, + all the OpenCL extension instructions) though not the intrinsics.
However I didn’t get around to using them because I have more important things to work on in the front end.

Then there is the question of what to do about Vulkan? I would love to have support for Vulkan in LLVM.
That would be relatively simple to set up for with SPIRV as a target, even more so with a tablegen based
infrastructure. I have no idea how that would work as an external project.

I also think that having it in an external project will greatly reduce the visibility in comparison to a target.
How many of you have cloned libclc for example? Not many I suspect. Probably because you are not
working on implementing OpenCL for a backend. And while libclc is useful to those implementing OpenCL
they are vastly outnumbered by those using OpenCL i.e. producing SPIR/SPIR-V. My usage of SPIR-V is
I generate it from my source files though LDC/LLVM then I hand it off to the OpenCL implementation.
Nowhere in that pipeline do I need something like libclc. Now libclc may be used in the implementation
but that’s a different copy of LLVM to the one that produced it.

TL;DR.

This really needs to be a target so that we can use intrinsics, have it as part of regular LLVM releases
so that it can be used by many frontends. Having an external project for assisting backends consuming
SPIR-V (a la libclc) is fine but that shouldn’t mean that the processes used for generating SPIR-V need to go
into a separate project.

Nic

I agree that having the conversion live as part of LLVM is the best option going forward.

libclc is an library implementation of the OpenCL builtins and I think its fine for that aspect of the converter,
i.e. consumption of SPIR-V into LLVM IR in preparation for code generation by LLVM by its various backends as a library
to link the generated code to, to live in an external repo.

This is fine because SPIR<->LLVM IR is trivial, SPIR-V<->LLVM is not.

Having the SPIR-V <-> LLVM-IR conversion part of the tool as an external repo as opposed to the llvm would
make it very difficult to use as a fontend:

First the changes to the build pipeline are a hinderance. In my fork of SPIRV-LLVM the backend is a target
because I couldn’t get CMake to link the libraries to LDC as a support library. This would be made even more
complicated with at external project. I would probably resort to invoking an external program despite integrated
conversion being the best solution.

Secondly (unless you've changed things) all of the builtins are not intrinsics, but C++ Itanium with extensions mangled.
This makes it so that anyone not implementing a C++ frontend has to deal with it, presumably by hardcoding the
names since C++ is very non-trivial. Even for projects like LDC (the LLVM based D compiler) which have a C++ mangler,
we still have to hardcode the names because Windows does not use Itanium and the compiler is not set up to do two
different forms of C++ mangling, and even if that were possible the non-standard extensions make it infeasible.
Whereas any LLVM frontend worth is salt has a way of exposing intrinsics.

The backend as it currently stands is not based on tablegen and that is required AFAIU to support intrinsics.
I have tablegen descriptions of the SPIR-V format mostly complete (all core instruction relevant to OpenCL +
most of the ones for Vulkan, + all the OpenCL extension instructions) though not the intrinsics.
However I didn’t get around to using them because I have more important things to work on in the front end.

Then there is the question of what to do about Vulkan? I would love to have support for Vulkan in LLVM.
That would be relatively simple to set up for with SPIRV as a target, even more so with a tablegen based
infrastructure. I have no idea how that would work as an external project.

I also think that having it in an external project will greatly reduce the visibility in comparison to a target.
How many of you have cloned libclc for example? Not many I suspect. Probably because you are not
working on implementing OpenCL for a backend. And while libclc is useful to those implementing OpenCL
they are vastly outnumbered by those using OpenCL i.e. producing SPIR/SPIR-V. My usage of SPIR-V is
I generate it from my source files though LDC/LLVM then I hand it off to the OpenCL implementation.
Nowhere in that pipeline do I need something like libclc. Now libclc may be used in the implementation
but that’s a different copy of LLVM to the one that produced it.

TL;DR.

This really needs to be a target so that we can use intrinsics, have it as part of regular LLVM releases
so that it can be used by many frontends. Having an external project for assisting backends consuming
SPIR-V (a la libclc) is fine but that shouldn’t mean that the processes used for generating SPIR-V need to go
into a separate project.

Yes, for compilers it would be much more convenient to have a backend, but what OpenCL implementations need (for example) is only a bidirectional converter.

I don't think anybody will oppose to the converter becoming a backend at some point (as long as we keep exposing the conversion passes as today), but at the current pace it will take years and I don't think it's fair for everybody that we keep this codebase in the limbo for much longer.

Currently there's people shipping this code in products, and have to carry heavily modified forks because there's no community upstream to contribute to.

So, I think we really need at this point to find some place where the community can gather and work together on stability, intrinsics, have a proper backend, etc.

This proposal is only about where the collaboration would happen in the near future. If at some point we have also a backend, and people want to have it along the other backends in the main LLVM repo, that will be great. But in the meantime we need a place to work together.

Regards,

Tomeu

I agree that having the conversion live as part of LLVM is

    > the best option going forward.

Yes. :slight_smile:

    > libclc is an library implementation of the OpenCL
    > builtins and I think its fine for that aspect of the
    > converter, i.e. consumption of SPIR-V into LLVM IR in
    > preparation for code generation by LLVM by its various
    > backends as a library to link the generated code to, to
    > live in an external repo.

    > This is fine because SPIR<->LLVM IR is trivial,
    > SPIR-V<->LLVM is not.

LLVM IR -> SPIR is not that trivial because for example SPIR 2.0
compliant bitcode requires to be encoded into LLVM 3.4 bitcode format,
which is not obvious from, say, LLVM 7.

By the way there is a market for another open-source project: generic
down-grader from modern bitcode to anything older. :slight_smile: There are some
specific versions flying around, but this is another story...

Yes, for compilers it would be much more convenient to have a backend, but what OpenCL implementations need (for example) is only a bidirectional converter.

Thankfully the difference between the two is a rather small amount of boiler plate, exposing passes vs. hooking the target infrastructure.
It is not difficult to have both, I have both at the moment.

I don’t think anybody will oppose to the converter becoming a backend at some point (as long as we keep exposing the conversion passes as today), but at the current pace it will take years and I don’t think it’s fair for everybody that we keep this codebase in the limbo for much longer.

Good, true.

Currently there’s people shipping this code in products, and have to carry heavily modified forks because there’s no community upstream to contribute to.

Heh, tell me about it.

So, I think we really need at this point to find some place where the community can gather and work together on stability, intrinsics, have a proper backend, etc.

Indeed.

This proposal is only about where the collaboration would happen in the near future. If at some point we have also a backend, and people want to have it along the other backends in the main LLVM repo, that will be great. But in the meantime we need a place to work together.

Ah, that makes more sense.

We don’t need to have the project on LLVM to begin with (and I suspect it will be easier that way).
When it is more stable and feature complete we can have it as an official external project as a precursor to the main LLVM repo (review, etc.) and then split off the libclc-like bit into its own repo.

Nic

I also think that having it in an external project will greatly reduce the visibility in comparison to a target. How many of you have cloned libclc for example?

The idea is to have it as a tool in the LLVM project space. This means it will become a part of the overall LLVM project but as an optional code base to the main LLVM backend code base. I don’t think this affect visibility that much. For example, Clang is also a tool project of LLVM and it’s just as popular as LLVM. It is only a matter of how useful it would be. We are convinced there are enough users of SPIRV converter at the moment for this to be adopted as a component of the LLVM overall infrastructure.

Cheers,
Anastasia

Hi,

for a few months already I have been asking around for opinions on how
people could best work together on Khronos' SPIR-V <-> LLVM-IR converter
and some consensus seems to have formed.

Most of the people I talked to favored having the converter become an
external tool within the LLVM project, similar to libclc. I think that
the LLVM project's processes, infrastructure and community form the best
place for this collaboration to happen.

I hope that having the converter as part of LLVM can help expand LLVM's
value proposition in heterogeneous computing, in part by complementing
the OpenCL C backend in clang.

Thus I would like to ask what the LLVM community needs to see from us
before SPIRV-LLVM can be accepted as an external tool, if at all.

Does the external tool exist already? I recommend starting by posting
the code publicly and then ensuring that going forward all development
and discussions about the tool are happening in a public space.

It's important to demonstrate that there is a developer community backing
the tool and that it won't be abandoned if it is added as an llvm
sub-project.

-Tom

I agree that having the conversion live as part of LLVM is the best option going forward.

libclc is an library implementation of the OpenCL builtins and I think its fine for that aspect of the converter,
i.e. consumption of SPIR-V into LLVM IR in preparation for code generation by LLVM by its various backends as a library
to link the generated code to, to live in an external repo.

This is fine because SPIR<->LLVM IR is trivial, SPIR-V<->LLVM is not.

Having the SPIR-V <-> LLVM-IR conversion part of the tool as an external repo as opposed to the llvm would
make it very difficult to use as a fontend:

First the changes to the build pipeline are a hinderance. In my fork of SPIRV-LLVM the backend is a target
because I couldn’t get CMake to link the libraries to LDC as a support library. This would be made even more
complicated with at external project. I would probably resort to invoking an external program despite integrated
conversion being the best solution.

Secondly (unless you've changed things) all of the builtins are not intrinsics, but C++ Itanium with extensions mangled.
This makes it so that anyone not implementing a C++ frontend has to deal with it, presumably by hardcoding the
names since C++ is very non-trivial. Even for projects like LDC (the LLVM based D compiler) which have a C++ mangler,
we still have to hardcode the names because Windows does not use Itanium and the compiler is not set up to do two
different forms of C++ mangling, and even if that were possible the non-standard extensions make it infeasible.
Whereas any LLVM frontend worth is salt has a way of exposing intrinsics.

The backend as it currently stands is not based on tablegen and that is required AFAIU to support intrinsics.
I have tablegen descriptions of the SPIR-V format mostly complete (all core instruction relevant to OpenCL +
most of the ones for Vulkan, + all the OpenCL extension instructions) though not the intrinsics.
However I didn’t get around to using them because I have more important things to work on in the front end.

Then there is the question of what to do about Vulkan? I would love to have support for Vulkan in LLVM.
That would be relatively simple to set up for with SPIRV as a target, even more so with a tablegen based
infrastructure. I have no idea how that would work as an external project.

I also think that having it in an external project will greatly reduce the visibility in comparison to a target.
How many of you have cloned libclc for example? Not many I suspect. Probably because you are not
working on implementing OpenCL for a backend. And while libclc is useful to those implementing OpenCL
they are vastly outnumbered by those using OpenCL i.e. producing SPIR/SPIR-V. My usage of SPIR-V is
I generate it from my source files though LDC/LLVM then I hand it off to the OpenCL implementation.
Nowhere in that pipeline do I need something like libclc. Now libclc may be used in the implementation
but that’s a different copy of LLVM to the one that produced it.

TL;DR.

This really needs to be a target so that we can use intrinsics, have it as part of regular LLVM releases
so that it can be used by many frontends. Having an external project for assisting backends consuming
SPIR-V (a la libclc) is fine but that shouldn’t mean that the processes used for generating SPIR-V need to go
into a separate project.

Yes, for compilers it would be much more convenient to have a backend, but what OpenCL implementations need (for example) is only a bidirectional converter.

I don't think anybody will oppose to the converter becoming a backend at some point (as long as we keep exposing the conversion passes as today), but at the current pace it will take years and I don't think it's fair for everybody that we keep this codebase in the limbo for much longer.

Currently there's people shipping this code in products, and have to carry heavily modified forks because there's no community upstream to contribute to.

So, I think we really need at this point to find some place where the community can gather and work together on stability, intrinsics, have a proper backend, etc.

This proposal is only about where the collaboration would happen in the near future. If at some point we have also a backend, and people want to have it along the other backends in the main LLVM repo, that will be great. But in the meantime we need a place to work together.

I agree with this sentiment. This code has been floating around for a
long time and an external tool is the path of least resistance to get
something working that we can all start collaborating on. I think it's
more important to provide something working now than to wait until we solve
the backend vs external tool debate. Just because we start with an external
tool doesn't mean that has to be the long-term solution.

-Tom

> Hi,
>
> for a few months already I have been asking around for opinions on how
> people could best work together on Khronos' SPIR-V <-> LLVM-IR converter
> and some consensus seems to have formed.
>
> Most of the people I talked to favored having the converter become an
> external tool within the LLVM project, similar to libclc. I think that
> the LLVM project's processes, infrastructure and community form the best
> place for this collaboration to happen.
>
> I hope that having the converter as part of LLVM can help expand LLVM's
> value proposition in heterogeneous computing, in part by complementing
> the OpenCL C backend in clang.
>
> Thus I would like to ask what the LLVM community needs to see from us
> before SPIRV-LLVM can be accepted as an external tool, if at all.
>

Does the external tool exist already? I recommend starting by posting
the code publicly and then ensuring that going forward all development
and discussions about the tool are happening in a public space.

The code is publicly available at https://github.com/pierremoreau/llvm-spirv.
It is based on https://github.com/KhronosGroup/SPIRV-LLVM/ and
https://github.com/thewilsonator/llvm-target-spirv/, stripped off of everything
not related to SPIR-V and updated to work with llvm HEAD.
(Some of the commits were lost on the way, so we are in the process of redoing
the stripping and updating.)

One user of that external tool will be Mesa [1] (for its OpenCL implementation
named clover) for
1. enabling clCreateProgramWithIL(KHR)? on AMD cards through clover, by
   translating SPIR-V to LLVM IR; (patches under review [2])
2. allowing additional drivers (nouveau, freedreno, etnativ) to be supported by
   clover, by compiling OpenCL C (via LLVM IR) to SPIR-V (and then translating
   from SPIR-V to NIR).

Regards,
Pierre

[1]: https://www.mesa3d.org/
[2]: https://patchwork.freedesktop.org/series/38728/

It’s important to demonstrate that there is a developer community backing
the tool and that it won’t be abandoned if it is added as an llvm
sub-project.

-Tom

Just to complete the picture, this is an initiative from within Khronos Group

to unify our effort to make this available as an LLVM component. A number of

companies have been involved in the original development of this converter and

there are more that have adopted this design in their propriety or open source

toolchains. Mesa and AMD Vulkan driver (https://github.com/GPUOpen-Drivers/AMDVLK)

are just some examples of the open source ones. There were a number of threads

regarding putting this work upstream in the past years. And due to several

conceptual differences it, unfortunately, took us a while to get an agreement

on the best integration approach. During this time a number of forks were created

that rebased this work to the top of trunk and also committed several improvements.

Some of them are just duplicated in various forks. It would help us if we finally

have it integrated with LLVM so we can keep it up to date and contribute common

changes. So there are a number of companies that want to contribute to this

currently.

@Tom, if you have any valuable experience to share with us on how to get this

accepted/integrated as a tool, it would be very helpful.

Thanks,
Anastasia

It's important to demonstrate that there is a developer community backing
the tool and that it won't be abandoned if it is added as an llvm
sub-project.

-Tom

Just to complete the picture, this is an initiative from within Khronos Group

to unify our effort to make this available as an LLVM component. A number of

companies have been involved in the original development of this converter and

there are more that have adopted this design in their propriety or open source

toolchains. Mesa and AMD Vulkan driver (https://github.com/GPUOpen-Drivers/AMDVLK)

are just some examples of the open source ones. There were a number of threads

regarding putting this work upstream in the past years. And due to several

conceptual differences it, unfortunately, took us a while to get an agreement

on the best integration approach. During this time a number of forks were created

that rebased this work to the top of trunk and also committed several improvements.

Some of them are just duplicated in various forks. It would help us if we finally

have it integrated with LLVM so we can keep it up to date and contribute common

changes. So there are a number of companies that want to contribute to this

currently.

@Tom, if you have any valuable experience to share with us on how to get this

accepted/integrated as a tool, it would be very helpful.

It's pretty much what I mentioned before. Put the code for the tool somewhere
public and start using that as the focal point for all development. Once that
is done then you can come back to the community to start a discussion about adding
it as a sub-project. It's much easier to have a discussion when there is actual
code to talk about.

-Tom

Hi,

for a few months already I have been asking around for opinions on how
people could best work together on Khronos' SPIR-V <-> LLVM-IR converter
and some consensus seems to have formed.

Most of the people I talked to favored having the converter become an
external tool within the LLVM project, similar to libclc. I think that
the LLVM project's processes, infrastructure and community form the best
place for this collaboration to happen.

I hope that having the converter as part of LLVM can help expand LLVM's
value proposition in heterogeneous computing, in part by complementing
the OpenCL C backend in clang.

Thus I would like to ask what the LLVM community needs to see from us
before SPIRV-LLVM can be accepted as an external tool, if at all.

Does the external tool exist already? I recommend starting by posting
the code publicly and then ensuring that going forward all development
and discussions about the tool are happening in a public space.

The code is publicly available at https://github.com/pierremoreau/llvm-spirv.
It is based on https://github.com/KhronosGroup/SPIRV-LLVM/ and
https://github.com/thewilsonator/llvm-target-spirv/, stripped off of everything
not related to SPIR-V and updated to work with llvm HEAD.
(Some of the commits were lost on the way, so we are in the process of redoing
the stripping and updating.)

This is great to see. Is this code the basis of the forks that Anastasia
talked about or did those come from somewhere else?

-Tom

This is great to see. Is this code the basis of the forks that Anastasia
talked about or did those come from somewhere else?

Yes, indeed the base is https://github.com/KhronosGroup/SPIRV-LLVM/ and then there are multiple forks that include some rework as well (some of which were announced on the LLVM channels). I think the biggest problems we are trying to solve is:

  1. Keeping up to date with the LLVM code base development.

  2. Providing unified common place for everyone to contribute their changes.

Now there are two extra goals that are more related to Clang:

  1. Missing targets that can be used as an end binary (except for AMD GPU). Addind SPIRV to LLVM would allow Clang open source users to generate this portable binary format without going to any other toolchains that just integrate Clang. This is also a reason why we keep maintaining Clang in all the toolchains. Hopefully, people will start improving LLVM for GPU targets upstream because they will be able to use SPIRV available directly in LLVM to demonstate their issues/improvements.

  2. There is a plan for adding OpenCL C++ support that mandates generation of SPIRV. I started a thread on this last week: http://lists.llvm.org/pipermail/cfe-dev/2018-February/056972.html

So if for the goals (1) and (2) above, we could setup separate repository outside of LLVM and try to spread the information about it well enough that everyone starts using it. This won’t help us with item (3) at all, and item (4) will be incomplete.

Cheers,
Anastasia

This is great to see. Is this code the basis of the forks that Anastasia

talked about or did those come from somewhere else?

Yes, indeed the base is https://github.com/KhronosGroup/SPIRV-LLVM/ and then there are multiple forks that include some rework as well (some of which were announced on the LLVM channels). I think the biggest problems we are trying to solve is:

1. Keeping up to date with the LLVM code base development.

2. Providing unified common place for everyone to contribute their changes.

Now there are two extra goals that are more related to Clang:

3. Missing targets that can be used as an end binary (except for AMD GPU). Addind SPIRV to LLVM would allow Clang open source users to generate this portable binary format without going to any other toolchains that just integrate Clang. This is also a reason why we keep maintaining Clang in all the toolchains. Hopefully, people will start improving LLVM for GPU targets upstream because they will be able to use SPIRV available directly in LLVM to demonstate their issues/improvements.

SPIR-V does not have to be a part of LLVM for you to do this. You can add
the SPIR-V target to clang and then define a SPIR-V toolchain (i.e. clang/Driver/Toolchains)
that uses the external tool to translate LLVM IR to SPIR-V.

-Tom

SPIR-V does not have to be a part of LLVM for you to do this. You can add
the SPIR-V target to clang and then define a SPIR-V toolchain (i.e. clang/Driver/Toolchains)
that uses the external tool to translate LLVM IR to SPIR-V.

Ok. I guess if Clang community accepts this way, it would be better to set up the SPIRV converter as a tool of LLVM.

So the question is are there any downsides of this? Or would anyone object if we add the converter to the LLVM project as an optional tool? We would of course take care of configuring and maintaining it ourselves.

Cheers,
Anastasia

IIUC that would make clang invoke the converter on the produced IR as an external program?
Having it available as only that would be a nuisance to those of us who would rather just call the passes directly, with eventual transition to a proper backend.
We need to have the converter, for both directions, available as an LLVM tool anyway for testing with lit (btw we really should make the asm output the same as the rest of the vulkan tools, the current format is really ugly and annoying to capture with regexen).

Nic

  • Brian

SPIR-V does not have to be a part of LLVM for you to do this. You can add
the SPIR-V target to clang and then define a SPIR-V toolchain (i.e. clang/Driver/Toolchains)
that uses the external tool to translate LLVM IR to SPIR-V.

Ok. I guess if Clang community accepts this way, it would be better to set up the SPIRV converter as a tool of LLVM.

So the question is are there any downsides of this? Or would anyone object if we add the converter to the LLVM project as an optional tool? We would of course take care of configuring and maintaining it ourselves.

There is no requirement that the tool needs to be an official part of the LLVM
project to implement to use it this way For example, the cuda toolchain
in clang relies on a few proprietary tools from NVIDIA.

I think too much emphasis is being placed on having this tool be part of the
LLVM project. This is a fine goal, but at this point the focus should be
on consolidating development on a single SPIR-V <-> LLVM code base. Pierre
has posted the link to one version of the tool, but it's still not clear,
at least to me, if a) this is what is being proposed to be added as an
official LLVM project and b) if this is the tool that Khronos members
want to push forward.

-Tom

I expect that if the converter is formally added as an LLVM project, that it will always be able to accept and produce the version of LLVM-IR for the release of LLVM it is aligned with.

However, I would also like to know if it will be able to accept LLVM-IR from previous releases of LLVM, and if so, what is the earliest version that it is likely to accept? We have some dependencies on accepting LLVM-IR previously generated by earlier versions of LLVM such as v3.4 and v3.7, so the ability of the tool to accept earlier versions is quite important.

The ability to emit older versions of LLVM-IR is not so important to us though, but it could be a useful capability.

Thanks,

    MartinO

Agreed. Why is it good for LLVM to include this tool?

If there was a strong rationale for doing so, it would probably make sense to be a new subproject of some sort rather than included in the main llvm repo (not sure if that is what was being proposed).

-Chris