Skip to content

Commit

Permalink
[SPIR-V] Allow setting SPIR-V version via target triple.
Browse files Browse the repository at this point in the history
Currently added versions are from v1.0 to v1.5, other versions
can be added as needed.

This change also adds documentation about SPIR-V target support
in LLVM.

Differential Revision: https://reviews.llvm.org/D124776
  • Loading branch information
Anastasia Stulova committed May 23, 2022
1 parent 0eccc92 commit 72832ef
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 5 deletions.
73 changes: 73 additions & 0 deletions llvm/docs/SPIRVUsage.rst
@@ -0,0 +1,73 @@
=============================
User Guide for SPIR-V Target
=============================

.. contents::
:local:

.. toctree::
:hidden:

Introduction
============

The SPIR-V target provides code generation for the SPIR-V binary format described
in `the official SPIR-V specification <https://www.khronos.org/registry/SPIR-V/>`_.

.. _spirv-target-triples:

Target Triples
==============

For cross-compilation into SPIR-V use option

``-target <Architecture><Subarchitecture>-<Vendor>-<OS>-<Environment>``

to specify the target triple:

.. table:: SPIR-V Architectures

============ ==============================================================
Architecture Description
============ ==============================================================
``spirv32`` SPIR-V with 32-bit pointer width.
``spirv64`` SPIR-V with 64-bit pointer width.
============ ==============================================================

.. table:: SPIR-V Subarchitectures

============ ==============================================================
Architecture Description
============ ==============================================================
*<empty>* SPIR-V version deduced by tools based on the compiled input.
``v1.0`` SPIR-V version 1.0.
``v1.1`` SPIR-V version 1.1.
``v1.2`` SPIR-V version 1.2.
``v1.3`` SPIR-V version 1.3.
``v1.4`` SPIR-V version 1.4.
``v1.5`` SPIR-V version 1.5.
============ ==============================================================

.. table:: SPIR-V Vendors

===================== ==============================================================
Vendor Description
===================== ==============================================================
*<empty>*/``unknown`` Generic SPIR-V target without any vendor-specific settings.
===================== ==============================================================

.. table:: Operating Systems

===================== ============================================================
OS Description
===================== ============================================================
*<empty>*/``unknown`` Defaults to the OpenCL runtime.
===================== ============================================================

.. table:: SPIR-V Environments

===================== ==============================================================
Environment Description
===================== ==============================================================
*<empty>*/``unknown`` Defaults to the OpenCL environment.
===================== ==============================================================
4 changes: 4 additions & 0 deletions llvm/docs/UserGuides.rst
Expand Up @@ -57,6 +57,7 @@ intermediate LLVM representation.
ResponseGuide
Remarks
SourceLevelDebugging
SPIRVUsage
StackSafetyAnalysis
SupportLibrary
TableGen/index
Expand Down Expand Up @@ -243,3 +244,6 @@ Additional Topics
This document describes a DWARF extension to allow location descriptions on
the DWARF expression stack. It is part of
:doc:`AMDGPUDwarfExtensionsForHeterogeneousDebugging`.

:doc:`SPIRVUsage`
This document describes using the SPIR-V target to compile GPU kernels.
10 changes: 9 additions & 1 deletion llvm/include/llvm/ADT/Triple.h
Expand Up @@ -149,7 +149,15 @@ class Triple {

MipsSubArch_r6,

PPCSubArch_spe
PPCSubArch_spe,

// SPIR-V sub-arch corresponds to its version.
SPIRVSubArch_v10,
SPIRVSubArch_v11,
SPIRVSubArch_v12,
SPIRVSubArch_v13,
SPIRVSubArch_v14,
SPIRVSubArch_v15,
};
enum VendorType {
UnknownVendor,
Expand Down
24 changes: 20 additions & 4 deletions llvm/lib/Support/Triple.cpp
Expand Up @@ -495,8 +495,10 @@ static Triple::ArchType parseArch(StringRef ArchName) {
.Case("hsail64", Triple::hsail64)
.Case("spir", Triple::spir)
.Case("spir64", Triple::spir64)
.Case("spirv32", Triple::spirv32)
.Case("spirv64", Triple::spirv64)
.Cases("spirv32", "spirv32v1.0", "spirv32v1.1", "spirv32v1.2",
"spirv32v1.3", "spirv32v1.4", "spirv32v1.5", Triple::spirv32)
.Cases("spirv64", "spirv64v1.0", "spirv64v1.1", "spirv64v1.2",
"spirv64v1.3", "spirv64v1.4", "spirv64v1.5", Triple::spirv64)
.StartsWith("kalimba", Triple::kalimba)
.Case("lanai", Triple::lanai)
.Case("renderscript32", Triple::renderscript32)
Expand Down Expand Up @@ -654,6 +656,16 @@ static Triple::SubArchType parseSubArch(StringRef SubArchName) {
if (SubArchName == "arm64e")
return Triple::AArch64SubArch_arm64e;

if (SubArchName.startswith("spirv"))
return StringSwitch<Triple::SubArchType>(SubArchName)
.EndsWith("v1.0", Triple::SPIRVSubArch_v10)
.EndsWith("v1.1", Triple::SPIRVSubArch_v11)
.EndsWith("v1.2", Triple::SPIRVSubArch_v12)
.EndsWith("v1.3", Triple::SPIRVSubArch_v13)
.EndsWith("v1.4", Triple::SPIRVSubArch_v14)
.EndsWith("v1.5", Triple::SPIRVSubArch_v15)
.Default(Triple::NoSubArch);

StringRef ARMSubArch = ARM::getCanonicalArchName(SubArchName);

// For now, this is the small part. Early return.
Expand Down Expand Up @@ -1511,7 +1523,9 @@ Triple Triple::get32BitArchVariant() const {
case Triple::riscv64: T.setArch(Triple::riscv32); break;
case Triple::sparcv9: T.setArch(Triple::sparc); break;
case Triple::spir64: T.setArch(Triple::spir); break;
case Triple::spirv64: T.setArch(Triple::spirv32); break;
case Triple::spirv64:
T.setArch(Triple::spirv32, getSubArch());
break;
case Triple::wasm64: T.setArch(Triple::wasm32); break;
case Triple::x86_64: T.setArch(Triple::x86); break;
}
Expand Down Expand Up @@ -1586,7 +1600,9 @@ Triple Triple::get64BitArchVariant() const {
case Triple::riscv32: T.setArch(Triple::riscv64); break;
case Triple::sparc: T.setArch(Triple::sparcv9); break;
case Triple::spir: T.setArch(Triple::spir64); break;
case Triple::spirv32: T.setArch(Triple::spirv64); break;
case Triple::spirv32:
T.setArch(Triple::spirv64, getSubArch());
break;
case Triple::thumb: T.setArch(Triple::aarch64); break;
case Triple::thumbeb: T.setArch(Triple::aarch64_be); break;
case Triple::wasm32: T.setArch(Triple::wasm64); break;
Expand Down
74 changes: 74 additions & 0 deletions llvm/unittests/ADT/TripleTest.cpp
Expand Up @@ -243,11 +243,85 @@ TEST(TripleTest, ParsedIDs) {

T = Triple("spirv32-unknown-unknown");
EXPECT_EQ(Triple::spirv32, T.getArch());
EXPECT_EQ(Triple::NoSubArch, T.getSubArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::UnknownOS, T.getOS());

T = Triple("spirv32v1.0-unknown-unknown");
EXPECT_EQ(Triple::spirv32, T.getArch());
EXPECT_EQ(Triple::SPIRVSubArch_v10, T.getSubArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::UnknownOS, T.getOS());

T = Triple("spirv32v1.1-unknown-unknown");
EXPECT_EQ(Triple::spirv32, T.getArch());
EXPECT_EQ(Triple::SPIRVSubArch_v11, T.getSubArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::UnknownOS, T.getOS());

T = Triple("spirv32v1.2-unknown-unknown");
EXPECT_EQ(Triple::spirv32, T.getArch());
EXPECT_EQ(Triple::SPIRVSubArch_v12, T.getSubArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::UnknownOS, T.getOS());

T = Triple("spirv32v1.3-unknown-unknown");
EXPECT_EQ(Triple::spirv32, T.getArch());
EXPECT_EQ(Triple::SPIRVSubArch_v13, T.getSubArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::UnknownOS, T.getOS());

T = Triple("spirv32v1.4-unknown-unknown");
EXPECT_EQ(Triple::spirv32, T.getArch());
EXPECT_EQ(Triple::SPIRVSubArch_v14, T.getSubArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::UnknownOS, T.getOS());

T = Triple("spirv32v1.5-unknown-unknown");
EXPECT_EQ(Triple::spirv32, T.getArch());
EXPECT_EQ(Triple::SPIRVSubArch_v15, T.getSubArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::UnknownOS, T.getOS());

T = Triple("spirv64-unknown-unknown");
EXPECT_EQ(Triple::spirv64, T.getArch());
EXPECT_EQ(Triple::NoSubArch, T.getSubArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::UnknownOS, T.getOS());

T = Triple("spirv64v1.0-unknown-unknown");
EXPECT_EQ(Triple::spirv64, T.getArch());
EXPECT_EQ(Triple::SPIRVSubArch_v10, T.getSubArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::UnknownOS, T.getOS());

T = Triple("spirv64v1.1-unknown-unknown");
EXPECT_EQ(Triple::spirv64, T.getArch());
EXPECT_EQ(Triple::SPIRVSubArch_v11, T.getSubArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::UnknownOS, T.getOS());

T = Triple("spirv64v1.2-unknown-unknown");
EXPECT_EQ(Triple::spirv64, T.getArch());
EXPECT_EQ(Triple::SPIRVSubArch_v12, T.getSubArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::UnknownOS, T.getOS());

T = Triple("spirv64v1.3-unknown-unknown");
EXPECT_EQ(Triple::spirv64, T.getArch());
EXPECT_EQ(Triple::SPIRVSubArch_v13, T.getSubArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::UnknownOS, T.getOS());

T = Triple("spirv64v1.4-unknown-unknown");
EXPECT_EQ(Triple::spirv64, T.getArch());
EXPECT_EQ(Triple::SPIRVSubArch_v14, T.getSubArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::UnknownOS, T.getOS());

T = Triple("spirv64v1.5-unknown-unknown");
EXPECT_EQ(Triple::spirv64, T.getArch());
EXPECT_EQ(Triple::SPIRVSubArch_v15, T.getSubArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::UnknownOS, T.getOS());

Expand Down

0 comments on commit 72832ef

Please sign in to comment.