1// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 2// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -O3 -o - -triple=amdgcn-amd-amdhsa \ 3// RUN: | FileCheck %s --check-prefix=AMDGCN 4// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -O3 -o - -triple=spirv64-unknown-unknown \ 5// RUN: | FileCheck %s --check-prefix=SPIRV 6 7// AMDGCN-LABEL: define dso_local i32 @load( 8// AMDGCN-SAME: ptr noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { 9// AMDGCN-NEXT: [[ENTRY:.*:]] 10// AMDGCN-NEXT: [[TMP0:%.*]] = load atomic i32, ptr [[P]] syncscope("agent") seq_cst, align 4 11// AMDGCN-NEXT: ret i32 [[TMP0]] 12// 13// SPIRV-LABEL: define spir_func i32 @load( 14// SPIRV-SAME: ptr addrspace(4) noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { 15// SPIRV-NEXT: [[ENTRY:.*:]] 16// SPIRV-NEXT: [[TMP0:%.*]] = load atomic i32, ptr addrspace(4) [[P]] syncscope("device") seq_cst, align 4 17// SPIRV-NEXT: ret i32 [[TMP0]] 18// 19int load(int *p) { return __atomic_load_n(p, __ATOMIC_SEQ_CST); } 20// AMDGCN-LABEL: define dso_local void @store( 21// AMDGCN-SAME: ptr noundef writeonly captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 22// AMDGCN-NEXT: [[ENTRY:.*:]] 23// AMDGCN-NEXT: store atomic i32 [[X]], ptr [[P]] syncscope("agent") seq_cst, align 4 24// AMDGCN-NEXT: ret void 25// 26// SPIRV-LABEL: define spir_func void @store( 27// SPIRV-SAME: ptr addrspace(4) noundef writeonly captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 28// SPIRV-NEXT: [[ENTRY:.*:]] 29// SPIRV-NEXT: store atomic i32 [[X]], ptr addrspace(4) [[P]] syncscope("device") seq_cst, align 4 30// SPIRV-NEXT: ret void 31// 32void store(int *p, int x) { return __atomic_store_n(p, x, __ATOMIC_SEQ_CST); } 33// AMDGCN-LABEL: define dso_local i32 @add( 34// AMDGCN-SAME: ptr noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 35// AMDGCN-NEXT: [[ENTRY:.*:]] 36// AMDGCN-NEXT: [[TMP0:%.*]] = atomicrmw add ptr [[P]], i32 [[X]] syncscope("agent") seq_cst, align 4 37// AMDGCN-NEXT: ret i32 [[TMP0]] 38// 39// SPIRV-LABEL: define spir_func i32 @add( 40// SPIRV-SAME: ptr addrspace(4) noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 41// SPIRV-NEXT: [[ENTRY:.*:]] 42// SPIRV-NEXT: [[TMP0:%.*]] = atomicrmw add ptr addrspace(4) [[P]], i32 [[X]] syncscope("device") seq_cst, align 4 43// SPIRV-NEXT: ret i32 [[TMP0]] 44// 45int add(int *p, int x) { return __atomic_fetch_add(p, x, __ATOMIC_SEQ_CST); } 46// AMDGCN-LABEL: define dso_local float @fadd( 47// AMDGCN-SAME: ptr noundef captures(none) [[P:%.*]], float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 48// AMDGCN-NEXT: [[ENTRY:.*:]] 49// AMDGCN-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr [[P]], float [[X]] syncscope("agent") seq_cst, align 4 50// AMDGCN-NEXT: ret float [[TMP0]] 51// 52// SPIRV-LABEL: define spir_func float @fadd( 53// SPIRV-SAME: ptr addrspace(4) noundef captures(none) [[P:%.*]], float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 54// SPIRV-NEXT: [[ENTRY:.*:]] 55// SPIRV-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr addrspace(4) [[P]], float [[X]] syncscope("device") seq_cst, align 4 56// SPIRV-NEXT: ret float [[TMP0]] 57// 58float fadd(float *p, float x) { return __atomic_fetch_add(p, x, __ATOMIC_SEQ_CST); } 59// AMDGCN-LABEL: define dso_local i32 @sub( 60// AMDGCN-SAME: ptr noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 61// AMDGCN-NEXT: [[ENTRY:.*:]] 62// AMDGCN-NEXT: [[TMP0:%.*]] = atomicrmw sub ptr [[P]], i32 [[X]] syncscope("agent") seq_cst, align 4 63// AMDGCN-NEXT: ret i32 [[TMP0]] 64// 65// SPIRV-LABEL: define spir_func i32 @sub( 66// SPIRV-SAME: ptr addrspace(4) noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 67// SPIRV-NEXT: [[ENTRY:.*:]] 68// SPIRV-NEXT: [[TMP0:%.*]] = atomicrmw sub ptr addrspace(4) [[P]], i32 [[X]] syncscope("device") seq_cst, align 4 69// SPIRV-NEXT: ret i32 [[TMP0]] 70// 71int sub(int *p, int x) { return __atomic_fetch_sub(p, x, __ATOMIC_SEQ_CST); } 72// AMDGCN-LABEL: define dso_local float @fsub( 73// AMDGCN-SAME: ptr noundef captures(none) [[P:%.*]], float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 74// AMDGCN-NEXT: [[ENTRY:.*:]] 75// AMDGCN-NEXT: [[TMP0:%.*]] = atomicrmw fsub ptr [[P]], float [[X]] syncscope("agent") seq_cst, align 4 76// AMDGCN-NEXT: ret float [[TMP0]] 77// 78// SPIRV-LABEL: define spir_func float @fsub( 79// SPIRV-SAME: ptr addrspace(4) noundef captures(none) [[P:%.*]], float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 80// SPIRV-NEXT: [[ENTRY:.*:]] 81// SPIRV-NEXT: [[TMP0:%.*]] = atomicrmw fsub ptr addrspace(4) [[P]], float [[X]] syncscope("device") seq_cst, align 4 82// SPIRV-NEXT: ret float [[TMP0]] 83// 84float fsub(float *p, float x) { return __atomic_fetch_sub(p, x, __ATOMIC_SEQ_CST); } 85// AMDGCN-LABEL: define dso_local i32 @and( 86// AMDGCN-SAME: ptr noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 87// AMDGCN-NEXT: [[ENTRY:.*:]] 88// AMDGCN-NEXT: [[TMP0:%.*]] = atomicrmw and ptr [[P]], i32 [[X]] syncscope("agent") seq_cst, align 4 89// AMDGCN-NEXT: ret i32 [[TMP0]] 90// 91// SPIRV-LABEL: define spir_func i32 @and( 92// SPIRV-SAME: ptr addrspace(4) noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 93// SPIRV-NEXT: [[ENTRY:.*:]] 94// SPIRV-NEXT: [[TMP0:%.*]] = atomicrmw and ptr addrspace(4) [[P]], i32 [[X]] syncscope("device") seq_cst, align 4 95// SPIRV-NEXT: ret i32 [[TMP0]] 96// 97int and(int *p, int x) { return __atomic_fetch_and(p, x, __ATOMIC_SEQ_CST); } 98// AMDGCN-LABEL: define dso_local i32 @nand( 99// AMDGCN-SAME: ptr noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 100// AMDGCN-NEXT: [[ENTRY:.*:]] 101// AMDGCN-NEXT: [[TMP0:%.*]] = atomicrmw nand ptr [[P]], i32 [[X]] syncscope("agent") seq_cst, align 4 102// AMDGCN-NEXT: ret i32 [[TMP0]] 103// 104// SPIRV-LABEL: define spir_func i32 @nand( 105// SPIRV-SAME: ptr addrspace(4) noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 106// SPIRV-NEXT: [[ENTRY:.*:]] 107// SPIRV-NEXT: [[TMP0:%.*]] = atomicrmw nand ptr addrspace(4) [[P]], i32 [[X]] syncscope("device") seq_cst, align 4 108// SPIRV-NEXT: ret i32 [[TMP0]] 109// 110int nand(int *p, int x) { return __atomic_fetch_nand(p, x, __ATOMIC_SEQ_CST); } 111// AMDGCN-LABEL: define dso_local i32 @or( 112// AMDGCN-SAME: ptr noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 113// AMDGCN-NEXT: [[ENTRY:.*:]] 114// AMDGCN-NEXT: [[TMP0:%.*]] = atomicrmw or ptr [[P]], i32 [[X]] syncscope("agent") seq_cst, align 4 115// AMDGCN-NEXT: ret i32 [[TMP0]] 116// 117// SPIRV-LABEL: define spir_func i32 @or( 118// SPIRV-SAME: ptr addrspace(4) noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 119// SPIRV-NEXT: [[ENTRY:.*:]] 120// SPIRV-NEXT: [[TMP0:%.*]] = atomicrmw or ptr addrspace(4) [[P]], i32 [[X]] syncscope("device") seq_cst, align 4 121// SPIRV-NEXT: ret i32 [[TMP0]] 122// 123int or(int *p, int x) { return __atomic_fetch_or(p, x, __ATOMIC_SEQ_CST); } 124// AMDGCN-LABEL: define dso_local i32 @xor( 125// AMDGCN-SAME: ptr noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 126// AMDGCN-NEXT: [[ENTRY:.*:]] 127// AMDGCN-NEXT: [[TMP0:%.*]] = atomicrmw xor ptr [[P]], i32 [[X]] syncscope("agent") seq_cst, align 4 128// AMDGCN-NEXT: ret i32 [[TMP0]] 129// 130// SPIRV-LABEL: define spir_func i32 @xor( 131// SPIRV-SAME: ptr addrspace(4) noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 132// SPIRV-NEXT: [[ENTRY:.*:]] 133// SPIRV-NEXT: [[TMP0:%.*]] = atomicrmw xor ptr addrspace(4) [[P]], i32 [[X]] syncscope("device") seq_cst, align 4 134// SPIRV-NEXT: ret i32 [[TMP0]] 135// 136int xor(int *p, int x) { return __atomic_fetch_xor(p, x, __ATOMIC_SEQ_CST); } 137// AMDGCN-LABEL: define dso_local i32 @min( 138// AMDGCN-SAME: ptr noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 139// AMDGCN-NEXT: [[ENTRY:.*:]] 140// AMDGCN-NEXT: [[TMP0:%.*]] = atomicrmw min ptr [[P]], i32 [[X]] syncscope("agent") seq_cst, align 4 141// AMDGCN-NEXT: ret i32 [[TMP0]] 142// 143// SPIRV-LABEL: define spir_func i32 @min( 144// SPIRV-SAME: ptr addrspace(4) noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 145// SPIRV-NEXT: [[ENTRY:.*:]] 146// SPIRV-NEXT: [[TMP0:%.*]] = atomicrmw min ptr addrspace(4) [[P]], i32 [[X]] syncscope("device") seq_cst, align 4 147// SPIRV-NEXT: ret i32 [[TMP0]] 148// 149int min(int *p, int x) { return __atomic_fetch_min(p, x, __ATOMIC_SEQ_CST); } 150// AMDGCN-LABEL: define dso_local float @fmin( 151// AMDGCN-SAME: ptr noundef captures(none) [[P:%.*]], float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 152// AMDGCN-NEXT: [[ENTRY:.*:]] 153// AMDGCN-NEXT: [[TMP0:%.*]] = atomicrmw fmin ptr [[P]], float [[X]] syncscope("agent") seq_cst, align 4 154// AMDGCN-NEXT: ret float [[TMP0]] 155// 156// SPIRV-LABEL: define spir_func float @fmin( 157// SPIRV-SAME: ptr addrspace(4) noundef captures(none) [[P:%.*]], float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 158// SPIRV-NEXT: [[ENTRY:.*:]] 159// SPIRV-NEXT: [[TMP0:%.*]] = atomicrmw fmin ptr addrspace(4) [[P]], float [[X]] syncscope("device") seq_cst, align 4 160// SPIRV-NEXT: ret float [[TMP0]] 161// 162float fmin(float *p, float x) { return __atomic_fetch_min(p, x, __ATOMIC_SEQ_CST); } 163// AMDGCN-LABEL: define dso_local i32 @max( 164// AMDGCN-SAME: ptr noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 165// AMDGCN-NEXT: [[ENTRY:.*:]] 166// AMDGCN-NEXT: [[TMP0:%.*]] = atomicrmw max ptr [[P]], i32 [[X]] syncscope("agent") seq_cst, align 4 167// AMDGCN-NEXT: ret i32 [[TMP0]] 168// 169// SPIRV-LABEL: define spir_func i32 @max( 170// SPIRV-SAME: ptr addrspace(4) noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 171// SPIRV-NEXT: [[ENTRY:.*:]] 172// SPIRV-NEXT: [[TMP0:%.*]] = atomicrmw max ptr addrspace(4) [[P]], i32 [[X]] syncscope("device") seq_cst, align 4 173// SPIRV-NEXT: ret i32 [[TMP0]] 174// 175int max(int *p, int x) { return __atomic_fetch_max(p, x, __ATOMIC_SEQ_CST); } 176// AMDGCN-LABEL: define dso_local float @fmax( 177// AMDGCN-SAME: ptr noundef captures(none) [[P:%.*]], float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 178// AMDGCN-NEXT: [[ENTRY:.*:]] 179// AMDGCN-NEXT: [[TMP0:%.*]] = atomicrmw fmax ptr [[P]], float [[X]] syncscope("agent") seq_cst, align 4 180// AMDGCN-NEXT: ret float [[TMP0]] 181// 182// SPIRV-LABEL: define spir_func float @fmax( 183// SPIRV-SAME: ptr addrspace(4) noundef captures(none) [[P:%.*]], float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 184// SPIRV-NEXT: [[ENTRY:.*:]] 185// SPIRV-NEXT: [[TMP0:%.*]] = atomicrmw fmax ptr addrspace(4) [[P]], float [[X]] syncscope("device") seq_cst, align 4 186// SPIRV-NEXT: ret float [[TMP0]] 187// 188float fmax(float *p, float x) { return __atomic_fetch_max(p, x, __ATOMIC_SEQ_CST); } 189// AMDGCN-LABEL: define dso_local i32 @xchg( 190// AMDGCN-SAME: ptr noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 191// AMDGCN-NEXT: [[ENTRY:.*:]] 192// AMDGCN-NEXT: [[TMP0:%.*]] = atomicrmw xchg ptr [[P]], i32 [[X]] syncscope("agent") seq_cst, align 4 193// AMDGCN-NEXT: ret i32 [[TMP0]] 194// 195// SPIRV-LABEL: define spir_func i32 @xchg( 196// SPIRV-SAME: ptr addrspace(4) noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { 197// SPIRV-NEXT: [[ENTRY:.*:]] 198// SPIRV-NEXT: [[TMP0:%.*]] = atomicrmw xchg ptr addrspace(4) [[P]], i32 [[X]] syncscope("device") seq_cst, align 4 199// SPIRV-NEXT: ret i32 [[TMP0]] 200// 201int xchg(int *p, int x) { return __atomic_exchange_n(p, x, __ATOMIC_SEQ_CST); } 202// AMDGCN-LABEL: define dso_local range(i32 0, 2) i32 @cmpxchg( 203// AMDGCN-SAME: ptr noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] { 204// AMDGCN-NEXT: [[ENTRY:.*:]] 205// AMDGCN-NEXT: [[TMP0:%.*]] = cmpxchg ptr [[P]], i32 [[X]], i32 [[Y]] syncscope("agent") seq_cst seq_cst, align 4 206// AMDGCN-NEXT: [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1 207// AMDGCN-NEXT: [[CONV:%.*]] = zext i1 [[TMP1]] to i32 208// AMDGCN-NEXT: ret i32 [[CONV]] 209// 210// SPIRV-LABEL: define spir_func range(i32 0, 2) i32 @cmpxchg( 211// SPIRV-SAME: ptr addrspace(4) noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] { 212// SPIRV-NEXT: [[ENTRY:.*:]] 213// SPIRV-NEXT: [[TMP0:%.*]] = cmpxchg ptr addrspace(4) [[P]], i32 [[X]], i32 [[Y]] syncscope("device") seq_cst seq_cst, align 4 214// SPIRV-NEXT: [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1 215// SPIRV-NEXT: [[CONV:%.*]] = zext i1 [[TMP1]] to i32 216// SPIRV-NEXT: ret i32 [[CONV]] 217// 218int cmpxchg(int *p, int x, int y) { return __atomic_compare_exchange(p, &x, &y, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } 219// AMDGCN-LABEL: define dso_local range(i32 0, 2) i32 @cmpxchg_weak( 220// AMDGCN-SAME: ptr noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] { 221// AMDGCN-NEXT: [[ENTRY:.*:]] 222// AMDGCN-NEXT: [[TMP0:%.*]] = cmpxchg weak ptr [[P]], i32 [[X]], i32 [[Y]] syncscope("agent") seq_cst seq_cst, align 4 223// AMDGCN-NEXT: [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1 224// AMDGCN-NEXT: [[CONV:%.*]] = zext i1 [[TMP1]] to i32 225// AMDGCN-NEXT: ret i32 [[CONV]] 226// 227// SPIRV-LABEL: define spir_func range(i32 0, 2) i32 @cmpxchg_weak( 228// SPIRV-SAME: ptr addrspace(4) noundef captures(none) [[P:%.*]], i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] { 229// SPIRV-NEXT: [[ENTRY:.*:]] 230// SPIRV-NEXT: [[TMP0:%.*]] = cmpxchg weak ptr addrspace(4) [[P]], i32 [[X]], i32 [[Y]] syncscope("device") seq_cst seq_cst, align 4 231// SPIRV-NEXT: [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1 232// SPIRV-NEXT: [[CONV:%.*]] = zext i1 [[TMP1]] to i32 233// SPIRV-NEXT: ret i32 [[CONV]] 234// 235int cmpxchg_weak(int *p, int x, int y) { return __atomic_compare_exchange(p, &x, &y, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } 236