blob: 9ae0e88a27a6a707f47f9dcf0b92cf5af5233703 [file] [edit]
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
// REQUIRES: amdgpu-registered-target
// RUN: %clang_cc1 %s -emit-llvm -O0 -o - \
// RUN: -triple=amdgcn-amd-amdhsa -std=c23 | FileCheck %s
// Test that [[clang::amdgpu_av("none")]] works with _Atomic type
// qualifier operations, which go through CGExprScalar and CGAtomic
// codegen paths.
// CHECK-LABEL: define dso_local void @test_atomic_rmw_add(
// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8, addrspace(5)
// CHECK-NEXT: [[P_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_ADDR]] to ptr
// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR_ASCAST]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR_ASCAST]], align 8
// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw add ptr [[TMP0]], i32 1 seq_cst, align 4, !mmra [[META2:![0-9]+]], !amdgpu.no.fine.grained.memory [[META3:![0-9]+]], !amdgpu.no.remote.memory [[META3]]
// CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1
// CHECK-NEXT: ret void
//
void test_atomic_rmw_add(_Atomic int *p) {
[[clang::amdgpu_av("none")]] *p += 1;
}
// CHECK-LABEL: define dso_local void @test_atomic_store(
// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8, addrspace(5)
// CHECK-NEXT: [[P_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_ADDR]] to ptr
// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR_ASCAST]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR_ASCAST]], align 8
// CHECK-NEXT: store atomic i32 42, ptr [[TMP0]] seq_cst, align 4, !mmra [[META2]]
// CHECK-NEXT: ret void
//
void test_atomic_store(_Atomic int *p) {
[[clang::amdgpu_av("none")]] *p = 42;
}
// CHECK-LABEL: define dso_local void @test_atomic_load(
// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8, addrspace(5)
// CHECK-NEXT: [[P_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_ADDR]] to ptr
// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR_ASCAST]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR_ASCAST]], align 8
// CHECK-NEXT: [[ATOMIC_LOAD:%.*]] = load atomic i32, ptr [[TMP0]] seq_cst, align 4, !mmra [[META2]]
// CHECK-NEXT: ret void
//
void test_atomic_load(_Atomic int *p) {
[[clang::amdgpu_av("none")]] (void)*p;
}
// --- Negative control: no attribute ---
// CHECK-LABEL: define dso_local void @test_no_attr(
// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8, addrspace(5)
// CHECK-NEXT: [[P_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_ADDR]] to ptr
// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR_ASCAST]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR_ASCAST]], align 8
// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw add ptr [[TMP0]], i32 1 seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META3]], !amdgpu.no.remote.memory [[META3]]
// CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1
// CHECK-NEXT: ret void
//
void test_no_attr(_Atomic int *p) {
*p += 1;
}
//.
// CHECK: [[META2]] = !{!"amdgcn-av", !"none"}
// CHECK: [[META3]] = !{}
//.