diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst index 5ca035b68392f..a183877c48cb2 100644 --- a/llvm/docs/SPIRVUsage.rst +++ b/llvm/docs/SPIRVUsage.rst @@ -14,10 +14,43 @@ Introduction The SPIR-V target provides code generation for the SPIR-V binary format described in `the official SPIR-V specification `_. +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 -============== +-------------- For cross-compilation into SPIR-V use option @@ -32,6 +65,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 +73,14 @@ to specify the target triple: =============== ============================================================== Subarchitecture Description =============== ============================================================== - ** SPIR-V version deduced by tools based on the compiled input. + ** 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 +97,9 @@ to specify the target triple: OS Description ===================== ============================================================ **/``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 @@ -69,20 +107,95 @@ to specify the target triple: ===================== ============================================================== Environment Description ===================== ============================================================== - **/``unknown`` Defaults to the OpenCL environment. + **/``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. -Representing special types in SPIR-V -==================================== +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-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`` + +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 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 `_. +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: +using target extension types and are represented as follows: .. table:: SPIR-V Opaque Types @@ -108,3 +221,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: + +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 +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.