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