1============================= 2User Guide for SPIR-V Target 3============================= 4 5.. contents:: 6 :local: 7 8.. toctree:: 9 :hidden: 10 11Introduction 12============ 13 14The SPIR-V target provides code generation for the SPIR-V binary format described 15in `the official SPIR-V specification <https://www.khronos.org/registry/SPIR-V/>`_. 16 17Usage 18===== 19 20The SPIR-V backend can be invoked either from LLVM's Static Compiler (llc) or Clang, 21allowing developers to compile LLVM intermediate language (IL) files or OpenCL kernel 22sources directly to SPIR-V. This section outlines the usage of various commands to 23leverage the SPIR-V backend for different purposes. 24 25Static Compiler Commands 26------------------------ 27 281. **Basic SPIR-V Compilation** 29 Command: `llc -mtriple=spirv32-unknown-unknown input.ll -o output.spvt` 30 Description: This command compiles an LLVM IL file (`input.ll`) to a SPIR-V binary (`output.spvt`) for a 32-bit architecture. 31 322. **Compilation with Extensions and Optimization** 33 Command: `llc -O1 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_arbitrary_precision_integers input.ll -o output.spvt` 34 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. 35 363. **Compilation with experimental NonSemantic.Shader.DebugInfo.100 support** 37 Command: `llc --spv-emit-nonsemantic-debug-info --spirv-ext=+SPV_KHR_non_semantic_info input.ll -o output.spvt` 38 Description: Compiles an LLVM IL file to SPIR-V with additional NonSemantic.Shader.DebugInfo.100 instructions. It enables the required SPV_KHR_non_semantic_info extension. 39 404. **SPIR-V Binary Generation** 41 Command: `llc -O0 -mtriple=spirv64-unknown-unknown -filetype=obj input.ll -o output.spvt` 42 Description: Generates a SPIR-V object file (`output.spvt`) from an LLVM module, targeting a 64-bit SPIR-V architecture with no optimizations. 43 44Clang Commands 45-------------- 46 471. **SPIR-V Generation** 48 Command: `clang –target=spirv64 input.cl` 49 Description: Generates a SPIR-V file directly from an OpenCL kernel source file (`input.cl`). 50 51Compiler Options 52================ 53 54.. _spirv-target-triples: 55 56Target Triples 57-------------- 58 59For cross-compilation into SPIR-V use option 60 61``-target <Architecture><Subarchitecture>-<Vendor>-<OS>-<Environment>`` 62 63to specify the target triple: 64 65 .. table:: SPIR-V Architectures 66 67 ============ ============================================================== 68 Architecture Description 69 ============ ============================================================== 70 ``spirv32`` SPIR-V with 32-bit pointer width. 71 ``spirv64`` SPIR-V with 64-bit pointer width. 72 ``spirv`` SPIR-V with logical memory layout. 73 ============ ============================================================== 74 75 .. table:: SPIR-V Subarchitectures 76 77 =============== ============================================================== 78 Subarchitecture Description 79 =============== ============================================================== 80 *<empty>* SPIR-V version deduced by backend based on the input. 81 ``v1.0`` SPIR-V version 1.0. 82 ``v1.1`` SPIR-V version 1.1. 83 ``v1.2`` SPIR-V version 1.2. 84 ``v1.3`` SPIR-V version 1.3. 85 ``v1.4`` SPIR-V version 1.4. 86 ``v1.5`` SPIR-V version 1.5. 87 ``v1.6`` SPIR-V version 1.6. 88 =============== ============================================================== 89 90 .. table:: SPIR-V Vendors 91 92 ===================== ============================================================== 93 Vendor Description 94 ===================== ============================================================== 95 *<empty>*/``unknown`` Generic SPIR-V target without any vendor-specific settings. 96 ``amd`` AMDGCN SPIR-V target, with support for target specific 97 builtins and ASM, meant to be consumed by AMDGCN toolchains. 98 ===================== ============================================================== 99 100 .. table:: Operating Systems 101 102 ===================== ============================================================== 103 OS Description 104 ===================== ============================================================== 105 *<empty>*/``unknown`` Defaults to the OpenCL runtime. 106 ``vulkan`` Vulkan shader runtime. 107 ``vulkan1.2`` Vulkan 1.2 runtime, corresponding to SPIR-V 1.5. 108 ``vulkan1.3`` Vulkan 1.3 runtime, corresponding to SPIR-V 1.6. 109 ``amdhsa`` AMDHSA runtime, meant to be used on HSA compatible runtimes, 110 corresponding to SPIR-V 1.6. 111 ===================== ============================================================== 112 113 .. table:: SPIR-V Environments 114 115 ===================== ============================================================== 116 Environment Description 117 ===================== ============================================================== 118 *<empty>*/``unknown`` OpenCL environment or deduced by backend based on the input. 119 ===================== ============================================================== 120 121Example: 122 123``-target spirv64v1.0`` can be used to compile for SPIR-V version 1.0 with 64-bit pointer width. 124 125``-target spirv64-amd-amdhsa`` can be used to compile for AMDGCN flavoured SPIR-V with 64-bit pointer width. 126 127.. _spirv-extensions: 128 129Extensions 130---------- 131 132The SPIR-V backend supports a variety of `extensions <https://github.com/KhronosGroup/SPIRV-Registry/tree/main/extensions>`_ 133that enable or enhance features beyond the core SPIR-V specification. 134These extensions can be enabled using the ``-spirv-extensions`` option 135followed by the name of the extension(s) you wish to enable. Below is a 136list of supported SPIR-V extensions, sorted alphabetically by their extension names: 137 138.. list-table:: Supported SPIR-V Extensions 139 :widths: 50 150 140 :header-rows: 1 141 142 * - Extension Name 143 - Description 144 * - ``SPV_EXT_arithmetic_fence`` 145 - Adds an instruction that prevents fast-math optimizations between its argument and the expression that contains it. 146 * - ``SPV_EXT_demote_to_helper_invocation`` 147 - Adds an instruction that demotes a fragment shader invocation to a helper invocation. 148 * - ``SPV_EXT_optnone`` 149 - Adds OptNoneEXT value for Function Control mask that indicates a request to not optimize the function. 150 * - ``SPV_EXT_shader_atomic_float16_add`` 151 - Extends the SPV_EXT_shader_atomic_float_add extension to support atomically adding to 16-bit floating-point numbers in memory. 152 * - ``SPV_EXT_shader_atomic_float_add`` 153 - Adds atomic add instruction on floating-point numbers. 154 * - ``SPV_EXT_shader_atomic_float_min_max`` 155 - Adds atomic min and max instruction on floating-point numbers. 156 * - ``SPV_INTEL_arbitrary_precision_integers`` 157 - Allows generating arbitrary width integer types. 158 * - ``SPV_INTEL_bfloat16_conversion`` 159 - Adds instructions to convert between single-precision 32-bit floating-point values and 16-bit bfloat16 values. 160 * - ``SPV_INTEL_cache_controls`` 161 - Allows cache control information to be applied to memory access instructions. 162 * - ``SPV_INTEL_float_controls2`` 163 - Adds execution modes and decorations to control floating-point computations. 164 * - ``SPV_INTEL_function_pointers`` 165 - Allows translation of function pointers. 166 * - ``SPV_INTEL_inline_assembly`` 167 - Allows to use inline assembly. 168 * - ``SPV_INTEL_global_variable_host_access`` 169 - Adds decorations that can be applied to global (module scope) variables. 170 * - ``SPV_INTEL_global_variable_fpga_decorations`` 171 - Adds decorations that can be applied to global (module scope) variables to help code generation for FPGA devices. 172 * - ``SPV_INTEL_media_block_io`` 173 - Adds additional subgroup block read and write functionality that allow applications to flexibly specify the width and height of the block to read from or write to a 2D image. 174 * - ``SPV_INTEL_optnone`` 175 - Adds OptNoneINTEL value for Function Control mask that indicates a request to not optimize the function. 176 * - ``SPV_INTEL_split_barrier`` 177 - Adds SPIR-V instructions to split a control barrier into two separate operations: the first indicates that an invocation has "arrived" at the barrier but should continue executing, and the second indicates that an invocation should "wait" for other invocations to arrive at the barrier before executing further. 178 * - ``SPV_INTEL_subgroups`` 179 - 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. 180 * - ``SPV_INTEL_usm_storage_classes`` 181 - Introduces two new storage classes that are subclasses of the CrossWorkgroup storage class that provides additional information that can enable optimization. 182 * - ``SPV_INTEL_variable_length_array`` 183 - Allows to allocate local arrays whose number of elements is unknown at compile time. 184 * - ``SPV_INTEL_joint_matrix`` 185 - Adds few matrix capabilities on top of SPV_KHR_cooperative_matrix extension, such as matrix prefetch, get element coordinate and checked load/store/construct instructions, tensor float 32 and bfloat type interpretations for multuply-add instruction. 186 * - ``SPV_KHR_bit_instructions`` 187 - Enables bit instructions to be used by SPIR-V modules without requiring the Shader capability. 188 * - ``SPV_KHR_expect_assume`` 189 - Provides additional information to a compiler, similar to the llvm.assume and llvm.expect intrinsics. 190 * - ``SPV_KHR_float_controls`` 191 - Provides new execution modes to control floating-point computations by overriding an implementation’s default behavior for rounding modes, denormals, signed zero, and infinities. 192 * - ``SPV_KHR_integer_dot_product`` 193 - Adds instructions for dot product operations on integer vectors with optional accumulation. Integer vectors includes 4-component vector of 8 bit integers and 4-component vectors of 8 bit integers packed into 32-bit integers. 194 * - ``SPV_KHR_linkonce_odr`` 195 - 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. 196 * - ``SPV_KHR_no_integer_wrap_decoration`` 197 - Adds decorations to indicate that a given instruction does not cause integer wrapping. 198 * - ``SPV_KHR_shader_clock`` 199 - Adds the extension cl_khr_kernel_clock that adds the ability for a kernel to sample the value from clocks provided by compute units. 200 * - ``SPV_KHR_subgroup_rotate`` 201 - Adds a new instruction that enables rotating values across invocations within a subgroup. 202 * - ``SPV_KHR_uniform_group_instructions`` 203 - Allows support for additional group operations within uniform control flow. 204 * - ``SPV_KHR_non_semantic_info`` 205 - Adds the ability to declare extended instruction sets that have no semantic impact and can be safely removed from a module. 206 207To 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: 208 209``-spirv-ext=+SPV_EXT_shader_atomic_float_add,+SPV_INTEL_arbitrary_precision_integers`` 210 211To enable all extensions, use the following option: 212``-spirv-ext=all`` 213 214To enable all extensions except specified, specify ``all`` followed by a list of disallowed extensions. For example: 215``-spirv-ext=all,-SPV_INTEL_arbitrary_precision_integers`` 216 217SPIR-V representation in LLVM IR 218================================ 219 220SPIR-V is intentionally designed for seamless integration with various Intermediate 221Representations (IRs), including LLVM IR, facilitating straightforward mappings for 222most of its entities. The development of the SPIR-V backend has been guided by a 223principle of compatibility with the `Khronos Group SPIR-V LLVM Translator <https://github.com/KhronosGroup/SPIRV-LLVM-Translator>`_. 224Consequently, the input representation accepted by the SPIR-V backend aligns closely 225with that detailed in `the SPIR-V Representation in LLVM document <https://github.com/KhronosGroup/SPIRV-LLVM-Translator/blob/main/docs/SPIRVRepresentationInLLVM.rst>`_. 226This document, along with the sections that follow, delineate the main points and focus 227on any differences between the LLVM IR that this backend processes and the conventions 228used by other tools. 229 230.. _spirv-special-types: 231 232Special types 233------------- 234 235SPIR-V specifies several kinds of opaque types. These types are represented 236using target extension types and are represented as follows: 237 238 .. table:: SPIR-V Opaque Types 239 240 ================== ====================== =========================================================================================== 241 SPIR-V Type LLVM type name LLVM type arguments 242 ================== ====================== =========================================================================================== 243 OpTypeImage ``spirv.Image`` sampled type, dimensionality, depth, arrayed, MS, sampled, image format, [access qualifier] 244 OpTypeSampler ``spirv.Sampler`` (none) 245 OpTypeSampledImage ``spirv.SampledImage`` sampled type, dimensionality, depth, arrayed, MS, sampled, image format, [access qualifier] 246 OpTypeEvent ``spirv.Event`` (none) 247 OpTypeDeviceEvent ``spirv.DeviceEvent`` (none) 248 OpTypeReserveId ``spirv.ReserveId`` (none) 249 OpTypeQueue ``spirv.Queue`` (none) 250 OpTypePipe ``spirv.Pipe`` access qualifier 251 OpTypePipeStorage ``spirv.PipeStorage`` (none) 252 ================== ====================== =========================================================================================== 253 254All integer arguments take the same value as they do in their `corresponding 255SPIR-V instruction <https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#_type_declaration_instructions>`_. 256For example, the OpenCL type ``image2d_depth_ro_t`` would be represented in 257SPIR-V IR as ``target("spirv.Image", void, 1, 1, 0, 0, 0, 0, 0)``, with its 258dimensionality parameter as ``1`` meaning 2D. Sampled image types include the 259parameters of its underlying image type, so that a sampled image for the 260previous type has the representation 261``target("spirv.SampledImage, void, 1, 1, 0, 0, 0, 0, 0)``. 262 263.. _spirv-intrinsics: 264 265Target Intrinsics 266----------------- 267 268The SPIR-V backend employs several LLVM IR intrinsics that facilitate various low-level 269operations essential for generating correct and efficient SPIR-V code. These intrinsics 270cover a range of functionalities from type assignment and memory management to control 271flow and atomic operations. Below is a detailed table of selected intrinsics used in the 272SPIR-V backend, along with their descriptions and argument details. 273 274.. list-table:: LLVM IR Intrinsics for SPIR-V 275 :widths: 25 15 20 40 276 :header-rows: 1 277 278 * - Intrinsic ID 279 - Return Type 280 - Argument Types 281 - Description 282 * - `int_spv_assign_type` 283 - None 284 - `[Type, Metadata]` 285 - Associates a type with metadata, crucial for maintaining type information in SPIR-V structures. Not emitted directly but supports the type system internally. 286 * - `int_spv_assign_ptr_type` 287 - None 288 - `[Type, Metadata, Integer]` 289 - 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. 290 * - `int_spv_assign_name` 291 - None 292 - `[Type, Vararg]` 293 - Assigns names to types or values, enhancing readability and debuggability of SPIR-V code. Not emitted directly but used for metadata enrichment. 294 * - `int_spv_value_md` 295 - None 296 - `[Metadata]` 297 - Assigns a set of attributes (such as name and data type) to a value that is the argument of the associated `llvm.fake.use` intrinsic call. The latter is used as a mean to map virtual registers created by IRTranslator to the original value. 298 * - `int_spv_assign_decoration` 299 - None 300 - `[Type, Metadata]` 301 - Assigns decoration to values by associating them with metadatas. Not emitted directly but used to support SPIR-V representation in LLVM IR. 302 * - `int_spv_track_constant` 303 - Type 304 - `[Type, Metadata]` 305 - Tracks constants in the SPIR-V module. Essential for optimizing and reducing redundancy. Emitted for internal use only. 306 * - `int_spv_init_global` 307 - None 308 - `[Type, Type]` 309 - Initializes global variables, a necessary step for ensuring correct global state management in SPIR-V. Emitted for internal use only. 310 * - `int_spv_unref_global` 311 - None 312 - `[Type]` 313 - Manages the lifetime of global variables by marking them as unreferenced, thus enabling optimizations related to global variable usage. Emitted for internal use only. 314 * - `int_spv_gep` 315 - Pointer 316 - `[Boolean, Type, Vararg]` 317 - 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. 318 * - `int_spv_load` 319 - 32-bit Integer 320 - `[Pointer, 16-bit Integer, 8-bit Integer]` 321 - Loads a value from a memory location. The additional integers specify memory access and alignment details, vital for ensuring correct and efficient memory operations. 322 * - `int_spv_store` 323 - None 324 - `[Type, Pointer, 16-bit Integer, 8-bit Integer]` 325 - Stores a value to a memory location. Like `int_spv_load`, it includes specifications for memory access and alignment, essential for memory operations. 326 * - `int_spv_extractv` 327 - Type 328 - `[32-bit Integer, Vararg]` 329 - Extracts a value from a vector, allowing for vector operations within SPIR-V. Enables manipulation of vector components. 330 * - `int_spv_insertv` 331 - 32-bit Integer 332 - `[32-bit Integer, Type, Vararg]` 333 - Inserts a value into a vector. Complementary to `int_spv_extractv`, it facilitates the construction and manipulation of vectors. 334 * - `int_spv_extractelt` 335 - Type 336 - `[Type, Any Integer]` 337 - Extracts an element from an aggregate type based on an index. Essential for operations on arrays and vectors. 338 * - `int_spv_insertelt` 339 - Type 340 - `[Type, Type, Any Integer]` 341 - Inserts an element into an aggregate type at a specified index. Allows for building and modifying arrays and vectors. 342 * - `int_spv_const_composite` 343 - Type 344 - `[Vararg]` 345 - Constructs a composite type from given elements. Key for creating arrays, structs, and vectors from individual components. 346 * - `int_spv_bitcast` 347 - Type 348 - `[Type]` 349 - Performs a bit-wise cast between types. Critical for type conversions that do not change the bit representation. 350 * - `int_spv_ptrcast` 351 - Type 352 - `[Type, Metadata, Integer]` 353 - Casts pointers between different types. Similar to `int_spv_bitcast` but specifically for pointers, taking into account SPIR-V's strict type system. 354 * - `int_spv_switch` 355 - None 356 - `[Type, Vararg]` 357 - Implements a multi-way branch based on a value. Enables complex control flow structures, similar to the switch statement in high-level languages. 358 * - `int_spv_cmpxchg` 359 - 32-bit Integer 360 - `[Type, Vararg]` 361 - Performs an atomic compare-and-exchange operation. Crucial for synchronization and concurrency control in compute shaders. 362 * - `int_spv_unreachable` 363 - None 364 - `[]` 365 - Marks a point in the code that should never be reached, enabling optimizations by indicating unreachable code paths. 366 * - `int_spv_alloca` 367 - Type 368 - `[]` 369 - Allocates memory on the stack. Fundamental for local variable storage in functions. 370 * - `int_spv_alloca_array` 371 - Type 372 - `[Any Integer]` 373 - Allocates an array on the stack. Extends `int_spv_alloca` to support array allocations, essential for temporary arrays. 374 * - `int_spv_undef` 375 - 32-bit Integer 376 - `[]` 377 - Generates an undefined value. Useful for optimizations and indicating uninitialized variables. 378 * - `int_spv_inline_asm` 379 - None 380 - `[Metadata, Metadata, Vararg]` 381 - Associates inline assembly features to inline assembly call instances by creating metadatas and preserving original arguments. Not emitted directly but used to support SPIR-V representation in LLVM IR. 382 * - `int_spv_assume` 383 - None 384 - `[1-bit Integer]` 385 - Provides hints to the optimizer about assumptions that can be made about program state. Improves optimization potential. 386 * - `int_spv_expect` 387 - Any Integer Type 388 - `[Type, Type]` 389 - Guides branch prediction by indicating expected branch paths. Enhances performance by optimizing common code paths. 390 * - `int_spv_thread_id` 391 - 32-bit Integer 392 - `[32-bit Integer]` 393 - Retrieves the thread ID within a workgroup. Essential for identifying execution context in parallel compute operations. 394 * - `int_spv_create_handle` 395 - Pointer 396 - `[8-bit Integer]` 397 - Creates a resource handle for graphics or compute resources. Facilitates the management and use of resources in shaders. 398 * - `int_spv_resource_handlefrombinding` 399 - spirv.Image 400 - `[32-bit Integer set, 32-bit Integer binding, 32-bit Integer arraySize, 32-bit Integer index, bool isUniformIndex]` 401 - Returns the handle for the resource at the given set and binding.\ 402 If `arraySize > 1`, then the binding represents an array of resources\ 403 of the given size, and the handle for the resource at the given index is returned.\ 404 If the index is possibly non-uniform, then `isUniformIndex` must get set to true. 405 * - `int_spv_typeBufferLoad` 406 - Scalar or vector 407 - `[spirv.Image ImageBuffer, 32-bit Integer coordinate]` 408 - Loads a value from a Vulkan image buffer at the given coordinate. The \ 409 image buffer data is assumed to be stored as a 4-element vector. If the \ 410 return type is a scalar, then the first element of the vector is \ 411 returned. If the return type is an n-element vector, then the first \ 412 n-elements of the 4-element vector are returned. 413 * - `int_spv_resource_store_typedbuffer` 414 - void 415 - `[spirv.Image Image, 32-bit Integer coordinate, vec4 data]` 416 - Stores the data to the image buffer at the given coordinate. The \ 417 data must be a 4-element vector. 418 419.. _spirv-builtin-functions: 420 421Builtin Functions 422----------------- 423 424The following section highlights the representation of SPIR-V builtins in LLVM IR, 425emphasizing builtins that do not have direct counterparts in LLVM. 426 427Instructions as Function Calls 428~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 429 430SPIR-V builtins without direct LLVM counterparts are represented as LLVM function calls. 431These functions, termed SPIR-V builtin functions, follow an IA64 mangling scheme with 432SPIR-V-specific extensions. Parsing non-mangled calls to builtins is supported in some cases, 433but not tested extensively. The general format is: 434 435.. code-block:: c 436 437 __spirv_{OpCodeName}{_OptionalPostfixes} 438 439Where `{OpCodeName}` is the SPIR-V opcode name sans the "Op" prefix, and 440`{OptionalPostfixes}` are decoration-specific postfixes, if any. The mangling and 441postfixes allow for the representation of SPIR-V's rich instruction set within LLVM's 442framework. 443 444Extended Instruction Sets 445~~~~~~~~~~~~~~~~~~~~~~~~~ 446 447SPIR-V defines several extended instruction sets for additional functionalities, such as 448OpenCL-specific operations. In LLVM IR, these are represented by function calls to 449mangled builtins and selected based on the environment. For example: 450 451.. code-block:: c 452 453 acos_f32 454 455represents the `acos` function from the OpenCL extended instruction set for a float32 456input. 457 458Builtin Variables 459~~~~~~~~~~~~~~~~~ 460 461SPIR-V builtin variables, which provide access to special hardware or execution model 462properties, are mapped to either LLVM function calls or LLVM global variables. The 463representation follows the naming convention: 464 465.. code-block:: c 466 467 __spirv_BuiltIn{VariableName} 468 469For instance, the SPIR-V builtin `GlobalInvocationId` is accessible in LLVM IR as 470`__spirv_BuiltInGlobalInvocationId`. 471 472Vector Load and Store Builtins 473~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 474 475SPIR-V's capabilities for loading and storing vectors are represented in LLVM IR using 476functions that mimic the SPIR-V instructions. These builtins handle cases that LLVM's 477native instructions do not directly support, enabling fine-grained control over memory 478operations. 479 480Atomic Operations 481~~~~~~~~~~~~~~~~~ 482 483SPIR-V's atomic operations, especially those operating on floating-point data, are 484represented in LLVM IR with corresponding function calls. These builtins ensure 485atomicity in operations where LLVM might not have direct support, essential for parallel 486execution and synchronization. 487 488Image Operations 489~~~~~~~~~~~~~~~~ 490 491SPIR-V provides extensive support for image and sampler operations, which LLVM 492represents through function calls to builtins. These include image reads, writes, and 493queries, allowing detailed manipulation of image data and parameters. 494 495Group and Subgroup Operations 496~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 497 498For workgroup and subgroup operations, LLVM uses function calls to represent SPIR-V's 499group-based instructions. These builtins facilitate group synchronization, data sharing, 500and collective operations essential for efficient parallel computation. 501