| // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 | |
| // REQUIRES: amdgpu-registered-target | |
| // RUN: %clang_cc1 %s -emit-llvm -O0 -o - \ | |
| // RUN: -triple=amdgcn-amd-amdhsa | FileCheck %s | |
| // Test that [[clang::amdgpu_av("none")]] on atomic builtins emits | |
| // !mmra !{!"amdgcn-av", !"none"} metadata on the resulting IR instructions. | |
| // CHECK-LABEL: define dso_local void @_Z21test_atomic_fetch_addPi( | |
| // CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0:[0-9]+]] { | |
| // CHECK-NEXT: entry: | |
| // CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) | |
| // CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4, addrspace(5) | |
| // CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4, 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 i32 1, ptr addrspace(5) [[DOTATOMICTMP]], align 4 | |
| // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(5) [[DOTATOMICTMP]], align 4 | |
| // CHECK-NEXT: [[TMP2:%.*]] = atomicrmw add ptr [[TMP0]], i32 [[TMP1]] seq_cst, align 4, !mmra [[META2:![0-9]+]], !amdgpu.no.fine.grained.memory [[META3:![0-9]+]], !amdgpu.no.remote.memory [[META3]] | |
| // CHECK-NEXT: store i32 [[TMP2]], ptr addrspace(5) [[ATOMIC_TEMP]], align 4 | |
| // CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr addrspace(5) [[ATOMIC_TEMP]], align 4 | |
| // CHECK-NEXT: ret void | |
| // | |
| void test_atomic_fetch_add(int *p) { | |
| [[clang::amdgpu_av("none")]] __atomic_fetch_add(p, 1, __ATOMIC_SEQ_CST); | |
| } | |
| // CHECK-LABEL: define dso_local void @_Z17test_atomic_storePi( | |
| // CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { | |
| // CHECK-NEXT: entry: | |
| // CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) | |
| // CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4, 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 i32 42, ptr addrspace(5) [[DOTATOMICTMP]], align 4 | |
| // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(5) [[DOTATOMICTMP]], align 4 | |
| // CHECK-NEXT: store atomic i32 [[TMP1]], ptr [[TMP0]] release, align 4, !mmra [[META2]] | |
| // CHECK-NEXT: ret void | |
| // | |
| void test_atomic_store(int *p) { | |
| [[clang::amdgpu_av("none")]] __atomic_store_n(p, 42, __ATOMIC_RELEASE); | |
| } | |
| // CHECK-LABEL: define dso_local void @_Z16test_atomic_loadPi( | |
| // CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { | |
| // CHECK-NEXT: entry: | |
| // CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) | |
| // CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4, 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:%.*]] = load atomic i32, ptr [[TMP0]] acquire, align 4, !mmra [[META2]] | |
| // CHECK-NEXT: store i32 [[TMP1]], ptr addrspace(5) [[ATOMIC_TEMP]], align 4 | |
| // CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(5) [[ATOMIC_TEMP]], align 4 | |
| // CHECK-NEXT: ret void | |
| // | |
| void test_atomic_load(int *p) { | |
| [[clang::amdgpu_av("none")]] __atomic_load_n(p, __ATOMIC_ACQUIRE); | |
| } | |
| // CHECK-LABEL: define dso_local void @_Z19test_atomic_cmpxchgPi( | |
| // CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { | |
| // CHECK-NEXT: entry: | |
| // CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) | |
| // CHECK-NEXT: [[EXPECTED:%.*]] = alloca i32, align 4, addrspace(5) | |
| // CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4, addrspace(5) | |
| // CHECK-NEXT: [[CMPXCHG_BOOL:%.*]] = alloca i8, align 1, addrspace(5) | |
| // CHECK-NEXT: [[P_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_ADDR]] to ptr | |
| // CHECK-NEXT: [[EXPECTED_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[EXPECTED]] to ptr | |
| // CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR_ASCAST]], align 8 | |
| // CHECK-NEXT: store i32 0, ptr [[EXPECTED_ASCAST]], align 4 | |
| // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR_ASCAST]], align 8 | |
| // CHECK-NEXT: store i32 1, ptr addrspace(5) [[DOTATOMICTMP]], align 4 | |
| // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[EXPECTED_ASCAST]], align 4 | |
| // CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(5) [[DOTATOMICTMP]], align 4 | |
| // CHECK-NEXT: [[TMP3:%.*]] = cmpxchg ptr [[TMP0]], i32 [[TMP1]], i32 [[TMP2]] seq_cst acquire, align 4, !mmra [[META2]] | |
| // CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i32, i1 } [[TMP3]], 0 | |
| // CHECK-NEXT: [[TMP5:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 | |
| // CHECK-NEXT: br i1 [[TMP5]], label [[CMPXCHG_CONTINUE:%.*]], label [[CMPXCHG_STORE_EXPECTED:%.*]] | |
| // CHECK: cmpxchg.store_expected: | |
| // CHECK-NEXT: store i32 [[TMP4]], ptr [[EXPECTED_ASCAST]], align 4 | |
| // CHECK-NEXT: br label [[CMPXCHG_CONTINUE]] | |
| // CHECK: cmpxchg.continue: | |
| // CHECK-NEXT: [[STOREDV:%.*]] = zext i1 [[TMP5]] to i8 | |
| // CHECK-NEXT: store i8 [[STOREDV]], ptr addrspace(5) [[CMPXCHG_BOOL]], align 1 | |
| // CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr addrspace(5) [[CMPXCHG_BOOL]], align 1 | |
| // CHECK-NEXT: [[LOADEDV:%.*]] = icmp ne i8 [[TMP6]], 0 | |
| // CHECK-NEXT: ret void | |
| // | |
| void test_atomic_cmpxchg(int *p) { | |
| int expected = 0; | |
| [[clang::amdgpu_av("none")]] __atomic_compare_exchange_n(p, &expected, 1, false, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE); | |
| } | |
| // CHECK-LABEL: define dso_local void @_Z24test_atomic_thread_fencev( | |
| // CHECK-SAME: ) #[[ATTR0]] { | |
| // CHECK-NEXT: entry: | |
| // CHECK-NEXT: fence seq_cst, !mmra [[META2]] | |
| // CHECK-NEXT: ret void | |
| // | |
| void test_atomic_thread_fence() { | |
| [[clang::amdgpu_av("none")]] __atomic_thread_fence(__ATOMIC_SEQ_CST); | |
| } | |
| // Verify that without the attribute, no !mmra metadata is emitted. | |
| // CHECK-LABEL: define dso_local void @_Z12test_no_attrPi( | |
| // CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { | |
| // CHECK-NEXT: entry: | |
| // CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) | |
| // CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4, addrspace(5) | |
| // CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4, 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 i32 1, ptr addrspace(5) [[DOTATOMICTMP]], align 4 | |
| // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(5) [[DOTATOMICTMP]], align 4 | |
| // CHECK-NEXT: [[TMP2:%.*]] = atomicrmw add ptr [[TMP0]], i32 [[TMP1]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META3]], !amdgpu.no.remote.memory [[META3]] | |
| // CHECK-NEXT: store i32 [[TMP2]], ptr addrspace(5) [[ATOMIC_TEMP]], align 4 | |
| // CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr addrspace(5) [[ATOMIC_TEMP]], align 4 | |
| // CHECK-NEXT: ret void | |
| // | |
| void test_no_attr(int *p) { | |
| __atomic_fetch_add(p, 1, __ATOMIC_SEQ_CST); | |
| } | |
| //. | |
| // CHECK: [[META2]] = !{!"amdgcn-av", !"none"} | |
| // CHECK: [[META3]] = !{} | |
| //. |