Home | History | Annotate | Download | only in X86
      1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
      2 ; RUN: llc < %s -mtriple=x86_64-- | FileCheck %s --check-prefix=CHECK --check-prefix=FASTINCDEC
      3 ; RUN: llc < %s -mtriple=x86_64-- -mattr=slow-incdec | FileCheck %s --check-prefix=CHECK --check-prefix=SLOWINCDEC
      4 
      5 define i32 @test_add_1_cmov_slt(i64* %p, i32 %a0, i32 %a1) #0 {
      6 ; FASTINCDEC-LABEL: test_add_1_cmov_slt:
      7 ; FASTINCDEC:       # %bb.0: # %entry
      8 ; FASTINCDEC-NEXT:    lock incq (%rdi)
      9 ; FASTINCDEC-NEXT:    cmovgl %edx, %esi
     10 ; FASTINCDEC-NEXT:    movl %esi, %eax
     11 ; FASTINCDEC-NEXT:    retq
     12 ;
     13 ; SLOWINCDEC-LABEL: test_add_1_cmov_slt:
     14 ; SLOWINCDEC:       # %bb.0: # %entry
     15 ; SLOWINCDEC-NEXT:    lock addq $1, (%rdi)
     16 ; SLOWINCDEC-NEXT:    cmovgl %edx, %esi
     17 ; SLOWINCDEC-NEXT:    movl %esi, %eax
     18 ; SLOWINCDEC-NEXT:    retq
     19 entry:
     20   %tmp0 = atomicrmw add i64* %p, i64 1 seq_cst
     21   %tmp1 = icmp slt i64 %tmp0, 0
     22   %tmp2 = select i1 %tmp1, i32 %a0, i32 %a1
     23   ret i32 %tmp2
     24 }
     25 
     26 define i32 @test_add_1_cmov_sge(i64* %p, i32 %a0, i32 %a1) #0 {
     27 ; FASTINCDEC-LABEL: test_add_1_cmov_sge:
     28 ; FASTINCDEC:       # %bb.0: # %entry
     29 ; FASTINCDEC-NEXT:    lock incq (%rdi)
     30 ; FASTINCDEC-NEXT:    cmovlel %edx, %esi
     31 ; FASTINCDEC-NEXT:    movl %esi, %eax
     32 ; FASTINCDEC-NEXT:    retq
     33 ;
     34 ; SLOWINCDEC-LABEL: test_add_1_cmov_sge:
     35 ; SLOWINCDEC:       # %bb.0: # %entry
     36 ; SLOWINCDEC-NEXT:    lock addq $1, (%rdi)
     37 ; SLOWINCDEC-NEXT:    cmovlel %edx, %esi
     38 ; SLOWINCDEC-NEXT:    movl %esi, %eax
     39 ; SLOWINCDEC-NEXT:    retq
     40 entry:
     41   %tmp0 = atomicrmw add i64* %p, i64 1 seq_cst
     42   %tmp1 = icmp sge i64 %tmp0, 0
     43   %tmp2 = select i1 %tmp1, i32 %a0, i32 %a1
     44   ret i32 %tmp2
     45 }
     46 
     47 define i32 @test_sub_1_cmov_sle(i64* %p, i32 %a0, i32 %a1) #0 {
     48 ; FASTINCDEC-LABEL: test_sub_1_cmov_sle:
     49 ; FASTINCDEC:       # %bb.0: # %entry
     50 ; FASTINCDEC-NEXT:    lock decq (%rdi)
     51 ; FASTINCDEC-NEXT:    cmovgel %edx, %esi
     52 ; FASTINCDEC-NEXT:    movl %esi, %eax
     53 ; FASTINCDEC-NEXT:    retq
     54 ;
     55 ; SLOWINCDEC-LABEL: test_sub_1_cmov_sle:
     56 ; SLOWINCDEC:       # %bb.0: # %entry
     57 ; SLOWINCDEC-NEXT:    lock addq $-1, (%rdi)
     58 ; SLOWINCDEC-NEXT:    cmovgel %edx, %esi
     59 ; SLOWINCDEC-NEXT:    movl %esi, %eax
     60 ; SLOWINCDEC-NEXT:    retq
     61 entry:
     62   %tmp0 = atomicrmw sub i64* %p, i64 1 seq_cst
     63   %tmp1 = icmp sle i64 %tmp0, 0
     64   %tmp2 = select i1 %tmp1, i32 %a0, i32 %a1
     65   ret i32 %tmp2
     66 }
     67 
     68 define i32 @test_sub_1_cmov_sgt(i64* %p, i32 %a0, i32 %a1) #0 {
     69 ; FASTINCDEC-LABEL: test_sub_1_cmov_sgt:
     70 ; FASTINCDEC:       # %bb.0: # %entry
     71 ; FASTINCDEC-NEXT:    lock decq (%rdi)
     72 ; FASTINCDEC-NEXT:    cmovll %edx, %esi
     73 ; FASTINCDEC-NEXT:    movl %esi, %eax
     74 ; FASTINCDEC-NEXT:    retq
     75 ;
     76 ; SLOWINCDEC-LABEL: test_sub_1_cmov_sgt:
     77 ; SLOWINCDEC:       # %bb.0: # %entry
     78 ; SLOWINCDEC-NEXT:    lock addq $-1, (%rdi)
     79 ; SLOWINCDEC-NEXT:    cmovll %edx, %esi
     80 ; SLOWINCDEC-NEXT:    movl %esi, %eax
     81 ; SLOWINCDEC-NEXT:    retq
     82 entry:
     83   %tmp0 = atomicrmw sub i64* %p, i64 1 seq_cst
     84   %tmp1 = icmp sgt i64 %tmp0, 0
     85   %tmp2 = select i1 %tmp1, i32 %a0, i32 %a1
     86   ret i32 %tmp2
     87 }
     88 
     89 ; FIXME: (setcc slt x, 0) gets combined into shr early.
     90 define i8 @test_add_1_setcc_slt(i64* %p) #0 {
     91 ; CHECK-LABEL: test_add_1_setcc_slt:
     92 ; CHECK:       # %bb.0: # %entry
     93 ; CHECK-NEXT:    movl $1, %eax
     94 ; CHECK-NEXT:    lock xaddq %rax, (%rdi)
     95 ; CHECK-NEXT:    shrq $63, %rax
     96 ; CHECK-NEXT:    # kill: def $al killed $al killed $rax
     97 ; CHECK-NEXT:    retq
     98 entry:
     99   %tmp0 = atomicrmw add i64* %p, i64 1 seq_cst
    100   %tmp1 = icmp slt i64 %tmp0, 0
    101   %tmp2 = zext i1 %tmp1 to i8
    102   ret i8 %tmp2
    103 }
    104 
    105 define i8 @test_sub_1_setcc_sgt(i64* %p) #0 {
    106 ; FASTINCDEC-LABEL: test_sub_1_setcc_sgt:
    107 ; FASTINCDEC:       # %bb.0: # %entry
    108 ; FASTINCDEC-NEXT:    lock decq (%rdi)
    109 ; FASTINCDEC-NEXT:    setge %al
    110 ; FASTINCDEC-NEXT:    retq
    111 ;
    112 ; SLOWINCDEC-LABEL: test_sub_1_setcc_sgt:
    113 ; SLOWINCDEC:       # %bb.0: # %entry
    114 ; SLOWINCDEC-NEXT:    lock addq $-1, (%rdi)
    115 ; SLOWINCDEC-NEXT:    setge %al
    116 ; SLOWINCDEC-NEXT:    retq
    117 entry:
    118   %tmp0 = atomicrmw sub i64* %p, i64 1 seq_cst
    119   %tmp1 = icmp sgt i64 %tmp0, 0
    120   %tmp2 = zext i1 %tmp1 to i8
    121   ret i8 %tmp2
    122 }
    123 
    124 define i32 @test_add_1_brcond_sge(i64* %p, i32 %a0, i32 %a1) #0 {
    125 ; FASTINCDEC-LABEL: test_add_1_brcond_sge:
    126 ; FASTINCDEC:       # %bb.0: # %entry
    127 ; FASTINCDEC-NEXT:    lock incq (%rdi)
    128 ; FASTINCDEC-NEXT:    jle .LBB6_2
    129 ; FASTINCDEC-NEXT:  # %bb.1: # %t
    130 ; FASTINCDEC-NEXT:    movl %esi, %eax
    131 ; FASTINCDEC-NEXT:    retq
    132 ; FASTINCDEC-NEXT:  .LBB6_2: # %f
    133 ; FASTINCDEC-NEXT:    movl %edx, %eax
    134 ; FASTINCDEC-NEXT:    retq
    135 ;
    136 ; SLOWINCDEC-LABEL: test_add_1_brcond_sge:
    137 ; SLOWINCDEC:       # %bb.0: # %entry
    138 ; SLOWINCDEC-NEXT:    lock addq $1, (%rdi)
    139 ; SLOWINCDEC-NEXT:    jle .LBB6_2
    140 ; SLOWINCDEC-NEXT:  # %bb.1: # %t
    141 ; SLOWINCDEC-NEXT:    movl %esi, %eax
    142 ; SLOWINCDEC-NEXT:    retq
    143 ; SLOWINCDEC-NEXT:  .LBB6_2: # %f
    144 ; SLOWINCDEC-NEXT:    movl %edx, %eax
    145 ; SLOWINCDEC-NEXT:    retq
    146 entry:
    147   %tmp0 = atomicrmw add i64* %p, i64 1 seq_cst
    148   %tmp1 = icmp sge i64 %tmp0, 0
    149   br i1 %tmp1, label %t, label %f
    150 t:
    151   ret i32 %a0
    152 f:
    153   ret i32 %a1
    154 }
    155 
    156 ; Also make sure we don't muck with condition codes that we should ignore.
    157 ; No need to test unsigned comparisons, as they should all be simplified.
    158 
    159 define i32 @test_add_1_cmov_sle(i64* %p, i32 %a0, i32 %a1) #0 {
    160 ; CHECK-LABEL: test_add_1_cmov_sle:
    161 ; CHECK:       # %bb.0: # %entry
    162 ; CHECK-NEXT:    movl $1, %eax
    163 ; CHECK-NEXT:    lock xaddq %rax, (%rdi)
    164 ; CHECK-NEXT:    testq %rax, %rax
    165 ; CHECK-NEXT:    cmovgl %edx, %esi
    166 ; CHECK-NEXT:    movl %esi, %eax
    167 ; CHECK-NEXT:    retq
    168 entry:
    169   %tmp0 = atomicrmw add i64* %p, i64 1 seq_cst
    170   %tmp1 = icmp sle i64 %tmp0, 0
    171   %tmp2 = select i1 %tmp1, i32 %a0, i32 %a1
    172   ret i32 %tmp2
    173 }
    174 
    175 define i32 @test_add_1_cmov_sgt(i64* %p, i32 %a0, i32 %a1) #0 {
    176 ; CHECK-LABEL: test_add_1_cmov_sgt:
    177 ; CHECK:       # %bb.0: # %entry
    178 ; CHECK-NEXT:    movl $1, %eax
    179 ; CHECK-NEXT:    lock xaddq %rax, (%rdi)
    180 ; CHECK-NEXT:    testq %rax, %rax
    181 ; CHECK-NEXT:    cmovlel %edx, %esi
    182 ; CHECK-NEXT:    movl %esi, %eax
    183 ; CHECK-NEXT:    retq
    184 entry:
    185   %tmp0 = atomicrmw add i64* %p, i64 1 seq_cst
    186   %tmp1 = icmp sgt i64 %tmp0, 0
    187   %tmp2 = select i1 %tmp1, i32 %a0, i32 %a1
    188   ret i32 %tmp2
    189 }
    190 
    191 ; Test a result being used by more than just the comparison.
    192 
    193 define i8 @test_add_1_setcc_sgt_reuse(i64* %p, i64* %p2) #0 {
    194 ; CHECK-LABEL: test_add_1_setcc_sgt_reuse:
    195 ; CHECK:       # %bb.0: # %entry
    196 ; CHECK-NEXT:    movl $1, %ecx
    197 ; CHECK-NEXT:    lock xaddq %rcx, (%rdi)
    198 ; CHECK-NEXT:    testq %rcx, %rcx
    199 ; CHECK-NEXT:    setg %al
    200 ; CHECK-NEXT:    movq %rcx, (%rsi)
    201 ; CHECK-NEXT:    retq
    202 entry:
    203   %tmp0 = atomicrmw add i64* %p, i64 1 seq_cst
    204   %tmp1 = icmp sgt i64 %tmp0, 0
    205   %tmp2 = zext i1 %tmp1 to i8
    206   store i64 %tmp0, i64* %p2
    207   ret i8 %tmp2
    208 }
    209 
    210 define i8 @test_sub_2_setcc_sgt(i64* %p) #0 {
    211 ; CHECK-LABEL: test_sub_2_setcc_sgt:
    212 ; CHECK:       # %bb.0: # %entry
    213 ; CHECK-NEXT:    movq $-2, %rax
    214 ; CHECK-NEXT:    lock xaddq %rax, (%rdi)
    215 ; CHECK-NEXT:    testq %rax, %rax
    216 ; CHECK-NEXT:    setg %al
    217 ; CHECK-NEXT:    retq
    218 entry:
    219   %tmp0 = atomicrmw sub i64* %p, i64 2 seq_cst
    220   %tmp1 = icmp sgt i64 %tmp0, 0
    221   %tmp2 = zext i1 %tmp1 to i8
    222   ret i8 %tmp2
    223 }
    224 
    225 define i8 @test_add_1_cmov_cmov(i64* %p, i8* %q) #0 {
    226 ; TODO: It's possible to use "lock inc" here, but both cmovs need to be updated.
    227 ; CHECK-LABEL: test_add_1_cmov_cmov:
    228 ; CHECK:       # %bb.0: # %entry
    229 ; CHECK-NEXT:    movl $1, %eax
    230 ; CHECK-NEXT:    lock xaddq %rax, (%rdi)
    231 ; CHECK-NEXT:    testq   %rax, %rax
    232 entry:
    233   %add = atomicrmw add i64* %p, i64 1 seq_cst
    234   %cmp = icmp slt i64 %add, 0
    235   %s1 = select i1 %cmp, i8 12, i8 34
    236   store i8 %s1, i8* %q
    237   %s2 = select i1 %cmp, i8 56, i8 78
    238   ret i8 %s2
    239 }
    240 
    241 define i8 @test_sub_1_cmp_1_setcc_eq(i64* %p) #0 {
    242 ; FASTINCDEC-LABEL: test_sub_1_cmp_1_setcc_eq:
    243 ; FASTINCDEC:       # %bb.0: # %entry
    244 ; FASTINCDEC-NEXT:    lock decq (%rdi)
    245 ; FASTINCDEC-NEXT:    sete %al
    246 ; FASTINCDEC-NEXT:    retq
    247 ;
    248 ; SLOWINCDEC-LABEL: test_sub_1_cmp_1_setcc_eq:
    249 ; SLOWINCDEC:       # %bb.0: # %entry
    250 ; SLOWINCDEC-NEXT:    lock subq $1, (%rdi)
    251 ; SLOWINCDEC-NEXT:    sete %al
    252 ; SLOWINCDEC-NEXT:    retq
    253 entry:
    254   %tmp0 = atomicrmw sub i64* %p, i64 1 seq_cst
    255   %tmp1 = icmp eq i64 %tmp0, 1
    256   %tmp2 = zext i1 %tmp1 to i8
    257   ret i8 %tmp2
    258 }
    259 
    260 define i8 @test_sub_1_cmp_1_setcc_ne(i64* %p) #0 {
    261 ; FASTINCDEC-LABEL: test_sub_1_cmp_1_setcc_ne:
    262 ; FASTINCDEC:       # %bb.0: # %entry
    263 ; FASTINCDEC-NEXT:    lock decq (%rdi)
    264 ; FASTINCDEC-NEXT:    setne %al
    265 ; FASTINCDEC-NEXT:    retq
    266 ;
    267 ; SLOWINCDEC-LABEL: test_sub_1_cmp_1_setcc_ne:
    268 ; SLOWINCDEC:       # %bb.0: # %entry
    269 ; SLOWINCDEC-NEXT:    lock subq $1, (%rdi)
    270 ; SLOWINCDEC-NEXT:    setne %al
    271 ; SLOWINCDEC-NEXT:    retq
    272 entry:
    273   %tmp0 = atomicrmw sub i64* %p, i64 1 seq_cst
    274   %tmp1 = icmp ne i64 %tmp0, 1
    275   %tmp2 = zext i1 %tmp1 to i8
    276   ret i8 %tmp2
    277 }
    278 
    279 define i8 @test_sub_1_cmp_1_setcc_ugt(i64* %p) #0 {
    280 ; CHECK-LABEL: test_sub_1_cmp_1_setcc_ugt:
    281 ; CHECK:       # %bb.0: # %entry
    282 ; CHECK-NEXT:    lock subq $1, (%rdi)
    283 ; CHECK-NEXT:    seta %al
    284 ; CHECK-NEXT:    retq
    285 entry:
    286   %tmp0 = atomicrmw sub i64* %p, i64 1 seq_cst
    287   %tmp1 = icmp ugt i64 %tmp0, 1
    288   %tmp2 = zext i1 %tmp1 to i8
    289   ret i8 %tmp2
    290 }
    291 
    292 ; FIXME: This test canonicalizes in a way that hides the fact that the
    293 ; comparison can be folded into the atomic subtract.
    294 define i8 @test_sub_1_cmp_1_setcc_sle(i64* %p) #0 {
    295 ; CHECK-LABEL: test_sub_1_cmp_1_setcc_sle:
    296 ; CHECK:       # %bb.0: # %entry
    297 ; CHECK-NEXT:    movq $-1, %rax
    298 ; CHECK-NEXT:    lock xaddq %rax, (%rdi)
    299 ; CHECK-NEXT:    cmpq $2, %rax
    300 ; CHECK-NEXT:    setl %al
    301 ; CHECK-NEXT:    retq
    302 entry:
    303   %tmp0 = atomicrmw sub i64* %p, i64 1 seq_cst
    304   %tmp1 = icmp sle i64 %tmp0, 1
    305   %tmp2 = zext i1 %tmp1 to i8
    306   ret i8 %tmp2
    307 }
    308 
    309 define i8 @test_sub_3_cmp_3_setcc_eq(i64* %p) #0 {
    310 ; CHECK-LABEL: test_sub_3_cmp_3_setcc_eq:
    311 ; CHECK:       # %bb.0: # %entry
    312 ; CHECK-NEXT:    lock subq $3, (%rdi)
    313 ; CHECK-NEXT:    sete %al
    314 ; CHECK-NEXT:    retq
    315 entry:
    316   %tmp0 = atomicrmw sub i64* %p, i64 3 seq_cst
    317   %tmp1 = icmp eq i64 %tmp0, 3
    318   %tmp2 = zext i1 %tmp1 to i8
    319   ret i8 %tmp2
    320 }
    321 
    322 ; FIXME: This test canonicalizes in a way that hides the fact that the
    323 ; comparison can be folded into the atomic subtract.
    324 define i8 @test_sub_3_cmp_3_setcc_uge(i64* %p) #0 {
    325 ; CHECK-LABEL: test_sub_3_cmp_3_setcc_uge:
    326 ; CHECK:       # %bb.0: # %entry
    327 ; CHECK-NEXT:    movq $-3, %rax
    328 ; CHECK-NEXT:    lock xaddq %rax, (%rdi)
    329 ; CHECK-NEXT:    cmpq $2, %rax
    330 ; CHECK-NEXT:    seta %al
    331 ; CHECK-NEXT:    retq
    332 entry:
    333   %tmp0 = atomicrmw sub i64* %p, i64 3 seq_cst
    334   %tmp1 = icmp uge i64 %tmp0, 3
    335   %tmp2 = zext i1 %tmp1 to i8
    336   ret i8 %tmp2
    337 }
    338 
    339 attributes #0 = { nounwind }
    340