; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s ; Test that SETCC_CARRY is not poison/undef ; SETCC_CARRY reads the carry flag from SUB/CMP operations ; Pattern: (a < b) ? -1 : 0 -> SETCC_CARRY with X86::COND_B define i32 @setcc_carry_i32_lt(i32 %a, i32 %b) { ; CHECK-LABEL: setcc_carry_i32_lt: ; CHECK: # %bb.0: ; CHECK-NEXT: xorl %eax, %eax ; CHECK-NEXT: cmpl %esi, %edi ; CHECK-NEXT: sbbl %eax, %eax ; CHECK-NEXT: retq %cmp = icmp ult i32 %a, %b %sel = select i1 %cmp, i32 -1, i32 0 ret i32 %sel } ; Pattern: (a >= b) ? 0 : -1 -> ~SETCC_CARRY with X86::COND_B define i32 @setcc_carry_i32_ge(i32 %a, i32 %b) { ; CHECK-LABEL: setcc_carry_i32_ge: ; CHECK: # %bb.0: ; CHECK-NEXT: xorl %eax, %eax ; CHECK-NEXT: cmpl %esi, %edi ; CHECK-NEXT: sbbl %eax, %eax ; CHECK-NEXT: retq %cmp = icmp uge i32 %a, %b %sel = select i1 %cmp, i32 0, i32 -1 ret i32 %sel } ; Pattern: (a < b) ? 1 : 0 -> SETCC_CARRY (zero-extended) define i32 @setcc_carry_i32_lt_zext(i32 %a, i32 %b) { ; CHECK-LABEL: setcc_carry_i32_lt_zext: ; CHECK: # %bb.0: ; CHECK-NEXT: xorl %eax, %eax ; CHECK-NEXT: cmpl %esi, %edi ; CHECK-NEXT: setb %al ; CHECK-NEXT: retq %cmp = icmp ult i32 %a, %b %ext = zext i1 %cmp to i32 ret i32 %ext } ; Test with i64 define i64 @setcc_carry_i64_lt(i64 %a, i64 %b) { ; CHECK-LABEL: setcc_carry_i64_lt: ; CHECK: # %bb.0: ; CHECK-NEXT: xorl %eax, %eax ; CHECK-NEXT: cmpq %rsi, %rdi ; CHECK-NEXT: sbbq %rax, %rax ; CHECK-NEXT: retq %cmp = icmp ult i64 %a, %b %sel = select i1 %cmp, i64 -1, i64 0 ret i64 %sel } ; Test with i8 define i8 @setcc_carry_i8_lt(i8 %a, i8 %b) { ; CHECK-LABEL: setcc_carry_i8_lt: ; CHECK: # %bb.0: ; CHECK-NEXT: xorl %eax, %eax ; CHECK-NEXT: cmpb %sil, %dil ; CHECK-NEXT: sbbl %eax, %eax ; CHECK-NEXT: # kill: def $al killed $al killed $eax ; CHECK-NEXT: retq %cmp = icmp ult i8 %a, %b %sel = select i1 %cmp, i8 -1, i8 0 ret i8 %sel } ; Test OR with SETCC_CARRY result define i32 @setcc_carry_or(i32 %a, i32 %b, i32 %y) { ; CHECK-LABEL: setcc_carry_or: ; CHECK: # %bb.0: ; CHECK-NEXT: cmpl %esi, %edi ; CHECK-NEXT: movl $-1, %eax ; CHECK-NEXT: cmovael %edx, %eax ; CHECK-NEXT: retq %cmp = icmp ult i32 %a, %b %sel = select i1 %cmp, i32 -1, i32 %y ret i32 %sel } ; Test with constant comparison (pattern: x <= MAX ? x : -1) define i32 @setcc_carry_clamp_max(i32 %x) { ; CHECK-LABEL: setcc_carry_clamp_max: ; CHECK: # %bb.0: ; CHECK-NEXT: cmpl $101, %edi ; CHECK-NEXT: movl $-1, %eax ; CHECK-NEXT: cmovbl %edi, %eax ; CHECK-NEXT: retq %cmp = icmp ugt i32 %x, 100 %sel = select i1 %cmp, i32 -1, i32 %x ret i32 %sel } ; Test SETCC_CARRY is not poison even with freeze ; This verifies isGuaranteedNotToBeUndefOrPoisonForTargetNode works define i32 @setcc_carry_with_freeze(i32 %a, i32 %b) { ; CHECK-LABEL: setcc_carry_with_freeze: ; CHECK: # %bb.0: ; CHECK-NEXT: xorl %eax, %eax ; CHECK-NEXT: cmpl %esi, %edi ; CHECK-NEXT: sbbl %eax, %eax ; CHECK-NEXT: retq %cmp = icmp ult i32 %a, %b %frozen = freeze i1 %cmp %sel = select i1 %frozen, i32 -1, i32 0 ret i32 %sel }