1 ; RUN: llc < %s -mtriple=x86_64-apple-macosx10.9 -verify-machineinstrs -mattr=cx16 | FileCheck %s 2 3 @var = global i128 0 4 5 define i128 @val_compare_and_swap(i128* %p, i128 %oldval, i128 %newval) { 6 ; CHECK-LABEL: val_compare_and_swap: 7 ; CHECK: movq %rsi, %rax 8 ; CHECK: movq %rcx, %rbx 9 ; CHECK: movq %r8, %rcx 10 ; CHECK: lock 11 ; CHECK: cmpxchg16b (%rdi) 12 13 %pair = cmpxchg i128* %p, i128 %oldval, i128 %newval acquire acquire 14 %val = extractvalue { i128, i1 } %pair, 0 15 ret i128 %val 16 } 17 18 define void @fetch_and_nand(i128* %p, i128 %bits) { 19 ; CHECK-LABEL: fetch_and_nand: 20 ; CHECK-DAG: movq %rdx, [[INCHI:%[a-z0-9]+]] 21 ; CHECK-DAG: movq (%rdi), %rax 22 ; CHECK-DAG: movq 8(%rdi), %rdx 23 24 ; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]: 25 ; CHECK: movq %rdx, %rcx 26 ; CHECK: andq [[INCHI]], %rcx 27 ; CHECK: movq %rax, %rbx 28 ; INCLO equivalent comes in in %rsi, so it makes sense it stays there. 29 ; CHECK: andq %rsi, %rbx 30 ; CHECK: notq %rbx 31 ; CHECK: notq %rcx 32 ; CHECK: lock 33 ; CHECK: cmpxchg16b (%rdi) 34 ; CHECK: jne [[LOOP]] 35 36 ; CHECK: movq %rax, _var 37 ; CHECK: movq %rdx, _var+8 38 %val = atomicrmw nand i128* %p, i128 %bits release 39 store i128 %val, i128* @var, align 16 40 ret void 41 } 42 43 define void @fetch_and_or(i128* %p, i128 %bits) { 44 ; CHECK-LABEL: fetch_and_or: 45 ; CHECK-DAG: movq %rdx, [[INCHI:%[a-z0-9]+]] 46 ; CHECK-DAG: movq (%rdi), %rax 47 ; CHECK-DAG: movq 8(%rdi), %rdx 48 49 ; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]: 50 ; CHECK: movq %rax, %rbx 51 ; INCLO equivalent comes in in %rsi, so it makes sense it stays there. 52 ; CHECK: orq %rsi, %rbx 53 ; CHECK: movq %rdx, %rcx 54 ; CHECK: orq [[INCHI]], %rcx 55 ; CHECK: lock 56 ; CHECK: cmpxchg16b (%rdi) 57 ; CHECK: jne [[LOOP]] 58 59 ; CHECK: movq %rax, _var 60 ; CHECK: movq %rdx, _var+8 61 62 %val = atomicrmw or i128* %p, i128 %bits seq_cst 63 store i128 %val, i128* @var, align 16 64 ret void 65 } 66 67 define void @fetch_and_add(i128* %p, i128 %bits) { 68 ; CHECK-LABEL: fetch_and_add: 69 ; CHECK-DAG: movq %rdx, [[INCHI:%[a-z0-9]+]] 70 ; CHECK-DAG: movq (%rdi), %rax 71 ; CHECK-DAG: movq 8(%rdi), %rdx 72 73 ; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]: 74 ; CHECK: movq %rax, %rbx 75 ; INCLO equivalent comes in in %rsi, so it makes sense it stays there. 76 ; CHECK: addq %rsi, %rbx 77 ; CHECK: movq %rdx, %rcx 78 ; CHECK: adcq [[INCHI]], %rcx 79 ; CHECK: lock 80 ; CHECK: cmpxchg16b (%rdi) 81 ; CHECK: jne [[LOOP]] 82 83 ; CHECK: movq %rax, _var 84 ; CHECK: movq %rdx, _var+8 85 86 %val = atomicrmw add i128* %p, i128 %bits seq_cst 87 store i128 %val, i128* @var, align 16 88 ret void 89 } 90 91 define void @fetch_and_sub(i128* %p, i128 %bits) { 92 ; CHECK-LABEL: fetch_and_sub: 93 ; CHECK-DAG: movq %rdx, [[INCHI:%[a-z0-9]+]] 94 ; CHECK-DAG: movq (%rdi), %rax 95 ; CHECK-DAG: movq 8(%rdi), %rdx 96 97 ; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]: 98 ; CHECK: movq %rax, %rbx 99 ; INCLO equivalent comes in in %rsi, so it makes sense it stays there. 100 ; CHECK: subq %rsi, %rbx 101 ; CHECK: movq %rdx, %rcx 102 ; CHECK: sbbq [[INCHI]], %rcx 103 ; CHECK: lock 104 ; CHECK: cmpxchg16b (%rdi) 105 ; CHECK: jne [[LOOP]] 106 107 ; CHECK: movq %rax, _var 108 ; CHECK: movq %rdx, _var+8 109 110 %val = atomicrmw sub i128* %p, i128 %bits seq_cst 111 store i128 %val, i128* @var, align 16 112 ret void 113 } 114 115 define void @fetch_and_min(i128* %p, i128 %bits) { 116 ; CHECK-LABEL: fetch_and_min: 117 ; CHECK-DAG: movq %rdx, [[INCHI:%[a-z0-9]+]] 118 ; CHECK-DAG: movq (%rdi), %rax 119 ; CHECK-DAG: movq 8(%rdi), %rdx 120 121 ; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]: 122 ; CHECK: cmpq 123 ; CHECK: sbbq 124 ; CHECK: setg 125 ; CHECK: cmovneq %rax, %rbx 126 ; CHECK: movq [[INCHI]], %rcx 127 ; CHECK: cmovneq %rdx, %rcx 128 ; CHECK: lock 129 ; CHECK: cmpxchg16b (%rdi) 130 ; CHECK: jne [[LOOP]] 131 132 ; CHECK: movq %rax, _var 133 ; CHECK: movq %rdx, _var+8 134 135 %val = atomicrmw min i128* %p, i128 %bits seq_cst 136 store i128 %val, i128* @var, align 16 137 ret void 138 } 139 140 define void @fetch_and_max(i128* %p, i128 %bits) { 141 ; CHECK-LABEL: fetch_and_max: 142 ; CHECK-DAG: movq %rdx, [[INCHI:%[a-z0-9]+]] 143 ; CHECK-DAG: movq (%rdi), %rax 144 ; CHECK-DAG: movq 8(%rdi), %rdx 145 146 ; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]: 147 ; CHECK: cmpq 148 ; CHECK: sbbq 149 ; CHECK: setge 150 ; CHECK: cmovneq %rax, %rbx 151 ; CHECK: movq [[INCHI]], %rcx 152 ; CHECK: cmovneq %rdx, %rcx 153 ; CHECK: lock 154 ; CHECK: cmpxchg16b (%rdi) 155 ; CHECK: jne [[LOOP]] 156 157 ; CHECK: movq %rax, _var 158 ; CHECK: movq %rdx, _var+8 159 160 %val = atomicrmw max i128* %p, i128 %bits seq_cst 161 store i128 %val, i128* @var, align 16 162 ret void 163 } 164 165 define void @fetch_and_umin(i128* %p, i128 %bits) { 166 ; CHECK-LABEL: fetch_and_umin: 167 ; CHECK-DAG: movq %rdx, [[INCHI:%[a-z0-9]+]] 168 ; CHECK-DAG: movq (%rdi), %rax 169 ; CHECK-DAG: movq 8(%rdi), %rdx 170 171 ; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]: 172 ; CHECK: cmpq 173 ; CHECK: sbbq 174 ; CHECK: seta 175 ; CHECK: cmovneq %rax, %rbx 176 ; CHECK: movq [[INCHI]], %rcx 177 ; CHECK: cmovneq %rdx, %rcx 178 ; CHECK: lock 179 ; CHECK: cmpxchg16b (%rdi) 180 ; CHECK: jne [[LOOP]] 181 182 ; CHECK: movq %rax, _var 183 ; CHECK: movq %rdx, _var+8 184 185 %val = atomicrmw umin i128* %p, i128 %bits seq_cst 186 store i128 %val, i128* @var, align 16 187 ret void 188 } 189 190 define void @fetch_and_umax(i128* %p, i128 %bits) { 191 ; CHECK-LABEL: fetch_and_umax: 192 ; CHECK-DAG: movq %rdx, [[INCHI:%[a-z0-9]+]] 193 ; CHECK-DAG: movq (%rdi), %rax 194 ; CHECK-DAG: movq 8(%rdi), %rdx 195 196 ; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]: 197 ; CHECK: cmpq 198 ; CHECK: sbbq 199 ; CHECK: setb 200 ; CHECK: cmovneq %rax, %rbx 201 ; CHECK: movq [[INCHI]], %rcx 202 ; CHECK: cmovneq %rdx, %rcx 203 ; CHECK: lock 204 ; CHECK: cmpxchg16b (%rdi) 205 ; CHECK: jne [[LOOP]] 206 207 ; CHECK: movq %rax, _var 208 ; CHECK: movq %rdx, _var+8 209 210 %val = atomicrmw umax i128* %p, i128 %bits seq_cst 211 store i128 %val, i128* @var, align 16 212 ret void 213 } 214 215 define i128 @atomic_load_seq_cst(i128* %p) { 216 ; CHECK-LABEL: atomic_load_seq_cst: 217 ; CHECK: xorl %eax, %eax 218 ; CHECK: xorl %edx, %edx 219 ; CHECK: xorl %ebx, %ebx 220 ; CHECK: xorl %ecx, %ecx 221 ; CHECK: lock 222 ; CHECK: cmpxchg16b (%rdi) 223 224 %r = load atomic i128, i128* %p seq_cst, align 16 225 ret i128 %r 226 } 227 228 define i128 @atomic_load_relaxed(i128* %p) { 229 ; CHECK: atomic_load_relaxed: 230 ; CHECK: xorl %eax, %eax 231 ; CHECK: xorl %edx, %edx 232 ; CHECK: xorl %ebx, %ebx 233 ; CHECK: xorl %ecx, %ecx 234 ; CHECK: lock 235 ; CHECK: cmpxchg16b (%rdi) 236 237 %r = load atomic i128, i128* %p monotonic, align 16 238 ret i128 %r 239 } 240 241 define void @atomic_store_seq_cst(i128* %p, i128 %in) { 242 ; CHECK-LABEL: atomic_store_seq_cst: 243 ; CHECK: movq %rdx, %rcx 244 ; CHECK: movq %rsi, %rbx 245 ; CHECK: movq (%rdi), %rax 246 ; CHECK: movq 8(%rdi), %rdx 247 248 ; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]: 249 ; CHECK: lock 250 ; CHECK: cmpxchg16b (%rdi) 251 ; CHECK: jne [[LOOP]] 252 ; CHECK-NOT: callq ___sync_lock_test_and_set_16 253 254 store atomic i128 %in, i128* %p seq_cst, align 16 255 ret void 256 } 257 258 define void @atomic_store_release(i128* %p, i128 %in) { 259 ; CHECK-LABEL: atomic_store_release: 260 ; CHECK: movq %rdx, %rcx 261 ; CHECK: movq %rsi, %rbx 262 ; CHECK: movq (%rdi), %rax 263 ; CHECK: movq 8(%rdi), %rdx 264 265 ; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]: 266 ; CHECK: lock 267 ; CHECK: cmpxchg16b (%rdi) 268 ; CHECK: jne [[LOOP]] 269 270 store atomic i128 %in, i128* %p release, align 16 271 ret void 272 } 273 274 define void @atomic_store_relaxed(i128* %p, i128 %in) { 275 ; CHECK-LABEL: atomic_store_relaxed: 276 ; CHECK: movq %rdx, %rcx 277 ; CHECK: movq %rsi, %rbx 278 ; CHECK: movq (%rdi), %rax 279 ; CHECK: movq 8(%rdi), %rdx 280 281 ; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]: 282 ; CHECK: lock 283 ; CHECK: cmpxchg16b (%rdi) 284 ; CHECK: jne [[LOOP]] 285 286 store atomic i128 %in, i128* %p unordered, align 16 287 ret void 288 } 289