You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			340 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			LLVM
		
	
	
	
	
	
			
		
		
	
	
			340 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			LLVM
		
	
	
	
	
	
| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 | |
| ; RUN: llc < %s -mtriple=x86_64-- | FileCheck %s --check-prefix=CHECK --check-prefix=FASTINCDEC
 | |
| ; RUN: llc < %s -mtriple=x86_64-- -mattr=slow-incdec | FileCheck %s --check-prefix=CHECK --check-prefix=SLOWINCDEC
 | |
| 
 | |
| define i32 @test_add_1_cmov_slt(i64* %p, i32 %a0, i32 %a1) #0 {
 | |
| ; FASTINCDEC-LABEL: test_add_1_cmov_slt:
 | |
| ; FASTINCDEC:       # %bb.0: # %entry
 | |
| ; FASTINCDEC-NEXT:    lock incq (%rdi)
 | |
| ; FASTINCDEC-NEXT:    cmovgl %edx, %esi
 | |
| ; FASTINCDEC-NEXT:    movl %esi, %eax
 | |
| ; FASTINCDEC-NEXT:    retq
 | |
| ;
 | |
| ; SLOWINCDEC-LABEL: test_add_1_cmov_slt:
 | |
| ; SLOWINCDEC:       # %bb.0: # %entry
 | |
| ; SLOWINCDEC-NEXT:    lock addq $1, (%rdi)
 | |
| ; SLOWINCDEC-NEXT:    cmovgl %edx, %esi
 | |
| ; SLOWINCDEC-NEXT:    movl %esi, %eax
 | |
| ; SLOWINCDEC-NEXT:    retq
 | |
| entry:
 | |
|   %tmp0 = atomicrmw add i64* %p, i64 1 seq_cst
 | |
|   %tmp1 = icmp slt i64 %tmp0, 0
 | |
|   %tmp2 = select i1 %tmp1, i32 %a0, i32 %a1
 | |
|   ret i32 %tmp2
 | |
| }
 | |
| 
 | |
| define i32 @test_add_1_cmov_sge(i64* %p, i32 %a0, i32 %a1) #0 {
 | |
| ; FASTINCDEC-LABEL: test_add_1_cmov_sge:
 | |
| ; FASTINCDEC:       # %bb.0: # %entry
 | |
| ; FASTINCDEC-NEXT:    lock incq (%rdi)
 | |
| ; FASTINCDEC-NEXT:    cmovlel %edx, %esi
 | |
| ; FASTINCDEC-NEXT:    movl %esi, %eax
 | |
| ; FASTINCDEC-NEXT:    retq
 | |
| ;
 | |
| ; SLOWINCDEC-LABEL: test_add_1_cmov_sge:
 | |
| ; SLOWINCDEC:       # %bb.0: # %entry
 | |
| ; SLOWINCDEC-NEXT:    lock addq $1, (%rdi)
 | |
| ; SLOWINCDEC-NEXT:    cmovlel %edx, %esi
 | |
| ; SLOWINCDEC-NEXT:    movl %esi, %eax
 | |
| ; SLOWINCDEC-NEXT:    retq
 | |
| entry:
 | |
|   %tmp0 = atomicrmw add i64* %p, i64 1 seq_cst
 | |
|   %tmp1 = icmp sge i64 %tmp0, 0
 | |
|   %tmp2 = select i1 %tmp1, i32 %a0, i32 %a1
 | |
|   ret i32 %tmp2
 | |
| }
 | |
| 
 | |
| define i32 @test_sub_1_cmov_sle(i64* %p, i32 %a0, i32 %a1) #0 {
 | |
| ; FASTINCDEC-LABEL: test_sub_1_cmov_sle:
 | |
| ; FASTINCDEC:       # %bb.0: # %entry
 | |
| ; FASTINCDEC-NEXT:    lock decq (%rdi)
 | |
| ; FASTINCDEC-NEXT:    cmovgel %edx, %esi
 | |
| ; FASTINCDEC-NEXT:    movl %esi, %eax
 | |
| ; FASTINCDEC-NEXT:    retq
 | |
| ;
 | |
| ; SLOWINCDEC-LABEL: test_sub_1_cmov_sle:
 | |
| ; SLOWINCDEC:       # %bb.0: # %entry
 | |
| ; SLOWINCDEC-NEXT:    lock addq $-1, (%rdi)
 | |
| ; SLOWINCDEC-NEXT:    cmovgel %edx, %esi
 | |
| ; SLOWINCDEC-NEXT:    movl %esi, %eax
 | |
| ; SLOWINCDEC-NEXT:    retq
 | |
| entry:
 | |
|   %tmp0 = atomicrmw sub i64* %p, i64 1 seq_cst
 | |
|   %tmp1 = icmp sle i64 %tmp0, 0
 | |
|   %tmp2 = select i1 %tmp1, i32 %a0, i32 %a1
 | |
|   ret i32 %tmp2
 | |
| }
 | |
| 
 | |
| define i32 @test_sub_1_cmov_sgt(i64* %p, i32 %a0, i32 %a1) #0 {
 | |
| ; FASTINCDEC-LABEL: test_sub_1_cmov_sgt:
 | |
| ; FASTINCDEC:       # %bb.0: # %entry
 | |
| ; FASTINCDEC-NEXT:    lock decq (%rdi)
 | |
| ; FASTINCDEC-NEXT:    cmovll %edx, %esi
 | |
| ; FASTINCDEC-NEXT:    movl %esi, %eax
 | |
| ; FASTINCDEC-NEXT:    retq
 | |
| ;
 | |
| ; SLOWINCDEC-LABEL: test_sub_1_cmov_sgt:
 | |
| ; SLOWINCDEC:       # %bb.0: # %entry
 | |
| ; SLOWINCDEC-NEXT:    lock addq $-1, (%rdi)
 | |
| ; SLOWINCDEC-NEXT:    cmovll %edx, %esi
 | |
| ; SLOWINCDEC-NEXT:    movl %esi, %eax
 | |
| ; SLOWINCDEC-NEXT:    retq
 | |
| entry:
 | |
|   %tmp0 = atomicrmw sub i64* %p, i64 1 seq_cst
 | |
|   %tmp1 = icmp sgt i64 %tmp0, 0
 | |
|   %tmp2 = select i1 %tmp1, i32 %a0, i32 %a1
 | |
|   ret i32 %tmp2
 | |
| }
 | |
| 
 | |
| ; FIXME: (setcc slt x, 0) gets combined into shr early.
 | |
| define i8 @test_add_1_setcc_slt(i64* %p) #0 {
 | |
| ; CHECK-LABEL: test_add_1_setcc_slt:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    movl $1, %eax
 | |
| ; CHECK-NEXT:    lock xaddq %rax, (%rdi)
 | |
| ; CHECK-NEXT:    shrq $63, %rax
 | |
| ; CHECK-NEXT:    # kill: def %al killed %al killed %rax
 | |
| ; CHECK-NEXT:    retq
 | |
| entry:
 | |
|   %tmp0 = atomicrmw add i64* %p, i64 1 seq_cst
 | |
|   %tmp1 = icmp slt i64 %tmp0, 0
 | |
|   %tmp2 = zext i1 %tmp1 to i8
 | |
|   ret i8 %tmp2
 | |
| }
 | |
| 
 | |
| define i8 @test_sub_1_setcc_sgt(i64* %p) #0 {
 | |
| ; FASTINCDEC-LABEL: test_sub_1_setcc_sgt:
 | |
| ; FASTINCDEC:       # %bb.0: # %entry
 | |
| ; FASTINCDEC-NEXT:    lock decq (%rdi)
 | |
| ; FASTINCDEC-NEXT:    setge %al
 | |
| ; FASTINCDEC-NEXT:    retq
 | |
| ;
 | |
| ; SLOWINCDEC-LABEL: test_sub_1_setcc_sgt:
 | |
| ; SLOWINCDEC:       # %bb.0: # %entry
 | |
| ; SLOWINCDEC-NEXT:    lock addq $-1, (%rdi)
 | |
| ; SLOWINCDEC-NEXT:    setge %al
 | |
| ; SLOWINCDEC-NEXT:    retq
 | |
| entry:
 | |
|   %tmp0 = atomicrmw sub i64* %p, i64 1 seq_cst
 | |
|   %tmp1 = icmp sgt i64 %tmp0, 0
 | |
|   %tmp2 = zext i1 %tmp1 to i8
 | |
|   ret i8 %tmp2
 | |
| }
 | |
| 
 | |
| define i32 @test_add_1_brcond_sge(i64* %p, i32 %a0, i32 %a1) #0 {
 | |
| ; FASTINCDEC-LABEL: test_add_1_brcond_sge:
 | |
| ; FASTINCDEC:       # %bb.0: # %entry
 | |
| ; FASTINCDEC-NEXT:    lock incq (%rdi)
 | |
| ; FASTINCDEC-NEXT:    jle .LBB6_2
 | |
| ; FASTINCDEC-NEXT:  # %bb.1: # %t
 | |
| ; FASTINCDEC-NEXT:    movl %esi, %eax
 | |
| ; FASTINCDEC-NEXT:    retq
 | |
| ; FASTINCDEC-NEXT:  .LBB6_2: # %f
 | |
| ; FASTINCDEC-NEXT:    movl %edx, %eax
 | |
| ; FASTINCDEC-NEXT:    retq
 | |
| ;
 | |
| ; SLOWINCDEC-LABEL: test_add_1_brcond_sge:
 | |
| ; SLOWINCDEC:       # %bb.0: # %entry
 | |
| ; SLOWINCDEC-NEXT:    lock addq $1, (%rdi)
 | |
| ; SLOWINCDEC-NEXT:    jle .LBB6_2
 | |
| ; SLOWINCDEC-NEXT:  # %bb.1: # %t
 | |
| ; SLOWINCDEC-NEXT:    movl %esi, %eax
 | |
| ; SLOWINCDEC-NEXT:    retq
 | |
| ; SLOWINCDEC-NEXT:  .LBB6_2: # %f
 | |
| ; SLOWINCDEC-NEXT:    movl %edx, %eax
 | |
| ; SLOWINCDEC-NEXT:    retq
 | |
| entry:
 | |
|   %tmp0 = atomicrmw add i64* %p, i64 1 seq_cst
 | |
|   %tmp1 = icmp sge i64 %tmp0, 0
 | |
|   br i1 %tmp1, label %t, label %f
 | |
| t:
 | |
|   ret i32 %a0
 | |
| f:
 | |
|   ret i32 %a1
 | |
| }
 | |
| 
 | |
| ; Also make sure we don't muck with condition codes that we should ignore.
 | |
| ; No need to test unsigned comparisons, as they should all be simplified.
 | |
| 
 | |
| define i32 @test_add_1_cmov_sle(i64* %p, i32 %a0, i32 %a1) #0 {
 | |
| ; CHECK-LABEL: test_add_1_cmov_sle:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    movl $1, %eax
 | |
| ; CHECK-NEXT:    lock xaddq %rax, (%rdi)
 | |
| ; CHECK-NEXT:    testq %rax, %rax
 | |
| ; CHECK-NEXT:    cmovgl %edx, %esi
 | |
| ; CHECK-NEXT:    movl %esi, %eax
 | |
| ; CHECK-NEXT:    retq
 | |
| entry:
 | |
|   %tmp0 = atomicrmw add i64* %p, i64 1 seq_cst
 | |
|   %tmp1 = icmp sle i64 %tmp0, 0
 | |
|   %tmp2 = select i1 %tmp1, i32 %a0, i32 %a1
 | |
|   ret i32 %tmp2
 | |
| }
 | |
| 
 | |
| define i32 @test_add_1_cmov_sgt(i64* %p, i32 %a0, i32 %a1) #0 {
 | |
| ; CHECK-LABEL: test_add_1_cmov_sgt:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    movl $1, %eax
 | |
| ; CHECK-NEXT:    lock xaddq %rax, (%rdi)
 | |
| ; CHECK-NEXT:    testq %rax, %rax
 | |
| ; CHECK-NEXT:    cmovlel %edx, %esi
 | |
| ; CHECK-NEXT:    movl %esi, %eax
 | |
| ; CHECK-NEXT:    retq
 | |
| entry:
 | |
|   %tmp0 = atomicrmw add i64* %p, i64 1 seq_cst
 | |
|   %tmp1 = icmp sgt i64 %tmp0, 0
 | |
|   %tmp2 = select i1 %tmp1, i32 %a0, i32 %a1
 | |
|   ret i32 %tmp2
 | |
| }
 | |
| 
 | |
| ; Test a result being used by more than just the comparison.
 | |
| 
 | |
| define i8 @test_add_1_setcc_sgt_reuse(i64* %p, i64* %p2) #0 {
 | |
| ; CHECK-LABEL: test_add_1_setcc_sgt_reuse:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    movl $1, %ecx
 | |
| ; CHECK-NEXT:    lock xaddq %rcx, (%rdi)
 | |
| ; CHECK-NEXT:    testq %rcx, %rcx
 | |
| ; CHECK-NEXT:    setg %al
 | |
| ; CHECK-NEXT:    movq %rcx, (%rsi)
 | |
| ; CHECK-NEXT:    retq
 | |
| entry:
 | |
|   %tmp0 = atomicrmw add i64* %p, i64 1 seq_cst
 | |
|   %tmp1 = icmp sgt i64 %tmp0, 0
 | |
|   %tmp2 = zext i1 %tmp1 to i8
 | |
|   store i64 %tmp0, i64* %p2
 | |
|   ret i8 %tmp2
 | |
| }
 | |
| 
 | |
| define i8 @test_sub_2_setcc_sgt(i64* %p) #0 {
 | |
| ; CHECK-LABEL: test_sub_2_setcc_sgt:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    movq $-2, %rax
 | |
| ; CHECK-NEXT:    lock xaddq %rax, (%rdi)
 | |
| ; CHECK-NEXT:    testq %rax, %rax
 | |
| ; CHECK-NEXT:    setg %al
 | |
| ; CHECK-NEXT:    retq
 | |
| entry:
 | |
|   %tmp0 = atomicrmw sub i64* %p, i64 2 seq_cst
 | |
|   %tmp1 = icmp sgt i64 %tmp0, 0
 | |
|   %tmp2 = zext i1 %tmp1 to i8
 | |
|   ret i8 %tmp2
 | |
| }
 | |
| 
 | |
| define i8 @test_add_1_cmov_cmov(i64* %p, i8* %q) #0 {
 | |
| ; TODO: It's possible to use "lock inc" here, but both cmovs need to be updated.
 | |
| ; CHECK-LABEL: test_add_1_cmov_cmov:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    movl $1, %eax
 | |
| ; CHECK-NEXT:    lock xaddq %rax, (%rdi)
 | |
| ; CHECK-NEXT:    testq   %rax, %rax
 | |
| entry:
 | |
|   %add = atomicrmw add i64* %p, i64 1 seq_cst
 | |
|   %cmp = icmp slt i64 %add, 0
 | |
|   %s1 = select i1 %cmp, i8 12, i8 34
 | |
|   store i8 %s1, i8* %q
 | |
|   %s2 = select i1 %cmp, i8 56, i8 78
 | |
|   ret i8 %s2
 | |
| }
 | |
| 
 | |
| define i8 @test_sub_1_cmp_1_setcc_eq(i64* %p) #0 {
 | |
| ; FASTINCDEC-LABEL: test_sub_1_cmp_1_setcc_eq:
 | |
| ; FASTINCDEC:       # %bb.0: # %entry
 | |
| ; FASTINCDEC-NEXT:    lock decq (%rdi)
 | |
| ; FASTINCDEC-NEXT:    sete %al
 | |
| ; FASTINCDEC-NEXT:    retq
 | |
| ;
 | |
| ; SLOWINCDEC-LABEL: test_sub_1_cmp_1_setcc_eq:
 | |
| ; SLOWINCDEC:       # %bb.0: # %entry
 | |
| ; SLOWINCDEC-NEXT:    lock subq $1, (%rdi)
 | |
| ; SLOWINCDEC-NEXT:    sete %al
 | |
| ; SLOWINCDEC-NEXT:    retq
 | |
| entry:
 | |
|   %tmp0 = atomicrmw sub i64* %p, i64 1 seq_cst
 | |
|   %tmp1 = icmp eq i64 %tmp0, 1
 | |
|   %tmp2 = zext i1 %tmp1 to i8
 | |
|   ret i8 %tmp2
 | |
| }
 | |
| 
 | |
| define i8 @test_sub_1_cmp_1_setcc_ne(i64* %p) #0 {
 | |
| ; FASTINCDEC-LABEL: test_sub_1_cmp_1_setcc_ne:
 | |
| ; FASTINCDEC:       # %bb.0: # %entry
 | |
| ; FASTINCDEC-NEXT:    lock decq (%rdi)
 | |
| ; FASTINCDEC-NEXT:    setne %al
 | |
| ; FASTINCDEC-NEXT:    retq
 | |
| ;
 | |
| ; SLOWINCDEC-LABEL: test_sub_1_cmp_1_setcc_ne:
 | |
| ; SLOWINCDEC:       # %bb.0: # %entry
 | |
| ; SLOWINCDEC-NEXT:    lock subq $1, (%rdi)
 | |
| ; SLOWINCDEC-NEXT:    setne %al
 | |
| ; SLOWINCDEC-NEXT:    retq
 | |
| entry:
 | |
|   %tmp0 = atomicrmw sub i64* %p, i64 1 seq_cst
 | |
|   %tmp1 = icmp ne i64 %tmp0, 1
 | |
|   %tmp2 = zext i1 %tmp1 to i8
 | |
|   ret i8 %tmp2
 | |
| }
 | |
| 
 | |
| define i8 @test_sub_1_cmp_1_setcc_ugt(i64* %p) #0 {
 | |
| ; CHECK-LABEL: test_sub_1_cmp_1_setcc_ugt:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    lock subq $1, (%rdi)
 | |
| ; CHECK-NEXT:    seta %al
 | |
| ; CHECK-NEXT:    retq
 | |
| entry:
 | |
|   %tmp0 = atomicrmw sub i64* %p, i64 1 seq_cst
 | |
|   %tmp1 = icmp ugt i64 %tmp0, 1
 | |
|   %tmp2 = zext i1 %tmp1 to i8
 | |
|   ret i8 %tmp2
 | |
| }
 | |
| 
 | |
| ; FIXME: This test canonicalizes in a way that hides the fact that the
 | |
| ; comparison can be folded into the atomic subtract.
 | |
| define i8 @test_sub_1_cmp_1_setcc_sle(i64* %p) #0 {
 | |
| ; CHECK-LABEL: test_sub_1_cmp_1_setcc_sle:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    movq $-1, %rax
 | |
| ; CHECK-NEXT:    lock xaddq %rax, (%rdi)
 | |
| ; CHECK-NEXT:    cmpq $2, %rax
 | |
| ; CHECK-NEXT:    setl %al
 | |
| ; CHECK-NEXT:    retq
 | |
| entry:
 | |
|   %tmp0 = atomicrmw sub i64* %p, i64 1 seq_cst
 | |
|   %tmp1 = icmp sle i64 %tmp0, 1
 | |
|   %tmp2 = zext i1 %tmp1 to i8
 | |
|   ret i8 %tmp2
 | |
| }
 | |
| 
 | |
| define i8 @test_sub_3_cmp_3_setcc_eq(i64* %p) #0 {
 | |
| ; CHECK-LABEL: test_sub_3_cmp_3_setcc_eq:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    lock subq $3, (%rdi)
 | |
| ; CHECK-NEXT:    sete %al
 | |
| ; CHECK-NEXT:    retq
 | |
| entry:
 | |
|   %tmp0 = atomicrmw sub i64* %p, i64 3 seq_cst
 | |
|   %tmp1 = icmp eq i64 %tmp0, 3
 | |
|   %tmp2 = zext i1 %tmp1 to i8
 | |
|   ret i8 %tmp2
 | |
| }
 | |
| 
 | |
| ; FIXME: This test canonicalizes in a way that hides the fact that the
 | |
| ; comparison can be folded into the atomic subtract.
 | |
| define i8 @test_sub_3_cmp_3_setcc_uge(i64* %p) #0 {
 | |
| ; CHECK-LABEL: test_sub_3_cmp_3_setcc_uge:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    movq $-3, %rax
 | |
| ; CHECK-NEXT:    lock xaddq %rax, (%rdi)
 | |
| ; CHECK-NEXT:    cmpq $2, %rax
 | |
| ; CHECK-NEXT:    seta %al
 | |
| ; CHECK-NEXT:    retq
 | |
| entry:
 | |
|   %tmp0 = atomicrmw sub i64* %p, i64 3 seq_cst
 | |
|   %tmp1 = icmp uge i64 %tmp0, 3
 | |
|   %tmp2 = zext i1 %tmp1 to i8
 | |
|   ret i8 %tmp2
 | |
| }
 | |
| 
 | |
| attributes #0 = { nounwind }
 |