This is an archive of the discontinued LLVM Phabricator instance.

[SPIR-V] Add a toolchain for SPIR-V in clang
ClosedPublic

Authored by Anastasia on Oct 25 2021, 12:15 AM.

Details

Summary

This patch adds a toolchain (TC) for SPIR-V. The TC is not complete but it is functional enough for producing SPIR-V assembly*1 and object code directly via clang from a language of choice, for example:

clang -target spirv64 foo.cl -c -o foo.spv
clang -target spirv64 baz.clcpp -c -o baz.spv
clang -target spirv64 bar.c -S -o bar.spt

The SPIR-V code is generated by the SPIRV-LLVM translator tool named llvm-spirv that is sought in PATH.

Linking of multiple input files is currently not supported but can be added separately. The options are:

  • Link using LLVM IR linker and then invoke llvm-spirv on the final linked module.
  • Linking using spirv-link of SPIR-V object files generated from llvm-spirv. Creates another dependency on external tools.

Feedback would be greatly appreciated...

Changes in the Driver and base ToolChain and Tool:
Added a mechanism to work with the lack of SPIR-V backend in LLVM for SPIR-V TC. Until SPIR-V backend lands on LLVM, compilation phases/actions should be bound for SPIR-V in the meantime as following:

  • compile -> tools::Clang
  • backend -> tools::SPIRV::Translator
  • assemble -> tools::SPIRV::Translator

However, Driver’s ToolSelector collapses compile-backend-assemble and compile-backend sequences to tools::Clang. To prevent this, added new {use,has}IntegratedBackend properties in ToolChain and Tool to which the ToolSelector reacts on, and which SPIR-V TC overrides.

This is contributed originally by @linjamaki along with the previous changes in the stack (D112404 - [SPIR-V] Add translator tool) to address feedback in (https://reviews.llvm.org/D110618#3062078) and other concerns around the SPIR-V toolchain adoption for languages other than HIP.

[1]: https://github.com/KhronosGroup/SPIRV-LLVM-Translator/wiki/SPIRV-Toolchain-for-Clang

This change relies on the following changes to llvm-spirv:

Diff Detail

Event Timeline

linjamaki created this revision.Oct 25 2021, 12:15 AM
linjamaki published this revision for review.Oct 25 2021, 12:23 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 25 2021, 12:23 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript

Cool. I like the direction... In the end it probably makes sense to separate clang compilation flow into more separate steps. This makes it more suitable to non-LLVM based backends or even MLIR towards Clang Intermediate Language. This looks like a fairly good starting point! Thanks!

Thus, please consider this as a potentially useful starting point for further work needed to support other frontends, hopefully good enough minimal code to get this side started with and our patch set integrated to the master.

Do I read it correctly that you would have no objections for others to rework this patch if needed? :)

Do I read it correctly that you would have no objections for others to rework this patch if needed? :)

Yes, anyone can work on this patch.

linjamaki updated this revision to Diff 383019.Oct 28 2021, 6:27 AM

Rebase on updated llvm-spirv tool (D112404).

Anastasia commandeered this revision.Dec 1 2021, 8:14 AM
Anastasia added a reviewer: linjamaki.
Anastasia updated this revision to Diff 391037.Dec 1 2021, 8:33 AM
Anastasia retitled this revision from [SPIR-V] Add a tool chain for SPIR-V (incomplete) to [SPIR-V] Add a toolchain for SPIR-V in clang.
Anastasia edited the summary of this revision. (Show Details)
Anastasia added reviewers: svenvh, azabaznov.
  • Rebased.
  • Added support for default compilation into binary without -c or -emit-llvm.
  • Added a warning about unsupported linking when multiple files are passed.
  • Added documentation.
  • Added more test cases.
Anastasia updated this revision to Diff 391064.Dec 1 2021, 9:48 AM
  • Exported full diff.
  • Added forgotten test cases.
  • Fixed typo in docs.
svenvh requested changes to this revision.Dec 2 2021, 7:03 AM
svenvh added inline comments.
clang/lib/Driver/Driver.cpp
3778

FIXME? (assuming this is something we want to address eventually)

clang/test/Driver/spirv-toolchain.cl
11

Any reason to not just check for llvm-spirv{{.*}}, for consistency with the clang check above?

clang/test/Misc/warning-flags.c
21 ↗(On Diff #391064)

The comment above says: "The list of warnings below should NEVER grow.", and the current patch violates that. You'll need to add a warning group to the new warning.

This revision now requires changes to proceed.Dec 2 2021, 7:03 AM
kpet added a subscriber: kpet.Dec 2 2021, 12:16 PM
Anastasia added inline comments.Dec 10 2021, 11:01 AM
clang/docs/UsersManual.rst
3559

Btw do we want to say anything about the limitations of translating IR when optimizations are enabled?

clang/test/Driver/spirv-toolchain.cl
11

Good question, apparently some tools get some target prefixes like if you look at Driver::generatePrefixedToolNames:
https://clang.llvm.org/doxygen/Driver_8cpp_source.html#l05169

But perhaps it doesn't happen for llvm-spirv and we can safely omit the prefix?

svenvh added inline comments.Dec 13 2021, 2:02 AM
clang/test/Driver/spirv-toolchain.cl
11

Having a target prefix for llvm-spirv seems a bit redundant indeed. Driver::generatePrefixedToolNames seems to add both a prefixed and non-prefixed tool name.

Addressed review comments from Sven:

  • Improved docs and code comments;
  • Simplified tests;
  • Added warning in a group.
  • Aligned with translator PRs after merge.

Note, that this change now references documentation from PR https://github.com/KhronosGroup/SPIRV-LLVM-Translator/pull/1342

Anastasia marked 2 inline comments as done.Dec 14 2021, 12:42 PM
svenvh accepted this revision.Dec 16 2021, 4:15 AM

Mostly some minor comments that you can address at commit time.

It would be good to get approval from another reviewer.

clang/docs/UsersManual.rst
3538
clang/test/Driver/spirv-toolchain.cl
11

I see you have taken out the checking of the prefix; my suggestion was to write llvm-spirv{{.*}}, to align with the clang check above.

This revision is now accepted and ready to land.Dec 16 2021, 4:15 AM

If I understand correctly, the default optimization level is -O2 for the OpenCL and OpenCL++ language mode (according to CompilerInvocation.cpp:getOptimizationLevel()). Since higher than -O0 may not work with the translator, should the SPIR-V tool chain override this default and set it to -O0 (unless a user passes some -O option)?

If I understand correctly, the default optimization level is -O2 for the OpenCL and OpenCL++ language mode (according to CompilerInvocation.cpp:getOptimizationLevel()). Since higher than -O0 may not work with the translator, should the SPIR-V tool chain override this default and set it to -O0 (unless a user passes some -O option)?

We could do that, although I also find it a bit confusing if one target behaves differently from the rest. I believe -O2 is clang's default, not specific to a particular language...

Also I have an impression that translating optimised IR mostly works.

And another aspect to consider is that we are also integrating the SPIR-V backend in parallel which should be supporting the optimizations fully. So I would prefer not to tailor the clang architecture to the use of the translator too much as it is only a temporary solution...

This revision was landed with ongoing or failed builds.Dec 23 2021, 7:10 AM
This revision was automatically updated to reflect the committed changes.

I slightly adjusted the test in eafc64ed6325eba962096d4a947d7e45e909bfde :)

-no-canonical-prefixes can usually be omitted.

I slightly adjusted the test in eafc64ed6325eba962096d4a947d7e45e909bfde :)

-no-canonical-prefixes can usually be omitted.

Thanks!