[llvm] [SPIR-V] Extend SPIRVUsage.rst document (PR #84744)

Michal Paszkowski via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 25 10:49:37 PDT 2024


https://github.com/michalpaszkowski updated https://github.com/llvm/llvm-project/pull/84744

>From 3e63bc5b42364080be5fe82a94596b46a934a4d3 Mon Sep 17 00:00:00 2001
From: Michal Paszkowski <michal at paszkowski.org>
Date: Mon, 11 Mar 2024 04:31:22 -0700
Subject: [PATCH 1/3] [SPIR-V] Extend SPIRVUsage.rst document

This pull request is the first step in extending the SPIRVUsage.rst document with information on how the backend can be used and what LLVM IR input it accepts.

Updated:
- Target triple description (Architecture, Subarchitecture, OS, Environments)

The following sections were added:
- SPIR-V Extensions
- LLVM IR Intrinsics
- SPIR-V Builtin Functions
---
 llvm/docs/SPIRVUsage.rst | 290 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 284 insertions(+), 6 deletions(-)

diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst
index 5ca035b68392f0..2196e13e604c2e 100644
--- a/llvm/docs/SPIRVUsage.rst
+++ b/llvm/docs/SPIRVUsage.rst
@@ -14,10 +14,13 @@ 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/>`_.
 
+Usage
+=====
+
 .. _spirv-target-triples:
 
 Target Triples
-==============
+--------------
 
 For cross-compilation into SPIR-V use option
 
@@ -32,6 +35,7 @@ to specify the target triple:
      ============ ==============================================================
      ``spirv32``   SPIR-V with 32-bit pointer width.
      ``spirv64``   SPIR-V with 64-bit pointer width.
+     ``spirv``     SPIR-V with logical memory layout.
      ============ ==============================================================
 
   .. table:: SPIR-V Subarchitectures
@@ -39,13 +43,14 @@ to specify the target triple:
      =============== ==============================================================
      Subarchitecture Description
      =============== ==============================================================
-     *<empty>*        SPIR-V version deduced by tools based on the compiled input.
+     *<empty>*        SPIR-V version deduced by backend based on the 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.
+     ``v1.6``         SPIR-V version 1.6.
      =============== ==============================================================
 
   .. table:: SPIR-V Vendors
@@ -62,6 +67,7 @@ to specify the target triple:
      OS                    Description
      ===================== ============================================================
      *<empty>*/``unknown``  Defaults to the OpenCL runtime.
+     ``vulkan``             Vulkan shader runtime.
      ===================== ============================================================
 
   .. table:: SPIR-V Environments
@@ -69,17 +75,82 @@ to specify the target triple:
      ===================== ==============================================================
      Environment           Description
      ===================== ==============================================================
-     *<empty>*/``unknown``  Defaults to the OpenCL environment.
+     *<empty>*/``unknown``  OpenCL environment or deduced by backend based on the input.
      ===================== ==============================================================
 
 Example:
 
 ``-target spirv64v1.0`` can be used to compile for SPIR-V version 1.0 with 64-bit pointer width.
 
-.. _spirv-types:
+.. _spirv-extensions:
+
+Extensions
+----------
+
+The SPIR-V backend supports a variety of extensions that enable or enhance features beyond the core SPIR-V specification. These extensions can be enabled using the ``-spirv-extensions`` option followed by the name of the extension(s) you wish to enable. Below is a list of supported SPIR-V extensions, sorted alphabetically by their extension names:
+
+.. list-table:: Supported SPIR-V Extensions
+   :widths: 50 150
+   :header-rows: 1
+
+   * - Extension Name
+     - Description
+   * - ``SPV_EXT_shader_atomic_float16_add``
+     - Extends the SPV_EXT_shader_atomic_float_add extension to support atomically adding to 16-bit floating-point numbers in memory.
+   * - ``SPV_EXT_shader_atomic_float_add``
+     - Adds atomic add instruction on floating-point numbers.
+   * - ``SPV_EXT_shader_atomic_float_min_max``
+     - Adds atomic min and max instruction on floating-point numbers.
+   * - ``SPV_INTEL_arbitrary_precision_integers``
+     - Allows generating arbitrary width integer types.
+   * - ``SPV_INTEL_bfloat16_conversion``
+     - Adds instructions to convert between single-precision 32-bit floating-point values and 16-bit bfloat16 values.
+   * - ``SPV_INTEL_function_pointers``
+     - Allows translation of function pointers.
+   * - ``SPV_INTEL_optnone``
+     - Adds OptNoneINTEL value for Function Control mask that indicates a request to not optimize the function.
+   * - ``SPV_INTEL_subgroups``
+     - Allows work items in a subgroup to share data without the use of local memory and work group barriers, and to utilize specialized hardware to load and store blocks of data from images or buffers.
+   * - ``SPV_INTEL_usm_storage_classes``
+     - Introduces two new storage classes that are subclasses of the CrossWorkgroup storage class that provides additional information that can enable optimization.
+   * - ``SPV_INTEL_variable_length_array``
+     - Allows to allocate local arrays whose number of elements is unknown at compile time.
+   * - ``SPV_KHR_bit_instructions``
+     - Enables bit instructions to be used by SPIR-V modules without requiring the Shader capability.
+   * - ``SPV_KHR_expect_assume``
+     - Provides additional information to a compiler, similar to the llvm.assume and llvm.expect intrinsics.
+   * - ``SPV_KHR_float_controls``
+     - Provides new execution modes to control floating-point computations by overriding an implementation’s default behavior for rounding modes, denormals, signed zero, and infinities.
+   * - ``SPV_KHR_linkonce_odr``
+     - Allows to use the LinkOnceODR linkage type that lets a function or global variable to be merged with other functions or global variables of the same name when linkage occurs.
+   * - ``SPV_KHR_no_integer_wrap_decoration``
+     - Adds decorations to indicate that a given instruction does not cause integer wrapping.
+   * - ``SPV_KHR_subgroup_rotate``
+     - Adds a new instruction that enables rotating values across invocations within a subgroup.
+   * - ``SPV_KHR_uniform_group_instructions``
+     - Allows support for additional group operations within uniform control flow.
+
+To enable multiple extensions, list them separated by spaces. For example, to enable support for atomic operations on floating-point numbers and arbitrary precision integers, use:
 
-Representing special types in SPIR-V
-====================================
+``-spirv-extensions=SPV_EXT_shader_atomic_float_add,SPV_INTEL_arbitrary_precision_integers``
+
+LLVM IR
+=======
+
+SPIR-V is intentionally designed for seamless integration with various Intermediate 
+Representations (IRs), including LLVM IR, facilitating straightforward mappings for 
+most of its entities. The development of the SPIR-V backend has been guided by a 
+principle of compatibility with the Khronos Group's SPIR-V LLVM Translator.
+Consequently, the input representation accepted by the SPIR-V backend aligns closely 
+with that detailed in `the SPIR-V Representation in LLVM document <https://github.com/KhronosGroup/SPIRV-LLVM-Translator/blob/main/docs/SPIRVRepresentationInLLVM.rst>`_. 
+This document, along with the sections that follow, delineate the main points and focus 
+on any differences between the LLVM IR that this backend processes and the conventions 
+used by other tools.
+
+.. _spirv-special-types:
+
+Special types
+-------------
 
 SPIR-V specifies several kinds of opaque types. These types are represented
 using target extension types. These types are represented as follows:
@@ -108,3 +179,210 @@ dimensionality parameter as ``1`` meaning 2D. Sampled image types include the
 parameters of its underlying image type, so that a sampled image for the
 previous type has the representation
 ``target("spirv.SampledImage, void, 1, 1, 0, 0, 0, 0, 0)``.
+
+.. _spirv-intrinsics:
+
+LLVM IR Intrinsics
+------------------
+
+The SPIR-V backend employs several LLVM IR intrinsics that facilitate various low-level 
+operations essential for generating correct and efficient SPIR-V code. These intrinsics 
+cover a range of functionalities from type assignment and memory management to control 
+flow and atomic operations. Below is a detailed table of selected intrinsics used in the 
+SPIR-V backend, along with their descriptions and argument details.
+
+.. list-table:: LLVM IR Intrinsics for SPIR-V
+   :widths: 25 15 20 40
+   :header-rows: 1
+
+   * - Intrinsic ID
+     - Return Type
+     - Argument Types
+     - Description
+   * - `int_spv_assign_type`
+     - None
+     - `[Type, Metadata]`
+     - Associates a type with metadata, crucial for maintaining type information in SPIR-V structures. Not emitted directly but supports the type system internally.
+   * - `int_spv_assign_ptr_type`
+     - None
+     - `[Type, Metadata, Integer]`
+     - Similar to `int_spv_assign_type`, but for pointer types with an additional integer specifying the storage class. Supports SPIR-V's detailed pointer type system. Not emitted directly.
+   * - `int_spv_assign_name`
+     - None
+     - `[Type, Vararg]`
+     - Assigns names to types or values, enhancing readability and debuggability of SPIR-V code. Not emitted directly but used for metadata enrichment.
+   * - `int_spv_track_constant`
+     - Type
+     - `[Type, Metadata]`
+     - Tracks constants in the SPIR-V module. Essential for optimizing and reducing redundancy. Emitted for internal use only.
+   * - `int_spv_init_global`
+     - None
+     - `[Type, Type]`
+     - Initializes global variables, a necessary step for ensuring correct global state management in SPIR-V. Emitted for internal use only.
+   * - `int_spv_unref_global`
+     - None
+     - `[Type]`
+     - Manages the lifetime of global variables by marking them as unreferenced, thus enabling optimizations related to global variable usage. Emitted for internal use only.
+   * - `int_spv_gep`
+     - Pointer
+     - `[Boolean, Type, Vararg]`
+     - Computes the address of a sub-element of an aggregate type. Critical for accessing array elements and structure fields. Supports conditionally addressing elements in a generic way.
+   * - `int_spv_load`
+     - 32-bit Integer
+     - `[Pointer, 16-bit Integer, 8-bit Integer]`
+     - Loads a value from a memory location. The additional integers specify memory access and alignment details, vital for ensuring correct and efficient memory operations.
+   * - `int_spv_store`
+     - None
+     - `[Type, Pointer, 16-bit Integer, 8-bit Integer]`
+     - Stores a value to a memory location. Like `int_spv_load`, it includes specifications for memory access and alignment, essential for memory operations.
+   * - `int_spv_extractv`
+     - Type
+     - `[32-bit Integer, Vararg]`
+     - Extracts a value from a vector, allowing for vector operations within SPIR-V. Enables manipulation of vector components.
+   * - `int_spv_insertv`
+     - 32-bit Integer
+     - `[32-bit Integer, Type, Vararg]`
+     - Inserts a value into a vector. Complementary to `int_spv_extractv`, it facilitates the construction and manipulation of vectors.
+   * - `int_spv_extractelt`
+     - Type
+     - `[Type, Any Integer]`
+     - Extracts an element from an aggregate type based on an index. Essential for operations on arrays and vectors.
+   * - `int_spv_insertelt`
+     - Type
+     - `[Type, Type, Any Integer]`
+     - Inserts an element into an aggregate type at a specified index. Allows for building and modifying arrays and vectors.
+   * - `int_spv_const_composite`
+     - 32-bit Integer
+     - `[Vararg]`
+     - Constructs a composite type from given elements. Key for creating arrays, structs, and vectors from individual components.
+   * - `int_spv_bitcast`
+     - Type
+     - `[Type]`
+     - Performs a bit-wise cast between types. Critical for type conversions that do not change the bit representation.
+   * - `int_spv_ptrcast`
+     - Type
+     - `[Type, Metadata, Integer]`
+     - Casts pointers between different types. Similar to `int_spv_bitcast` but specifically for pointers, taking into account SPIR-V's strict type system.
+   * - `int_spv_switch`
+     - None
+     - `[Type, Vararg]`
+     - Implements a multi-way branch based on a value. Enables complex control flow structures, similar to the switch statement in high-level languages.
+   * - `int_spv_cmpxchg`
+     - 32-bit Integer
+     - `[Type, Vararg]`
+     - Performs an atomic compare-and-exchange operation. Crucial for synchronization and concurrency control in compute shaders.
+   * - `int_spv_unreachable`
+     - None
+     - `[]`
+     - Marks a point in the code that should never be reached, enabling optimizations by indicating unreachable code paths.
+   * - `int_spv_alloca`
+     - Type
+     - `[]`
+     - Allocates memory on the stack. Fundamental for local variable storage in functions.
+   * - `int_spv_alloca_array`
+     - Type
+     - `[Any Integer]`
+     - Allocates an array on the stack. Extends `int_spv_alloca` to support array allocations, essential for temporary arrays.
+   * - `int_spv_undef`
+     - 32-bit Integer
+     - `[]`
+     - Generates an undefined value. Useful for optimizations and indicating uninitialized variables.
+   * - `int_spv_assume`
+     - None
+     - `[1-bit Integer]`
+     - Provides hints to the optimizer about assumptions that can be made about program state. Improves optimization potential.
+   * - `int_spv_expect`
+     - Any Integer Type
+     - `[Type, Type]`
+     - Guides branch prediction by indicating expected branch paths. Enhances performance by optimizing common code paths.
+   * - `int_spv_thread_id`
+     - 32-bit Integer
+     - `[32-bit Integer]`
+     - Retrieves the thread ID within a workgroup. Essential for identifying execution context in parallel compute operations.
+   * - `int_spv_create_handle`
+     - Pointer
+     - `[8-bit Integer]`
+     - Creates a resource handle for graphics or compute resources. Facilitates the management and use of resources in shaders.
+
+.. _spirv-builtin-functions:
+
+Builtin Functions
+-----------------
+
+The following section highlights the representation of SPIR-V builtins in LLVM IR, 
+emphasizing builtins that do not have direct counterparts in LLVM.
+
+Instructions as Function Calls
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+SPIR-V builtins without direct LLVM counterparts are represented as LLVM function calls. 
+These functions, termed SPIR-V builtin functions, follow an IA64 mangling scheme with 
+SPIR-V-specific extensions. Parsing non-mangled calls to builtins is supported in some cases, 
+but not tested extensively. The general format is:
+
+.. code-block:: c
+
+  __spirv_{OpCodeName}{_OptionalPostfixes}
+
+Where `{OpCodeName}` is the SPIR-V opcode name sans the "Op" prefix, and 
+`{OptionalPostfixes}` are decoration-specific postfixes, if any. The mangling and 
+postfixes allow for the representation of SPIR-V's rich instruction set within LLVM's 
+framework.
+
+Extended Instruction Sets
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+SPIR-V defines several extended instruction sets for additional functionalities, such as 
+OpenCL-specific operations. In LLVM IR, these are represented by function calls to 
+mangled builtins and selected based on the environment. For example:
+
+.. code-block:: c
+
+  acos_f32
+
+represents the `acos` function from the OpenCL extended instruction set for a float32 
+input.
+
+Builtin Variables
+~~~~~~~~~~~~~~~~~
+
+SPIR-V builtin variables, which provide access to special hardware or execution model 
+properties, are mapped to either LLVM function calls or LLVM global variables. The 
+representation follows the naming convention:
+
+.. code-block:: c
+
+  __spirv_BuiltIn{VariableName}
+
+For instance, the SPIR-V builtin `GlobalInvocationId` is accessible in LLVM IR as 
+`__spirv_BuiltInGlobalInvocationId`.
+
+Vector Load and Store Builtins
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+SPIR-V's capabilities for loading and storing vectors are represented in LLVM IR using 
+functions that mimic the SPIR-V instructions. These builtins handle cases that LLVM's 
+native instructions do not directly support, enabling fine-grained control over memory 
+operations.
+
+Atomic Operations
+~~~~~~~~~~~~~~~~~
+
+SPIR-V's atomic operations, especially those operating on floating-point data, are 
+represented in LLVM IR with corresponding function calls. These builtins ensure 
+atomicity in operations where LLVM might not have direct support, essential for parallel 
+execution and synchronization.
+
+Image Operations
+~~~~~~~~~~~~~~~~
+
+SPIR-V provides extensive support for image and sampler operations, which LLVM 
+represents through function calls to builtins. These include image reads, writes, and 
+queries, allowing detailed manipulation of image data and parameters.
+
+Group and Subgroup Operations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For workgroup and subgroup operations, LLVM uses function calls to represent SPIR-V's 
+group-based instructions. These builtins facilitate group synchronization, data sharing, 
+and collective operations essential for efficient parallel computation.

>From 983dc1b7a7e31e0839fde8308b951549072f27c8 Mon Sep 17 00:00:00 2001
From: Michal Paszkowski <michal at paszkowski.org>
Date: Mon, 25 Mar 2024 10:44:49 -0700
Subject: [PATCH 2/3] Review changes

---
 llvm/docs/SPIRVUsage.rst | 54 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 48 insertions(+), 6 deletions(-)

diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst
index 2196e13e604c2e..ca5e4e7177f369 100644
--- a/llvm/docs/SPIRVUsage.rst
+++ b/llvm/docs/SPIRVUsage.rst
@@ -17,6 +17,36 @@ in  `the official SPIR-V specification <https://www.khronos.org/registry/SPIR-V/
 Usage
 =====
 
+The SPIR-V backend can be invoked either from LLVM's Static Compiler (llc) or Clang, 
+allowing developers to compile LLVM intermediate language (IL) files or OpenCL kernel 
+sources directly to SPIR-V. This section outlines the usage of various commands to 
+leverage the SPIR-V backend for different purposes.
+
+Static Compiler Commands
+------------------------
+
+1. **Basic SPIR-V Compilation**
+   Command: `llc -mtriple=spirv32-unknown-unknown input.ll -o output.spvt`
+   Description: This command compiles an LLVM IL file (`input.ll`) to a SPIR-V binary (`output.spvt`) for a 32-bit architecture.
+
+2. **Compilation with Extensions and Optimization**
+   Command: `llc -O1 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_arbitrary_precision_integers input.ll -o output.spvt`
+   Description: Compiles an LLVM IL file to SPIR-V with (`-O1`) optimizations, targeting a 64-bit architecture. It enables the SPV_INTEL_arbitrary_precision_integers extension.
+
+3. **SPIR-V Binary Generation**
+   Command: `llc -O0 -mtriple=spirv64-unknown-unknown -filetype=obj input.ll -o output.spvt`
+   Description: Generates a SPIR-V object file (`output.spvt`) from an LLVM module, targeting a 64-bit SPIR-V architecture with no optimizations.
+
+Clang Commands
+--------------
+
+1. **SPIR-V Generation**
+   Command: `clang –target=spirv64 input.cl`
+   Description: Generates a SPIR-V file directly from an OpenCL kernel source file (`input.cl`).
+
+Compiler Options
+================
+
 .. _spirv-target-triples:
 
 Target Triples
@@ -68,6 +98,8 @@ to specify the target triple:
      ===================== ============================================================
      *<empty>*/``unknown``  Defaults to the OpenCL runtime.
      ``vulkan``             Vulkan shader runtime.
+     ``vulkan1.2``          Vulkan 1.2 runtime, corresponding to SPIR-V 1.5.
+     ``vulkan1.3``          Vulkan 1.3 runtime, corresponding to SPIR-V 1.6.
      ===================== ============================================================
 
   .. table:: SPIR-V Environments
@@ -87,7 +119,11 @@ Example:
 Extensions
 ----------
 
-The SPIR-V backend supports a variety of extensions that enable or enhance features beyond the core SPIR-V specification. These extensions can be enabled using the ``-spirv-extensions`` option followed by the name of the extension(s) you wish to enable. Below is a list of supported SPIR-V extensions, sorted alphabetically by their extension names:
+The SPIR-V backend supports a variety of `extensions <https://github.com/KhronosGroup/SPIRV-Registry/tree/main/extensions>`_ 
+that enable or enhance features beyond the core SPIR-V specification. 
+These extensions can be enabled using the ``-spirv-extensions`` option 
+followed by the name of the extension(s) you wish to enable. Below is a 
+list of supported SPIR-V extensions, sorted alphabetically by their extension names:
 
 .. list-table:: Supported SPIR-V Extensions
    :widths: 50 150
@@ -132,15 +168,21 @@ The SPIR-V backend supports a variety of extensions that enable or enhance featu
 
 To enable multiple extensions, list them separated by spaces. For example, to enable support for atomic operations on floating-point numbers and arbitrary precision integers, use:
 
-``-spirv-extensions=SPV_EXT_shader_atomic_float_add,SPV_INTEL_arbitrary_precision_integers``
+``-spirv-ext=+SPV_EXT_shader_atomic_float_add,+SPV_INTEL_arbitrary_precision_integers``
+
+To enable all extensions, use the following option:
+``-spirv-ext=all``
+
+To enable all extensions except specified, specify ``all`` followed by a list of disallowed extensions. For example:
+``-spirv-ext=all,-SPV_INTEL_arbitrary_precision_integers``
 
-LLVM IR
-=======
+SPIR-V representation in LLVM IR
+================================
 
 SPIR-V is intentionally designed for seamless integration with various Intermediate 
 Representations (IRs), including LLVM IR, facilitating straightforward mappings for 
 most of its entities. The development of the SPIR-V backend has been guided by a 
-principle of compatibility with the Khronos Group's SPIR-V LLVM Translator.
+principle of compatibility with the `Khronos Group SPIR-V LLVM Translator <https://github.com/KhronosGroup/SPIRV-LLVM-Translator>`_.
 Consequently, the input representation accepted by the SPIR-V backend aligns closely 
 with that detailed in `the SPIR-V Representation in LLVM document <https://github.com/KhronosGroup/SPIRV-LLVM-Translator/blob/main/docs/SPIRVRepresentationInLLVM.rst>`_. 
 This document, along with the sections that follow, delineate the main points and focus 
@@ -153,7 +195,7 @@ Special types
 -------------
 
 SPIR-V specifies several kinds of opaque types. These types are represented
-using target extension types. These types are represented as follows:
+using target extension types and are represented as follows:
 
   .. table:: SPIR-V Opaque Types
 

>From e1a190aba1f5d1ab8c8fa9265b1435ee9e2b1ece Mon Sep 17 00:00:00 2001
From: Michal Paszkowski <michal at paszkowski.org>
Date: Mon, 25 Mar 2024 10:49:19 -0700
Subject: [PATCH 3/3] Review changes 2

---
 llvm/docs/SPIRVUsage.rst | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst
index ca5e4e7177f369..a183877c48cb22 100644
--- a/llvm/docs/SPIRVUsage.rst
+++ b/llvm/docs/SPIRVUsage.rst
@@ -224,8 +224,8 @@ previous type has the representation
 
 .. _spirv-intrinsics:
 
-LLVM IR Intrinsics
-------------------
+Target Intrinsics
+-----------------
 
 The SPIR-V backend employs several LLVM IR intrinsics that facilitate various low-level 
 operations essential for generating correct and efficient SPIR-V code. These intrinsics 



More information about the llvm-commits mailing list