| ; RUN: opt -S -mtriple=amdgpu9.00-amd-amdhsa -passes='amdgpu-atomic-optimizer<strategy=dpp>,verify<domtree>' %s | FileCheck %s |
| ; RUN: opt -S -mtriple=amdgpu9.00-amd-amdhsa -passes='amdgpu-atomic-optimizer<strategy=iterative>,verify<domtree>' %s | FileCheck %s |
| |
| ; Both operands are uniform. The scalar lane count must not be cast to a vector. |
| ; CHECK-LABEL: define amdgpu_kernel void @global_uniform_vector_add( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: %old = atomicrmw add ptr addrspace(1) %ptr, <2 x i32> <i32 1, i32 2> monotonic, align 8 |
| ; CHECK-NEXT: ret void |
| |
| define amdgpu_kernel void @global_uniform_vector_add(ptr addrspace(1) %ptr) { |
| entry: |
| %old = atomicrmw add ptr addrspace(1) %ptr, <2 x i32> <i32 1, i32 2> monotonic |
| ret void |
| } |
| |
| ; Cover result reconstruction for an idempotent operation and the LDS path. |
| ; CHECK-LABEL: define amdgpu_kernel void @local_uniform_vector_and( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: %old = atomicrmw and ptr addrspace(3) %ptr, <2 x i32> <i32 1, i32 2> monotonic, align 8 |
| ; CHECK-NEXT: store <2 x i32> %old, ptr addrspace(1) %out, align 8 |
| ; CHECK-NEXT: ret void |
| |
| define amdgpu_kernel void @local_uniform_vector_and(ptr addrspace(3) %ptr, ptr addrspace(1) %out) { |
| entry: |
| %old = atomicrmw and ptr addrspace(3) %ptr, <2 x i32> <i32 1, i32 2> monotonic |
| store <2 x i32> %old, ptr addrspace(1) %out |
| ret void |
| } |
| |
| ; Buffer atomic intrinsics must also skip vector operands, with and without uses. |
| ; CHECK-LABEL: define amdgpu_kernel void @raw_ptr_buffer_uniform_vector_add( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: %old = call <2 x i32> @llvm.amdgcn.raw.ptr.buffer.atomic.add.v2i32(<2 x i32> <i32 1, i32 2>, ptr addrspace(8) %rsrc, i32 0, i32 0, i32 0) |
| ; CHECK-NEXT: ret void |
| |
| define amdgpu_kernel void @raw_ptr_buffer_uniform_vector_add(ptr addrspace(8) %rsrc) { |
| entry: |
| %old = call <2 x i32> @llvm.amdgcn.raw.ptr.buffer.atomic.add.v2i32(<2 x i32> <i32 1, i32 2>, ptr addrspace(8) %rsrc, i32 0, i32 0, i32 0) |
| ret void |
| } |
| |
| ; CHECK-LABEL: define amdgpu_kernel void @struct_ptr_buffer_uniform_vector_and( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: %old = call <2 x i32> @llvm.amdgcn.struct.ptr.buffer.atomic.and.v2i32(<2 x i32> <i32 1, i32 2>, ptr addrspace(8) %rsrc, i32 0, i32 0, i32 0, i32 0) |
| ; CHECK-NEXT: store <2 x i32> %old, ptr addrspace(1) %out, align 8 |
| ; CHECK-NEXT: ret void |
| |
| define amdgpu_kernel void @struct_ptr_buffer_uniform_vector_and(ptr addrspace(8) %rsrc, ptr addrspace(1) %out) { |
| entry: |
| %old = call <2 x i32> @llvm.amdgcn.struct.ptr.buffer.atomic.and.v2i32(<2 x i32> <i32 1, i32 2>, ptr addrspace(8) %rsrc, i32 0, i32 0, i32 0, i32 0) |
| store <2 x i32> %old, ptr addrspace(1) %out |
| ret void |
| } |
| |
| ; Scalar uniform operands narrower than 32 bits remain eligible. Moving the |
| ; divergent-value isLegalCrossLaneType check to the common path would lose this. |
| ; CHECK-LABEL: define amdgpu_kernel void @global_uniform_scalar_i16( |
| ; CHECK: call {{.*}} @llvm.amdgcn.ballot. |
| ; CHECK: atomicrmw add ptr addrspace(1) %ptr, i16 %{{.*}} monotonic |
| |
| define amdgpu_kernel void @global_uniform_scalar_i16(ptr addrspace(1) %ptr, i16 %val) { |
| entry: |
| %old = atomicrmw add ptr addrspace(1) %ptr, i16 %val monotonic |
| ret void |
| } |