[SPIR-V] Allow setting SPIR-V version via target triple.
authorAnastasia Stulova <anastasia.stulova@arm.com>
Mon, 23 May 2022 13:03:54 +0000 (14:03 +0100)
committerAnastasia Stulova <anastasia.stulova@arm.com>
Mon, 23 May 2022 13:24:00 +0000 (14:24 +0100)
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

llvm/docs/SPIRVUsage.rst [new file with mode: 0644]
llvm/docs/UserGuides.rst
llvm/include/llvm/ADT/Triple.h
llvm/lib/Support/Triple.cpp
llvm/unittests/ADT/TripleTest.cpp

diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst
new file mode 100644 (file)
index 0000000..7529b5d
--- /dev/null
@@ -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.
+     ===================== ==============================================================
index efee7d3..533d2cf 100644 (file)
@@ -57,6 +57,7 @@ intermediate LLVM representation.
    ResponseGuide\r
    Remarks\r
    SourceLevelDebugging\r
+   SPIRVUsage\r
    StackSafetyAnalysis\r
    SupportLibrary\r
    TableGen/index\r
@@ -243,3 +244,6 @@ Additional Topics
    This document describes a DWARF extension to allow location descriptions on\r
    the DWARF expression stack. It is part of\r
    :doc:`AMDGPUDwarfExtensionsForHeterogeneousDebugging`.\r
+\r
+:doc:`SPIRVUsage`\r
+   This document describes using the SPIR-V target to compile GPU kernels.\r
index e140331..b1deb3e 100644 (file)
@@ -149,7 +149,15 @@ public:
 
     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,
index 4aacad4..6696d15 100644 (file)
@@ -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)
@@ -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.
@@ -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;
   }
@@ -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;
index 19e5978..3b6a582 100644 (file)
@@ -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());