From f4058b98aeef1943ecad6064de585863baca0fa5 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Wed, 12 Jul 2017 17:56:46 +0000 Subject: [PATCH] [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 --- lib/Target/X86/X86ISelLowering.cpp | 61 +++++++++++++++++------------- test/CodeGen/X86/sbb.ll | 7 +--- 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 3d08037e728..ad3f4123c34 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -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(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(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(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(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 diff --git a/test/CodeGen/X86/sbb.ll b/test/CodeGen/X86/sbb.ll index e5025dc13c8..b6e8ebf6ed0 100644 --- a/test/CodeGen/X86/sbb.ll +++ b/test/CodeGen/X86/sbb.ll @@ -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 %AX %EAX +; CHECK-NEXT: sbbw %ax, %ax ; CHECK-NEXT: retq %cmp = icmp ult i16 %y, %x %zext = zext i1 %cmp to i16