diff --git a/llvm/test/CodeGen/X86/subcarry.ll b/llvm/test/CodeGen/X86/subcarry.ll --- a/llvm/test/CodeGen/X86/subcarry.ll +++ b/llvm/test/CodeGen/X86/subcarry.ll @@ -652,6 +652,8 @@ ret void } +; unsigned less than of two 2x64 integers +; TODO: This should be optimized to cmp + sbb. define i1 @subcarry_ult_2x64(i64 %x0, i64 %x1, i64 %y0, i64 %y1) nounwind { ; CHECK-LABEL: subcarry_ult_2x64: ; CHECK: # %bb.0: @@ -670,3 +672,48 @@ %b1 = or i1 %b10, %b11 ret i1 %b1 } + +; New version of subcarry_ult_2x64 after the InstCombine change +; https://github.com/llvm/llvm-project/commit/926e7312b2f20f2f7b0a3d5ddbd29da5625507f3 +; This is also the result of "naive" implementation (x1 < y1) | ((x0 < y0) & (x1 == y1)). +; C source: https://godbolt.org/z/W1qqvqGbr +; TODO: This should be optimized to cmp + sbb. +define i1 @subcarry_ult_2x64_2(i64 %x0, i64 %x1, i64 %y0, i64 %y1) nounwind { +; CHECK-LABEL: subcarry_ult_2x64_2: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: cmpq %rdx, %rdi +; CHECK-NEXT: setb %dl +; CHECK-NEXT: cmpq %rcx, %rsi +; CHECK-NEXT: setb %cl +; CHECK-NEXT: sete %al +; CHECK-NEXT: andb %dl, %al +; CHECK-NEXT: orb %cl, %al +; CHECK-NEXT: retq +entry: + %0 = icmp ult i64 %x0, %y0 + %1 = icmp ult i64 %x1, %y1 + %2 = icmp eq i64 %x1, %y1 + %3 = and i1 %0, %2 + %4 = or i1 %1, %3 + ret i1 %4 +} + +; unsigned less than of 2x64 and i64 integers +; The IR comes from C source that uses __builtin_subcl but also the naive version (x0 < y) & (x1 == 0). +; https://godbolt.org/z/W1qqvqGbr +; TODO: This should be optimized to cmp + sbb. +define i1 @subcarry_ult_2x64_1x64(i64 %x0, i64 %x1, i64 %y) nounwind { +; CHECK-LABEL: subcarry_ult_2x64_1x64: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: cmpq %rdx, %rdi +; CHECK-NEXT: setb %cl +; CHECK-NEXT: testq %rsi, %rsi +; CHECK-NEXT: sete %al +; CHECK-NEXT: andb %cl, %al +; CHECK-NEXT: retq +entry: + %0 = icmp ult i64 %x0, %y + %1 = icmp eq i64 %x1, 0 + %2 = and i1 %1, %0 + ret i1 %2 +}