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 %rsi, %rax 123 ; CHECK: setbe [[CMP:%[a-z0-9]+]] 124 ; CHECK: cmpq [[INCHI]], %rdx 125 ; CHECK: setle [[HICMP:%[a-z0-9]+]] 126 ; CHECK: je [[USE_LO:.?LBB[0-9]+_[0-9]+]] 127 128 ; CHECK: movb [[HICMP]], [[CMP]] 129 ; CHECK: [[USE_LO]]: 130 ; CHECK: testb [[CMP]], [[CMP]] 131 ; CHECK: movq %rsi, %rbx 132 ; CHECK: cmovneq %rax, %rbx 133 ; CHECK: movq [[INCHI]], %rcx 134 ; CHECK: cmovneq %rdx, %rcx 135 ; CHECK: lock 136 ; CHECK: cmpxchg16b (%rdi) 137 ; CHECK: jne [[LOOP]] 138 139 ; CHECK: movq %rax, _var 140 ; CHECK: movq %rdx, _var+8 141 142 %val = atomicrmw min i128* %p, i128 %bits seq_cst 143 store i128 %val, i128* @var, align 16 144 ret void 145 } 146 147 define void @fetch_and_max(i128* %p, i128 %bits) { 148 ; CHECK-LABEL: fetch_and_max: 149 ; CHECK-DAG: movq %rdx, [[INCHI:%[a-z0-9]+]] 150 ; CHECK-DAG: movq (%rdi), %rax 151 ; CHECK-DAG: movq 8(%rdi), %rdx 152 153 ; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]: 154 ; CHECK: cmpq %rsi, %rax 155 ; CHECK: setae [[CMP:%[a-z0-9]+]] 156 ; CHECK: cmpq [[INCHI]], %rdx 157 ; CHECK: setge [[HICMP:%[a-z0-9]+]] 158 ; CHECK: je [[USE_LO:.?LBB[0-9]+_[0-9]+]] 159 160 ; CHECK: movb [[HICMP]], [[CMP]] 161 ; CHECK: [[USE_LO]]: 162 ; CHECK: testb [[CMP]], [[CMP]] 163 ; CHECK: movq %rsi, %rbx 164 ; CHECK: cmovneq %rax, %rbx 165 ; CHECK: movq [[INCHI]], %rcx 166 ; CHECK: cmovneq %rdx, %rcx 167 ; CHECK: lock 168 ; CHECK: cmpxchg16b (%rdi) 169 ; CHECK: jne [[LOOP]] 170 171 ; CHECK: movq %rax, _var 172 ; CHECK: movq %rdx, _var+8 173 174 %val = atomicrmw max i128* %p, i128 %bits seq_cst 175 store i128 %val, i128* @var, align 16 176 ret void 177 } 178 179 define void @fetch_and_umin(i128* %p, i128 %bits) { 180 ; CHECK-LABEL: fetch_and_umin: 181 ; CHECK-DAG: movq %rdx, [[INCHI:%[a-z0-9]+]] 182 ; CHECK-DAG: movq (%rdi), %rax 183 ; CHECK-DAG: movq 8(%rdi), %rdx 184 185 ; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]: 186 ; CHECK: cmpq %rsi, %rax 187 ; CHECK: setbe [[CMP:%[a-z0-9]+]] 188 ; CHECK: cmpq [[INCHI]], %rdx 189 ; CHECK: setbe [[HICMP:%[a-z0-9]+]] 190 ; CHECK: je [[USE_LO:.?LBB[0-9]+_[0-9]+]] 191 192 ; CHECK: movb [[HICMP]], [[CMP]] 193 ; CHECK: [[USE_LO]]: 194 ; CHECK: testb [[CMP]], [[CMP]] 195 ; CHECK: movq %rsi, %rbx 196 ; CHECK: cmovneq %rax, %rbx 197 ; CHECK: movq [[INCHI]], %rcx 198 ; CHECK: cmovneq %rdx, %rcx 199 ; CHECK: lock 200 ; CHECK: cmpxchg16b (%rdi) 201 ; CHECK: jne [[LOOP]] 202 203 ; CHECK: movq %rax, _var 204 ; CHECK: movq %rdx, _var+8 205 206 %val = atomicrmw umin i128* %p, i128 %bits seq_cst 207 store i128 %val, i128* @var, align 16 208 ret void 209 } 210 211 define void @fetch_and_umax(i128* %p, i128 %bits) { 212 ; CHECK-LABEL: fetch_and_umax: 213 ; CHECK-DAG: movq %rdx, [[INCHI:%[a-z0-9]+]] 214 ; CHECK-DAG: movq (%rdi), %rax 215 ; CHECK-DAG: movq 8(%rdi), %rdx 216 217 ; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]: 218 ; CHECK: cmpq %rax, %rsi 219 ; CHECK: setb [[CMP:%[a-z0-9]+]] 220 ; CHECK: cmpq [[INCHI]], %rdx 221 ; CHECK: seta [[HICMP:%[a-z0-9]+]] 222 ; CHECK: je [[USE_LO:.?LBB[0-9]+_[0-9]+]] 223 224 ; CHECK: movb [[HICMP]], [[CMP]] 225 ; CHECK: [[USE_LO]]: 226 ; CHECK: testb [[CMP]], [[CMP]] 227 ; CHECK: movq %rsi, %rbx 228 ; CHECK: cmovneq %rax, %rbx 229 ; CHECK: movq [[INCHI]], %rcx 230 ; CHECK: cmovneq %rdx, %rcx 231 ; CHECK: lock 232 ; CHECK: cmpxchg16b (%rdi) 233 ; CHECK: jne [[LOOP]] 234 235 ; CHECK: movq %rax, _var 236 ; CHECK: movq %rdx, _var+8 237 238 %val = atomicrmw umax i128* %p, i128 %bits seq_cst 239 store i128 %val, i128* @var, align 16 240 ret void 241 } 242 243 define i128 @atomic_load_seq_cst(i128* %p) { 244 ; CHECK-LABEL: atomic_load_seq_cst: 245 ; CHECK: xorl %eax, %eax 246 ; CHECK: xorl %edx, %edx 247 ; CHECK: xorl %ebx, %ebx 248 ; CHECK: xorl %ecx, %ecx 249 ; CHECK: lock 250 ; CHECK: cmpxchg16b (%rdi) 251 252 %r = load atomic i128, i128* %p seq_cst, align 16 253 ret i128 %r 254 } 255 256 define i128 @atomic_load_relaxed(i128* %p) { 257 ; CHECK: atomic_load_relaxed: 258 ; CHECK: xorl %eax, %eax 259 ; CHECK: xorl %edx, %edx 260 ; CHECK: xorl %ebx, %ebx 261 ; CHECK: xorl %ecx, %ecx 262 ; CHECK: lock 263 ; CHECK: cmpxchg16b (%rdi) 264 265 %r = load atomic i128, i128* %p monotonic, align 16 266 ret i128 %r 267 } 268 269 define void @atomic_store_seq_cst(i128* %p, i128 %in) { 270 ; CHECK-LABEL: atomic_store_seq_cst: 271 ; CHECK: movq %rdx, %rcx 272 ; CHECK: movq %rsi, %rbx 273 ; CHECK: movq (%rdi), %rax 274 ; CHECK: movq 8(%rdi), %rdx 275 276 ; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]: 277 ; CHECK: lock 278 ; CHECK: cmpxchg16b (%rdi) 279 ; CHECK: jne [[LOOP]] 280 ; CHECK-NOT: callq ___sync_lock_test_and_set_16 281 282 store atomic i128 %in, i128* %p seq_cst, align 16 283 ret void 284 } 285 286 define void @atomic_store_release(i128* %p, i128 %in) { 287 ; CHECK-LABEL: atomic_store_release: 288 ; CHECK: movq %rdx, %rcx 289 ; CHECK: movq %rsi, %rbx 290 ; CHECK: movq (%rdi), %rax 291 ; CHECK: movq 8(%rdi), %rdx 292 293 ; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]: 294 ; CHECK: lock 295 ; CHECK: cmpxchg16b (%rdi) 296 ; CHECK: jne [[LOOP]] 297 298 store atomic i128 %in, i128* %p release, align 16 299 ret void 300 } 301 302 define void @atomic_store_relaxed(i128* %p, i128 %in) { 303 ; CHECK-LABEL: atomic_store_relaxed: 304 ; CHECK: movq %rdx, %rcx 305 ; CHECK: movq %rsi, %rbx 306 ; CHECK: movq (%rdi), %rax 307 ; CHECK: movq 8(%rdi), %rdx 308 309 ; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]: 310 ; CHECK: lock 311 ; CHECK: cmpxchg16b (%rdi) 312 ; CHECK: jne [[LOOP]] 313 314 store atomic i128 %in, i128* %p unordered, align 16 315 ret void 316 } 317