Open skl131313 opened 7 years ago
Currently the translator only supports OpenCL.
After I'm done getting LDC to support OpenCL SPIR-V then if there is sufficient demand (principally within the D community, but other contributors are ofc welcome) I may consider making a fork of llvm off the latest version, updating this (OpenCL SPIR-V) to the latest llvm version and adding a Vulkan backend to it. Possibly also considering trying to integrate Microsoft's recently open-sourced DirectXShaderCompiler, although it's git history will definitely be bjorked. Will wait till development of it has matured a bit.
If I get around to doing that I will be changing a few things: most noticeably using llvm intrinsics for the OpenCL/Vulkan intrinsics rather than "itanium with extensions" C++ mangling, making it far easier to use with other tools.
@thewilsonator: while working on https://github.com/keryell/triSYCL/ I am looking at leveraging http://alphanew.net/index.php?section=alphanew&site=overview&lang=eng&newsID=111 Perhaps you can use it too?
@keryell Well, it doesn't have releases which makes doing CI difficult, see #201. It is also 105 commits behind KhronosGroup/SPIRV-LLVM 3.6.1 and is on LLVM 3.9.0 as opposed to the final release of that series 3.9.1. It also hasn't received any commits for 11 months.
Hence why I am considering doing it myself. Also I will probably put the lib/SPIRV
and tools/llvm-spirv
and tools/spirv-tool
in their own submodules, to keep things separate and easily identifiable. Will do the same for MS's DirectXShaderCompiler.
Please be aware that the dialect of SPIR-V accepted by Vulkan is significantly different from the dialect accepted by OpenCL. For starters, see the validation rules in the SPIR-V spec for "Shader" vs. "Kernel". Also, check extra restrictions in SPIR-V environment spec in the Vulkan spec: https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/html/vkspec.html#spirvenv
Isn't it just SPIR-V core + Vulkan specific capabilities + Vulkan specific operations (a.k.a. "standard library functions")?
Yes, but that's a big difference from SPIR-V for OpenCL. You're subtracting out a lot of assumptions made by SPIRV-LLVM assuming it's targeting OpenCL.
Examples:
In Vulkan all your control flow has to be "structured", with OpLoopMerge and OpSelectionMerge at key points in the control flow graph. If you've lost that original control flow intent from the source language, then you've changed semantics of the program. In OpenCL, you only have to ensure control flow is reducible. That's way simpler to maintain through the compiler flow.
Storage classes are completely different. Vulkan has about 10 valid storage classes, and OpenCL has 4. Vulkan's set is not a superset of OpenCL's.
OpenCL uses physical addressing, where all types automatically have a fixed size and alignment. Vulkan requires logical addressing. For objects in storage classes exposed to the host API (e.g. Uniform), layout annotations have to be applied.
Vulkan's LogicalAddressing model assumes that pointers don't alias unless proven otherwise. OpenCL is like C in that the default is the opposite: pointers are assumed to alias unless proven otherwise.
I urge you to consider all the details first before diving in by writing code.
@thewilsonator: we always appreciate contributions. :-) On the SPIR-V side, the current LLVM library producing SPIR-V should be updated to a real SPIR-V LLVM back-end, if you are looking to some reorganization ideas...
My reorg ideas are
lib/spirv
,tools/llvm-spirv
and spirv-tool
, principally to make keeping up with master easier, but also reduce the size if the code base since AFAIK other than include/llvm/Support/SPIRV.h
and the relevant build script files nothing else is changed by this project other than the above listed directory.llvm.spirv.opencl.*
?). This will break clang/anything relying on this. It is of no concern to me, but surely will be for others. Will try to leverage .td
tools for this. Should make doing the equivalent for Vulkan easier.TargetMachine
so we can run the dead simple optimisation passes, and fit in with the "normal" backend pipeline.However I won't have any time to do this until August at the earliest.
@dneto0 thanks for the pointers.
Point 1 seems like a good candidate for an intrinsic function to mark the end.
Point 2 doesn't OpenCL have 5? Private, Local, Global, Constant and Generic? Also seems like a good candidate for addrspace qualification. edit: or is this const, volatile, restrict, ???, @?
Found them all valid SPIR-V storage classes are
Point 3 I'm less sure of, but it seems that metadata should work here.
Point 4 It is the host language's problem to annotate everything with noalias
.
@thewilsonator: About storage classes. Yes, OpenCL has 5 (I forgot Generic).
The validity rules are in two places:
There's a matching one for OpenCL.
@keryell I have got a fork of llvm 5.0 with spir and spir64 proper targets (also made a Triple::spirl
for logical spirv memory to ease Vulcan support if I get around to it) at https://github.com/thewilsonator/llvm/tree/compute
This is about the last point before I begin to change it use use intrinsics instead of mangled C++, and thus break compatibility with https://github.com/KhronosGroup/SPIR/tree/spirv-1.0 (although the upgrade from 3.6.1 to 5.0 will most definitely have broken things). Let me know if you (or others) want to collaborate on this, more eyes hands and bug reporters are always good.
I am OK with that. Thanks for the efforts.
@thewilsonator For now I am busy on my SYCL device compiler with 3.9, SPIR and SPIR-V. So, along with other projects too, I do not have the bandwidth for more... :-( But at some point I hope there will be some convergence in future versions. :-) Thanks for the work.
Oh well. I'm sure it will be there when you decide you need to update your llvm version. Good luck!
Sorry to ask here, but this issue has been open for a while and seems to serve like a forum (given the project lacks an actual forum).
I see the default branch is 3.6, but there is a 3.8 branch which is listed as active. The 3.8 branch does not pass continuous integration, though.
I need to work on fixing bugs on an LLVM related project for gaining familiarity with it and this seems a good place for me to pick up bugs.
Thanks in advance.
Ok, I think I figured out this question. The project is based on LLVM 3.6 and that is what the 3.6 branch contains. There was an attempt to upgrade to LLVM 3.8.1 but the tests are not passing with the new version, which is the reason why we are stuck on the 3.6 branch.
Someone has to figure out why the tests are failing with the upgraded version. I could try to look at that then. Tell me if there is anything else you would like me to focus on. For any suggestions, feel free to contact me (abel.bernabeu@gmail.com).
Just an update to all: there is reasonable interest from the LLVM people for upstreaming my work (see http://lists.llvm.org/pipermail/llvm-dev/2017-May/112538.html), which is an updated version of this, as well as some interest from the D community to support Vulkan as part of that.
I can agree on most of your suggestions.
However, suggesting that this project should be an LLVM backend is understimating the main attractive of the khronos branch: that it is a bidirectional translator.
It can translate back and forth between LLVM IR and SPIRV because the library keeps the mapping bijective, and that property should be retained for the project to gain traction.
For someone who has a pre-existing frontend and a pre-existing backend, the library allows to use SPIRV as a standard program exchange format.
llvm-spirv llvm-spirv (reversing)
+-----^-----+ +-----^-----+
| | | |
source -> ll -> spirv spirv-> ll -> binary
| | | |
+-----v------+ +-----v-----+
Existing frontend Existing backend
Is there such a thing as an abstraction of a bidirectional LLVM IR translator on the LLVM framework? I do not think so, but I could be wrong. Having a SPIRV backend is just half of the whole picture.
Ideally you want the concept of bidirectional translator abstracted on an LLVM interface, and then we would stop having SPIRV-LLVM as a library.
that it is a bidirectional translator
It is that at the moment and it will remain one. In fact I hope to improve it by integrating it (not quite the right word) with the other backends i.e. translate the intrinsics. There are some discussions/reservations about the exact implementation but ...
project to gain traction
The last functional commit to this repo was at the start of December...
For someone who has a pre-existing frontend
Thats precisely why I am doing this, see my first post.
and a pre-existing backend, the library allows to use SPIRV as a standard program exchange format
My changes integrate far better with the LLVM machinery and so opens this up to more backends, all that would be required would be to translate the intrinsics. No to mention with stay up to date with LLVM instead of falling 2 years and counting behind.
Ideally you want the concept of bidirectional translator abstracted on an LLVM interface, and then we would stop having SPIRV-LLVM as a library.
That's what llvm-spirv
is for, to do the reverse translation. The intrinsic translation will have to be added to it but that requires someone with knowledge of the other backends, who are most likely to be found in the LLVM project itself.
Ok, if we still can translate back and forth I guess your fork deserves a try. I would never object to people forking open source stuff :)
Am not an expert in LLVM and I have only started spending o couple hours a week on getting the 3.8 branch on a better shape than it is now. My modest short term goal is getting the continuous integration functional by fixing the current failures. From what I have seen so far some of the issues are due to the tests needing an update but others need fixing the translator.
Apart from that, I did try to manually merge the functional changes from the 3.6 branch that where missing in my working copy of 3.8. The merged tree builds and seems to work, which tells me that, once the continuous integration works, we could start cherry picking from 3.6 into 3.8 trying to keep the history of who made what change.
Neither am I :)
My plan is to:
1) finish moving to an intrinsics/tablegen format. This requires writing a backend for tablegen, and will enabling removing all of the mangling code and custom table stuff.
2) port the tests across from this repo, update them to account for (1) and fix any breakages.
3) make llvm-spirv
usable.
4) change the assembly format to match the reference implementation and update the tests accordingly.
5) assuming I haven't forgotten anything upstream it to LLVM.
I currently have to translate a large codebase from C++11 to Vulkan compute.
I am wondering whether the more sensible approach would be to rather have a transpiler from C++ to SPIRV for Vulkan
The frontend could then:
The backend would have to:
That of course is a oversimplification.
@abergmeier-dsfishlabs I think you would have better luck scripting clang to do the translations of C++ to Vulkan Compute source for you, rather than go via SPIR-V.
If you do decide to go the SPIR-V route https://github.com/google/clspv may be of interest.
C++ to Vulkan Spir-V compute shaders is something that I want as well. There is plenty of CUDA source that would justify that. AMD stuff as well.
Vulkan was supposed to bring compute and graphics together no?
Not sure if Vulkan is currently supported or not, but it seems only OpenCL is?