From 72832efc941aa9a0366b3e73031ecf5101355f5f Mon Sep 17 00:00:00 2001 From: Anastasia Stulova Date: Mon, 23 May 2022 14:03:54 +0100 Subject: [PATCH] [SPIR-V] Allow setting SPIR-V version via target triple. 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 | 73 ++++++++++++++++++++++++++++++++++++++ llvm/docs/UserGuides.rst | 4 +++ llvm/include/llvm/ADT/Triple.h | 10 +++++- llvm/lib/Support/Triple.cpp | 24 ++++++++++--- llvm/unittests/ADT/TripleTest.cpp | 74 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 180 insertions(+), 5 deletions(-) create mode 100644 llvm/docs/SPIRVUsage.rst diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst new file mode 100644 index 0000000..7529b5d --- /dev/null +++ b/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 `_. + +.. _spirv-target-triples: + +Target Triples +============== + +For cross-compilation into SPIR-V use option + +``-target ---`` + +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 + ============ ============================================================== + ** 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 + ===================== ============================================================== + **/``unknown`` Generic SPIR-V target without any vendor-specific settings. + ===================== ============================================================== + + .. table:: Operating Systems + + ===================== ============================================================ + OS Description + ===================== ============================================================ + **/``unknown`` Defaults to the OpenCL runtime. + ===================== ============================================================ + + .. table:: SPIR-V Environments + + ===================== ============================================================== + Environment Description + ===================== ============================================================== + **/``unknown`` Defaults to the OpenCL environment. + ===================== ============================================================== diff --git a/llvm/docs/UserGuides.rst b/llvm/docs/UserGuides.rst index efee7d3..533d2cf 100644 --- a/llvm/docs/UserGuides.rst +++ b/llvm/docs/UserGuides.rst @@ -57,6 +57,7 @@ intermediate LLVM representation. ResponseGuide Remarks SourceLevelDebugging + SPIRVUsage StackSafetyAnalysis SupportLibrary TableGen/index @@ -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. diff --git a/llvm/include/llvm/ADT/Triple.h b/llvm/include/llvm/ADT/Triple.h index e140331..b1deb3e 100644 --- a/llvm/include/llvm/ADT/Triple.h +++ b/llvm/include/llvm/ADT/Triple.h @@ -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, diff --git a/llvm/lib/Support/Triple.cpp b/llvm/lib/Support/Triple.cpp index 4aacad4..6696d15 100644 --- a/llvm/lib/Support/Triple.cpp +++ b/llvm/lib/Support/Triple.cpp @@ -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(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; diff --git a/llvm/unittests/ADT/TripleTest.cpp b/llvm/unittests/ADT/TripleTest.cpp index 19e5978..3b6a582 100644 --- a/llvm/unittests/ADT/TripleTest.cpp +++ b/llvm/unittests/ADT/TripleTest.cpp @@ -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()); -- 2.7.4