| ============================= | |
| User Guide for AMDGPU Backend | |
| ============================= | |
| .. contents:: | |
| :local: | |
| Introduction | |
| ============ | |
| The AMDGPU backend provides ISA code generation for AMD GPUs, starting with the | |
| R600 family up until the current GCN families. It lives in the | |
| ``lib/Target/AMDGPU`` directory. | |
| LLVM | |
| ==== | |
| .. _amdgpu-target-triples: | |
| Target Triples | |
| -------------- | |
| Use the ``clang -target <Architecture>-<Vendor>-<OS>-<Environment>`` option to | |
| specify the target triple: | |
| .. table:: AMDGPU Architectures | |
| :name: amdgpu-architecture-table | |
| ============ ============================================================== | |
| Architecture Description | |
| ============ ============================================================== | |
| ``r600`` AMD GPUs HD2XXX-HD6XXX for graphics and compute shaders. | |
| ``amdgcn`` AMD GPUs GCN GFX6 onwards for graphics and compute shaders. | |
| ============ ============================================================== | |
| .. table:: AMDGPU Vendors | |
| :name: amdgpu-vendor-table | |
| ============ ============================================================== | |
| Vendor Description | |
| ============ ============================================================== | |
| ``amd`` Can be used for all AMD GPU usage. | |
| ``mesa3d`` Can be used if the OS is ``mesa3d``. | |
| ============ ============================================================== | |
| .. table:: AMDGPU Operating Systems | |
| :name: amdgpu-os-table | |
| ============== ============================================================ | |
| OS Description | |
| ============== ============================================================ | |
| *<empty>* Defaults to the *unknown* OS. | |
| ``amdhsa`` Compute kernels executed on HSA [HSA]_ compatible runtimes | |
| such as AMD's ROCm [AMD-ROCm]_. | |
| ``amdpal`` Graphic shaders and compute kernels executed on AMD PAL | |
| runtime. | |
| ``mesa3d`` Graphic shaders and compute kernels executed on Mesa 3D | |
| runtime. | |
| ============== ============================================================ | |
| .. table:: AMDGPU Environments | |
| :name: amdgpu-environment-table | |
| ============ ============================================================== | |
| Environment Description | |
| ============ ============================================================== | |
| *<empty>* Default. | |
| ============ ============================================================== | |
| .. _amdgpu-processors: | |
| Processors | |
| ---------- | |
| Use the ``clang -mcpu <Processor>`` option to specify the AMD GPU processor. The | |
| names from both the *Processor* and *Alternative Processor* can be used. | |
| .. table:: AMDGPU Processors | |
| :name: amdgpu-processor-table | |
| =========== =============== ============ ===== ========= ======= ================== | |
| Processor Alternative Target dGPU/ Target ROCm Example | |
| Processor Triple APU Features Support Products | |
| Architecture Supported | |
| [Default] | |
| =========== =============== ============ ===== ========= ======= ================== | |
| **Radeon HD 2000/3000 Series (R600)** [AMD-RADEON-HD-2000-3000]_ | |
| ----------------------------------------------------------------------------------- | |
| ``r600`` ``r600`` dGPU | |
| ``r630`` ``r600`` dGPU | |
| ``rs880`` ``r600`` dGPU | |
| ``rv670`` ``r600`` dGPU | |
| **Radeon HD 4000 Series (R700)** [AMD-RADEON-HD-4000]_ | |
| ----------------------------------------------------------------------------------- | |
| ``rv710`` ``r600`` dGPU | |
| ``rv730`` ``r600`` dGPU | |
| ``rv770`` ``r600`` dGPU | |
| **Radeon HD 5000 Series (Evergreen)** [AMD-RADEON-HD-5000]_ | |
| ----------------------------------------------------------------------------------- | |
| ``cedar`` ``r600`` dGPU | |
| ``cypress`` ``r600`` dGPU | |
| ``juniper`` ``r600`` dGPU | |
| ``redwood`` ``r600`` dGPU | |
| ``sumo`` ``r600`` dGPU | |
| **Radeon HD 6000 Series (Northern Islands)** [AMD-RADEON-HD-6000]_ | |
| ----------------------------------------------------------------------------------- | |
| ``barts`` ``r600`` dGPU | |
| ``caicos`` ``r600`` dGPU | |
| ``cayman`` ``r600`` dGPU | |
| ``turks`` ``r600`` dGPU | |
| **GCN GFX6 (Southern Islands (SI))** [AMD-GCN-GFX6]_ | |
| ----------------------------------------------------------------------------------- | |
| ``gfx600`` - ``tahiti`` ``amdgcn`` dGPU | |
| ``gfx601`` - ``hainan`` ``amdgcn`` dGPU | |
| - ``oland`` | |
| - ``pitcairn`` | |
| - ``verde`` | |
| **GCN GFX7 (Sea Islands (CI))** [AMD-GCN-GFX7]_ | |
| ----------------------------------------------------------------------------------- | |
| ``gfx700`` - ``kaveri`` ``amdgcn`` APU - A6-7000 | |
| - A6 Pro-7050B | |
| - A8-7100 | |
| - A8 Pro-7150B | |
| - A10-7300 | |
| - A10 Pro-7350B | |
| - FX-7500 | |
| - A8-7200P | |
| - A10-7400P | |
| - FX-7600P | |
| ``gfx701`` - ``hawaii`` ``amdgcn`` dGPU ROCm - FirePro W8100 | |
| - FirePro W9100 | |
| - FirePro S9150 | |
| - FirePro S9170 | |
| ``gfx702`` ``amdgcn`` dGPU ROCm - Radeon R9 290 | |
| - Radeon R9 290x | |
| - Radeon R390 | |
| - Radeon R390x | |
| ``gfx703`` - ``kabini`` ``amdgcn`` APU - E1-2100 | |
| - ``mullins`` - E1-2200 | |
| - E1-2500 | |
| - E2-3000 | |
| - E2-3800 | |
| - A4-5000 | |
| - A4-5100 | |
| - A6-5200 | |
| - A4 Pro-3340B | |
| ``gfx704`` - ``bonaire`` ``amdgcn`` dGPU - Radeon HD 7790 | |
| - Radeon HD 8770 | |
| - R7 260 | |
| - R7 260X | |
| **GCN GFX8 (Volcanic Islands (VI))** [AMD-GCN-GFX8]_ | |
| ----------------------------------------------------------------------------------- | |
| ``gfx801`` - ``carrizo`` ``amdgcn`` APU - xnack - A6-8500P | |
| [on] - Pro A6-8500B | |
| - A8-8600P | |
| - Pro A8-8600B | |
| - FX-8800P | |
| - Pro A12-8800B | |
| \ ``amdgcn`` APU - xnack ROCm - A10-8700P | |
| [on] - Pro A10-8700B | |
| - A10-8780P | |
| \ ``amdgcn`` APU - xnack - A10-9600P | |
| [on] - A10-9630P | |
| - A12-9700P | |
| - A12-9730P | |
| - FX-9800P | |
| - FX-9830P | |
| \ ``amdgcn`` APU - xnack - E2-9010 | |
| [on] - A6-9210 | |
| - A9-9410 | |
| ``gfx802`` - ``iceland`` ``amdgcn`` dGPU - xnack ROCm - FirePro S7150 | |
| - ``tonga`` [off] - FirePro S7100 | |
| - FirePro W7100 | |
| - Radeon R285 | |
| - Radeon R9 380 | |
| - Radeon R9 385 | |
| - Mobile FirePro | |
| M7170 | |
| ``gfx803`` - ``fiji`` ``amdgcn`` dGPU - xnack ROCm - Radeon R9 Nano | |
| [off] - Radeon R9 Fury | |
| - Radeon R9 FuryX | |
| - Radeon Pro Duo | |
| - FirePro S9300x2 | |
| - Radeon Instinct MI8 | |
| \ - ``polaris10`` ``amdgcn`` dGPU - xnack ROCm - Radeon RX 470 | |
| [off] - Radeon RX 480 | |
| - Radeon Instinct MI6 | |
| \ - ``polaris11`` ``amdgcn`` dGPU - xnack ROCm - Radeon RX 460 | |
| [off] | |
| ``gfx810`` - ``stoney`` ``amdgcn`` APU - xnack | |
| [on] | |
| **GCN GFX9** [AMD-GCN-GFX9]_ | |
| ----------------------------------------------------------------------------------- | |
| ``gfx900`` ``amdgcn`` dGPU - xnack ROCm - Radeon Vega | |
| [off] Frontier Edition | |
| - Radeon RX Vega 56 | |
| - Radeon RX Vega 64 | |
| - Radeon RX Vega 64 | |
| Liquid | |
| - Radeon Instinct MI25 | |
| ``gfx902`` ``amdgcn`` APU - xnack - Ryzen 3 2200G | |
| [on] - Ryzen 5 2400G | |
| ``gfx904`` ``amdgcn`` dGPU - xnack *TBA* | |
| [off] | |
| .. TODO | |
| Add product | |
| names. | |
| ``gfx906`` ``amdgcn`` dGPU - xnack *TBA* | |
| [off] | |
| .. TODO | |
| Add product | |
| names. | |
| =========== =============== ============ ===== ========= ======= ================== | |
| .. _amdgpu-target-features: | |
| Target Features | |
| --------------- | |
| Target features control how code is generated to support certain | |
| processor specific features. Not all target features are supported by | |
| all processors. The runtime must ensure that the features supported by | |
| the device used to execute the code match the features enabled when | |
| generating the code. A mismatch of features may result in incorrect | |
| execution, or a reduction in performance. | |
| The target features supported by each processor, and the default value | |
| used if not specified explicitly, is listed in | |
| :ref:`amdgpu-processor-table`. | |
| Use the ``clang -m[no-]<TargetFeature>`` option to specify the AMD GPU | |
| target features. | |
| For example: | |
| ``-mxnack`` | |
| Enable the ``xnack`` feature. | |
| ``-mno-xnack`` | |
| Disable the ``xnack`` feature. | |
| .. table:: AMDGPU Target Features | |
| :name: amdgpu-target-feature-table | |
| ============== ================================================== | |
| Target Feature Description | |
| ============== ================================================== | |
| -m[no-]xnack Enable/disable generating code that has | |
| memory clauses that are compatible with | |
| having XNACK replay enabled. | |
| This is used for demand paging and page | |
| migration. If XNACK replay is enabled in | |
| the device, then if a page fault occurs | |
| the code may execute incorrectly if the | |
| ``xnack`` feature is not enabled. Executing | |
| code that has the feature enabled on a | |
| device that does not have XNACK replay | |
| enabled will execute correctly, but may | |
| be less performant than code with the | |
| feature disabled. | |
| ============== ================================================== | |
| .. _amdgpu-address-spaces: | |
| Address Spaces | |
| -------------- | |
| The AMDGPU backend uses the following address space mappings. | |
| The memory space names used in the table, aside from the region memory space, is | |
| from the OpenCL standard. | |
| LLVM Address Space number is used throughout LLVM (for example, in LLVM IR). | |
| .. table:: Address Space Mapping | |
| :name: amdgpu-address-space-mapping-table | |
| ================== ================= | |
| LLVM Address Space Memory Space | |
| ================== ================= | |
| 0 Generic (Flat) | |
| 1 Global | |
| 2 Region (GDS) | |
| 3 Local (group/LDS) | |
| 4 Constant | |
| 5 Private (Scratch) | |
| 6 Constant 32-bit | |
| ================== ================= | |
| .. _amdgpu-memory-scopes: | |
| Memory Scopes | |
| ------------- | |
| This section provides LLVM memory synchronization scopes supported by the AMDGPU | |
| backend memory model when the target triple OS is ``amdhsa`` (see | |
| :ref:`amdgpu-amdhsa-memory-model` and :ref:`amdgpu-target-triples`). | |
| The memory model supported is based on the HSA memory model [HSA]_ which is | |
| based in turn on HRF-indirect with scope inclusion [HRF]_. The happens-before | |
| relation is transitive over the synchonizes-with relation independent of scope, | |
| and synchonizes-with allows the memory scope instances to be inclusive (see | |
| table :ref:`amdgpu-amdhsa-llvm-sync-scopes-table`). | |
| This is different to the OpenCL [OpenCL]_ memory model which does not have scope | |
| inclusion and requires the memory scopes to exactly match. However, this | |
| is conservatively correct for OpenCL. | |
| .. table:: AMDHSA LLVM Sync Scopes | |
| :name: amdgpu-amdhsa-llvm-sync-scopes-table | |
| ================ ========================================================== | |
| LLVM Sync Scope Description | |
| ================ ========================================================== | |
| *none* The default: ``system``. | |
| Synchronizes with, and participates in modification and | |
| seq_cst total orderings with, other operations (except | |
| image operations) for all address spaces (except private, | |
| or generic that accesses private) provided the other | |
| operation's sync scope is: | |
| - ``system``. | |
| - ``agent`` and executed by a thread on the same agent. | |
| - ``workgroup`` and executed by a thread in the same | |
| workgroup. | |
| - ``wavefront`` and executed by a thread in the same | |
| wavefront. | |
| ``agent`` Synchronizes with, and participates in modification and | |
| seq_cst total orderings with, other operations (except | |
| image operations) for all address spaces (except private, | |
| or generic that accesses private) provided the other | |
| operation's sync scope is: | |
| - ``system`` or ``agent`` and executed by a thread on the | |
| same agent. | |
| - ``workgroup`` and executed by a thread in the same | |
| workgroup. | |
| - ``wavefront`` and executed by a thread in the same | |
| wavefront. | |
| ``workgroup`` Synchronizes with, and participates in modification and | |
| seq_cst total orderings with, other operations (except | |
| image operations) for all address spaces (except private, | |
| or generic that accesses private) provided the other | |
| operation's sync scope is: | |
| - ``system``, ``agent`` or ``workgroup`` and executed by a | |
| thread in the same workgroup. | |
| - ``wavefront`` and executed by a thread in the same | |
| wavefront. | |
| ``wavefront`` Synchronizes with, and participates in modification and | |
| seq_cst total orderings with, other operations (except | |
| image operations) for all address spaces (except private, | |
| or generic that accesses private) provided the other | |
| operation's sync scope is: | |
| - ``system``, ``agent``, ``workgroup`` or ``wavefront`` | |
| and executed by a thread in the same wavefront. | |
| ``singlethread`` Only synchronizes with, and participates in modification | |
| and seq_cst total orderings with, other operations (except | |
| image operations) running in the same thread for all | |
| address spaces (for example, in signal handlers). | |
| ================ ========================================================== | |
| AMDGPU Intrinsics | |
| ----------------- | |
| The AMDGPU backend implements the following LLVM IR intrinsics. | |
| *This section is WIP.* | |
| .. TODO | |
| List AMDGPU intrinsics | |
| AMDGPU Attributes | |
| ----------------- | |
| The AMDGPU backend supports the following LLVM IR attributes. | |
| .. table:: AMDGPU LLVM IR Attributes | |
| :name: amdgpu-llvm-ir-attributes-table | |
| ======================================= ========================================================== | |
| LLVM Attribute Description | |
| ======================================= ========================================================== | |
| "amdgpu-flat-work-group-size"="min,max" Specify the minimum and maximum flat work group sizes that | |
| will be specified when the kernel is dispatched. Generated | |
| by the ``amdgpu_flat_work_group_size`` CLANG attribute [CLANG-ATTR]_. | |
| "amdgpu-implicitarg-num-bytes"="n" Number of kernel argument bytes to add to the kernel | |
| argument block size for the implicit arguments. This | |
| varies by OS and language (for OpenCL see | |
| :ref:`opencl-kernel-implicit-arguments-appended-for-amdhsa-os-table`). | |
| "amdgpu-max-work-group-size"="n" Specify the maximum work-group size that will be specifed | |
| when the kernel is dispatched. | |
| "amdgpu-num-sgpr"="n" Specifies the number of SGPRs to use. Generated by | |
| the ``amdgpu_num_sgpr`` CLANG attribute [CLANG-ATTR]_. | |
| "amdgpu-num-vgpr"="n" Specifies the number of VGPRs to use. Generated by the | |
| ``amdgpu_num_vgpr`` CLANG attribute [CLANG-ATTR]_. | |
| "amdgpu-waves-per-eu"="m,n" Specify the minimum and maximum number of waves per | |
| execution unit. Generated by the ``amdgpu_waves_per_eu`` | |
| CLANG attribute [CLANG-ATTR]_. | |
| ======================================= ========================================================== | |
| Code Object | |
| =========== | |
| The AMDGPU backend generates a standard ELF [ELF]_ relocatable code object that | |
| can be linked by ``lld`` to produce a standard ELF shared code object which can | |
| be loaded and executed on an AMDGPU target. | |
| Header | |
| ------ | |
| The AMDGPU backend uses the following ELF header: | |
| .. table:: AMDGPU ELF Header | |
| :name: amdgpu-elf-header-table | |
| ========================== =============================== | |
| Field Value | |
| ========================== =============================== | |
| ``e_ident[EI_CLASS]`` ``ELFCLASS64`` | |
| ``e_ident[EI_DATA]`` ``ELFDATA2LSB`` | |
| ``e_ident[EI_OSABI]`` - ``ELFOSABI_NONE`` | |
| - ``ELFOSABI_AMDGPU_HSA`` | |
| - ``ELFOSABI_AMDGPU_PAL`` | |
| - ``ELFOSABI_AMDGPU_MESA3D`` | |
| ``e_ident[EI_ABIVERSION]`` - ``ELFABIVERSION_AMDGPU_HSA`` | |
| - ``ELFABIVERSION_AMDGPU_PAL`` | |
| - ``ELFABIVERSION_AMDGPU_MESA3D`` | |
| ``e_type`` - ``ET_REL`` | |
| - ``ET_DYN`` | |
| ``e_machine`` ``EM_AMDGPU`` | |
| ``e_entry`` 0 | |
| ``e_flags`` See :ref:`amdgpu-elf-header-e_flags-table` | |
| ========================== =============================== | |
| .. | |
| .. table:: AMDGPU ELF Header Enumeration Values | |
| :name: amdgpu-elf-header-enumeration-values-table | |
| =============================== ===== | |
| Name Value | |
| =============================== ===== | |
| ``EM_AMDGPU`` 224 | |
| ``ELFOSABI_NONE`` 0 | |
| ``ELFOSABI_AMDGPU_HSA`` 64 | |
| ``ELFOSABI_AMDGPU_PAL`` 65 | |
| ``ELFOSABI_AMDGPU_MESA3D`` 66 | |
| ``ELFABIVERSION_AMDGPU_HSA`` 1 | |
| ``ELFABIVERSION_AMDGPU_PAL`` 0 | |
| ``ELFABIVERSION_AMDGPU_MESA3D`` 0 | |
| =============================== ===== | |
| ``e_ident[EI_CLASS]`` | |
| The ELF class is: | |
| * ``ELFCLASS32`` for ``r600`` architecture. | |
| * ``ELFCLASS64`` for ``amdgcn`` architecture which only supports 64 | |
| bit applications. | |
| ``e_ident[EI_DATA]`` | |
| All AMDGPU targets use ``ELFDATA2LSB`` for little-endian byte ordering. | |
| ``e_ident[EI_OSABI]`` | |
| One of the following AMD GPU architecture specific OS ABIs | |
| (see :ref:`amdgpu-os-table`): | |
| * ``ELFOSABI_NONE`` for *unknown* OS. | |
| * ``ELFOSABI_AMDGPU_HSA`` for ``amdhsa`` OS. | |
| * ``ELFOSABI_AMDGPU_PAL`` for ``amdpal`` OS. | |
| * ``ELFOSABI_AMDGPU_MESA3D`` for ``mesa3D`` OS. | |
| ``e_ident[EI_ABIVERSION]`` | |
| The ABI version of the AMD GPU architecture specific OS ABI to which the code | |
| object conforms: | |
| * ``ELFABIVERSION_AMDGPU_HSA`` is used to specify the version of AMD HSA | |
| runtime ABI. | |
| * ``ELFABIVERSION_AMDGPU_PAL`` is used to specify the version of AMD PAL | |
| runtime ABI. | |
| * ``ELFABIVERSION_AMDGPU_MESA3D`` is used to specify the version of AMD MESA | |
| 3D runtime ABI. | |
| ``e_type`` | |
| Can be one of the following values: | |
| ``ET_REL`` | |
| The type produced by the AMD GPU backend compiler as it is relocatable code | |
| object. | |
| ``ET_DYN`` | |
| The type produced by the linker as it is a shared code object. | |
| The AMD HSA runtime loader requires a ``ET_DYN`` code object. | |
| ``e_machine`` | |
| The value ``EM_AMDGPU`` is used for the machine for all processors supported | |
| by the ``r600`` and ``amdgcn`` architectures (see | |
| :ref:`amdgpu-processor-table`). The specific processor is specified in the | |
| ``EF_AMDGPU_MACH`` bit field of the ``e_flags`` (see | |
| :ref:`amdgpu-elf-header-e_flags-table`). | |
| ``e_entry`` | |
| The entry point is 0 as the entry points for individual kernels must be | |
| selected in order to invoke them through AQL packets. | |
| ``e_flags`` | |
| The AMDGPU backend uses the following ELF header flags: | |
| .. table:: AMDGPU ELF Header ``e_flags`` | |
| :name: amdgpu-elf-header-e_flags-table | |
| ================================= ========== ============================= | |
| Name Value Description | |
| ================================= ========== ============================= | |
| **AMDGPU Processor Flag** See :ref:`amdgpu-processor-table`. | |
| -------------------------------------------- ----------------------------- | |
| ``EF_AMDGPU_MACH`` 0x000000ff AMDGPU processor selection | |
| mask for | |
| ``EF_AMDGPU_MACH_xxx`` values | |
| defined in | |
| :ref:`amdgpu-ef-amdgpu-mach-table`. | |
| ``EF_AMDGPU_XNACK`` 0x00000100 Indicates if the ``xnack`` | |
| target feature is | |
| enabled for all code | |
| contained in the code object. | |
| If the processor | |
| does not support the | |
| ``xnack`` target | |
| feature then must | |
| be 0. | |
| See | |
| :ref:`amdgpu-target-features`. | |
| ================================= ========== ============================= | |
| .. table:: AMDGPU ``EF_AMDGPU_MACH`` Values | |
| :name: amdgpu-ef-amdgpu-mach-table | |
| ================================= ========== ============================= | |
| Name Value Description (see | |
| :ref:`amdgpu-processor-table`) | |
| ================================= ========== ============================= | |
| ``EF_AMDGPU_MACH_NONE`` 0x000 *not specified* | |
| ``EF_AMDGPU_MACH_R600_R600`` 0x001 ``r600`` | |
| ``EF_AMDGPU_MACH_R600_R630`` 0x002 ``r630`` | |
| ``EF_AMDGPU_MACH_R600_RS880`` 0x003 ``rs880`` | |
| ``EF_AMDGPU_MACH_R600_RV670`` 0x004 ``rv670`` | |
| ``EF_AMDGPU_MACH_R600_RV710`` 0x005 ``rv710`` | |
| ``EF_AMDGPU_MACH_R600_RV730`` 0x006 ``rv730`` | |
| ``EF_AMDGPU_MACH_R600_RV770`` 0x007 ``rv770`` | |
| ``EF_AMDGPU_MACH_R600_CEDAR`` 0x008 ``cedar`` | |
| ``EF_AMDGPU_MACH_R600_CYPRESS`` 0x009 ``cypress`` | |
| ``EF_AMDGPU_MACH_R600_JUNIPER`` 0x00a ``juniper`` | |
| ``EF_AMDGPU_MACH_R600_REDWOOD`` 0x00b ``redwood`` | |
| ``EF_AMDGPU_MACH_R600_SUMO`` 0x00c ``sumo`` | |
| ``EF_AMDGPU_MACH_R600_BARTS`` 0x00d ``barts`` | |
| ``EF_AMDGPU_MACH_R600_CAICOS`` 0x00e ``caicos`` | |
| ``EF_AMDGPU_MACH_R600_CAYMAN`` 0x00f ``cayman`` | |
| ``EF_AMDGPU_MACH_R600_TURKS`` 0x010 ``turks`` | |
| *reserved* 0x011 - Reserved for ``r600`` | |
| 0x01f architecture processors. | |
| ``EF_AMDGPU_MACH_AMDGCN_GFX600`` 0x020 ``gfx600`` | |
| ``EF_AMDGPU_MACH_AMDGCN_GFX601`` 0x021 ``gfx601`` | |
| ``EF_AMDGPU_MACH_AMDGCN_GFX700`` 0x022 ``gfx700`` | |
| ``EF_AMDGPU_MACH_AMDGCN_GFX701`` 0x023 ``gfx701`` | |
| ``EF_AMDGPU_MACH_AMDGCN_GFX702`` 0x024 ``gfx702`` | |
| ``EF_AMDGPU_MACH_AMDGCN_GFX703`` 0x025 ``gfx703`` | |
| ``EF_AMDGPU_MACH_AMDGCN_GFX704`` 0x026 ``gfx704`` | |
| *reserved* 0x027 Reserved. | |
| ``EF_AMDGPU_MACH_AMDGCN_GFX801`` 0x028 ``gfx801`` | |
| ``EF_AMDGPU_MACH_AMDGCN_GFX802`` 0x029 ``gfx802`` | |
| ``EF_AMDGPU_MACH_AMDGCN_GFX803`` 0x02a ``gfx803`` | |
| ``EF_AMDGPU_MACH_AMDGCN_GFX810`` 0x02b ``gfx810`` | |
| ``EF_AMDGPU_MACH_AMDGCN_GFX900`` 0x02c ``gfx900`` | |
| ``EF_AMDGPU_MACH_AMDGCN_GFX902`` 0x02d ``gfx902`` | |
| ``EF_AMDGPU_MACH_AMDGCN_GFX904`` 0x02e ``gfx904`` | |
| ``EF_AMDGPU_MACH_AMDGCN_GFX906`` 0x02f ``gfx906`` | |
| *reserved* 0x030 Reserved. | |
| ================================= ========== ============================= | |
| Sections | |
| -------- | |
| An AMDGPU target ELF code object has the standard ELF sections which include: | |
| .. table:: AMDGPU ELF Sections | |
| :name: amdgpu-elf-sections-table | |
| ================== ================ ================================= | |
| Name Type Attributes | |
| ================== ================ ================================= | |
| ``.bss`` ``SHT_NOBITS`` ``SHF_ALLOC`` + ``SHF_WRITE`` | |
| ``.data`` ``SHT_PROGBITS`` ``SHF_ALLOC`` + ``SHF_WRITE`` | |
| ``.debug_``\ *\** ``SHT_PROGBITS`` *none* | |
| ``.dynamic`` ``SHT_DYNAMIC`` ``SHF_ALLOC`` | |
| ``.dynstr`` ``SHT_PROGBITS`` ``SHF_ALLOC`` | |
| ``.dynsym`` ``SHT_PROGBITS`` ``SHF_ALLOC`` | |
| ``.got`` ``SHT_PROGBITS`` ``SHF_ALLOC`` + ``SHF_WRITE`` | |
| ``.hash`` ``SHT_HASH`` ``SHF_ALLOC`` | |
| ``.note`` ``SHT_NOTE`` *none* | |
| ``.rela``\ *name* ``SHT_RELA`` *none* | |
| ``.rela.dyn`` ``SHT_RELA`` *none* | |
| ``.rodata`` ``SHT_PROGBITS`` ``SHF_ALLOC`` | |
| ``.shstrtab`` ``SHT_STRTAB`` *none* | |
| ``.strtab`` ``SHT_STRTAB`` *none* | |
| ``.symtab`` ``SHT_SYMTAB`` *none* | |
| ``.text`` ``SHT_PROGBITS`` ``SHF_ALLOC`` + ``SHF_EXECINSTR`` | |
| ================== ================ ================================= | |
| These sections have their standard meanings (see [ELF]_) and are only generated | |
| if needed. | |
| ``.debug``\ *\** | |
| The standard DWARF sections. See :ref:`amdgpu-dwarf` for information on the | |
| DWARF produced by the AMDGPU backend. | |
| ``.dynamic``, ``.dynstr``, ``.dynsym``, ``.hash`` | |
| The standard sections used by a dynamic loader. | |
| ``.note`` | |
| See :ref:`amdgpu-note-records` for the note records supported by the AMDGPU | |
| backend. | |
| ``.rela``\ *name*, ``.rela.dyn`` | |
| For relocatable code objects, *name* is the name of the section that the | |
| relocation records apply. For example, ``.rela.text`` is the section name for | |
| relocation records associated with the ``.text`` section. | |
| For linked shared code objects, ``.rela.dyn`` contains all the relocation | |
| records from each of the relocatable code object's ``.rela``\ *name* sections. | |
| See :ref:`amdgpu-relocation-records` for the relocation records supported by | |
| the AMDGPU backend. | |
| ``.text`` | |
| The executable machine code for the kernels and functions they call. Generated | |
| as position independent code. See :ref:`amdgpu-code-conventions` for | |
| information on conventions used in the isa generation. | |
| .. _amdgpu-note-records: | |
| Note Records | |
| ------------ | |
| As required by ``ELFCLASS32`` and ``ELFCLASS64``, minimal zero byte padding must | |
| be generated after the ``name`` field to ensure the ``desc`` field is 4 byte | |
| aligned. In addition, minimal zero byte padding must be generated to ensure the | |
| ``desc`` field size is a multiple of 4 bytes. The ``sh_addralign`` field of the | |
| ``.note`` section must be at least 4 to indicate at least 8 byte alignment. | |
| The AMDGPU backend code object uses the following ELF note records in the | |
| ``.note`` section. The *Description* column specifies the layout of the note | |
| record's ``desc`` field. All fields are consecutive bytes. Note records with | |
| variable size strings have a corresponding ``*_size`` field that specifies the | |
| number of bytes, including the terminating null character, in the string. The | |
| string(s) come immediately after the preceding fields. | |
| Additional note records can be present. | |
| .. table:: AMDGPU ELF Note Records | |
| :name: amdgpu-elf-note-records-table | |
| ===== ============================== ====================================== | |
| Name Type Description | |
| ===== ============================== ====================================== | |
| "AMD" ``NT_AMD_AMDGPU_HSA_METADATA`` <metadata null terminated string> | |
| ===== ============================== ====================================== | |
| .. | |
| .. table:: AMDGPU ELF Note Record Enumeration Values | |
| :name: amdgpu-elf-note-record-enumeration-values-table | |
| ============================== ===== | |
| Name Value | |
| ============================== ===== | |
| *reserved* 0-9 | |
| ``NT_AMD_AMDGPU_HSA_METADATA`` 10 | |
| *reserved* 11 | |
| ============================== ===== | |
| ``NT_AMD_AMDGPU_HSA_METADATA`` | |
| Specifies extensible metadata associated with the code objects executed on HSA | |
| [HSA]_ compatible runtimes such as AMD's ROCm [AMD-ROCm]_. It is required when | |
| the target triple OS is ``amdhsa`` (see :ref:`amdgpu-target-triples`). See | |
| :ref:`amdgpu-amdhsa-code-object-metadata` for the syntax of the code | |
| object metadata string. | |
| .. _amdgpu-symbols: | |
| Symbols | |
| ------- | |
| Symbols include the following: | |
| .. table:: AMDGPU ELF Symbols | |
| :name: amdgpu-elf-symbols-table | |
| ===================== ============== ============= ================== | |
| Name Type Section Description | |
| ===================== ============== ============= ================== | |
| *link-name* ``STT_OBJECT`` - ``.data`` Global variable | |
| - ``.rodata`` | |
| - ``.bss`` | |
| *link-name*\ ``.kd`` ``STT_OBJECT`` - ``.rodata`` Kernel descriptor | |
| *link-name* ``STT_FUNC`` - ``.text`` Kernel entry point | |
| ===================== ============== ============= ================== | |
| Global variable | |
| Global variables both used and defined by the compilation unit. | |
| If the symbol is defined in the compilation unit then it is allocated in the | |
| appropriate section according to if it has initialized data or is readonly. | |
| If the symbol is external then its section is ``STN_UNDEF`` and the loader | |
| will resolve relocations using the definition provided by another code object | |
| or explicitly defined by the runtime. | |
| All global symbols, whether defined in the compilation unit or external, are | |
| accessed by the machine code indirectly through a GOT table entry. This | |
| allows them to be preemptable. The GOT table is only supported when the target | |
| triple OS is ``amdhsa`` (see :ref:`amdgpu-target-triples`). | |
| .. TODO | |
| Add description of linked shared object symbols. Seems undefined symbols | |
| are marked as STT_NOTYPE. | |
| Kernel descriptor | |
| Every HSA kernel has an associated kernel descriptor. It is the address of the | |
| kernel descriptor that is used in the AQL dispatch packet used to invoke the | |
| kernel, not the kernel entry point. The layout of the HSA kernel descriptor is | |
| defined in :ref:`amdgpu-amdhsa-kernel-descriptor`. | |
| Kernel entry point | |
| Every HSA kernel also has a symbol for its machine code entry point. | |
| .. _amdgpu-relocation-records: | |
| Relocation Records | |
| ------------------ | |
| AMDGPU backend generates ``Elf64_Rela`` relocation records. Supported | |
| relocatable fields are: | |
| ``word32`` | |
| This specifies a 32-bit field occupying 4 bytes with arbitrary byte | |
| alignment. These values use the same byte order as other word values in the | |
| AMD GPU architecture. | |
| ``word64`` | |
| This specifies a 64-bit field occupying 8 bytes with arbitrary byte | |
| alignment. These values use the same byte order as other word values in the | |
| AMD GPU architecture. | |
| Following notations are used for specifying relocation calculations: | |
| **A** | |
| Represents the addend used to compute the value of the relocatable field. | |
| **G** | |
| Represents the offset into the global offset table at which the relocation | |
| entry's symbol will reside during execution. | |
| **GOT** | |
| Represents the address of the global offset table. | |
| **P** | |
| Represents the place (section offset for ``et_rel`` or address for ``et_dyn``) | |
| of the storage unit being relocated (computed using ``r_offset``). | |
| **S** | |
| Represents the value of the symbol whose index resides in the relocation | |
| entry. Relocations not using this must specify a symbol index of ``STN_UNDEF``. | |
| **B** | |
| Represents the base address of a loaded executable or shared object which is | |
| the difference between the ELF address and the actual load address. Relocations | |
| using this are only valid in executable or shared objects. | |
| The following relocation types are supported: | |
| .. table:: AMDGPU ELF Relocation Records | |
| :name: amdgpu-elf-relocation-records-table | |
| ========================== ======= ===== ========== ============================== | |
| Relocation Type Kind Value Field Calculation | |
| ========================== ======= ===== ========== ============================== | |
| ``R_AMDGPU_NONE`` 0 *none* *none* | |
| ``R_AMDGPU_ABS32_LO`` Static, 1 ``word32`` (S + A) & 0xFFFFFFFF | |
| Dynamic | |
| ``R_AMDGPU_ABS32_HI`` Static, 2 ``word32`` (S + A) >> 32 | |
| Dynamic | |
| ``R_AMDGPU_ABS64`` Static, 3 ``word64`` S + A | |
| Dynamic | |
| ``R_AMDGPU_REL32`` Static 4 ``word32`` S + A - P | |
| ``R_AMDGPU_REL64`` Static 5 ``word64`` S + A - P | |
| ``R_AMDGPU_ABS32`` Static, 6 ``word32`` S + A | |
| Dynamic | |
| ``R_AMDGPU_GOTPCREL`` Static 7 ``word32`` G + GOT + A - P | |
| ``R_AMDGPU_GOTPCREL32_LO`` Static 8 ``word32`` (G + GOT + A - P) & 0xFFFFFFFF | |
| ``R_AMDGPU_GOTPCREL32_HI`` Static 9 ``word32`` (G + GOT + A - P) >> 32 | |
| ``R_AMDGPU_REL32_LO`` Static 10 ``word32`` (S + A - P) & 0xFFFFFFFF | |
| ``R_AMDGPU_REL32_HI`` Static 11 ``word32`` (S + A - P) >> 32 | |
| *reserved* 12 | |
| ``R_AMDGPU_RELATIVE64`` Dynamic 13 ``word64`` B + A | |
| ========================== ======= ===== ========== ============================== | |
| ``R_AMDGPU_ABS32_LO`` and ``R_AMDGPU_ABS32_HI`` are only supported by | |
| the ``mesa3d`` OS, which does not support ``R_AMDGPU_ABS64``. | |
| There is no current OS loader support for 32 bit programs and so | |
| ``R_AMDGPU_ABS32`` is not used. | |
| .. _amdgpu-dwarf: | |
| DWARF | |
| ----- | |
| Standard DWARF [DWARF]_ Version 5 sections can be generated. These contain | |
| information that maps the code object executable code and data to the source | |
| language constructs. It can be used by tools such as debuggers and profilers. | |
| Address Space Mapping | |
| ~~~~~~~~~~~~~~~~~~~~~ | |
| The following address space mapping is used: | |
| .. table:: AMDGPU DWARF Address Space Mapping | |
| :name: amdgpu-dwarf-address-space-mapping-table | |
| =================== ================= | |
| DWARF Address Space Memory Space | |
| =================== ================= | |
| 1 Private (Scratch) | |
| 2 Local (group/LDS) | |
| *omitted* Global | |
| *omitted* Constant | |
| *omitted* Generic (Flat) | |
| *not supported* Region (GDS) | |
| =================== ================= | |
| See :ref:`amdgpu-address-spaces` for information on the memory space terminology | |
| used in the table. | |
| An ``address_class`` attribute is generated on pointer type DIEs to specify the | |
| DWARF address space of the value of the pointer when it is in the *private* or | |
| *local* address space. Otherwise the attribute is omitted. | |
| An ``XDEREF`` operation is generated in location list expressions for variables | |
| that are allocated in the *private* and *local* address space. Otherwise no | |
| ``XDREF`` is omitted. | |
| Register Mapping | |
| ~~~~~~~~~~~~~~~~ | |
| *This section is WIP.* | |
| .. TODO | |
| Define DWARF register enumeration. | |
| If want to present a wavefront state then should expose vector registers as | |
| 64 wide (rather than per work-item view that LLVM uses). Either as separate | |
| registers, or a 64x4 byte single register. In either case use a new LANE op | |
| (akin to XDREF) to select the current lane usage in a location | |
| expression. This would also allow scalar register spilling to vector register | |
| lanes to be expressed (currently no debug information is being generated for | |
| spilling). If choose a wide single register approach then use LANE in | |
| conjunction with PIECE operation to select the dword part of the register for | |
| the current lane. If the separate register approach then use LANE to select | |
| the register. | |
| Source Text | |
| ~~~~~~~~~~~ | |
| Source text for online-compiled programs (e.g. those compiled by the OpenCL | |
| runtime) may be embedded into the DWARF v5 line table using the ``clang | |
| -gembed-source`` option, described in table :ref:`amdgpu-debug-options`. | |
| For example: | |
| ``-gembed-source`` | |
| Enable the embedded source DWARF v5 extension. | |
| ``-gno-embed-source`` | |
| Disable the embedded source DWARF v5 extension. | |
| .. table:: AMDGPU Debug Options | |
| :name: amdgpu-debug-options | |
| ==================== ================================================== | |
| Debug Flag Description | |
| ==================== ================================================== | |
| -g[no-]embed-source Enable/disable embedding source text in DWARF | |
| debug sections. Useful for environments where | |
| source cannot be written to disk, such as | |
| when performing online compilation. | |
| ==================== ================================================== | |
| This option enables one extended content types in the DWARF v5 Line Number | |
| Program Header, which is used to encode embedded source. | |
| .. table:: AMDGPU DWARF Line Number Program Header Extended Content Types | |
| :name: amdgpu-dwarf-extended-content-types | |
| ============================ ====================== | |
| Content Type Form | |
| ============================ ====================== | |
| ``DW_LNCT_LLVM_source`` ``DW_FORM_line_strp`` | |
| ============================ ====================== | |
| The source field will contain the UTF-8 encoded, null-terminated source text | |
| with ``'\n'`` line endings. When the source field is present, consumers can use | |
| the embedded source instead of attempting to discover the source on disk. When | |
| the source field is absent, consumers can access the file to get the source | |
| text. | |
| The above content type appears in the ``file_name_entry_format`` field of the | |
| line table prologue, and its corresponding value appear in the ``file_names`` | |
| field. The current encoding of the content type is documented in table | |
| :ref:`amdgpu-dwarf-extended-content-types-encoding` | |
| .. table:: AMDGPU DWARF Line Number Program Header Extended Content Types Encoding | |
| :name: amdgpu-dwarf-extended-content-types-encoding | |
| ============================ ==================== | |
| Content Type Value | |
| ============================ ==================== | |
| ``DW_LNCT_LLVM_source`` 0x2001 | |
| ============================ ==================== | |
| .. _amdgpu-code-conventions: | |
| Code Conventions | |
| ================ | |
| This section provides code conventions used for each supported target triple OS | |
| (see :ref:`amdgpu-target-triples`). | |
| AMDHSA | |
| ------ | |
| This section provides code conventions used when the target triple OS is | |
| ``amdhsa`` (see :ref:`amdgpu-target-triples`). | |
| .. _amdgpu-amdhsa-code-object-target-identification: | |
| Code Object Target Identification | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| The AMDHSA OS uses the following syntax to specify the code object | |
| target as a single string: | |
| ``<Architecture>-<Vendor>-<OS>-<Environment>-<Processor><Target Features>`` | |
| Where: | |
| - ``<Architecture>``, ``<Vendor>``, ``<OS>`` and ``<Environment>`` | |
| are the same as the *Target Triple* (see | |
| :ref:`amdgpu-target-triples`). | |
| - ``<Processor>`` is the same as the *Processor* (see | |
| :ref:`amdgpu-processors`). | |
| - ``<Target Features>`` is a list of the enabled *Target Features* | |
| (see :ref:`amdgpu-target-features`), each prefixed by a plus, that | |
| apply to *Processor*. The list must be in the same order as listed | |
| in the table :ref:`amdgpu-target-feature-table`. Note that *Target | |
| Features* must be included in the list if they are enabled even if | |
| that is the default for *Processor*. | |
| For example: | |
| ``"amdgcn-amd-amdhsa--gfx902+xnack"`` | |
| .. _amdgpu-amdhsa-code-object-metadata: | |
| Code Object Metadata | |
| ~~~~~~~~~~~~~~~~~~~~ | |
| The code object metadata specifies extensible metadata associated with the code | |
| objects executed on HSA [HSA]_ compatible runtimes such as AMD's ROCm | |
| [AMD-ROCm]_. It is specified by the ``NT_AMD_AMDGPU_HSA_METADATA`` note record | |
| (see :ref:`amdgpu-note-records`) and is required when the target triple OS is | |
| ``amdhsa`` (see :ref:`amdgpu-target-triples`). It must contain the minimum | |
| information necessary to support the ROCM kernel queries. For example, the | |
| segment sizes needed in a dispatch packet. In addition, a high level language | |
| runtime may require other information to be included. For example, the AMD | |
| OpenCL runtime records kernel argument information. | |
| The metadata is specified as a YAML formatted string (see [YAML]_ and | |
| :doc:`YamlIO`). | |
| .. TODO | |
| Is the string null terminated? It probably should not if YAML allows it to | |
| contain null characters, otherwise it should be. | |
| The metadata is represented as a single YAML document comprised of the mapping | |
| defined in table :ref:`amdgpu-amdhsa-code-object-metadata-mapping-table` and | |
| referenced tables. | |
| For boolean values, the string values of ``false`` and ``true`` are used for | |
| false and true respectively. | |
| Additional information can be added to the mappings. To avoid conflicts, any | |
| non-AMD key names should be prefixed by "*vendor-name*.". | |
| .. table:: AMDHSA Code Object Metadata Mapping | |
| :name: amdgpu-amdhsa-code-object-metadata-mapping-table | |
| ========== ============== ========= ======================================= | |
| String Key Value Type Required? Description | |
| ========== ============== ========= ======================================= | |
| "Version" sequence of Required - The first integer is the major | |
| 2 integers version. Currently 1. | |
| - The second integer is the minor | |
| version. Currently 0. | |
| "Printf" sequence of Each string is encoded information | |
| strings about a printf function call. The | |
| encoded information is organized as | |
| fields separated by colon (':'): | |
| ``ID:N:S[0]:S[1]:...:S[N-1]:FormatString`` | |
| where: | |
| ``ID`` | |
| A 32 bit integer as a unique id for | |
| each printf function call | |
| ``N`` | |
| A 32 bit integer equal to the number | |
| of arguments of printf function call | |
| minus 1 | |
| ``S[i]`` (where i = 0, 1, ... , N-1) | |
| 32 bit integers for the size in bytes | |
| of the i-th FormatString argument of | |
| the printf function call | |
| FormatString | |
| The format string passed to the | |
| printf function call. | |
| "Kernels" sequence of Required Sequence of the mappings for each | |
| mapping kernel in the code object. See | |
| :ref:`amdgpu-amdhsa-code-object-kernel-metadata-mapping-table` | |
| for the definition of the mapping. | |
| ========== ============== ========= ======================================= | |
| .. | |
| .. table:: AMDHSA Code Object Kernel Metadata Mapping | |
| :name: amdgpu-amdhsa-code-object-kernel-metadata-mapping-table | |
| ================= ============== ========= ================================ | |
| String Key Value Type Required? Description | |
| ================= ============== ========= ================================ | |
| "Name" string Required Source name of the kernel. | |
| "SymbolName" string Required Name of the kernel | |
| descriptor ELF symbol. | |
| "Language" string Source language of the kernel. | |
| Values include: | |
| - "OpenCL C" | |
| - "OpenCL C++" | |
| - "HCC" | |
| - "OpenMP" | |
| "LanguageVersion" sequence of - The first integer is the major | |
| 2 integers version. | |
| - The second integer is the | |
| minor version. | |
| "Attrs" mapping Mapping of kernel attributes. | |
| See | |
| :ref:`amdgpu-amdhsa-code-object-kernel-attribute-metadata-mapping-table` | |
| for the mapping definition. | |
| "Args" sequence of Sequence of mappings of the | |
| mapping kernel arguments. See | |
| :ref:`amdgpu-amdhsa-code-object-kernel-argument-metadata-mapping-table` | |
| for the definition of the mapping. | |
| "CodeProps" mapping Mapping of properties related to | |
| the kernel code. See | |
| :ref:`amdgpu-amdhsa-code-object-kernel-code-properties-metadata-mapping-table` | |
| for the mapping definition. | |
| ================= ============== ========= ================================ | |
| .. | |
| .. table:: AMDHSA Code Object Kernel Attribute Metadata Mapping | |
| :name: amdgpu-amdhsa-code-object-kernel-attribute-metadata-mapping-table | |
| =================== ============== ========= ============================== | |
| String Key Value Type Required? Description | |
| =================== ============== ========= ============================== | |
| "ReqdWorkGroupSize" sequence of If not 0, 0, 0 then all values | |
| 3 integers must be >=1 and the dispatch | |
| work-group size X, Y, Z must | |
| correspond to the specified | |
| values. Defaults to 0, 0, 0. | |
| Corresponds to the OpenCL | |
| ``reqd_work_group_size`` | |
| attribute. | |
| "WorkGroupSizeHint" sequence of The dispatch work-group size | |
| 3 integers X, Y, Z is likely to be the | |
| specified values. | |
| Corresponds to the OpenCL | |
| ``work_group_size_hint`` | |
| attribute. | |
| "VecTypeHint" string The name of a scalar or vector | |
| type. | |
| Corresponds to the OpenCL | |
| ``vec_type_hint`` attribute. | |
| "RuntimeHandle" string The external symbol name | |
| associated with a kernel. | |
| OpenCL runtime allocates a | |
| global buffer for the symbol | |
| and saves the kernel's address | |
| to it, which is used for | |
| device side enqueueing. Only | |
| available for device side | |
| enqueued kernels. | |
| =================== ============== ========= ============================== | |
| .. | |
| .. table:: AMDHSA Code Object Kernel Argument Metadata Mapping | |
| :name: amdgpu-amdhsa-code-object-kernel-argument-metadata-mapping-table | |
| ================= ============== ========= ================================ | |
| String Key Value Type Required? Description | |
| ================= ============== ========= ================================ | |
| "Name" string Kernel argument name. | |
| "TypeName" string Kernel argument type name. | |
| "Size" integer Required Kernel argument size in bytes. | |
| "Align" integer Required Kernel argument alignment in | |
| bytes. Must be a power of two. | |
| "ValueKind" string Required Kernel argument kind that | |
| specifies how to set up the | |
| corresponding argument. | |
| Values include: | |
| "ByValue" | |
| The argument is copied | |
| directly into the kernarg. | |
| "GlobalBuffer" | |
| A global address space pointer | |
| to the buffer data is passed | |
| in the kernarg. | |
| "DynamicSharedPointer" | |
| A group address space pointer | |
| to dynamically allocated LDS | |
| is passed in the kernarg. | |
| "Sampler" | |
| A global address space | |
| pointer to a S# is passed in | |
| the kernarg. | |
| "Image" | |
| A global address space | |
| pointer to a T# is passed in | |
| the kernarg. | |
| "Pipe" | |
| A global address space pointer | |
| to an OpenCL pipe is passed in | |
| the kernarg. | |
| "Queue" | |
| A global address space pointer | |
| to an OpenCL device enqueue | |
| queue is passed in the | |
| kernarg. | |
| "HiddenGlobalOffsetX" | |
| The OpenCL grid dispatch | |
| global offset for the X | |
| dimension is passed in the | |
| kernarg. | |
| "HiddenGlobalOffsetY" | |
| The OpenCL grid dispatch | |
| global offset for the Y | |
| dimension is passed in the | |
| kernarg. | |
| "HiddenGlobalOffsetZ" | |
| The OpenCL grid dispatch | |
| global offset for the Z | |
| dimension is passed in the | |
| kernarg. | |
| "HiddenNone" | |
| An argument that is not used | |
| by the kernel. Space needs to | |
| be left for it, but it does | |
| not need to be set up. | |
| "HiddenPrintfBuffer" | |
| A global address space pointer | |
| to the runtime printf buffer | |
| is passed in kernarg. | |
| "HiddenDefaultQueue" | |
| A global address space pointer | |
| to the OpenCL device enqueue | |
| queue that should be used by | |
| the kernel by default is | |
| passed in the kernarg. | |
| "HiddenCompletionAction" | |
| A global address space pointer | |
| to help link enqueued kernels into | |
| the ancestor tree for determining | |
| when the parent kernel has finished. | |
| "ValueType" string Required Kernel argument value type. Only | |
| present if "ValueKind" is | |
| "ByValue". For vector data | |
| types, the value is for the | |
| element type. Values include: | |
| - "Struct" | |
| - "I8" | |
| - "U8" | |
| - "I16" | |
| - "U16" | |
| - "F16" | |
| - "I32" | |
| - "U32" | |
| - "F32" | |
| - "I64" | |
| - "U64" | |
| - "F64" | |
| .. TODO | |
| How can it be determined if a | |
| vector type, and what size | |
| vector? | |
| "PointeeAlign" integer Alignment in bytes of pointee | |
| type for pointer type kernel | |
| argument. Must be a power | |
| of 2. Only present if | |
| "ValueKind" is | |
| "DynamicSharedPointer". | |
| "AddrSpaceQual" string Kernel argument address space | |
| qualifier. Only present if | |
| "ValueKind" is "GlobalBuffer" or | |
| "DynamicSharedPointer". Values | |
| are: | |
| - "Private" | |
| - "Global" | |
| - "Constant" | |
| - "Local" | |
| - "Generic" | |
| - "Region" | |
| .. TODO | |
| Is GlobalBuffer only Global | |
| or Constant? Is | |
| DynamicSharedPointer always | |
| Local? Can HCC allow Generic? | |
| How can Private or Region | |
| ever happen? | |
| "AccQual" string Kernel argument access | |
| qualifier. Only present if | |
| "ValueKind" is "Image" or | |
| "Pipe". Values | |
| are: | |
| - "ReadOnly" | |
| - "WriteOnly" | |
| - "ReadWrite" | |
| .. TODO | |
| Does this apply to | |
| GlobalBuffer? | |
| "ActualAccQual" string The actual memory accesses | |
| performed by the kernel on the | |
| kernel argument. Only present if | |
| "ValueKind" is "GlobalBuffer", | |
| "Image", or "Pipe". This may be | |
| more restrictive than indicated | |
| by "AccQual" to reflect what the | |
| kernel actual does. If not | |
| present then the runtime must | |
| assume what is implied by | |
| "AccQual" and "IsConst". Values | |
| are: | |
| - "ReadOnly" | |
| - "WriteOnly" | |
| - "ReadWrite" | |
| "IsConst" boolean Indicates if the kernel argument | |
| is const qualified. Only present | |
| if "ValueKind" is | |
| "GlobalBuffer". | |
| "IsRestrict" boolean Indicates if the kernel argument | |
| is restrict qualified. Only | |
| present if "ValueKind" is | |
| "GlobalBuffer". | |
| "IsVolatile" boolean Indicates if the kernel argument | |
| is volatile qualified. Only | |
| present if "ValueKind" is | |
| "GlobalBuffer". | |
| "IsPipe" boolean Indicates if the kernel argument | |
| is pipe qualified. Only present | |
| if "ValueKind" is "Pipe". | |
| .. TODO | |
| Can GlobalBuffer be pipe | |
| qualified? | |
| ================= ============== ========= ================================ | |
| .. | |
| .. table:: AMDHSA Code Object Kernel Code Properties Metadata Mapping | |
| :name: amdgpu-amdhsa-code-object-kernel-code-properties-metadata-mapping-table | |
| ============================ ============== ========= ===================== | |
| String Key Value Type Required? Description | |
| ============================ ============== ========= ===================== | |
| "KernargSegmentSize" integer Required The size in bytes of | |
| the kernarg segment | |
| that holds the values | |
| of the arguments to | |
| the kernel. | |
| "GroupSegmentFixedSize" integer Required The amount of group | |
| segment memory | |
| required by a | |
| work-group in | |
| bytes. This does not | |
| include any | |
| dynamically allocated | |
| group segment memory | |
| that may be added | |
| when the kernel is | |
| dispatched. | |
| "PrivateSegmentFixedSize" integer Required The amount of fixed | |
| private address space | |
| memory required for a | |
| work-item in | |
| bytes. If the kernel | |
| uses a dynamic call | |
| stack then additional | |
| space must be added | |
| to this value for the | |
| call stack. | |
| "KernargSegmentAlign" integer Required The maximum byte | |
| alignment of | |
| arguments in the | |
| kernarg segment. Must | |
| be a power of 2. | |
| "WavefrontSize" integer Required Wavefront size. Must | |
| be a power of 2. | |
| "NumSGPRs" integer Required Number of scalar | |
| registers used by a | |
| wavefront for | |
| GFX6-GFX9. This | |
| includes the special | |
| SGPRs for VCC, Flat | |
| Scratch (GFX7-GFX9) | |
| and XNACK (for | |
| GFX8-GFX9). It does | |
| not include the 16 | |
| SGPR added if a trap | |
| handler is | |
| enabled. It is not | |
| rounded up to the | |
| allocation | |
| granularity. | |
| "NumVGPRs" integer Required Number of vector | |
| registers used by | |
| each work-item for | |
| GFX6-GFX9 | |
| "MaxFlatWorkGroupSize" integer Required Maximum flat | |
| work-group size | |
| supported by the | |
| kernel in work-items. | |
| Must be >=1 and | |
| consistent with | |
| ReqdWorkGroupSize if | |
| not 0, 0, 0. | |
| "NumSpilledSGPRs" integer Number of stores from | |
| a scalar register to | |
| a register allocator | |
| created spill | |
| location. | |
| "NumSpilledVGPRs" integer Number of stores from | |
| a vector register to | |
| a register allocator | |
| created spill | |
| location. | |
| ============================ ============== ========= ===================== | |
| .. | |
| Kernel Dispatch | |
| ~~~~~~~~~~~~~~~ | |
| The HSA architected queuing language (AQL) defines a user space memory interface | |
| that can be used to control the dispatch of kernels, in an agent independent | |
| way. An agent can have zero or more AQL queues created for it using the ROCm | |
| runtime, in which AQL packets (all of which are 64 bytes) can be placed. See the | |
| *HSA Platform System Architecture Specification* [HSA]_ for the AQL queue | |
| mechanics and packet layouts. | |
| The packet processor of a kernel agent is responsible for detecting and | |
| dispatching HSA kernels from the AQL queues associated with it. For AMD GPUs the | |
| packet processor is implemented by the hardware command processor (CP), | |
| asynchronous dispatch controller (ADC) and shader processor input controller | |
| (SPI). | |
| The ROCm runtime can be used to allocate an AQL queue object. It uses the kernel | |
| mode driver to initialize and register the AQL queue with CP. | |
| To dispatch a kernel the following actions are performed. This can occur in the | |
| CPU host program, or from an HSA kernel executing on a GPU. | |
| 1. A pointer to an AQL queue for the kernel agent on which the kernel is to be | |
| executed is obtained. | |
| 2. A pointer to the kernel descriptor (see | |
| :ref:`amdgpu-amdhsa-kernel-descriptor`) of the kernel to execute is | |
| obtained. It must be for a kernel that is contained in a code object that that | |
| was loaded by the ROCm runtime on the kernel agent with which the AQL queue is | |
| associated. | |
| 3. Space is allocated for the kernel arguments using the ROCm runtime allocator | |
| for a memory region with the kernarg property for the kernel agent that will | |
| execute the kernel. It must be at least 16 byte aligned. | |
| 4. Kernel argument values are assigned to the kernel argument memory | |
| allocation. The layout is defined in the *HSA Programmer's Language Reference* | |
| [HSA]_. For AMDGPU the kernel execution directly accesses the kernel argument | |
| memory in the same way constant memory is accessed. (Note that the HSA | |
| specification allows an implementation to copy the kernel argument contents to | |
| another location that is accessed by the kernel.) | |
| 5. An AQL kernel dispatch packet is created on the AQL queue. The ROCm runtime | |
| api uses 64 bit atomic operations to reserve space in the AQL queue for the | |
| packet. The packet must be set up, and the final write must use an atomic | |
| store release to set the packet kind to ensure the packet contents are | |
| visible to the kernel agent. AQL defines a doorbell signal mechanism to | |
| notify the kernel agent that the AQL queue has been updated. These rules, and | |
| the layout of the AQL queue and kernel dispatch packet is defined in the *HSA | |
| System Architecture Specification* [HSA]_. | |
| 6. A kernel dispatch packet includes information about the actual dispatch, | |
| such as grid and work-group size, together with information from the code | |
| object about the kernel, such as segment sizes. The ROCm runtime queries on | |
| the kernel symbol can be used to obtain the code object values which are | |
| recorded in the :ref:`amdgpu-amdhsa-code-object-metadata`. | |
| 7. CP executes micro-code and is responsible for detecting and setting up the | |
| GPU to execute the wavefronts of a kernel dispatch. | |
| 8. CP ensures that when the a wavefront starts executing the kernel machine | |
| code, the scalar general purpose registers (SGPR) and vector general purpose | |
| registers (VGPR) are set up as required by the machine code. The required | |
| setup is defined in the :ref:`amdgpu-amdhsa-kernel-descriptor`. The initial | |
| register state is defined in | |
| :ref:`amdgpu-amdhsa-initial-kernel-execution-state`. | |
| 9. The prolog of the kernel machine code (see | |
| :ref:`amdgpu-amdhsa-kernel-prolog`) sets up the machine state as necessary | |
| before continuing executing the machine code that corresponds to the kernel. | |
| 10. When the kernel dispatch has completed execution, CP signals the completion | |
| signal specified in the kernel dispatch packet if not 0. | |
| .. _amdgpu-amdhsa-memory-spaces: | |
| Memory Spaces | |
| ~~~~~~~~~~~~~ | |
| The memory space properties are: | |
| .. table:: AMDHSA Memory Spaces | |
| :name: amdgpu-amdhsa-memory-spaces-table | |
| ================= =========== ======== ======= ================== | |
| Memory Space Name HSA Segment Hardware Address NULL Value | |
| Name Name Size | |
| ================= =========== ======== ======= ================== | |
| Private private scratch 32 0x00000000 | |
| Local group LDS 32 0xFFFFFFFF | |
| Global global global 64 0x0000000000000000 | |
| Constant constant *same as 64 0x0000000000000000 | |
| global* | |
| Generic flat flat 64 0x0000000000000000 | |
| Region N/A GDS 32 *not implemented | |
| for AMDHSA* | |
| ================= =========== ======== ======= ================== | |
| The global and constant memory spaces both use global virtual addresses, which | |
| are the same virtual address space used by the CPU. However, some virtual | |
| addresses may only be accessible to the CPU, some only accessible by the GPU, | |
| and some by both. | |
| Using the constant memory space indicates that the data will not change during | |
| the execution of the kernel. This allows scalar read instructions to be | |
| used. The vector and scalar L1 caches are invalidated of volatile data before | |
| each kernel dispatch execution to allow constant memory to change values between | |
| kernel dispatches. | |
| The local memory space uses the hardware Local Data Store (LDS) which is | |
| automatically allocated when the hardware creates work-groups of wavefronts, and | |
| freed when all the wavefronts of a work-group have terminated. The data store | |
| (DS) instructions can be used to access it. | |
| The private memory space uses the hardware scratch memory support. If the kernel | |
| uses scratch, then the hardware allocates memory that is accessed using | |
| wavefront lane dword (4 byte) interleaving. The mapping used from private | |
| address to physical address is: | |
| ``wavefront-scratch-base + | |
| (private-address * wavefront-size * 4) + | |
| (wavefront-lane-id * 4)`` | |
| There are different ways that the wavefront scratch base address is determined | |
| by a wavefront (see :ref:`amdgpu-amdhsa-initial-kernel-execution-state`). This | |
| memory can be accessed in an interleaved manner using buffer instruction with | |
| the scratch buffer descriptor and per wavefront scratch offset, by the scratch | |
| instructions, or by flat instructions. If each lane of a wavefront accesses the | |
| same private address, the interleaving results in adjacent dwords being accessed | |
| and hence requires fewer cache lines to be fetched. Multi-dword access is not | |
| supported except by flat and scratch instructions in GFX9. | |
| The generic address space uses the hardware flat address support available in | |
| GFX7-GFX9. This uses two fixed ranges of virtual addresses (the private and | |
| local appertures), that are outside the range of addressible global memory, to | |
| map from a flat address to a private or local address. | |
| FLAT instructions can take a flat address and access global, private (scratch) | |
| and group (LDS) memory depending in if the address is within one of the | |
| apperture ranges. Flat access to scratch requires hardware aperture setup and | |
| setup in the kernel prologue (see :ref:`amdgpu-amdhsa-flat-scratch`). Flat | |
| access to LDS requires hardware aperture setup and M0 (GFX7-GFX8) register setup | |
| (see :ref:`amdgpu-amdhsa-m0`). | |
| To convert between a segment address and a flat address the base address of the | |
| appertures address can be used. For GFX7-GFX8 these are available in the | |
| :ref:`amdgpu-amdhsa-hsa-aql-queue` the address of which can be obtained with | |
| Queue Ptr SGPR (see :ref:`amdgpu-amdhsa-initial-kernel-execution-state`). For | |
| GFX9 the appature base addresses are directly available as inline constant | |
| registers ``SRC_SHARED_BASE/LIMIT`` and ``SRC_PRIVATE_BASE/LIMIT``. In 64 bit | |
| address mode the apperture sizes are 2^32 bytes and the base is aligned to 2^32 | |
| which makes it easier to convert from flat to segment or segment to flat. | |
| Image and Samplers | |
| ~~~~~~~~~~~~~~~~~~ | |
| Image and sample handles created by the ROCm runtime are 64 bit addresses of a | |
| hardware 32 byte V# and 48 byte S# object respectively. In order to support the | |
| HSA ``query_sampler`` operations two extra dwords are used to store the HSA BRIG | |
| enumeration values for the queries that are not trivially deducible from the S# | |
| representation. | |
| HSA Signals | |
| ~~~~~~~~~~~ | |
| HSA signal handles created by the ROCm runtime are 64 bit addresses of a | |
| structure allocated in memory accessible from both the CPU and GPU. The | |
| structure is defined by the ROCm runtime and subject to change between releases | |
| (see [AMD-ROCm-github]_). | |
| .. _amdgpu-amdhsa-hsa-aql-queue: | |
| HSA AQL Queue | |
| ~~~~~~~~~~~~~ | |
| The HSA AQL queue structure is defined by the ROCm runtime and subject to change | |
| between releases (see [AMD-ROCm-github]_). For some processors it contains | |
| fields needed to implement certain language features such as the flat address | |
| aperture bases. It also contains fields used by CP such as managing the | |
| allocation of scratch memory. | |
| .. _amdgpu-amdhsa-kernel-descriptor: | |
| Kernel Descriptor | |
| ~~~~~~~~~~~~~~~~~ | |
| A kernel descriptor consists of the information needed by CP to initiate the | |
| execution of a kernel, including the entry point address of the machine code | |
| that implements the kernel. | |
| Kernel Descriptor for GFX6-GFX9 | |
| +++++++++++++++++++++++++++++++ | |
| CP microcode requires the Kernel descriptor to be allocated on 64 byte | |
| alignment. | |
| .. table:: Kernel Descriptor for GFX6-GFX9 | |
| :name: amdgpu-amdhsa-kernel-descriptor-gfx6-gfx9-table | |
| ======= ======= =============================== ============================ | |
| Bits Size Field Name Description | |
| ======= ======= =============================== ============================ | |
| 31:0 4 bytes GROUP_SEGMENT_FIXED_SIZE The amount of fixed local | |
| address space memory | |
| required for a work-group | |
| in bytes. This does not | |
| include any dynamically | |
| allocated local address | |
| space memory that may be | |
| added when the kernel is | |
| dispatched. | |
| 63:32 4 bytes PRIVATE_SEGMENT_FIXED_SIZE The amount of fixed | |
| private address space | |
| memory required for a | |
| work-item in bytes. If | |
| is_dynamic_callstack is 1 | |
| then additional space must | |
| be added to this value for | |
| the call stack. | |
| 127:64 8 bytes Reserved, must be 0. | |
| 191:128 8 bytes KERNEL_CODE_ENTRY_BYTE_OFFSET Byte offset (possibly | |
| negative) from base | |
| address of kernel | |
| descriptor to kernel's | |
| entry point instruction | |
| which must be 256 byte | |
| aligned. | |
| 383:192 24 Reserved, must be 0. | |
| bytes | |
| 415:384 4 bytes COMPUTE_PGM_RSRC1 Compute Shader (CS) | |
| program settings used by | |
| CP to set up | |
| ``COMPUTE_PGM_RSRC1`` | |
| configuration | |
| register. See | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc1-gfx6-gfx9-table`. | |
| 447:416 4 bytes COMPUTE_PGM_RSRC2 Compute Shader (CS) | |
| program settings used by | |
| CP to set up | |
| ``COMPUTE_PGM_RSRC2`` | |
| configuration | |
| register. See | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc2-gfx6-gfx9-table`. | |
| 448 1 bit ENABLE_SGPR_PRIVATE_SEGMENT Enable the setup of the | |
| _BUFFER SGPR user data registers | |
| (see | |
| :ref:`amdgpu-amdhsa-initial-kernel-execution-state`). | |
| The total number of SGPR | |
| user data registers | |
| requested must not exceed | |
| 16 and match value in | |
| ``compute_pgm_rsrc2.user_sgpr.user_sgpr_count``. | |
| Any requests beyond 16 | |
| will be ignored. | |
| 449 1 bit ENABLE_SGPR_DISPATCH_PTR *see above* | |
| 450 1 bit ENABLE_SGPR_QUEUE_PTR *see above* | |
| 451 1 bit ENABLE_SGPR_KERNARG_SEGMENT_PTR *see above* | |
| 452 1 bit ENABLE_SGPR_DISPATCH_ID *see above* | |
| 453 1 bit ENABLE_SGPR_FLAT_SCRATCH_INIT *see above* | |
| 454 1 bit ENABLE_SGPR_PRIVATE_SEGMENT *see above* | |
| _SIZE | |
| 455 1 bit Reserved, must be 0. | |
| 511:456 8 bytes Reserved, must be 0. | |
| 512 **Total size 64 bytes.** | |
| ======= ==================================================================== | |
| .. | |
| .. table:: compute_pgm_rsrc1 for GFX6-GFX9 | |
| :name: amdgpu-amdhsa-compute_pgm_rsrc1-gfx6-gfx9-table | |
| ======= ======= =============================== =========================================================================== | |
| Bits Size Field Name Description | |
| ======= ======= =============================== =========================================================================== | |
| 5:0 6 bits GRANULATED_WORKITEM_VGPR_COUNT Number of vector register | |
| blocks used by each work-item; | |
| granularity is device | |
| specific: | |
| GFX6-GFX9 | |
| - vgprs_used 0..256 | |
| - max(0, ceil(vgprs_used / 4) - 1) | |
| Where vgprs_used is defined | |
| as the highest VGPR number | |
| explicitly referenced plus | |
| one. | |
| Used by CP to set up | |
| ``COMPUTE_PGM_RSRC1.VGPRS``. | |
| The | |
| :ref:`amdgpu-assembler` | |
| calculates this | |
| automatically for the | |
| selected processor from | |
| values provided to the | |
| `.amdhsa_kernel` directive | |
| by the | |
| `.amdhsa_next_free_vgpr` | |
| nested directive (see | |
| :ref:`amdhsa-kernel-directives-table`). | |
| 9:6 4 bits GRANULATED_WAVEFRONT_SGPR_COUNT Number of scalar register | |
| blocks used by a wavefront; | |
| granularity is device | |
| specific: | |
| GFX6-GFX8 | |
| - sgprs_used 0..112 | |
| - max(0, ceil(sgprs_used / 8) - 1) | |
| GFX9 | |
| - sgprs_used 0..112 | |
| - 2 * max(0, ceil(sgprs_used / 16) - 1) | |
| Where sgprs_used is | |
| defined as the highest | |
| SGPR number explicitly | |
| referenced plus one, plus | |
| a target-specific number | |
| of additional special | |
| SGPRs for VCC, | |
| FLAT_SCRATCH (GFX7+) and | |
| XNACK_MASK (GFX8+), and | |
| any additional | |
| target-specific | |
| limitations. It does not | |
| include the 16 SGPRs added | |
| if a trap handler is | |
| enabled. | |
| The target-specific | |
| limitations and special | |
| SGPR layout are defined in | |
| the hardware | |
| documentation, which can | |
| be found in the | |
| :ref:`amdgpu-processors` | |
| table. | |
| Used by CP to set up | |
| ``COMPUTE_PGM_RSRC1.SGPRS``. | |
| The | |
| :ref:`amdgpu-assembler` | |
| calculates this | |
| automatically for the | |
| selected processor from | |
| values provided to the | |
| `.amdhsa_kernel` directive | |
| by the | |
| `.amdhsa_next_free_sgpr` | |
| and `.amdhsa_reserve_*` | |
| nested directives (see | |
| :ref:`amdhsa-kernel-directives-table`). | |
| 11:10 2 bits PRIORITY Must be 0. | |
| Start executing wavefront | |
| at the specified priority. | |
| CP is responsible for | |
| filling in | |
| ``COMPUTE_PGM_RSRC1.PRIORITY``. | |
| 13:12 2 bits FLOAT_ROUND_MODE_32 Wavefront starts execution | |
| with specified rounding | |
| mode for single (32 | |
| bit) floating point | |
| precision floating point | |
| operations. | |
| Floating point rounding | |
| mode values are defined in | |
| :ref:`amdgpu-amdhsa-floating-point-rounding-mode-enumeration-values-table`. | |
| Used by CP to set up | |
| ``COMPUTE_PGM_RSRC1.FLOAT_MODE``. | |
| 15:14 2 bits FLOAT_ROUND_MODE_16_64 Wavefront starts execution | |
| with specified rounding | |
| denorm mode for half/double (16 | |
| and 64 bit) floating point | |
| precision floating point | |
| operations. | |
| Floating point rounding | |
| mode values are defined in | |
| :ref:`amdgpu-amdhsa-floating-point-rounding-mode-enumeration-values-table`. | |
| Used by CP to set up | |
| ``COMPUTE_PGM_RSRC1.FLOAT_MODE``. | |
| 17:16 2 bits FLOAT_DENORM_MODE_32 Wavefront starts execution | |
| with specified denorm mode | |
| for single (32 | |
| bit) floating point | |
| precision floating point | |
| operations. | |
| Floating point denorm mode | |
| values are defined in | |
| :ref:`amdgpu-amdhsa-floating-point-denorm-mode-enumeration-values-table`. | |
| Used by CP to set up | |
| ``COMPUTE_PGM_RSRC1.FLOAT_MODE``. | |
| 19:18 2 bits FLOAT_DENORM_MODE_16_64 Wavefront starts execution | |
| with specified denorm mode | |
| for half/double (16 | |
| and 64 bit) floating point | |
| precision floating point | |
| operations. | |
| Floating point denorm mode | |
| values are defined in | |
| :ref:`amdgpu-amdhsa-floating-point-denorm-mode-enumeration-values-table`. | |
| Used by CP to set up | |
| ``COMPUTE_PGM_RSRC1.FLOAT_MODE``. | |
| 20 1 bit PRIV Must be 0. | |
| Start executing wavefront | |
| in privilege trap handler | |
| mode. | |
| CP is responsible for | |
| filling in | |
| ``COMPUTE_PGM_RSRC1.PRIV``. | |
| 21 1 bit ENABLE_DX10_CLAMP Wavefront starts execution | |
| with DX10 clamp mode | |
| enabled. Used by the vector | |
| ALU to force DX10 style | |
| treatment of NaN's (when | |
| set, clamp NaN to zero, | |
| otherwise pass NaN | |
| through). | |
| Used by CP to set up | |
| ``COMPUTE_PGM_RSRC1.DX10_CLAMP``. | |
| 22 1 bit DEBUG_MODE Must be 0. | |
| Start executing wavefront | |
| in single step mode. | |
| CP is responsible for | |
| filling in | |
| ``COMPUTE_PGM_RSRC1.DEBUG_MODE``. | |
| 23 1 bit ENABLE_IEEE_MODE Wavefront starts execution | |
| with IEEE mode | |
| enabled. Floating point | |
| opcodes that support | |
| exception flag gathering | |
| will quiet and propagate | |
| signaling-NaN inputs per | |
| IEEE 754-2008. Min_dx10 and | |
| max_dx10 become IEEE | |
| 754-2008 compliant due to | |
| signaling-NaN propagation | |
| and quieting. | |
| Used by CP to set up | |
| ``COMPUTE_PGM_RSRC1.IEEE_MODE``. | |
| 24 1 bit BULKY Must be 0. | |
| Only one work-group allowed | |
| to execute on a compute | |
| unit. | |
| CP is responsible for | |
| filling in | |
| ``COMPUTE_PGM_RSRC1.BULKY``. | |
| 25 1 bit CDBG_USER Must be 0. | |
| Flag that can be used to | |
| control debugging code. | |
| CP is responsible for | |
| filling in | |
| ``COMPUTE_PGM_RSRC1.CDBG_USER``. | |
| 26 1 bit FP16_OVFL GFX6-GFX8 | |
| Reserved, must be 0. | |
| GFX9 | |
| Wavefront starts execution | |
| with specified fp16 overflow | |
| mode. | |
| - If 0, fp16 overflow generates | |
| +/-INF values. | |
| - If 1, fp16 overflow that is the | |
| result of an +/-INF input value | |
| or divide by 0 produces a +/-INF, | |
| otherwise clamps computed | |
| overflow to +/-MAX_FP16 as | |
| appropriate. | |
| Used by CP to set up | |
| ``COMPUTE_PGM_RSRC1.FP16_OVFL``. | |
| 31:27 5 bits Reserved, must be 0. | |
| 32 **Total size 4 bytes** | |
| ======= =================================================================================================================== | |
| .. | |
| .. table:: compute_pgm_rsrc2 for GFX6-GFX9 | |
| :name: amdgpu-amdhsa-compute_pgm_rsrc2-gfx6-gfx9-table | |
| ======= ======= =============================== =========================================================================== | |
| Bits Size Field Name Description | |
| ======= ======= =============================== =========================================================================== | |
| 0 1 bit ENABLE_SGPR_PRIVATE_SEGMENT Enable the setup of the | |
| _WAVEFRONT_OFFSET SGPR wavefront scratch offset | |
| system register (see | |
| :ref:`amdgpu-amdhsa-initial-kernel-execution-state`). | |
| Used by CP to set up | |
| ``COMPUTE_PGM_RSRC2.SCRATCH_EN``. | |
| 5:1 5 bits USER_SGPR_COUNT The total number of SGPR | |
| user data registers | |
| requested. This number must | |
| match the number of user | |
| data registers enabled. | |
| Used by CP to set up | |
| ``COMPUTE_PGM_RSRC2.USER_SGPR``. | |
| 6 1 bit ENABLE_TRAP_HANDLER Must be 0. | |
| This bit represents | |
| ``COMPUTE_PGM_RSRC2.TRAP_PRESENT``, | |
| which is set by the CP if | |
| the runtime has installed a | |
| trap handler. | |
| 7 1 bit ENABLE_SGPR_WORKGROUP_ID_X Enable the setup of the | |
| system SGPR register for | |
| the work-group id in the X | |
| dimension (see | |
| :ref:`amdgpu-amdhsa-initial-kernel-execution-state`). | |
| Used by CP to set up | |
| ``COMPUTE_PGM_RSRC2.TGID_X_EN``. | |
| 8 1 bit ENABLE_SGPR_WORKGROUP_ID_Y Enable the setup of the | |
| system SGPR register for | |
| the work-group id in the Y | |
| dimension (see | |
| :ref:`amdgpu-amdhsa-initial-kernel-execution-state`). | |
| Used by CP to set up | |
| ``COMPUTE_PGM_RSRC2.TGID_Y_EN``. | |
| 9 1 bit ENABLE_SGPR_WORKGROUP_ID_Z Enable the setup of the | |
| system SGPR register for | |
| the work-group id in the Z | |
| dimension (see | |
| :ref:`amdgpu-amdhsa-initial-kernel-execution-state`). | |
| Used by CP to set up | |
| ``COMPUTE_PGM_RSRC2.TGID_Z_EN``. | |
| 10 1 bit ENABLE_SGPR_WORKGROUP_INFO Enable the setup of the | |
| system SGPR register for | |
| work-group information (see | |
| :ref:`amdgpu-amdhsa-initial-kernel-execution-state`). | |
| Used by CP to set up | |
| ``COMPUTE_PGM_RSRC2.TGID_SIZE_EN``. | |
| 12:11 2 bits ENABLE_VGPR_WORKITEM_ID Enable the setup of the | |
| VGPR system registers used | |
| for the work-item ID. | |
| :ref:`amdgpu-amdhsa-system-vgpr-work-item-id-enumeration-values-table` | |
| defines the values. | |
| Used by CP to set up | |
| ``COMPUTE_PGM_RSRC2.TIDIG_CMP_CNT``. | |
| 13 1 bit ENABLE_EXCEPTION_ADDRESS_WATCH Must be 0. | |
| Wavefront starts execution | |
| with address watch | |
| exceptions enabled which | |
| are generated when L1 has | |
| witnessed a thread access | |
| an *address of | |
| interest*. | |
| CP is responsible for | |
| filling in the address | |
| watch bit in | |
| ``COMPUTE_PGM_RSRC2.EXCP_EN_MSB`` | |
| according to what the | |
| runtime requests. | |
| 14 1 bit ENABLE_EXCEPTION_MEMORY Must be 0. | |
| Wavefront starts execution | |
| with memory violation | |
| exceptions exceptions | |
| enabled which are generated | |
| when a memory violation has | |
| occurred for this wavefront from | |
| L1 or LDS | |
| (write-to-read-only-memory, | |
| mis-aligned atomic, LDS | |
| address out of range, | |
| illegal address, etc.). | |
| CP sets the memory | |
| violation bit in | |
| ``COMPUTE_PGM_RSRC2.EXCP_EN_MSB`` | |
| according to what the | |
| runtime requests. | |
| 23:15 9 bits GRANULATED_LDS_SIZE Must be 0. | |
| CP uses the rounded value | |
| from the dispatch packet, | |
| not this value, as the | |
| dispatch may contain | |
| dynamically allocated group | |
| segment memory. CP writes | |
| directly to | |
| ``COMPUTE_PGM_RSRC2.LDS_SIZE``. | |
| Amount of group segment | |
| (LDS) to allocate for each | |
| work-group. Granularity is | |
| device specific: | |
| GFX6: | |
| roundup(lds-size / (64 * 4)) | |
| GFX7-GFX9: | |
| roundup(lds-size / (128 * 4)) | |
| 24 1 bit ENABLE_EXCEPTION_IEEE_754_FP Wavefront starts execution | |
| _INVALID_OPERATION with specified exceptions | |
| enabled. | |
| Used by CP to set up | |
| ``COMPUTE_PGM_RSRC2.EXCP_EN`` | |
| (set from bits 0..6). | |
| IEEE 754 FP Invalid | |
| Operation | |
| 25 1 bit ENABLE_EXCEPTION_FP_DENORMAL FP Denormal one or more | |
| _SOURCE input operands is a | |
| denormal number | |
| 26 1 bit ENABLE_EXCEPTION_IEEE_754_FP IEEE 754 FP Division by | |
| _DIVISION_BY_ZERO Zero | |
| 27 1 bit ENABLE_EXCEPTION_IEEE_754_FP IEEE 754 FP FP Overflow | |
| _OVERFLOW | |
| 28 1 bit ENABLE_EXCEPTION_IEEE_754_FP IEEE 754 FP Underflow | |
| _UNDERFLOW | |
| 29 1 bit ENABLE_EXCEPTION_IEEE_754_FP IEEE 754 FP Inexact | |
| _INEXACT | |
| 30 1 bit ENABLE_EXCEPTION_INT_DIVIDE_BY Integer Division by Zero | |
| _ZERO (rcp_iflag_f32 instruction | |
| only) | |
| 31 1 bit Reserved, must be 0. | |
| 32 **Total size 4 bytes.** | |
| ======= =================================================================================================================== | |
| .. | |
| .. table:: Floating Point Rounding Mode Enumeration Values | |
| :name: amdgpu-amdhsa-floating-point-rounding-mode-enumeration-values-table | |
| ====================================== ===== ============================== | |
| Enumeration Name Value Description | |
| ====================================== ===== ============================== | |
| FLOAT_ROUND_MODE_NEAR_EVEN 0 Round Ties To Even | |
| FLOAT_ROUND_MODE_PLUS_INFINITY 1 Round Toward +infinity | |
| FLOAT_ROUND_MODE_MINUS_INFINITY 2 Round Toward -infinity | |
| FLOAT_ROUND_MODE_ZERO 3 Round Toward 0 | |
| ====================================== ===== ============================== | |
| .. | |
| .. table:: Floating Point Denorm Mode Enumeration Values | |
| :name: amdgpu-amdhsa-floating-point-denorm-mode-enumeration-values-table | |
| ====================================== ===== ============================== | |
| Enumeration Name Value Description | |
| ====================================== ===== ============================== | |
| FLOAT_DENORM_MODE_FLUSH_SRC_DST 0 Flush Source and Destination | |
| Denorms | |
| FLOAT_DENORM_MODE_FLUSH_DST 1 Flush Output Denorms | |
| FLOAT_DENORM_MODE_FLUSH_SRC 2 Flush Source Denorms | |
| FLOAT_DENORM_MODE_FLUSH_NONE 3 No Flush | |
| ====================================== ===== ============================== | |
| .. | |
| .. table:: System VGPR Work-Item ID Enumeration Values | |
| :name: amdgpu-amdhsa-system-vgpr-work-item-id-enumeration-values-table | |
| ======================================== ===== ============================ | |
| Enumeration Name Value Description | |
| ======================================== ===== ============================ | |
| SYSTEM_VGPR_WORKITEM_ID_X 0 Set work-item X dimension | |
| ID. | |
| SYSTEM_VGPR_WORKITEM_ID_X_Y 1 Set work-item X and Y | |
| dimensions ID. | |
| SYSTEM_VGPR_WORKITEM_ID_X_Y_Z 2 Set work-item X, Y and Z | |
| dimensions ID. | |
| SYSTEM_VGPR_WORKITEM_ID_UNDEFINED 3 Undefined. | |
| ======================================== ===== ============================ | |
| .. _amdgpu-amdhsa-initial-kernel-execution-state: | |
| Initial Kernel Execution State | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| This section defines the register state that will be set up by the packet | |
| processor prior to the start of execution of every wavefront. This is limited by | |
| the constraints of the hardware controllers of CP/ADC/SPI. | |
| The order of the SGPR registers is defined, but the compiler can specify which | |
| ones are actually setup in the kernel descriptor using the ``enable_sgpr_*`` bit | |
| fields (see :ref:`amdgpu-amdhsa-kernel-descriptor`). The register numbers used | |
| for enabled registers are dense starting at SGPR0: the first enabled register is | |
| SGPR0, the next enabled register is SGPR1 etc.; disabled registers do not have | |
| an SGPR number. | |
| The initial SGPRs comprise up to 16 User SRGPs that are set by CP and apply to | |
| all wavefronts of the grid. It is possible to specify more than 16 User SGPRs using | |
| the ``enable_sgpr_*`` bit fields, in which case only the first 16 are actually | |
| initialized. These are then immediately followed by the System SGPRs that are | |
| set up by ADC/SPI and can have different values for each wavefront of the grid | |
| dispatch. | |
| SGPR register initial state is defined in | |
| :ref:`amdgpu-amdhsa-sgpr-register-set-up-order-table`. | |
| .. table:: SGPR Register Set Up Order | |
| :name: amdgpu-amdhsa-sgpr-register-set-up-order-table | |
| ========== ========================== ====== ============================== | |
| SGPR Order Name Number Description | |
| (kernel descriptor enable of | |
| field) SGPRs | |
| ========== ========================== ====== ============================== | |
| First Private Segment Buffer 4 V# that can be used, together | |
| (enable_sgpr_private with Scratch Wavefront Offset | |
| _segment_buffer) as an offset, to access the | |
| private memory space using a | |
| segment address. | |
| CP uses the value provided by | |
| the runtime. | |
| then Dispatch Ptr 2 64 bit address of AQL dispatch | |
| (enable_sgpr_dispatch_ptr) packet for kernel dispatch | |
| actually executing. | |
| then Queue Ptr 2 64 bit address of amd_queue_t | |
| (enable_sgpr_queue_ptr) object for AQL queue on which | |
| the dispatch packet was | |
| queued. | |
| then Kernarg Segment Ptr 2 64 bit address of Kernarg | |
| (enable_sgpr_kernarg segment. This is directly | |
| _segment_ptr) copied from the | |
| kernarg_address in the kernel | |
| dispatch packet. | |
| Having CP load it once avoids | |
| loading it at the beginning of | |
| every wavefront. | |
| then Dispatch Id 2 64 bit Dispatch ID of the | |
| (enable_sgpr_dispatch_id) dispatch packet being | |
| executed. | |
| then Flat Scratch Init 2 This is 2 SGPRs: | |
| (enable_sgpr_flat_scratch | |
| _init) GFX6 | |
| Not supported. | |
| GFX7-GFX8 | |
| The first SGPR is a 32 bit | |
| byte offset from | |
| ``SH_HIDDEN_PRIVATE_BASE_VIMID`` | |
| to per SPI base of memory | |
| for scratch for the queue | |
| executing the kernel | |
| dispatch. CP obtains this | |
| from the runtime. (The | |
| Scratch Segment Buffer base | |
| address is | |
| ``SH_HIDDEN_PRIVATE_BASE_VIMID`` | |
| plus this offset.) The value | |
| of Scratch Wavefront Offset must | |
| be added to this offset by | |
| the kernel machine code, | |
| right shifted by 8, and | |
| moved to the FLAT_SCRATCH_HI | |
| SGPR register. | |
| FLAT_SCRATCH_HI corresponds | |
| to SGPRn-4 on GFX7, and | |
| SGPRn-6 on GFX8 (where SGPRn | |
| is the highest numbered SGPR | |
| allocated to the wavefront). | |
| FLAT_SCRATCH_HI is | |
| multiplied by 256 (as it is | |
| in units of 256 bytes) and | |
| added to | |
| ``SH_HIDDEN_PRIVATE_BASE_VIMID`` | |
| to calculate the per wavefront | |
| FLAT SCRATCH BASE in flat | |
| memory instructions that | |
| access the scratch | |
| apperture. | |
| The second SGPR is 32 bit | |
| byte size of a single | |
| work-item's scratch memory | |
| usage. CP obtains this from | |
| the runtime, and it is | |
| always a multiple of DWORD. | |
| CP checks that the value in | |
| the kernel dispatch packet | |
| Private Segment Byte Size is | |
| not larger, and requests the | |
| runtime to increase the | |
| queue's scratch size if | |
| necessary. The kernel code | |
| must move it to | |
| FLAT_SCRATCH_LO which is | |
| SGPRn-3 on GFX7 and SGPRn-5 | |
| on GFX8. FLAT_SCRATCH_LO is | |
| used as the FLAT SCRATCH | |
| SIZE in flat memory | |
| instructions. Having CP load | |
| it once avoids loading it at | |
| the beginning of every | |
| wavefront. | |
| GFX9 | |
| This is the | |
| 64 bit base address of the | |
| per SPI scratch backing | |
| memory managed by SPI for | |
| the queue executing the | |
| kernel dispatch. CP obtains | |
| this from the runtime (and | |
| divides it if there are | |
| multiple Shader Arrays each | |
| with its own SPI). The value | |
| of Scratch Wavefront Offset must | |
| be added by the kernel | |
| machine code and the result | |
| moved to the FLAT_SCRATCH | |
| SGPR which is SGPRn-6 and | |
| SGPRn-5. It is used as the | |
| FLAT SCRATCH BASE in flat | |
| memory instructions. | |
| then Private Segment Size 1 The 32 bit byte size of a | |
| (enable_sgpr_private single | |
| work-item's | |
| scratch_segment_size) memory | |
| allocation. This is the | |
| value from the kernel | |
| dispatch packet Private | |
| Segment Byte Size rounded up | |
| by CP to a multiple of | |
| DWORD. | |
| Having CP load it once avoids | |
| loading it at the beginning of | |
| every wavefront. | |
| This is not used for | |
| GFX7-GFX8 since it is the same | |
| value as the second SGPR of | |
| Flat Scratch Init. However, it | |
| may be needed for GFX9 which | |
| changes the meaning of the | |
| Flat Scratch Init value. | |
| then Grid Work-Group Count X 1 32 bit count of the number of | |
| (enable_sgpr_grid work-groups in the X dimension | |
| _workgroup_count_X) for the grid being | |
| executed. Computed from the | |
| fields in the kernel dispatch | |
| packet as ((grid_size.x + | |
| workgroup_size.x - 1) / | |
| workgroup_size.x). | |
| then Grid Work-Group Count Y 1 32 bit count of the number of | |
| (enable_sgpr_grid work-groups in the Y dimension | |
| _workgroup_count_Y && for the grid being | |
| less than 16 previous executed. Computed from the | |
| SGPRs) fields in the kernel dispatch | |
| packet as ((grid_size.y + | |
| workgroup_size.y - 1) / | |
| workgroupSize.y). | |
| Only initialized if <16 | |
| previous SGPRs initialized. | |
| then Grid Work-Group Count Z 1 32 bit count of the number of | |
| (enable_sgpr_grid work-groups in the Z dimension | |
| _workgroup_count_Z && for the grid being | |
| less than 16 previous executed. Computed from the | |
| SGPRs) fields in the kernel dispatch | |
| packet as ((grid_size.z + | |
| workgroup_size.z - 1) / | |
| workgroupSize.z). | |
| Only initialized if <16 | |
| previous SGPRs initialized. | |
| then Work-Group Id X 1 32 bit work-group id in X | |
| (enable_sgpr_workgroup_id dimension of grid for | |
| _X) wavefront. | |
| then Work-Group Id Y 1 32 bit work-group id in Y | |
| (enable_sgpr_workgroup_id dimension of grid for | |
| _Y) wavefront. | |
| then Work-Group Id Z 1 32 bit work-group id in Z | |
| (enable_sgpr_workgroup_id dimension of grid for | |
| _Z) wavefront. | |
| then Work-Group Info 1 {first_wavefront, 14'b0000, | |
| (enable_sgpr_workgroup ordered_append_term[10:0], | |
| _info) threadgroup_size_in_wavefronts[5:0]} | |
| then Scratch Wavefront Offset 1 32 bit byte offset from base | |
| (enable_sgpr_private of scratch base of queue | |
| _segment_wavefront_offset) executing the kernel | |
| dispatch. Must be used as an | |
| offset with Private | |
| segment address when using | |
| Scratch Segment Buffer. It | |
| must be used to set up FLAT | |
| SCRATCH for flat addressing | |
| (see | |
| :ref:`amdgpu-amdhsa-flat-scratch`). | |
| ========== ========================== ====== ============================== | |
| The order of the VGPR registers is defined, but the compiler can specify which | |
| ones are actually setup in the kernel descriptor using the ``enable_vgpr*`` bit | |
| fields (see :ref:`amdgpu-amdhsa-kernel-descriptor`). The register numbers used | |
| for enabled registers are dense starting at VGPR0: the first enabled register is | |
| VGPR0, the next enabled register is VGPR1 etc.; disabled registers do not have a | |
| VGPR number. | |
| VGPR register initial state is defined in | |
| :ref:`amdgpu-amdhsa-vgpr-register-set-up-order-table`. | |
| .. table:: VGPR Register Set Up Order | |
| :name: amdgpu-amdhsa-vgpr-register-set-up-order-table | |
| ========== ========================== ====== ============================== | |
| VGPR Order Name Number Description | |
| (kernel descriptor enable of | |
| field) VGPRs | |
| ========== ========================== ====== ============================== | |
| First Work-Item Id X 1 32 bit work item id in X | |
| (Always initialized) dimension of work-group for | |
| wavefront lane. | |
| then Work-Item Id Y 1 32 bit work item id in Y | |
| (enable_vgpr_workitem_id dimension of work-group for | |
| > 0) wavefront lane. | |
| then Work-Item Id Z 1 32 bit work item id in Z | |
| (enable_vgpr_workitem_id dimension of work-group for | |
| > 1) wavefront lane. | |
| ========== ========================== ====== ============================== | |
| The setting of registers is done by GPU CP/ADC/SPI hardware as follows: | |
| 1. SGPRs before the Work-Group Ids are set by CP using the 16 User Data | |
| registers. | |
| 2. Work-group Id registers X, Y, Z are set by ADC which supports any | |
| combination including none. | |
| 3. Scratch Wavefront Offset is set by SPI in a per wavefront basis which is why | |
| its value cannot included with the flat scratch init value which is per queue. | |
| 4. The VGPRs are set by SPI which only supports specifying either (X), (X, Y) | |
| or (X, Y, Z). | |
| Flat Scratch register pair are adjacent SGRRs so they can be moved as a 64 bit | |
| value to the hardware required SGPRn-3 and SGPRn-4 respectively. | |
| The global segment can be accessed either using buffer instructions (GFX6 which | |
| has V# 64 bit address support), flat instructions (GFX7-GFX9), or global | |
| instructions (GFX9). | |
| If buffer operations are used then the compiler can generate a V# with the | |
| following properties: | |
| * base address of 0 | |
| * no swizzle | |
| * ATC: 1 if IOMMU present (such as APU) | |
| * ptr64: 1 | |
| * MTYPE set to support memory coherence that matches the runtime (such as CC for | |
| APU and NC for dGPU). | |
| .. _amdgpu-amdhsa-kernel-prolog: | |
| Kernel Prolog | |
| ~~~~~~~~~~~~~ | |
| .. _amdgpu-amdhsa-m0: | |
| M0 | |
| ++ | |
| GFX6-GFX8 | |
| The M0 register must be initialized with a value at least the total LDS size | |
| if the kernel may access LDS via DS or flat operations. Total LDS size is | |
| available in dispatch packet. For M0, it is also possible to use maximum | |
| possible value of LDS for given target (0x7FFF for GFX6 and 0xFFFF for | |
| GFX7-GFX8). | |
| GFX9 | |
| The M0 register is not used for range checking LDS accesses and so does not | |
| need to be initialized in the prolog. | |
| .. _amdgpu-amdhsa-flat-scratch: | |
| Flat Scratch | |
| ++++++++++++ | |
| If the kernel may use flat operations to access scratch memory, the prolog code | |
| must set up FLAT_SCRATCH register pair (FLAT_SCRATCH_LO/FLAT_SCRATCH_HI which | |
| are in SGPRn-4/SGPRn-3). Initialization uses Flat Scratch Init and Scratch Wavefront | |
| Offset SGPR registers (see :ref:`amdgpu-amdhsa-initial-kernel-execution-state`): | |
| GFX6 | |
| Flat scratch is not supported. | |
| GFX7-GFX8 | |
| 1. The low word of Flat Scratch Init is 32 bit byte offset from | |
| ``SH_HIDDEN_PRIVATE_BASE_VIMID`` to the base of scratch backing memory | |
| being managed by SPI for the queue executing the kernel dispatch. This is | |
| the same value used in the Scratch Segment Buffer V# base address. The | |
| prolog must add the value of Scratch Wavefront Offset to get the wavefront's byte | |
| scratch backing memory offset from ``SH_HIDDEN_PRIVATE_BASE_VIMID``. Since | |
| FLAT_SCRATCH_LO is in units of 256 bytes, the offset must be right shifted | |
| by 8 before moving into FLAT_SCRATCH_LO. | |
| 2. The second word of Flat Scratch Init is 32 bit byte size of a single | |
| work-items scratch memory usage. This is directly loaded from the kernel | |
| dispatch packet Private Segment Byte Size and rounded up to a multiple of | |
| DWORD. Having CP load it once avoids loading it at the beginning of every | |
| wavefront. The prolog must move it to FLAT_SCRATCH_LO for use as FLAT SCRATCH | |
| SIZE. | |
| GFX9 | |
| The Flat Scratch Init is the 64 bit address of the base of scratch backing | |
| memory being managed by SPI for the queue executing the kernel dispatch. The | |
| prolog must add the value of Scratch Wavefront Offset and moved to the FLAT_SCRATCH | |
| pair for use as the flat scratch base in flat memory instructions. | |
| .. _amdgpu-amdhsa-memory-model: | |
| Memory Model | |
| ~~~~~~~~~~~~ | |
| This section describes the mapping of LLVM memory model onto AMDGPU machine code | |
| (see :ref:`memmodel`). *The implementation is WIP.* | |
| .. TODO | |
| Update when implementation complete. | |
| The AMDGPU backend supports the memory synchronization scopes specified in | |
| :ref:`amdgpu-memory-scopes`. | |
| The code sequences used to implement the memory model are defined in table | |
| :ref:`amdgpu-amdhsa-memory-model-code-sequences-gfx6-gfx9-table`. | |
| The sequences specify the order of instructions that a single thread must | |
| execute. The ``s_waitcnt`` and ``buffer_wbinvl1_vol`` are defined with respect | |
| to other memory instructions executed by the same thread. This allows them to be | |
| moved earlier or later which can allow them to be combined with other instances | |
| of the same instruction, or hoisted/sunk out of loops to improve | |
| performance. Only the instructions related to the memory model are given; | |
| additional ``s_waitcnt`` instructions are required to ensure registers are | |
| defined before being used. These may be able to be combined with the memory | |
| model ``s_waitcnt`` instructions as described above. | |
| The AMDGPU backend supports the following memory models: | |
| HSA Memory Model [HSA]_ | |
| The HSA memory model uses a single happens-before relation for all address | |
| spaces (see :ref:`amdgpu-address-spaces`). | |
| OpenCL Memory Model [OpenCL]_ | |
| The OpenCL memory model which has separate happens-before relations for the | |
| global and local address spaces. Only a fence specifying both global and | |
| local address space, and seq_cst instructions join the relationships. Since | |
| the LLVM ``memfence`` instruction does not allow an address space to be | |
| specified the OpenCL fence has to convervatively assume both local and | |
| global address space was specified. However, optimizations can often be | |
| done to eliminate the additional ``s_waitcnt`` instructions when there are | |
| no intervening memory instructions which access the corresponding address | |
| space. The code sequences in the table indicate what can be omitted for the | |
| OpenCL memory. The target triple environment is used to determine if the | |
| source language is OpenCL (see :ref:`amdgpu-opencl`). | |
| ``ds/flat_load/store/atomic`` instructions to local memory are termed LDS | |
| operations. | |
| ``buffer/global/flat_load/store/atomic`` instructions to global memory are | |
| termed vector memory operations. | |
| For GFX6-GFX9: | |
| * Each agent has multiple compute units (CU). | |
| * Each CU has multiple SIMDs that execute wavefronts. | |
| * The wavefronts for a single work-group are executed in the same CU but may be | |
| executed by different SIMDs. | |
| * Each CU has a single LDS memory shared by the wavefronts of the work-groups | |
| executing on it. | |
| * All LDS operations of a CU are performed as wavefront wide operations in a | |
| global order and involve no caching. Completion is reported to a wavefront in | |
| execution order. | |
| * The LDS memory has multiple request queues shared by the SIMDs of a | |
| CU. Therefore, the LDS operations performed by different wavefronts of a work-group | |
| can be reordered relative to each other, which can result in reordering the | |
| visibility of vector memory operations with respect to LDS operations of other | |
| wavefronts in the same work-group. A ``s_waitcnt lgkmcnt(0)`` is required to | |
| ensure synchronization between LDS operations and vector memory operations | |
| between wavefronts of a work-group, but not between operations performed by the | |
| same wavefront. | |
| * The vector memory operations are performed as wavefront wide operations and | |
| completion is reported to a wavefront in execution order. The exception is | |
| that for GFX7-GFX9 ``flat_load/store/atomic`` instructions can report out of | |
| vector memory order if they access LDS memory, and out of LDS operation order | |
| if they access global memory. | |
| * The vector memory operations access a single vector L1 cache shared by all | |
| SIMDs a CU. Therefore, no special action is required for coherence between the | |
| lanes of a single wavefront, or for coherence between wavefronts in the same | |
| work-group. A ``buffer_wbinvl1_vol`` is required for coherence between wavefronts | |
| executing in different work-groups as they may be executing on different CUs. | |
| * The scalar memory operations access a scalar L1 cache shared by all wavefronts | |
| on a group of CUs. The scalar and vector L1 caches are not coherent. However, | |
| scalar operations are used in a restricted way so do not impact the memory | |
| model. See :ref:`amdgpu-amdhsa-memory-spaces`. | |
| * The vector and scalar memory operations use an L2 cache shared by all CUs on | |
| the same agent. | |
| * The L2 cache has independent channels to service disjoint ranges of virtual | |
| addresses. | |
| * Each CU has a separate request queue per channel. Therefore, the vector and | |
| scalar memory operations performed by wavefronts executing in different work-groups | |
| (which may be executing on different CUs) of an agent can be reordered | |
| relative to each other. A ``s_waitcnt vmcnt(0)`` is required to ensure | |
| synchronization between vector memory operations of different CUs. It ensures a | |
| previous vector memory operation has completed before executing a subsequent | |
| vector memory or LDS operation and so can be used to meet the requirements of | |
| acquire and release. | |
| * The L2 cache can be kept coherent with other agents on some targets, or ranges | |
| of virtual addresses can be set up to bypass it to ensure system coherence. | |
| Private address space uses ``buffer_load/store`` using the scratch V# (GFX6-GFX8), | |
| or ``scratch_load/store`` (GFX9). Since only a single thread is accessing the | |
| memory, atomic memory orderings are not meaningful and all accesses are treated | |
| as non-atomic. | |
| Constant address space uses ``buffer/global_load`` instructions (or equivalent | |
| scalar memory instructions). Since the constant address space contents do not | |
| change during the execution of a kernel dispatch it is not legal to perform | |
| stores, and atomic memory orderings are not meaningful and all access are | |
| treated as non-atomic. | |
| A memory synchronization scope wider than work-group is not meaningful for the | |
| group (LDS) address space and is treated as work-group. | |
| The memory model does not support the region address space which is treated as | |
| non-atomic. | |
| Acquire memory ordering is not meaningful on store atomic instructions and is | |
| treated as non-atomic. | |
| Release memory ordering is not meaningful on load atomic instructions and is | |
| treated a non-atomic. | |
| Acquire-release memory ordering is not meaningful on load or store atomic | |
| instructions and is treated as acquire and release respectively. | |
| AMDGPU backend only uses scalar memory operations to access memory that is | |
| proven to not change during the execution of the kernel dispatch. This includes | |
| constant address space and global address space for program scope const | |
| variables. Therefore the kernel machine code does not have to maintain the | |
| scalar L1 cache to ensure it is coherent with the vector L1 cache. The scalar | |
| and vector L1 caches are invalidated between kernel dispatches by CP since | |
| constant address space data may change between kernel dispatch executions. See | |
| :ref:`amdgpu-amdhsa-memory-spaces`. | |
| The one execption is if scalar writes are used to spill SGPR registers. In this | |
| case the AMDGPU backend ensures the memory location used to spill is never | |
| accessed by vector memory operations at the same time. If scalar writes are used | |
| then a ``s_dcache_wb`` is inserted before the ``s_endpgm`` and before a function | |
| return since the locations may be used for vector memory instructions by a | |
| future wavefront that uses the same scratch area, or a function call that creates a | |
| frame at the same address, respectively. There is no need for a ``s_dcache_inv`` | |
| as all scalar writes are write-before-read in the same thread. | |
| Scratch backing memory (which is used for the private address space) | |
| is accessed with MTYPE NC_NV (non-coherenent non-volatile). Since the private | |
| address space is only accessed by a single thread, and is always | |
| write-before-read, there is never a need to invalidate these entries from the L1 | |
| cache. Hence all cache invalidates are done as ``*_vol`` to only invalidate the | |
| volatile cache lines. | |
| On dGPU the kernarg backing memory is accessed as UC (uncached) to avoid needing | |
| to invalidate the L2 cache. This also causes it to be treated as | |
| non-volatile and so is not invalidated by ``*_vol``. On APU it is accessed as CC | |
| (cache coherent) and so the L2 cache will coherent with the CPU and other | |
| agents. | |
| .. table:: AMDHSA Memory Model Code Sequences GFX6-GFX9 | |
| :name: amdgpu-amdhsa-memory-model-code-sequences-gfx6-gfx9-table | |
| ============ ============ ============== ========== =============================== | |
| LLVM Instr LLVM Memory LLVM Memory AMDGPU AMDGPU Machine Code | |
| Ordering Sync Scope Address | |
| Space | |
| ============ ============ ============== ========== =============================== | |
| **Non-Atomic** | |
| ----------------------------------------------------------------------------------- | |
| load *none* *none* - global - !volatile & !nontemporal | |
| - generic | |
| - private 1. buffer/global/flat_load | |
| - constant | |
| - volatile & !nontemporal | |
| 1. buffer/global/flat_load | |
| glc=1 | |
| - nontemporal | |
| 1. buffer/global/flat_load | |
| glc=1 slc=1 | |
| load *none* *none* - local 1. ds_load | |
| store *none* *none* - global - !nontemporal | |
| - generic | |
| - private 1. buffer/global/flat_store | |
| - constant | |
| - nontemporal | |
| 1. buffer/global/flat_stote | |
| glc=1 slc=1 | |
| store *none* *none* - local 1. ds_store | |
| **Unordered Atomic** | |
| ----------------------------------------------------------------------------------- | |
| load atomic unordered *any* *any* *Same as non-atomic*. | |
| store atomic unordered *any* *any* *Same as non-atomic*. | |
| atomicrmw unordered *any* *any* *Same as monotonic | |
| atomic*. | |
| **Monotonic Atomic** | |
| ----------------------------------------------------------------------------------- | |
| load atomic monotonic - singlethread - global 1. buffer/global/flat_load | |
| - wavefront - generic | |
| - workgroup | |
| load atomic monotonic - singlethread - local 1. ds_load | |
| - wavefront | |
| - workgroup | |
| load atomic monotonic - agent - global 1. buffer/global/flat_load | |
| - system - generic glc=1 | |
| store atomic monotonic - singlethread - global 1. buffer/global/flat_store | |
| - wavefront - generic | |
| - workgroup | |
| - agent | |
| - system | |
| store atomic monotonic - singlethread - local 1. ds_store | |
| - wavefront | |
| - workgroup | |
| atomicrmw monotonic - singlethread - global 1. buffer/global/flat_atomic | |
| - wavefront - generic | |
| - workgroup | |
| - agent | |
| - system | |
| atomicrmw monotonic - singlethread - local 1. ds_atomic | |
| - wavefront | |
| - workgroup | |
| **Acquire Atomic** | |
| ----------------------------------------------------------------------------------- | |
| load atomic acquire - singlethread - global 1. buffer/global/ds/flat_load | |
| - wavefront - local | |
| - generic | |
| load atomic acquire - workgroup - global 1. buffer/global/flat_load | |
| load atomic acquire - workgroup - local 1. ds_load | |
| 2. s_waitcnt lgkmcnt(0) | |
| - If OpenCL, omit. | |
| - Must happen before | |
| any following | |
| global/generic | |
| load/load | |
| atomic/store/store | |
| atomic/atomicrmw. | |
| - Ensures any | |
| following global | |
| data read is no | |
| older than the load | |
| atomic value being | |
| acquired. | |
| load atomic acquire - workgroup - generic 1. flat_load | |
| 2. s_waitcnt lgkmcnt(0) | |
| - If OpenCL, omit. | |
| - Must happen before | |
| any following | |
| global/generic | |
| load/load | |
| atomic/store/store | |
| atomic/atomicrmw. | |
| - Ensures any | |
| following global | |
| data read is no | |
| older than the load | |
| atomic value being | |
| acquired. | |
| load atomic acquire - agent - global 1. buffer/global/flat_load | |
| - system glc=1 | |
| 2. s_waitcnt vmcnt(0) | |
| - Must happen before | |
| following | |
| buffer_wbinvl1_vol. | |
| - Ensures the load | |
| has completed | |
| before invalidating | |
| the cache. | |
| 3. buffer_wbinvl1_vol | |
| - Must happen before | |
| any following | |
| global/generic | |
| load/load | |
| atomic/atomicrmw. | |
| - Ensures that | |
| following | |
| loads will not see | |
| stale global data. | |
| load atomic acquire - agent - generic 1. flat_load glc=1 | |
| - system 2. s_waitcnt vmcnt(0) & | |
| lgkmcnt(0) | |
| - If OpenCL omit | |
| lgkmcnt(0). | |
| - Must happen before | |
| following | |
| buffer_wbinvl1_vol. | |
| - Ensures the flat_load | |
| has completed | |
| before invalidating | |
| the cache. | |
| 3. buffer_wbinvl1_vol | |
| - Must happen before | |
| any following | |
| global/generic | |
| load/load | |
| atomic/atomicrmw. | |
| - Ensures that | |
| following loads | |
| will not see stale | |
| global data. | |
| atomicrmw acquire - singlethread - global 1. buffer/global/ds/flat_atomic | |
| - wavefront - local | |
| - generic | |
| atomicrmw acquire - workgroup - global 1. buffer/global/flat_atomic | |
| atomicrmw acquire - workgroup - local 1. ds_atomic | |
| 2. waitcnt lgkmcnt(0) | |
| - If OpenCL, omit. | |
| - Must happen before | |
| any following | |
| global/generic | |
| load/load | |
| atomic/store/store | |
| atomic/atomicrmw. | |
| - Ensures any | |
| following global | |
| data read is no | |
| older than the | |
| atomicrmw value | |
| being acquired. | |
| atomicrmw acquire - workgroup - generic 1. flat_atomic | |
| 2. waitcnt lgkmcnt(0) | |
| - If OpenCL, omit. | |
| - Must happen before | |
| any following | |
| global/generic | |
| load/load | |
| atomic/store/store | |
| atomic/atomicrmw. | |
| - Ensures any | |
| following global | |
| data read is no | |
| older than the | |
| atomicrmw value | |
| being acquired. | |
| atomicrmw acquire - agent - global 1. buffer/global/flat_atomic | |
| - system 2. s_waitcnt vmcnt(0) | |
| - Must happen before | |
| following | |
| buffer_wbinvl1_vol. | |
| - Ensures the | |
| atomicrmw has | |
| completed before | |
| invalidating the | |
| cache. | |
| 3. buffer_wbinvl1_vol | |
| - Must happen before | |
| any following | |
| global/generic | |
| load/load | |
| atomic/atomicrmw. | |
| - Ensures that | |
| following loads | |
| will not see stale | |
| global data. | |
| atomicrmw acquire - agent - generic 1. flat_atomic | |
| - system 2. s_waitcnt vmcnt(0) & | |
| lgkmcnt(0) | |
| - If OpenCL, omit | |
| lgkmcnt(0). | |
| - Must happen before | |
| following | |
| buffer_wbinvl1_vol. | |
| - Ensures the | |
| atomicrmw has | |
| completed before | |
| invalidating the | |
| cache. | |
| 3. buffer_wbinvl1_vol | |
| - Must happen before | |
| any following | |
| global/generic | |
| load/load | |
| atomic/atomicrmw. | |
| - Ensures that | |
| following loads | |
| will not see stale | |
| global data. | |
| fence acquire - singlethread *none* *none* | |
| - wavefront | |
| fence acquire - workgroup *none* 1. s_waitcnt lgkmcnt(0) | |
| - If OpenCL and | |
| address space is | |
| not generic, omit. | |
| - However, since LLVM | |
| currently has no | |
| address space on | |
| the fence need to | |
| conservatively | |
| always generate. If | |
| fence had an | |
| address space then | |
| set to address | |
| space of OpenCL | |
| fence flag, or to | |
| generic if both | |
| local and global | |
| flags are | |
| specified. | |
| - Must happen after | |
| any preceding | |
| local/generic load | |
| atomic/atomicrmw | |
| with an equal or | |
| wider sync scope | |
| and memory ordering | |
| stronger than | |
| unordered (this is | |
| termed the | |
| fence-paired-atomic). | |
| - Must happen before | |
| any following | |
| global/generic | |
| load/load | |
| atomic/store/store | |
| atomic/atomicrmw. | |
| - Ensures any | |
| following global | |
| data read is no | |
| older than the | |
| value read by the | |
| fence-paired-atomic. | |
| fence acquire - agent *none* 1. s_waitcnt lgkmcnt(0) & | |
| - system vmcnt(0) | |
| - If OpenCL and | |
| address space is | |
| not generic, omit | |
| lgkmcnt(0). | |
| - However, since LLVM | |
| currently has no | |
| address space on | |
| the fence need to | |
| conservatively | |
| always generate | |
| (see comment for | |
| previous fence). | |
| - Could be split into | |
| separate s_waitcnt | |
| vmcnt(0) and | |
| s_waitcnt | |
| lgkmcnt(0) to allow | |
| them to be | |
| independently moved | |
| according to the | |
| following rules. | |
| - s_waitcnt vmcnt(0) | |
| must happen after | |
| any preceding | |
| global/generic load | |
| atomic/atomicrmw | |
| with an equal or | |
| wider sync scope | |
| and memory ordering | |
| stronger than | |
| unordered (this is | |
| termed the | |
| fence-paired-atomic). | |
| - s_waitcnt lgkmcnt(0) | |
| must happen after | |
| any preceding | |
| local/generic load | |
| atomic/atomicrmw | |
| with an equal or | |
| wider sync scope | |
| and memory ordering | |
| stronger than | |
| unordered (this is | |
| termed the | |
| fence-paired-atomic). | |
| - Must happen before | |
| the following | |
| buffer_wbinvl1_vol. | |
| - Ensures that the | |
| fence-paired atomic | |
| has completed | |
| before invalidating | |
| the | |
| cache. Therefore | |
| any following | |
| locations read must | |
| be no older than | |
| the value read by | |
| the | |
| fence-paired-atomic. | |
| 2. buffer_wbinvl1_vol | |
| - Must happen before any | |
| following global/generic | |
| load/load | |
| atomic/store/store | |
| atomic/atomicrmw. | |
| - Ensures that | |
| following loads | |
| will not see stale | |
| global data. | |
| **Release Atomic** | |
| ----------------------------------------------------------------------------------- | |
| store atomic release - singlethread - global 1. buffer/global/ds/flat_store | |
| - wavefront - local | |
| - generic | |
| store atomic release - workgroup - global 1. s_waitcnt lgkmcnt(0) | |
| - If OpenCL, omit. | |
| - Must happen after | |
| any preceding | |
| local/generic | |
| load/store/load | |
| atomic/store | |
| atomic/atomicrmw. | |
| - Must happen before | |
| the following | |
| store. | |
| - Ensures that all | |
| memory operations | |
| to local have | |
| completed before | |
| performing the | |
| store that is being | |
| released. | |
| 2. buffer/global/flat_store | |
| store atomic release - workgroup - local 1. ds_store | |
| store atomic release - workgroup - generic 1. s_waitcnt lgkmcnt(0) | |
| - If OpenCL, omit. | |
| - Must happen after | |
| any preceding | |
| local/generic | |
| load/store/load | |
| atomic/store | |
| atomic/atomicrmw. | |
| - Must happen before | |
| the following | |
| store. | |
| - Ensures that all | |
| memory operations | |
| to local have | |
| completed before | |
| performing the | |
| store that is being | |
| released. | |
| 2. flat_store | |
| store atomic release - agent - global 1. s_waitcnt lgkmcnt(0) & | |
| - system - generic vmcnt(0) | |
| - If OpenCL, omit | |
| lgkmcnt(0). | |
| - Could be split into | |
| separate s_waitcnt | |
| vmcnt(0) and | |
| s_waitcnt | |
| lgkmcnt(0) to allow | |
| them to be | |
| independently moved | |
| according to the | |
| following rules. | |
| - s_waitcnt vmcnt(0) | |
| must happen after | |
| any preceding | |
| global/generic | |
| load/store/load | |
| atomic/store | |
| atomic/atomicrmw. | |
| - s_waitcnt lgkmcnt(0) | |
| must happen after | |
| any preceding | |
| local/generic | |
| load/store/load | |
| atomic/store | |
| atomic/atomicrmw. | |
| - Must happen before | |
| the following | |
| store. | |
| - Ensures that all | |
| memory operations | |
| to memory have | |
| completed before | |
| performing the | |
| store that is being | |
| released. | |
| 2. buffer/global/ds/flat_store | |
| atomicrmw release - singlethread - global 1. buffer/global/ds/flat_atomic | |
| - wavefront - local | |
| - generic | |
| atomicrmw release - workgroup - global 1. s_waitcnt lgkmcnt(0) | |
| - If OpenCL, omit. | |
| - Must happen after | |
| any preceding | |
| local/generic | |
| load/store/load | |
| atomic/store | |
| atomic/atomicrmw. | |
| - Must happen before | |
| the following | |
| atomicrmw. | |
| - Ensures that all | |
| memory operations | |
| to local have | |
| completed before | |
| performing the | |
| atomicrmw that is | |
| being released. | |
| 2. buffer/global/flat_atomic | |
| atomicrmw release - workgroup - local 1. ds_atomic | |
| atomicrmw release - workgroup - generic 1. s_waitcnt lgkmcnt(0) | |
| - If OpenCL, omit. | |
| - Must happen after | |
| any preceding | |
| local/generic | |
| load/store/load | |
| atomic/store | |
| atomic/atomicrmw. | |
| - Must happen before | |
| the following | |
| atomicrmw. | |
| - Ensures that all | |
| memory operations | |
| to local have | |
| completed before | |
| performing the | |
| atomicrmw that is | |
| being released. | |
| 2. flat_atomic | |
| atomicrmw release - agent - global 1. s_waitcnt lgkmcnt(0) & | |
| - system - generic vmcnt(0) | |
| - If OpenCL, omit | |
| lgkmcnt(0). | |
| - Could be split into | |
| separate s_waitcnt | |
| vmcnt(0) and | |
| s_waitcnt | |
| lgkmcnt(0) to allow | |
| them to be | |
| independently moved | |
| according to the | |
| following rules. | |
| - s_waitcnt vmcnt(0) | |
| must happen after | |
| any preceding | |
| global/generic | |
| load/store/load | |
| atomic/store | |
| atomic/atomicrmw. | |
| - s_waitcnt lgkmcnt(0) | |
| must happen after | |
| any preceding | |
| local/generic | |
| load/store/load | |
| atomic/store | |
| atomic/atomicrmw. | |
| - Must happen before | |
| the following | |
| atomicrmw. | |
| - Ensures that all | |
| memory operations | |
| to global and local | |
| have completed | |
| before performing | |
| the atomicrmw that | |
| is being released. | |
| 2. buffer/global/ds/flat_atomic | |
| fence release - singlethread *none* *none* | |
| - wavefront | |
| fence release - workgroup *none* 1. s_waitcnt lgkmcnt(0) | |
| - If OpenCL and | |
| address space is | |
| not generic, omit. | |
| - However, since LLVM | |
| currently has no | |
| address space on | |
| the fence need to | |
| conservatively | |
| always generate. If | |
| fence had an | |
| address space then | |
| set to address | |
| space of OpenCL | |
| fence flag, or to | |
| generic if both | |
| local and global | |
| flags are | |
| specified. | |
| - Must happen after | |
| any preceding | |
| local/generic | |
| load/load | |
| atomic/store/store | |
| atomic/atomicrmw. | |
| - Must happen before | |
| any following store | |
| atomic/atomicrmw | |
| with an equal or | |
| wider sync scope | |
| and memory ordering | |
| stronger than | |
| unordered (this is | |
| termed the | |
| fence-paired-atomic). | |
| - Ensures that all | |
| memory operations | |
| to local have | |
| completed before | |
| performing the | |
| following | |
| fence-paired-atomic. | |
| fence release - agent *none* 1. s_waitcnt lgkmcnt(0) & | |
| - system vmcnt(0) | |
| - If OpenCL and | |
| address space is | |
| not generic, omit | |
| lgkmcnt(0). | |
| - If OpenCL and | |
| address space is | |
| local, omit | |
| vmcnt(0). | |
| - However, since LLVM | |
| currently has no | |
| address space on | |
| the fence need to | |
| conservatively | |
| always generate. If | |
| fence had an | |
| address space then | |
| set to address | |
| space of OpenCL | |
| fence flag, or to | |
| generic if both | |
| local and global | |
| flags are | |
| specified. | |
| - Could be split into | |
| separate s_waitcnt | |
| vmcnt(0) and | |
| s_waitcnt | |
| lgkmcnt(0) to allow | |
| them to be | |
| independently moved | |
| according to the | |
| following rules. | |
| - s_waitcnt vmcnt(0) | |
| must happen after | |
| any preceding | |
| global/generic | |
| load/store/load | |
| atomic/store | |
| atomic/atomicrmw. | |
| - s_waitcnt lgkmcnt(0) | |
| must happen after | |
| any preceding | |
| local/generic | |
| load/store/load | |
| atomic/store | |
| atomic/atomicrmw. | |
| - Must happen before | |
| any following store | |
| atomic/atomicrmw | |
| with an equal or | |
| wider sync scope | |
| and memory ordering | |
| stronger than | |
| unordered (this is | |
| termed the | |
| fence-paired-atomic). | |
| - Ensures that all | |
| memory operations | |
| have | |
| completed before | |
| performing the | |
| following | |
| fence-paired-atomic. | |
| **Acquire-Release Atomic** | |
| ----------------------------------------------------------------------------------- | |
| atomicrmw acq_rel - singlethread - global 1. buffer/global/ds/flat_atomic | |
| - wavefront - local | |
| - generic | |
| atomicrmw acq_rel - workgroup - global 1. s_waitcnt lgkmcnt(0) | |
| - If OpenCL, omit. | |
| - Must happen after | |
| any preceding | |
| local/generic | |
| load/store/load | |
| atomic/store | |
| atomic/atomicrmw. | |
| - Must happen before | |
| the following | |
| atomicrmw. | |
| - Ensures that all | |
| memory operations | |
| to local have | |
| completed before | |
| performing the | |
| atomicrmw that is | |
| being released. | |
| 2. buffer/global/flat_atomic | |
| atomicrmw acq_rel - workgroup - local 1. ds_atomic | |
| 2. s_waitcnt lgkmcnt(0) | |
| - If OpenCL, omit. | |
| - Must happen before | |
| any following | |
| global/generic | |
| load/load | |
| atomic/store/store | |
| atomic/atomicrmw. | |
| - Ensures any | |
| following global | |
| data read is no | |
| older than the load | |
| atomic value being | |
| acquired. | |
| atomicrmw acq_rel - workgroup - generic 1. s_waitcnt lgkmcnt(0) | |
| - If OpenCL, omit. | |
| - Must happen after | |
| any preceding | |
| local/generic | |
| load/store/load | |
| atomic/store | |
| atomic/atomicrmw. | |
| - Must happen before | |
| the following | |
| atomicrmw. | |
| - Ensures that all | |
| memory operations | |
| to local have | |
| completed before | |
| performing the | |
| atomicrmw that is | |
| being released. | |
| 2. flat_atomic | |
| 3. s_waitcnt lgkmcnt(0) | |
| - If OpenCL, omit. | |
| - Must happen before | |
| any following | |
| global/generic | |
| load/load | |
| atomic/store/store | |
| atomic/atomicrmw. | |
| - Ensures any | |
| following global | |
| data read is no | |
| older than the load | |
| atomic value being | |
| acquired. | |
| atomicrmw acq_rel - agent - global 1. s_waitcnt lgkmcnt(0) & | |
| - system vmcnt(0) | |
| - If OpenCL, omit | |
| lgkmcnt(0). | |
| - Could be split into | |
| separate s_waitcnt | |
| vmcnt(0) and | |
| s_waitcnt | |
| lgkmcnt(0) to allow | |
| them to be | |
| independently moved | |
| according to the | |
| following rules. | |
| - s_waitcnt vmcnt(0) | |
| must happen after | |
| any preceding | |
| global/generic | |
| load/store/load | |
| atomic/store | |
| atomic/atomicrmw. | |
| - s_waitcnt lgkmcnt(0) | |
| must happen after | |
| any preceding | |
| local/generic | |
| load/store/load | |
| atomic/store | |
| atomic/atomicrmw. | |
| - Must happen before | |
| the following | |
| atomicrmw. | |
| - Ensures that all | |
| memory operations | |
| to global have | |
| completed before | |
| performing the | |
| atomicrmw that is | |
| being released. | |
| 2. buffer/global/flat_atomic | |
| 3. s_waitcnt vmcnt(0) | |
| - Must happen before | |
| following | |
| buffer_wbinvl1_vol. | |
| - Ensures the | |
| atomicrmw has | |
| completed before | |
| invalidating the | |
| cache. | |
| 4. buffer_wbinvl1_vol | |
| - Must happen before | |
| any following | |
| global/generic | |
| load/load | |
| atomic/atomicrmw. | |
| - Ensures that | |
| following loads | |
| will not see stale | |
| global data. | |
| atomicrmw acq_rel - agent - generic 1. s_waitcnt lgkmcnt(0) & | |
| - system vmcnt(0) | |
| - If OpenCL, omit | |
| lgkmcnt(0). | |
| - Could be split into | |
| separate s_waitcnt | |
| vmcnt(0) and | |
| s_waitcnt | |
| lgkmcnt(0) to allow | |
| them to be | |
| independently moved | |
| according to the | |
| following rules. | |
| - s_waitcnt vmcnt(0) | |
| must happen after | |
| any preceding | |
| global/generic | |
| load/store/load | |
| atomic/store | |
| atomic/atomicrmw. | |
| - s_waitcnt lgkmcnt(0) | |
| must happen after | |
| any preceding | |
| local/generic | |
| load/store/load | |
| atomic/store | |
| atomic/atomicrmw. | |
| - Must happen before | |
| the following | |
| atomicrmw. | |
| - Ensures that all | |
| memory operations | |
| to global have | |
| completed before | |
| performing the | |
| atomicrmw that is | |
| being released. | |
| 2. flat_atomic | |
| 3. s_waitcnt vmcnt(0) & | |
| lgkmcnt(0) | |
| - If OpenCL, omit | |
| lgkmcnt(0). | |
| - Must happen before | |
| following | |
| buffer_wbinvl1_vol. | |
| - Ensures the | |
| atomicrmw has | |
| completed before | |
| invalidating the | |
| cache. | |
| 4. buffer_wbinvl1_vol | |
| - Must happen before | |
| any following | |
| global/generic | |
| load/load | |
| atomic/atomicrmw. | |
| - Ensures that | |
| following loads | |
| will not see stale | |
| global data. | |
| fence acq_rel - singlethread *none* *none* | |
| - wavefront | |
| fence acq_rel - workgroup *none* 1. s_waitcnt lgkmcnt(0) | |
| - If OpenCL and | |
| address space is | |
| not generic, omit. | |
| - However, | |
| since LLVM | |
| currently has no | |
| address space on | |
| the fence need to | |
| conservatively | |
| always generate | |
| (see comment for | |
| previous fence). | |
| - Must happen after | |
| any preceding | |
| local/generic | |
| load/load | |
| atomic/store/store | |
| atomic/atomicrmw. | |
| - Must happen before | |
| any following | |
| global/generic | |
| load/load | |
| atomic/store/store | |
| atomic/atomicrmw. | |
| - Ensures that all | |
| memory operations | |
| to local have | |
| completed before | |
| performing any | |
| following global | |
| memory operations. | |
| - Ensures that the | |
| preceding | |
| local/generic load | |
| atomic/atomicrmw | |
| with an equal or | |
| wider sync scope | |
| and memory ordering | |
| stronger than | |
| unordered (this is | |
| termed the | |
| acquire-fence-paired-atomic | |
| ) has completed | |
| before following | |
| global memory | |
| operations. This | |
| satisfies the | |
| requirements of | |
| acquire. | |
| - Ensures that all | |
| previous memory | |
| operations have | |
| completed before a | |
| following | |
| local/generic store | |
| atomic/atomicrmw | |
| with an equal or | |
| wider sync scope | |
| and memory ordering | |
| stronger than | |
| unordered (this is | |
| termed the | |
| release-fence-paired-atomic | |
| ). This satisfies the | |
| requirements of | |
| release. | |
| fence acq_rel - agent *none* 1. s_waitcnt lgkmcnt(0) & | |
| - system vmcnt(0) | |
| - If OpenCL and | |
| address space is | |
| not generic, omit | |
| lgkmcnt(0). | |
| - However, since LLVM | |
| currently has no | |
| address space on | |
| the fence need to | |
| conservatively | |
| always generate | |
| (see comment for | |
| previous fence). | |
| - Could be split into | |
| separate s_waitcnt | |
| vmcnt(0) and | |
| s_waitcnt | |
| lgkmcnt(0) to allow | |
| them to be | |
| independently moved | |
| according to the | |
| following rules. | |
| - s_waitcnt vmcnt(0) | |
| must happen after | |
| any preceding | |
| global/generic | |
| load/store/load | |
| atomic/store | |
| atomic/atomicrmw. | |
| - s_waitcnt lgkmcnt(0) | |
| must happen after | |
| any preceding | |
| local/generic | |
| load/store/load | |
| atomic/store | |
| atomic/atomicrmw. | |
| - Must happen before | |
| the following | |
| buffer_wbinvl1_vol. | |
| - Ensures that the | |
| preceding | |
| global/local/generic | |
| load | |
| atomic/atomicrmw | |
| with an equal or | |
| wider sync scope | |
| and memory ordering | |
| stronger than | |
| unordered (this is | |
| termed the | |
| acquire-fence-paired-atomic | |
| ) has completed | |
| before invalidating | |
| the cache. This | |
| satisfies the | |
| requirements of | |
| acquire. | |
| - Ensures that all | |
| previous memory | |
| operations have | |
| completed before a | |
| following | |
| global/local/generic | |
| store | |
| atomic/atomicrmw | |
| with an equal or | |
| wider sync scope | |
| and memory ordering | |
| stronger than | |
| unordered (this is | |
| termed the | |
| release-fence-paired-atomic | |
| ). This satisfies the | |
| requirements of | |
| release. | |
| 2. buffer_wbinvl1_vol | |
| - Must happen before | |
| any following | |
| global/generic | |
| load/load | |
| atomic/store/store | |
| atomic/atomicrmw. | |
| - Ensures that | |
| following loads | |
| will not see stale | |
| global data. This | |
| satisfies the | |
| requirements of | |
| acquire. | |
| **Sequential Consistent Atomic** | |
| ----------------------------------------------------------------------------------- | |
| load atomic seq_cst - singlethread - global *Same as corresponding | |
| - wavefront - local load atomic acquire, | |
| - generic except must generated | |
| all instructions even | |
| for OpenCL.* | |
| load atomic seq_cst - workgroup - global 1. s_waitcnt lgkmcnt(0) | |
| - generic | |
| - Must | |
| happen after | |
| preceding | |
| global/generic load | |
| atomic/store | |
| atomic/atomicrmw | |
| with memory | |
| ordering of seq_cst | |
| and with equal or | |
| wider sync scope. | |
| (Note that seq_cst | |
| fences have their | |
| own s_waitcnt | |
| lgkmcnt(0) and so do | |
| not need to be | |
| considered.) | |
| - Ensures any | |
| preceding | |
| sequential | |
| consistent local | |
| memory instructions | |
| have completed | |
| before executing | |
| this sequentially | |
| consistent | |
| instruction. This | |
| prevents reordering | |
| a seq_cst store | |
| followed by a | |
| seq_cst load. (Note | |
| that seq_cst is | |
| stronger than | |
| acquire/release as | |
| the reordering of | |
| load acquire | |
| followed by a store | |
| release is | |
| prevented by the | |
| waitcnt of | |
| the release, but | |
| there is nothing | |
| preventing a store | |
| release followed by | |
| load acquire from | |
| competing out of | |
| order.) | |
| 2. *Following | |
| instructions same as | |
| corresponding load | |
| atomic acquire, | |
| except must generated | |
| all instructions even | |
| for OpenCL.* | |
| load atomic seq_cst - workgroup - local *Same as corresponding | |
| load atomic acquire, | |
| except must generated | |
| all instructions even | |
| for OpenCL.* | |
| load atomic seq_cst - agent - global 1. s_waitcnt lgkmcnt(0) & | |
| - system - generic vmcnt(0) | |
| - Could be split into | |
| separate s_waitcnt | |
| vmcnt(0) | |
| and s_waitcnt | |
| lgkmcnt(0) to allow | |
| them to be | |
| independently moved | |
| according to the | |
| following rules. | |
| - waitcnt lgkmcnt(0) | |
| must happen after | |
| preceding | |
| global/generic load | |
| atomic/store | |
| atomic/atomicrmw | |
| with memory | |
| ordering of seq_cst | |
| and with equal or | |
| wider sync scope. | |
| (Note that seq_cst | |
| fences have their | |
| own s_waitcnt | |
| lgkmcnt(0) and so do | |
| not need to be | |
| considered.) | |
| - waitcnt vmcnt(0) | |
| must happen after | |
| preceding | |
| global/generic load | |
| atomic/store | |
| atomic/atomicrmw | |
| with memory | |
| ordering of seq_cst | |
| and with equal or | |
| wider sync scope. | |
| (Note that seq_cst | |
| fences have their | |
| own s_waitcnt | |
| vmcnt(0) and so do | |
| not need to be | |
| considered.) | |
| - Ensures any | |
| preceding | |
| sequential | |
| consistent global | |
| memory instructions | |
| have completed | |
| before executing | |
| this sequentially | |
| consistent | |
| instruction. This | |
| prevents reordering | |
| a seq_cst store | |
| followed by a | |
| seq_cst load. (Note | |
| that seq_cst is | |
| stronger than | |
| acquire/release as | |
| the reordering of | |
| load acquire | |
| followed by a store | |
| release is | |
| prevented by the | |
| waitcnt of | |
| the release, but | |
| there is nothing | |
| preventing a store | |
| release followed by | |
| load acquire from | |
| competing out of | |
| order.) | |
| 2. *Following | |
| instructions same as | |
| corresponding load | |
| atomic acquire, | |
| except must generated | |
| all instructions even | |
| for OpenCL.* | |
| store atomic seq_cst - singlethread - global *Same as corresponding | |
| - wavefront - local store atomic release, | |
| - workgroup - generic except must generated | |
| all instructions even | |
| for OpenCL.* | |
| store atomic seq_cst - agent - global *Same as corresponding | |
| - system - generic store atomic release, | |
| except must generated | |
| all instructions even | |
| for OpenCL.* | |
| atomicrmw seq_cst - singlethread - global *Same as corresponding | |
| - wavefront - local atomicrmw acq_rel, | |
| - workgroup - generic except must generated | |
| all instructions even | |
| for OpenCL.* | |
| atomicrmw seq_cst - agent - global *Same as corresponding | |
| - system - generic atomicrmw acq_rel, | |
| except must generated | |
| all instructions even | |
| for OpenCL.* | |
| fence seq_cst - singlethread *none* *Same as corresponding | |
| - wavefront fence acq_rel, | |
| - workgroup except must generated | |
| - agent all instructions even | |
| - system for OpenCL.* | |
| ============ ============ ============== ========== =============================== | |
| The memory order also adds the single thread optimization constrains defined in | |
| table | |
| :ref:`amdgpu-amdhsa-memory-model-single-thread-optimization-constraints-gfx6-gfx9-table`. | |
| .. table:: AMDHSA Memory Model Single Thread Optimization Constraints GFX6-GFX9 | |
| :name: amdgpu-amdhsa-memory-model-single-thread-optimization-constraints-gfx6-gfx9-table | |
| ============ ============================================================== | |
| LLVM Memory Optimization Constraints | |
| Ordering | |
| ============ ============================================================== | |
| unordered *none* | |
| monotonic *none* | |
| acquire - If a load atomic/atomicrmw then no following load/load | |
| atomic/store/ store atomic/atomicrmw/fence instruction can | |
| be moved before the acquire. | |
| - If a fence then same as load atomic, plus no preceding | |
| associated fence-paired-atomic can be moved after the fence. | |
| release - If a store atomic/atomicrmw then no preceding load/load | |
| atomic/store/ store atomic/atomicrmw/fence instruction can | |
| be moved after the release. | |
| - If a fence then same as store atomic, plus no following | |
| associated fence-paired-atomic can be moved before the | |
| fence. | |
| acq_rel Same constraints as both acquire and release. | |
| seq_cst - If a load atomic then same constraints as acquire, plus no | |
| preceding sequentially consistent load atomic/store | |
| atomic/atomicrmw/fence instruction can be moved after the | |
| seq_cst. | |
| - If a store atomic then the same constraints as release, plus | |
| no following sequentially consistent load atomic/store | |
| atomic/atomicrmw/fence instruction can be moved before the | |
| seq_cst. | |
| - If an atomicrmw/fence then same constraints as acq_rel. | |
| ============ ============================================================== | |
| Trap Handler ABI | |
| ~~~~~~~~~~~~~~~~ | |
| For code objects generated by AMDGPU backend for HSA [HSA]_ compatible runtimes | |
| (such as ROCm [AMD-ROCm]_), the runtime installs a trap handler that supports | |
| the ``s_trap`` instruction with the following usage: | |
| .. table:: AMDGPU Trap Handler for AMDHSA OS | |
| :name: amdgpu-trap-handler-for-amdhsa-os-table | |
| =================== =============== =============== ======================= | |
| Usage Code Sequence Trap Handler Description | |
| Inputs | |
| =================== =============== =============== ======================= | |
| reserved ``s_trap 0x00`` Reserved by hardware. | |
| ``debugtrap(arg)`` ``s_trap 0x01`` ``SGPR0-1``: Reserved for HSA | |
| ``queue_ptr`` ``debugtrap`` | |
| ``VGPR0``: intrinsic (not | |
| ``arg`` implemented). | |
| ``llvm.trap`` ``s_trap 0x02`` ``SGPR0-1``: Causes dispatch to be | |
| ``queue_ptr`` terminated and its | |
| associated queue put | |
| into the error state. | |
| ``llvm.debugtrap`` ``s_trap 0x03`` - If debugger not | |
| installed then | |
| behaves as a | |
| no-operation. The | |
| trap handler is | |
| entered and | |
| immediately returns | |
| to continue | |
| execution of the | |
| wavefront. | |
| - If the debugger is | |
| installed, causes | |
| the debug trap to be | |
| reported by the | |
| debugger and the | |
| wavefront is put in | |
| the halt state until | |
| resumed by the | |
| debugger. | |
| reserved ``s_trap 0x04`` Reserved. | |
| reserved ``s_trap 0x05`` Reserved. | |
| reserved ``s_trap 0x06`` Reserved. | |
| debugger breakpoint ``s_trap 0x07`` Reserved for debugger | |
| breakpoints. | |
| reserved ``s_trap 0x08`` Reserved. | |
| reserved ``s_trap 0xfe`` Reserved. | |
| reserved ``s_trap 0xff`` Reserved. | |
| =================== =============== =============== ======================= | |
| AMDPAL | |
| ------ | |
| This section provides code conventions used when the target triple OS is | |
| ``amdpal`` (see :ref:`amdgpu-target-triples`) for passing runtime parameters | |
| from the application/runtime to each invocation of a hardware shader. These | |
| parameters include both generic, application-controlled parameters called | |
| *user data* as well as system-generated parameters that are a product of the | |
| draw or dispatch execution. | |
| User Data | |
| ~~~~~~~~~ | |
| Each hardware stage has a set of 32-bit *user data registers* which can be | |
| written from a command buffer and then loaded into SGPRs when waves are launched | |
| via a subsequent dispatch or draw operation. This is the way most arguments are | |
| passed from the application/runtime to a hardware shader. | |
| Compute User Data | |
| ~~~~~~~~~~~~~~~~~ | |
| Compute shader user data mappings are simpler than graphics shaders, and have a | |
| fixed mapping. | |
| Note that there are always 10 available *user data entries* in registers - | |
| entries beyond that limit must be fetched from memory (via the spill table | |
| pointer) by the shader. | |
| .. table:: PAL Compute Shader User Data Registers | |
| :name: pal-compute-user-data-registers | |
| ============= ================================ | |
| User Register Description | |
| ============= ================================ | |
| 0 Global Internal Table (32-bit pointer) | |
| 1 Per-Shader Internal Table (32-bit pointer) | |
| 2 - 11 Application-Controlled User Data (10 32-bit values) | |
| 12 Spill Table (32-bit pointer) | |
| 13 - 14 Thread Group Count (64-bit pointer) | |
| 15 GDS Range | |
| ============= ================================ | |
| Graphics User Data | |
| ~~~~~~~~~~~~~~~~~~ | |
| Graphics pipelines support a much more flexible user data mapping: | |
| .. table:: PAL Graphics Shader User Data Registers | |
| :name: pal-graphics-user-data-registers | |
| ============= ================================ | |
| User Register Description | |
| ============= ================================ | |
| 0 Global Internal Table (32-bit pointer) | |
| + Per-Shader Internal Table (32-bit pointer) | |
| + 1-15 Application Controlled User Data | |
| (1-15 Contiguous 32-bit Values in Registers) | |
| + Spill Table (32-bit pointer) | |
| + Draw Index (First Stage Only) | |
| + Vertex Offset (First Stage Only) | |
| + Instance Offset (First Stage Only) | |
| ============= ================================ | |
| The placement of the global internal table remains fixed in the first *user | |
| data SGPR register*. Otherwise all parameters are optional, and can be mapped | |
| to any desired *user data SGPR register*, with the following regstrictions: | |
| * Draw Index, Vertex Offset, and Instance Offset can only be used by the first | |
| activehardware stage in a graphics pipeline (i.e. where the API vertex | |
| shader runs). | |
| * Application-controlled user data must be mapped into a contiguous range of | |
| user data registers. | |
| * The application-controlled user data range supports compaction remapping, so | |
| only *entries* that are actually consumed by the shader must be assigned to | |
| corresponding *registers*. Note that in order to support an efficient runtime | |
| implementation, the remapping must pack *registers* in the same order as | |
| *entries*, with unused *entries* removed. | |
| .. _pal_global_internal_table: | |
| Global Internal Table | |
| ~~~~~~~~~~~~~~~~~~~~~ | |
| The global internal table is a table of *shader resource descriptors* (SRDs) that | |
| define how certain engine-wide, runtime-managed resources should be accessed | |
| from a shader. The majority of these resources have HW-defined formats, and it | |
| is up to the compiler to write/read data as required by the target hardware. | |
| The following table illustrates the required format: | |
| .. table:: PAL Global Internal Table | |
| :name: pal-git-table | |
| ============= ================================ | |
| Offset Description | |
| ============= ================================ | |
| 0-3 Graphics Scratch SRD | |
| 4-7 Compute Scratch SRD | |
| 8-11 ES/GS Ring Output SRD | |
| 12-15 ES/GS Ring Input SRD | |
| 16-19 GS/VS Ring Output #0 | |
| 20-23 GS/VS Ring Output #1 | |
| 24-27 GS/VS Ring Output #2 | |
| 28-31 GS/VS Ring Output #3 | |
| 32-35 GS/VS Ring Input SRD | |
| 36-39 Tessellation Factor Buffer SRD | |
| 40-43 Off-Chip LDS Buffer SRD | |
| 44-47 Off-Chip Param Cache Buffer SRD | |
| 48-51 Sample Position Buffer SRD | |
| 52 vaRange::ShadowDescriptorTable High Bits | |
| ============= ================================ | |
| The pointer to the global internal table passed to the shader as user data | |
| is a 32-bit pointer. The top 32 bits should be assumed to be the same as | |
| the top 32 bits of the pipeline, so the shader may use the program | |
| counter's top 32 bits. | |
| Unspecified OS | |
| -------------- | |
| This section provides code conventions used when the target triple OS is | |
| empty (see :ref:`amdgpu-target-triples`). | |
| Trap Handler ABI | |
| ~~~~~~~~~~~~~~~~ | |
| For code objects generated by AMDGPU backend for non-amdhsa OS, the runtime does | |
| not install a trap handler. The ``llvm.trap`` and ``llvm.debugtrap`` | |
| instructions are handled as follows: | |
| .. table:: AMDGPU Trap Handler for Non-AMDHSA OS | |
| :name: amdgpu-trap-handler-for-non-amdhsa-os-table | |
| =============== =============== =========================================== | |
| Usage Code Sequence Description | |
| =============== =============== =========================================== | |
| llvm.trap s_endpgm Causes wavefront to be terminated. | |
| llvm.debugtrap *none* Compiler warning given that there is no | |
| trap handler installed. | |
| =============== =============== =========================================== | |
| Source Languages | |
| ================ | |
| .. _amdgpu-opencl: | |
| OpenCL | |
| ------ | |
| When the language is OpenCL the following differences occur: | |
| 1. The OpenCL memory model is used (see :ref:`amdgpu-amdhsa-memory-model`). | |
| 2. The AMDGPU backend appends additional arguments to the kernel's explicit | |
| arguments for the AMDHSA OS (see | |
| :ref:`opencl-kernel-implicit-arguments-appended-for-amdhsa-os-table`). | |
| 3. Additional metadata is generated | |
| (see :ref:`amdgpu-amdhsa-code-object-metadata`). | |
| .. table:: OpenCL kernel implicit arguments appended for AMDHSA OS | |
| :name: opencl-kernel-implicit-arguments-appended-for-amdhsa-os-table | |
| ======== ==== ========= =========================================== | |
| Position Byte Byte Description | |
| Size Alignment | |
| ======== ==== ========= =========================================== | |
| 1 8 8 OpenCL Global Offset X | |
| 2 8 8 OpenCL Global Offset Y | |
| 3 8 8 OpenCL Global Offset Z | |
| 4 8 8 OpenCL address of printf buffer | |
| 5 8 8 OpenCL address of virtual queue used by | |
| enqueue_kernel. | |
| 6 8 8 OpenCL address of AqlWrap struct used by | |
| enqueue_kernel. | |
| ======== ==== ========= =========================================== | |
| .. _amdgpu-hcc: | |
| HCC | |
| --- | |
| When the language is HCC the following differences occur: | |
| 1. The HSA memory model is used (see :ref:`amdgpu-amdhsa-memory-model`). | |
| .. _amdgpu-assembler: | |
| Assembler | |
| --------- | |
| AMDGPU backend has LLVM-MC based assembler which is currently in development. | |
| It supports AMDGCN GFX6-GFX9. | |
| This section describes general syntax for instructions and operands. | |
| Instructions | |
| ~~~~~~~~~~~~ | |
| .. toctree:: | |
| :hidden: | |
| AMDGPUAsmGFX7 | |
| AMDGPUAsmGFX8 | |
| AMDGPUAsmGFX9 | |
| AMDGPUOperandSyntax | |
| An instruction has the following syntax: | |
| *<opcode> <operand0>, <operand1>,... <modifier0> <modifier1>...* | |
| Note that operands are normally comma-separated while modifiers are space-separated. | |
| The order of operands and modifiers is fixed. Most modifiers are optional and may be omitted. | |
| See detailed instruction syntax description for :doc:`GFX7<AMDGPUAsmGFX7>`, | |
| :doc:`GFX8<AMDGPUAsmGFX8>` and :doc:`GFX9<AMDGPUAsmGFX9>`. | |
| Note that features under development are not included in this description. | |
| For more information about instructions, their semantics and supported combinations of | |
| operands, refer to one of instruction set architecture manuals | |
| [AMD-GCN-GFX6]_, [AMD-GCN-GFX7]_, [AMD-GCN-GFX8]_ and [AMD-GCN-GFX9]_. | |
| Operands | |
| ~~~~~~~~ | |
| The following syntax for register operands is supported: | |
| * SGPR registers: s0, ... or s[0], ... | |
| * VGPR registers: v0, ... or v[0], ... | |
| * TTMP registers: ttmp0, ... or ttmp[0], ... | |
| * Special registers: exec (exec_lo, exec_hi), vcc (vcc_lo, vcc_hi), flat_scratch (flat_scratch_lo, flat_scratch_hi) | |
| * Special trap registers: tba (tba_lo, tba_hi), tma (tma_lo, tma_hi) | |
| * Register pairs, quads, etc: s[2:3], v[10:11], ttmp[5:6], s[4:7], v[12:15], ttmp[4:7], s[8:15], ... | |
| * Register lists: [s0, s1], [ttmp0, ttmp1, ttmp2, ttmp3] | |
| * Register index expressions: v[2*2], s[1-1:2-1] | |
| * 'off' indicates that an operand is not enabled | |
| Modifiers | |
| ~~~~~~~~~ | |
| Detailed description of modifiers may be found :doc:`here<AMDGPUOperandSyntax>`. | |
| Instruction Examples | |
| ~~~~~~~~~~~~~~~~~~~~ | |
| DS | |
| ++ | |
| .. code-block:: nasm | |
| ds_add_u32 v2, v4 offset:16 | |
| ds_write_src2_b64 v2 offset0:4 offset1:8 | |
| ds_cmpst_f32 v2, v4, v6 | |
| ds_min_rtn_f64 v[8:9], v2, v[4:5] | |
| For full list of supported instructions, refer to "LDS/GDS instructions" in ISA Manual. | |
| FLAT | |
| ++++ | |
| .. code-block:: nasm | |
| flat_load_dword v1, v[3:4] | |
| flat_store_dwordx3 v[3:4], v[5:7] | |
| flat_atomic_swap v1, v[3:4], v5 glc | |
| flat_atomic_cmpswap v1, v[3:4], v[5:6] glc slc | |
| flat_atomic_fmax_x2 v[1:2], v[3:4], v[5:6] glc | |
| For full list of supported instructions, refer to "FLAT instructions" in ISA Manual. | |
| MUBUF | |
| +++++ | |
| .. code-block:: nasm | |
| buffer_load_dword v1, off, s[4:7], s1 | |
| buffer_store_dwordx4 v[1:4], v2, ttmp[4:7], s1 offen offset:4 glc tfe | |
| buffer_store_format_xy v[1:2], off, s[4:7], s1 | |
| buffer_wbinvl1 | |
| buffer_atomic_inc v1, v2, s[8:11], s4 idxen offset:4 slc | |
| For full list of supported instructions, refer to "MUBUF Instructions" in ISA Manual. | |
| SMRD/SMEM | |
| +++++++++ | |
| .. code-block:: nasm | |
| s_load_dword s1, s[2:3], 0xfc | |
| s_load_dwordx8 s[8:15], s[2:3], s4 | |
| s_load_dwordx16 s[88:103], s[2:3], s4 | |
| s_dcache_inv_vol | |
| s_memtime s[4:5] | |
| For full list of supported instructions, refer to "Scalar Memory Operations" in ISA Manual. | |
| SOP1 | |
| ++++ | |
| .. code-block:: nasm | |
| s_mov_b32 s1, s2 | |
| s_mov_b64 s[0:1], 0x80000000 | |
| s_cmov_b32 s1, 200 | |
| s_wqm_b64 s[2:3], s[4:5] | |
| s_bcnt0_i32_b64 s1, s[2:3] | |
| s_swappc_b64 s[2:3], s[4:5] | |
| s_cbranch_join s[4:5] | |
| For full list of supported instructions, refer to "SOP1 Instructions" in ISA Manual. | |
| SOP2 | |
| ++++ | |
| .. code-block:: nasm | |
| s_add_u32 s1, s2, s3 | |
| s_and_b64 s[2:3], s[4:5], s[6:7] | |
| s_cselect_b32 s1, s2, s3 | |
| s_andn2_b32 s2, s4, s6 | |
| s_lshr_b64 s[2:3], s[4:5], s6 | |
| s_ashr_i32 s2, s4, s6 | |
| s_bfm_b64 s[2:3], s4, s6 | |
| s_bfe_i64 s[2:3], s[4:5], s6 | |
| s_cbranch_g_fork s[4:5], s[6:7] | |
| For full list of supported instructions, refer to "SOP2 Instructions" in ISA Manual. | |
| SOPC | |
| ++++ | |
| .. code-block:: nasm | |
| s_cmp_eq_i32 s1, s2 | |
| s_bitcmp1_b32 s1, s2 | |
| s_bitcmp0_b64 s[2:3], s4 | |
| s_setvskip s3, s5 | |
| For full list of supported instructions, refer to "SOPC Instructions" in ISA Manual. | |
| SOPP | |
| ++++ | |
| .. code-block:: nasm | |
| s_barrier | |
| s_nop 2 | |
| s_endpgm | |
| s_waitcnt 0 ; Wait for all counters to be 0 | |
| s_waitcnt vmcnt(0) & expcnt(0) & lgkmcnt(0) ; Equivalent to above | |
| s_waitcnt vmcnt(1) ; Wait for vmcnt counter to be 1. | |
| s_sethalt 9 | |
| s_sleep 10 | |
| s_sendmsg 0x1 | |
| s_sendmsg sendmsg(MSG_INTERRUPT) | |
| s_trap 1 | |
| For full list of supported instructions, refer to "SOPP Instructions" in ISA Manual. | |
| Unless otherwise mentioned, little verification is performed on the operands | |
| of SOPP Instructions, so it is up to the programmer to be familiar with the | |
| range or acceptable values. | |
| VALU | |
| ++++ | |
| For vector ALU instruction opcodes (VOP1, VOP2, VOP3, VOPC, VOP_DPP, VOP_SDWA), | |
| the assembler will automatically use optimal encoding based on its operands. | |
| To force specific encoding, one can add a suffix to the opcode of the instruction: | |
| * _e32 for 32-bit VOP1/VOP2/VOPC | |
| * _e64 for 64-bit VOP3 | |
| * _dpp for VOP_DPP | |
| * _sdwa for VOP_SDWA | |
| VOP1/VOP2/VOP3/VOPC examples: | |
| .. code-block:: nasm | |
| v_mov_b32 v1, v2 | |
| v_mov_b32_e32 v1, v2 | |
| v_nop | |
| v_cvt_f64_i32_e32 v[1:2], v2 | |
| v_floor_f32_e32 v1, v2 | |
| v_bfrev_b32_e32 v1, v2 | |
| v_add_f32_e32 v1, v2, v3 | |
| v_mul_i32_i24_e64 v1, v2, 3 | |
| v_mul_i32_i24_e32 v1, -3, v3 | |
| v_mul_i32_i24_e32 v1, -100, v3 | |
| v_addc_u32 v1, s[0:1], v2, v3, s[2:3] | |
| v_max_f16_e32 v1, v2, v3 | |
| VOP_DPP examples: | |
| .. code-block:: nasm | |
| v_mov_b32 v0, v0 quad_perm:[0,2,1,1] | |
| v_sin_f32 v0, v0 row_shl:1 row_mask:0xa bank_mask:0x1 bound_ctrl:0 | |
| v_mov_b32 v0, v0 wave_shl:1 | |
| v_mov_b32 v0, v0 row_mirror | |
| v_mov_b32 v0, v0 row_bcast:31 | |
| v_mov_b32 v0, v0 quad_perm:[1,3,0,1] row_mask:0xa bank_mask:0x1 bound_ctrl:0 | |
| v_add_f32 v0, v0, |v0| row_shl:1 row_mask:0xa bank_mask:0x1 bound_ctrl:0 | |
| v_max_f16 v1, v2, v3 row_shl:1 row_mask:0xa bank_mask:0x1 bound_ctrl:0 | |
| VOP_SDWA examples: | |
| .. code-block:: nasm | |
| v_mov_b32 v1, v2 dst_sel:BYTE_0 dst_unused:UNUSED_PRESERVE src0_sel:DWORD | |
| v_min_u32 v200, v200, v1 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:BYTE_1 src1_sel:DWORD | |
| v_sin_f32 v0, v0 dst_unused:UNUSED_PAD src0_sel:WORD_1 | |
| v_fract_f32 v0, |v0| dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 | |
| v_cmpx_le_u32 vcc, v1, v2 src0_sel:BYTE_2 src1_sel:WORD_0 | |
| For full list of supported instructions, refer to "Vector ALU instructions". | |
| .. TODO | |
| Remove once we switch to code object v3 by default. | |
| HSA Code Object Directives | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| AMDGPU ABI defines auxiliary data in output code object. In assembly source, | |
| one can specify them with assembler directives. | |
| .hsa_code_object_version major, minor | |
| +++++++++++++++++++++++++++++++++++++ | |
| *major* and *minor* are integers that specify the version of the HSA code | |
| object that will be generated by the assembler. | |
| .hsa_code_object_isa [major, minor, stepping, vendor, arch] | |
| +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
| *major*, *minor*, and *stepping* are all integers that describe the instruction | |
| set architecture (ISA) version of the assembly program. | |
| *vendor* and *arch* are quoted strings. *vendor* should always be equal to | |
| "AMD" and *arch* should always be equal to "AMDGPU". | |
| By default, the assembler will derive the ISA version, *vendor*, and *arch* | |
| from the value of the -mcpu option that is passed to the assembler. | |
| .amdgpu_hsa_kernel (name) | |
| +++++++++++++++++++++++++ | |
| This directives specifies that the symbol with given name is a kernel entry point | |
| (label) and the object should contain corresponding symbol of type STT_AMDGPU_HSA_KERNEL. | |
| .amd_kernel_code_t | |
| ++++++++++++++++++ | |
| This directive marks the beginning of a list of key / value pairs that are used | |
| to specify the amd_kernel_code_t object that will be emitted by the assembler. | |
| The list must be terminated by the *.end_amd_kernel_code_t* directive. For | |
| any amd_kernel_code_t values that are unspecified a default value will be | |
| used. The default value for all keys is 0, with the following exceptions: | |
| - *kernel_code_version_major* defaults to 1. | |
| - *machine_kind* defaults to 1. | |
| - *machine_version_major*, *machine_version_minor*, and | |
| *machine_version_stepping* are derived from the value of the -mcpu option | |
| that is passed to the assembler. | |
| - *kernel_code_entry_byte_offset* defaults to 256. | |
| - *wavefront_size* defaults to 6. | |
| - *kernarg_segment_alignment*, *group_segment_alignment*, and | |
| *private_segment_alignment* default to 4. Note that alignments are specified | |
| as a power of two, so a value of **n** means an alignment of 2^ **n**. | |
| The *.amd_kernel_code_t* directive must be placed immediately after the | |
| function label and before any instructions. | |
| For a full list of amd_kernel_code_t keys, refer to AMDGPU ABI document, | |
| comments in lib/Target/AMDGPU/AmdKernelCodeT.h and test/CodeGen/AMDGPU/hsa.s. | |
| Here is an example of a minimal amd_kernel_code_t specification: | |
| .. code-block:: none | |
| .hsa_code_object_version 1,0 | |
| .hsa_code_object_isa | |
| .hsatext | |
| .globl hello_world | |
| .p2align 8 | |
| .amdgpu_hsa_kernel hello_world | |
| hello_world: | |
| .amd_kernel_code_t | |
| enable_sgpr_kernarg_segment_ptr = 1 | |
| is_ptr64 = 1 | |
| compute_pgm_rsrc1_vgprs = 0 | |
| compute_pgm_rsrc1_sgprs = 0 | |
| compute_pgm_rsrc2_user_sgpr = 2 | |
| kernarg_segment_byte_size = 8 | |
| wavefront_sgpr_count = 2 | |
| workitem_vgpr_count = 3 | |
| .end_amd_kernel_code_t | |
| s_load_dwordx2 s[0:1], s[0:1] 0x0 | |
| v_mov_b32 v0, 3.14159 | |
| s_waitcnt lgkmcnt(0) | |
| v_mov_b32 v1, s0 | |
| v_mov_b32 v2, s1 | |
| flat_store_dword v[1:2], v0 | |
| s_endpgm | |
| .Lfunc_end0: | |
| .size hello_world, .Lfunc_end0-hello_world | |
| Predefined Symbols (-mattr=+code-object-v3) | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| The AMDGPU assembler defines and updates some symbols automatically. These | |
| symbols do not affect code generation. | |
| .amdgcn.gfx_generation_number | |
| +++++++++++++++++++++++++++++ | |
| Set to the GFX generation number of the target being assembled for. For | |
| example, when assembling for a "GFX9" target this will be set to the integer | |
| value "9". The possible GFX generation numbers are presented in | |
| :ref:`amdgpu-processors`. | |
| .amdgcn.next_free_vgpr | |
| ++++++++++++++++++++++ | |
| Set to zero before assembly begins. At each instruction, if the current value | |
| of this symbol is less than or equal to the maximum VGPR number explicitly | |
| referenced within that instruction then the symbol value is updated to equal | |
| that VGPR number plus one. | |
| May be used to set the `.amdhsa_next_free_vpgr` directive in | |
| :ref:`amdhsa-kernel-directives-table`. | |
| May be set at any time, e.g. manually set to zero at the start of each kernel. | |
| .amdgcn.next_free_sgpr | |
| ++++++++++++++++++++++ | |
| Set to zero before assembly begins. At each instruction, if the current value | |
| of this symbol is less than or equal the maximum SGPR number explicitly | |
| referenced within that instruction then the symbol value is updated to equal | |
| that SGPR number plus one. | |
| May be used to set the `.amdhsa_next_free_spgr` directive in | |
| :ref:`amdhsa-kernel-directives-table`. | |
| May be set at any time, e.g. manually set to zero at the start of each kernel. | |
| Code Object Directives (-mattr=+code-object-v3) | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| Directives which begin with ``.amdgcn`` are valid for all ``amdgcn`` | |
| architecture processors, and are not OS-specific. Directives which begin with | |
| ``.amdhsa`` are specific to ``amdgcn`` architecture processors when the | |
| ``amdhsa`` OS is specified. See :ref:`amdgpu-target-triples` and | |
| :ref:`amdgpu-processors`. | |
| .amdgcn_target <target> | |
| +++++++++++++++++++++++ | |
| Optional directive which declares the target supported by the containing | |
| assembler source file. Valid values are described in | |
| :ref:`amdgpu-amdhsa-code-object-target-identification`. Used by the assembler | |
| to validate command-line options such as ``-triple``, ``-mcpu``, and those | |
| which specify target features. | |
| .amdhsa_kernel <name> | |
| +++++++++++++++++++++ | |
| Creates a correctly aligned AMDHSA kernel descriptor and a symbol, | |
| ``<name>.kd``, in the current location of the current section. Only valid when | |
| the OS is ``amdhsa``. ``<name>`` must be a symbol that labels the first | |
| instruction to execute, and does not need to be previously defined. | |
| Marks the beginning of a list of directives used to generate the bytes of a | |
| kernel descriptor, as described in :ref:`amdgpu-amdhsa-kernel-descriptor`. | |
| Directives which may appear in this list are described in | |
| :ref:`amdhsa-kernel-directives-table`. Directives may appear in any order, must | |
| be valid for the target being assembled for, and cannot be repeated. Directives | |
| support the range of values specified by the field they reference in | |
| :ref:`amdgpu-amdhsa-kernel-descriptor`. If a directive is not specified, it is | |
| assumed to have its default value, unless it is marked as "Required", in which | |
| case it is an error to omit the directive. This list of directives is | |
| terminated by an ``.end_amdhsa_kernel`` directive. | |
| .. table:: AMDHSA Kernel Assembler Directives | |
| :name: amdhsa-kernel-directives-table | |
| ======================================================== ================ ============ =================== | |
| Directive Default Supported On Description | |
| ======================================================== ================ ============ =================== | |
| ``.amdhsa_group_segment_fixed_size`` 0 GFX6-GFX9 Controls GROUP_SEGMENT_FIXED_SIZE in | |
| :ref:`amdgpu-amdhsa-kernel-descriptor-gfx6-gfx9-table`. | |
| ``.amdhsa_private_segment_fixed_size`` 0 GFX6-GFX9 Controls PRIVATE_SEGMENT_FIXED_SIZE in | |
| :ref:`amdgpu-amdhsa-kernel-descriptor-gfx6-gfx9-table`. | |
| ``.amdhsa_user_sgpr_private_segment_buffer`` 0 GFX6-GFX9 Controls ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER in | |
| :ref:`amdgpu-amdhsa-kernel-descriptor-gfx6-gfx9-table`. | |
| ``.amdhsa_user_sgpr_dispatch_ptr`` 0 GFX6-GFX9 Controls ENABLE_SGPR_DISPATCH_PTR in | |
| :ref:`amdgpu-amdhsa-kernel-descriptor-gfx6-gfx9-table`. | |
| ``.amdhsa_user_sgpr_queue_ptr`` 0 GFX6-GFX9 Controls ENABLE_SGPR_QUEUE_PTR in | |
| :ref:`amdgpu-amdhsa-kernel-descriptor-gfx6-gfx9-table`. | |
| ``.amdhsa_user_sgpr_kernarg_segment_ptr`` 0 GFX6-GFX9 Controls ENABLE_SGPR_KERNARG_SEGMENT_PTR in | |
| :ref:`amdgpu-amdhsa-kernel-descriptor-gfx6-gfx9-table`. | |
| ``.amdhsa_user_sgpr_dispatch_id`` 0 GFX6-GFX9 Controls ENABLE_SGPR_DISPATCH_ID in | |
| :ref:`amdgpu-amdhsa-kernel-descriptor-gfx6-gfx9-table`. | |
| ``.amdhsa_user_sgpr_flat_scratch_init`` 0 GFX6-GFX9 Controls ENABLE_SGPR_FLAT_SCRATCH_INIT in | |
| :ref:`amdgpu-amdhsa-kernel-descriptor-gfx6-gfx9-table`. | |
| ``.amdhsa_user_sgpr_private_segment_size`` 0 GFX6-GFX9 Controls ENABLE_SGPR_PRIVATE_SEGMENT_SIZE in | |
| :ref:`amdgpu-amdhsa-kernel-descriptor-gfx6-gfx9-table`. | |
| ``.amdhsa_system_sgpr_private_segment_wavefront_offset`` 0 GFX6-GFX9 Controls ENABLE_SGPR_PRIVATE_SEGMENT_WAVEFRONT_OFFSET in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc2-gfx6-gfx9-table`. | |
| ``.amdhsa_system_sgpr_workgroup_id_x`` 1 GFX6-GFX9 Controls ENABLE_SGPR_WORKGROUP_ID_X in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc2-gfx6-gfx9-table`. | |
| ``.amdhsa_system_sgpr_workgroup_id_y`` 0 GFX6-GFX9 Controls ENABLE_SGPR_WORKGROUP_ID_Y in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc2-gfx6-gfx9-table`. | |
| ``.amdhsa_system_sgpr_workgroup_id_z`` 0 GFX6-GFX9 Controls ENABLE_SGPR_WORKGROUP_ID_Z in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc2-gfx6-gfx9-table`. | |
| ``.amdhsa_system_sgpr_workgroup_info`` 0 GFX6-GFX9 Controls ENABLE_SGPR_WORKGROUP_INFO in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc2-gfx6-gfx9-table`. | |
| ``.amdhsa_system_vgpr_workitem_id`` 0 GFX6-GFX9 Controls ENABLE_VGPR_WORKITEM_ID in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc2-gfx6-gfx9-table`. | |
| Possible values are defined in | |
| :ref:`amdgpu-amdhsa-system-vgpr-work-item-id-enumeration-values-table`. | |
| ``.amdhsa_next_free_vgpr`` Required GFX6-GFX9 Maximum VGPR number explicitly referenced, plus one. | |
| Used to calculate GRANULATED_WORKITEM_VGPR_COUNT in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc1-gfx6-gfx9-table`. | |
| ``.amdhsa_next_free_sgpr`` Required GFX6-GFX9 Maximum SGPR number explicitly referenced, plus one. | |
| Used to calculate GRANULATED_WAVEFRONT_SGPR_COUNT in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc1-gfx6-gfx9-table`. | |
| ``.amdhsa_reserve_vcc`` 1 GFX6-GFX9 Whether the kernel may use the special VCC SGPR. | |
| Used to calculate GRANULATED_WAVEFRONT_SGPR_COUNT in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc1-gfx6-gfx9-table`. | |
| ``.amdhsa_reserve_flat_scratch`` 1 GFX7-GFX9 Whether the kernel may use flat instructions to access | |
| scratch memory. Used to calculate | |
| GRANULATED_WAVEFRONT_SGPR_COUNT in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc1-gfx6-gfx9-table`. | |
| ``.amdhsa_reserve_xnack_mask`` Target GFX8-GFX9 Whether the kernel may trigger XNACK replay. | |
| Feature Used to calculate GRANULATED_WAVEFRONT_SGPR_COUNT in | |
| Specific :ref:`amdgpu-amdhsa-compute_pgm_rsrc1-gfx6-gfx9-table`. | |
| (+xnack) | |
| ``.amdhsa_float_round_mode_32`` 0 GFX6-GFX9 Controls FLOAT_ROUND_MODE_32 in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc1-gfx6-gfx9-table`. | |
| Possible values are defined in | |
| :ref:`amdgpu-amdhsa-floating-point-rounding-mode-enumeration-values-table`. | |
| ``.amdhsa_float_round_mode_16_64`` 0 GFX6-GFX9 Controls FLOAT_ROUND_MODE_16_64 in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc1-gfx6-gfx9-table`. | |
| Possible values are defined in | |
| :ref:`amdgpu-amdhsa-floating-point-rounding-mode-enumeration-values-table`. | |
| ``.amdhsa_float_denorm_mode_32`` 0 GFX6-GFX9 Controls FLOAT_DENORM_MODE_32 in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc1-gfx6-gfx9-table`. | |
| Possible values are defined in | |
| :ref:`amdgpu-amdhsa-floating-point-denorm-mode-enumeration-values-table`. | |
| ``.amdhsa_float_denorm_mode_16_64`` 3 GFX6-GFX9 Controls FLOAT_DENORM_MODE_16_64 in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc1-gfx6-gfx9-table`. | |
| Possible values are defined in | |
| :ref:`amdgpu-amdhsa-floating-point-denorm-mode-enumeration-values-table`. | |
| ``.amdhsa_dx10_clamp`` 1 GFX6-GFX9 Controls ENABLE_DX10_CLAMP in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc1-gfx6-gfx9-table`. | |
| ``.amdhsa_ieee_mode`` 1 GFX6-GFX9 Controls ENABLE_IEEE_MODE in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc1-gfx6-gfx9-table`. | |
| ``.amdhsa_fp16_overflow`` 0 GFX9 Controls FP16_OVFL in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc1-gfx6-gfx9-table`. | |
| ``.amdhsa_exception_fp_ieee_invalid_op`` 0 GFX6-GFX9 Controls ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc2-gfx6-gfx9-table`. | |
| ``.amdhsa_exception_fp_denorm_src`` 0 GFX6-GFX9 Controls ENABLE_EXCEPTION_FP_DENORMAL_SOURCE in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc2-gfx6-gfx9-table`. | |
| ``.amdhsa_exception_fp_ieee_div_zero`` 0 GFX6-GFX9 Controls ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc2-gfx6-gfx9-table`. | |
| ``.amdhsa_exception_fp_ieee_overflow`` 0 GFX6-GFX9 Controls ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc2-gfx6-gfx9-table`. | |
| ``.amdhsa_exception_fp_ieee_underflow`` 0 GFX6-GFX9 Controls ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc2-gfx6-gfx9-table`. | |
| ``.amdhsa_exception_fp_ieee_inexact`` 0 GFX6-GFX9 Controls ENABLE_EXCEPTION_IEEE_754_FP_INEXACT in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc2-gfx6-gfx9-table`. | |
| ``.amdhsa_exception_int_div_zero`` 0 GFX6-GFX9 Controls ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO in | |
| :ref:`amdgpu-amdhsa-compute_pgm_rsrc2-gfx6-gfx9-table`. | |
| ======================================================== ================ ============ =================== | |
| Example HSA Source Code (-mattr=+code-object-v3) | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| Here is an example of a minimal assembly source file, defining one HSA kernel: | |
| .. code-block:: nasm | |
| .amdgcn_target "amdgcn-amd-amdhsa--gfx900+xnack" // optional | |
| .text | |
| .globl hello_world | |
| .p2align 8 | |
| .type hello_world,@function | |
| hello_world: | |
| s_load_dwordx2 s[0:1], s[0:1] 0x0 | |
| v_mov_b32 v0, 3.14159 | |
| s_waitcnt lgkmcnt(0) | |
| v_mov_b32 v1, s0 | |
| v_mov_b32 v2, s1 | |
| flat_store_dword v[1:2], v0 | |
| s_endpgm | |
| .Lfunc_end0: | |
| .size hello_world, .Lfunc_end0-hello_world | |
| .rodata | |
| .p2align 6 | |
| .amdhsa_kernel hello_world | |
| .amdhsa_user_sgpr_kernarg_segment_ptr 1 | |
| .amdhsa_next_free_vgpr .amdgcn.next_free_vgpr | |
| .amdhsa_next_free_sgpr .amdgcn.next_free_sgpr | |
| .end_amdhsa_kernel | |
| Additional Documentation | |
| ======================== | |
| .. [AMD-RADEON-HD-2000-3000] `AMD R6xx shader ISA <http://developer.amd.com/wordpress/media/2012/10/R600_Instruction_Set_Architecture.pdf>`__ | |
| .. [AMD-RADEON-HD-4000] `AMD R7xx shader ISA <http://developer.amd.com/wordpress/media/2012/10/R700-Family_Instruction_Set_Architecture.pdf>`__ | |
| .. [AMD-RADEON-HD-5000] `AMD Evergreen shader ISA <http://developer.amd.com/wordpress/media/2012/10/AMD_Evergreen-Family_Instruction_Set_Architecture.pdf>`__ | |
| .. [AMD-RADEON-HD-6000] `AMD Cayman/Trinity shader ISA <http://developer.amd.com/wordpress/media/2012/10/AMD_HD_6900_Series_Instruction_Set_Architecture.pdf>`__ | |
| .. [AMD-GCN-GFX6] `AMD Southern Islands Series ISA <http://developer.amd.com/wordpress/media/2012/12/AMD_Southern_Islands_Instruction_Set_Architecture.pdf>`__ | |
| .. [AMD-GCN-GFX7] `AMD Sea Islands Series ISA <http://developer.amd.com/wordpress/media/2013/07/AMD_Sea_Islands_Instruction_Set_Architecture.pdf>`_ | |
| .. [AMD-GCN-GFX8] `AMD GCN3 Instruction Set Architecture <http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_GCN3_Instruction_Set_Architecture_rev1.1.pdf>`__ | |
| .. [AMD-GCN-GFX9] `AMD "Vega" Instruction Set Architecture <http://developer.amd.com/wordpress/media/2013/12/Vega_Shader_ISA_28July2017.pdf>`__ | |
| .. [AMD-ROCm] `ROCm: Open Platform for Development, Discovery and Education Around GPU Computing <http://gpuopen.com/compute-product/rocm/>`__ | |
| .. [AMD-ROCm-github] `ROCm github <http://github.com/RadeonOpenCompute>`__ | |
| .. [HSA] `Heterogeneous System Architecture (HSA) Foundation <http://www.hsafoundation.com/>`__ | |
| .. [ELF] `Executable and Linkable Format (ELF) <http://www.sco.com/developers/gabi/>`__ | |
| .. [DWARF] `DWARF Debugging Information Format <http://dwarfstd.org/>`__ | |
| .. [YAML] `YAML Ain't Markup Language (YAML™) Version 1.2 <http://www.yaml.org/spec/1.2/spec.html>`__ | |
| .. [OpenCL] `The OpenCL Specification Version 2.0 <http://www.khronos.org/registry/cl/specs/opencl-2.0.pdf>`__ | |
| .. [HRF] `Heterogeneous-race-free Memory Models <http://benedictgaster.org/wp-content/uploads/2014/01/asplos269-FINAL.pdf>`__ | |
| .. [CLANG-ATTR] `Attributes in Clang <http://clang.llvm.org/docs/AttributeReference.html>`__ |