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 5define 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: movl %esi, %eax 9; FASTINCDEC-NEXT: lock incq (%rdi) 10; FASTINCDEC-NEXT: cmovgl %edx, %eax 11; FASTINCDEC-NEXT: retq 12; 13; SLOWINCDEC-LABEL: test_add_1_cmov_slt: 14; SLOWINCDEC: # %bb.0: # %entry 15; SLOWINCDEC-NEXT: movl %esi, %eax 16; SLOWINCDEC-NEXT: lock addq $1, (%rdi) 17; SLOWINCDEC-NEXT: cmovgl %edx, %eax 18; SLOWINCDEC-NEXT: retq 19entry: 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 26define 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: movl %esi, %eax 30; FASTINCDEC-NEXT: lock incq (%rdi) 31; FASTINCDEC-NEXT: cmovlel %edx, %eax 32; FASTINCDEC-NEXT: retq 33; 34; SLOWINCDEC-LABEL: test_add_1_cmov_sge: 35; SLOWINCDEC: # %bb.0: # %entry 36; SLOWINCDEC-NEXT: movl %esi, %eax 37; SLOWINCDEC-NEXT: lock addq $1, (%rdi) 38; SLOWINCDEC-NEXT: cmovlel %edx, %eax 39; SLOWINCDEC-NEXT: retq 40entry: 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 47define 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: movl %esi, %eax 51; FASTINCDEC-NEXT: lock decq (%rdi) 52; FASTINCDEC-NEXT: cmovgel %edx, %eax 53; FASTINCDEC-NEXT: retq 54; 55; SLOWINCDEC-LABEL: test_sub_1_cmov_sle: 56; SLOWINCDEC: # %bb.0: # %entry 57; SLOWINCDEC-NEXT: movl %esi, %eax 58; SLOWINCDEC-NEXT: lock addq $-1, (%rdi) 59; SLOWINCDEC-NEXT: cmovgel %edx, %eax 60; SLOWINCDEC-NEXT: retq 61entry: 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 68define 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: movl %esi, %eax 72; FASTINCDEC-NEXT: lock decq (%rdi) 73; FASTINCDEC-NEXT: cmovll %edx, %eax 74; FASTINCDEC-NEXT: retq 75; 76; SLOWINCDEC-LABEL: test_sub_1_cmov_sgt: 77; SLOWINCDEC: # %bb.0: # %entry 78; SLOWINCDEC-NEXT: movl %esi, %eax 79; SLOWINCDEC-NEXT: lock addq $-1, (%rdi) 80; SLOWINCDEC-NEXT: cmovll %edx, %eax 81; SLOWINCDEC-NEXT: retq 82entry: 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. 90define 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 98entry: 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 105define 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 117entry: 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 124define 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 146entry: 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 150t: 151 ret i32 %a0 152f: 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 159define 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 %esi, %eax 163; CHECK-NEXT: movl $1, %ecx 164; CHECK-NEXT: lock xaddq %rcx, (%rdi) 165; CHECK-NEXT: testq %rcx, %rcx 166; CHECK-NEXT: cmovgl %edx, %eax 167; CHECK-NEXT: retq 168entry: 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 175define 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 %esi, %eax 179; CHECK-NEXT: movl $1, %ecx 180; CHECK-NEXT: lock xaddq %rcx, (%rdi) 181; CHECK-NEXT: testq %rcx, %rcx 182; CHECK-NEXT: cmovlel %edx, %eax 183; CHECK-NEXT: retq 184entry: 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 193define 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 202entry: 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 210define 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 218entry: 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 225define 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 232entry: 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 241define 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 253entry: 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 260define 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 272entry: 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 279define 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 285entry: 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. 294define 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 302entry: 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 309define 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 315entry: 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. 324define 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 332entry: 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 339attributes #0 = { nounwind } 340