mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-27 13:40:30 +00:00
[x86] improve SBB optimizations for SETB/SETA with subtract
This is another step towards removing a combine that turns sext into select of constants and preparing the backend for an IR future where select is the canonical form. Earlier commits in this area: https://reviews.llvm.org/rL306040 https://reviews.llvm.org/rL306072 https://reviews.llvm.org/rL307404 (https://reviews.llvm.org/D34652) https://reviews.llvm.org/rL307471 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@307821 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8751bf94c8
commit
f4058b98ae
@ -35005,6 +35005,40 @@ static SDValue combineAddOrSubToADCOrSBB(SDNode *N, SelectionDAG &DAG) {
|
||||
EVT VT = N->getValueType(0);
|
||||
X86::CondCode CC = (X86::CondCode)Y.getConstantOperandVal(0);
|
||||
|
||||
// If X is -1 or 0, then we have an opportunity to avoid constants required in
|
||||
// the general case below.
|
||||
auto *ConstantX = dyn_cast<ConstantSDNode>(X);
|
||||
if (ConstantX) {
|
||||
if ((!IsSub && CC == X86::COND_AE && ConstantX->isAllOnesValue()) ||
|
||||
(IsSub && CC == X86::COND_B && ConstantX->isNullValue())) {
|
||||
// This is a complicated way to get -1 or 0 from the carry flag:
|
||||
// -1 + SETAE --> -1 + (!CF) --> CF ? -1 : 0 --> SBB %eax, %eax
|
||||
// 0 - SETB --> 0 - (CF) --> CF ? -1 : 0 --> SBB %eax, %eax
|
||||
return DAG.getNode(X86ISD::SETCC_CARRY, DL, VT,
|
||||
DAG.getConstant(X86::COND_B, DL, MVT::i8),
|
||||
Y.getOperand(1));
|
||||
}
|
||||
|
||||
if ((!IsSub && CC == X86::COND_BE && ConstantX->isAllOnesValue()) ||
|
||||
(IsSub && CC == X86::COND_A && ConstantX->isNullValue())) {
|
||||
SDValue EFLAGS = Y->getOperand(1);
|
||||
if (EFLAGS.getOpcode() == X86ISD::SUB && EFLAGS.hasOneUse() &&
|
||||
EFLAGS.getValueType().isInteger() &&
|
||||
!isa<ConstantSDNode>(EFLAGS.getOperand(1))) {
|
||||
// Swap the operands of a SUB, and we have the same pattern as above.
|
||||
// -1 + SETBE (SUB A, B) --> -1 + SETAE (SUB B, A) --> SUB + SBB
|
||||
// 0 - SETA (SUB A, B) --> 0 - SETB (SUB B, A) --> SUB + SBB
|
||||
SDValue NewSub = DAG.getNode(
|
||||
X86ISD::SUB, SDLoc(EFLAGS), EFLAGS.getNode()->getVTList(),
|
||||
EFLAGS.getOperand(1), EFLAGS.getOperand(0));
|
||||
SDValue NewEFLAGS = SDValue(NewSub.getNode(), EFLAGS.getResNo());
|
||||
return DAG.getNode(X86ISD::SETCC_CARRY, DL, VT,
|
||||
DAG.getConstant(X86::COND_B, DL, MVT::i8),
|
||||
NewEFLAGS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CC == X86::COND_B) {
|
||||
// X + SETB Z --> X + (mask SBB Z, Z)
|
||||
// X - SETB Z --> X - (mask SBB Z, Z)
|
||||
@ -35015,33 +35049,6 @@ static SDValue combineAddOrSubToADCOrSBB(SDNode *N, SelectionDAG &DAG) {
|
||||
return DAG.getNode(IsSub ? ISD::SUB : ISD::ADD, DL, VT, X, SBB);
|
||||
}
|
||||
|
||||
auto *ConstantX = dyn_cast<ConstantSDNode>(X);
|
||||
if (!IsSub && ConstantX && ConstantX->isAllOnesValue()) {
|
||||
if (CC == X86::COND_AE) {
|
||||
// This is a complicated way to get -1 or 0 from the carry flag:
|
||||
// -1 + SETAE --> -1 + (!CF) --> CF ? -1 : 0 --> SBB %eax, %eax
|
||||
// We don't have to match the subtract equivalent because sub X, 1 is
|
||||
// canonicalized to add X, -1.
|
||||
return DAG.getNode(X86ISD::SETCC_CARRY, DL, VT,
|
||||
DAG.getConstant(X86::COND_B, DL, MVT::i8),
|
||||
Y.getOperand(1));
|
||||
}
|
||||
|
||||
SDValue EFLAGS = Y->getOperand(1);
|
||||
if (CC == X86::COND_BE && EFLAGS.getOpcode() == X86ISD::SUB &&
|
||||
EFLAGS.hasOneUse() && EFLAGS.getValueType().isInteger() &&
|
||||
!isa<ConstantSDNode>(EFLAGS.getOperand(1))) {
|
||||
// Swap the operands of a SUB, and we have the same pattern as above.
|
||||
// -1 + SETBE (SUB A, B) --> -1 + SETAE (SUB B, A) --> SBB %eax, %eax
|
||||
SDValue NewSub =
|
||||
DAG.getNode(X86ISD::SUB, SDLoc(EFLAGS), EFLAGS.getNode()->getVTList(),
|
||||
EFLAGS.getOperand(1), EFLAGS.getOperand(0));
|
||||
SDValue NewEFLAGS = SDValue(NewSub.getNode(), EFLAGS.getResNo());
|
||||
return DAG.getNode(X86ISD::SETCC_CARRY, DL, VT,
|
||||
DAG.getConstant(X86::COND_B, DL, MVT::i8), NewEFLAGS);
|
||||
}
|
||||
}
|
||||
|
||||
if (CC == X86::COND_A) {
|
||||
SDValue EFLAGS = Y->getOperand(1);
|
||||
// Try to convert COND_A into COND_B in an attempt to facilitate
|
||||
|
@ -191,9 +191,8 @@ define i32 @uge_select_0_or_neg1_sub(i32 %x, i32 %y) nounwind {
|
||||
define i64 @ugt_select_neg1_or_0_sub(i64 %x, i64 %y) nounwind {
|
||||
; CHECK-LABEL: ugt_select_neg1_or_0_sub:
|
||||
; CHECK: # BB#0:
|
||||
; CHECK-NEXT: xorl %eax, %eax
|
||||
; CHECK-NEXT: cmpq %rdi, %rsi
|
||||
; CHECK-NEXT: sbbq $0, %rax
|
||||
; CHECK-NEXT: sbbq %rax, %rax
|
||||
; CHECK-NEXT: retq
|
||||
%cmp = icmp ugt i64 %x, %y
|
||||
%zext = zext i1 %cmp to i64
|
||||
@ -207,10 +206,8 @@ define i64 @ugt_select_neg1_or_0_sub(i64 %x, i64 %y) nounwind {
|
||||
define i16 @ult_select_neg1_or_0_sub(i16 %x, i16 %y) nounwind {
|
||||
; CHECK-LABEL: ult_select_neg1_or_0_sub:
|
||||
; CHECK: # BB#0:
|
||||
; CHECK-NEXT: xorl %eax, %eax
|
||||
; CHECK-NEXT: cmpw %di, %si
|
||||
; CHECK-NEXT: sbbl $0, %eax
|
||||
; CHECK-NEXT: # kill: %AX<def> %AX<kill> %EAX<kill>
|
||||
; CHECK-NEXT: sbbw %ax, %ax
|
||||
; CHECK-NEXT: retq
|
||||
%cmp = icmp ult i16 %y, %x
|
||||
%zext = zext i1 %cmp to i16
|
||||
|
Loading…
Reference in New Issue
Block a user