Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 33 additions & 8 deletions llvm/lib/Target/X86/X86ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52388,16 +52388,41 @@ static SDValue combineAddOrSubToADCOrSBB(bool IsSub, const SDLoc &DL, EVT VT,
// Do not flip "e > c", where "c" is a constant, because Cmp instruction
// cannot take an immediate as its first operand.
//
if (EFLAGS.getOpcode() == X86ISD::SUB && EFLAGS.getNode()->hasOneUse() &&
EFLAGS.getValueType().isInteger() &&
!isa<ConstantSDNode>(EFLAGS.getOperand(1))) {
SDValue NewSub =
DAG.getNode(X86ISD::SUB, SDLoc(EFLAGS), EFLAGS.getNode()->getVTList(),
EFLAGS.getOperand(1), EFLAGS.getOperand(0));
SDValue NewEFLAGS = NewSub.getValue(EFLAGS.getResNo());
// If EFLAGS is from a CMP that compares the same operands as the earlier
// SUB producing X (i.e. CMP X, Y), we can directly use the carry flag with
// SBB/ADC without creating a flipped SUB.
if (EFLAGS.getOpcode() == X86ISD::CMP &&
EFLAGS.getValueType().isInteger() && X == EFLAGS.getOperand(0)) {
return DAG.getNode(IsSub ? X86ISD::SBB : X86ISD::ADC, DL,
DAG.getVTList(VT, MVT::i32), X,
DAG.getConstant(0, DL, VT), NewEFLAGS);
DAG.getConstant(0, DL, VT), EFLAGS);
}

if (EFLAGS.getOpcode() == X86ISD::SUB &&
EFLAGS.getValueType().isInteger() &&
!isa<ConstantSDNode>(EFLAGS.getOperand(1))) {
// Only create NewSub if we know one of the folds will succeed to avoid
// introducing a temporary node that may persist and affect one-use checks
// below.
if (EFLAGS.getNode()->hasOneUse()) {
SDValue NewSub = DAG.getNode(
X86ISD::SUB, SDLoc(EFLAGS), EFLAGS.getNode()->getVTList(),
EFLAGS.getOperand(1), EFLAGS.getOperand(0));
SDValue NewEFLAGS = NewSub.getValue(EFLAGS.getResNo());
return DAG.getNode(IsSub ? X86ISD::SBB : X86ISD::ADC, DL,
DAG.getVTList(VT, MVT::i32), X,
DAG.getConstant(0, DL, VT), NewEFLAGS);
}

if (IsSub && X == EFLAGS.getValue(0)) {
SDValue NewSub = DAG.getNode(
X86ISD::SUB, SDLoc(EFLAGS), EFLAGS.getNode()->getVTList(),
EFLAGS.getOperand(1), EFLAGS.getOperand(0));
SDValue NewEFLAGS = NewSub.getValue(EFLAGS.getResNo());
return DAG.getNode(X86ISD::SBB, DL, DAG.getVTList(VT, MVT::i32),
EFLAGS.getOperand(0), EFLAGS.getOperand(1),
NewEFLAGS);
}
}
}

Expand Down
29 changes: 29 additions & 0 deletions llvm/test/CodeGen/X86/sbb.ll
Original file line number Diff line number Diff line change
Expand Up @@ -365,3 +365,32 @@ define i32 @uge_sext_add(i32 %0, i32 %1, i32 %2) {
%6 = add nsw i32 %5, %0
ret i32 %6
}

define i32 @sub_sub_ugt(i32 %a, i32 %b) {
; CHECK-LABEL: sub_sub_ugt:
; CHECK: # %bb.0:
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: cmpl %edi, %esi
; CHECK-NEXT: sbbl %esi, %eax
; CHECK-NEXT: retq
%cmp = icmp ugt i32 %a, %b
%conv = zext i1 %cmp to i32
%sub = sub i32 %a, %b
%res = sub i32 %sub, %conv
ret i32 %res
}

define i32 @sub_sub_ult(i32 %a, i32 %b) {
; CHECK-LABEL: sub_sub_ult:
; CHECK: # %bb.0:
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: cmpl %edi, %esi
; CHECK-NEXT: sbbl %esi, %eax
; CHECK-NEXT: retq
%cmp = icmp ult i32 %b, %a
%conv = zext i1 %cmp to i32
%sub = sub i32 %a, %b
%res = sub i32 %sub, %conv
ret i32 %res
}