Home | History | Annotate | Download | only in X86
      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