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; 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 18define 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 43define 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 67define 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 91define 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 115define 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 140define 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 165define 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 190define 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 215define 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 228define 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 241define 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 258define 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 274define 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