1; RUN: llc < %s -mtriple=x86_64-apple-macosx10.9 -verify-machineinstrs -mattr=cx16 | FileCheck %s 2 3@var = global i128 0 4 5define 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 23define 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 48define 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 72define 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 96define 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 120define 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 145define 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 170define 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 195define 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 220define 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 233define 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 246define 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 263define 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 279define 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