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