| // 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]] = !{} |
| //. |