From ac12e1602f7c7491f34a687f98171b8931f209c9 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Thu, 22 Jun 2017 23:47:15 +0000 Subject: [PATCH] [x86] add/sub (X==0) --> sbb(cmp X, 1) This is very similar to the transform in: https://reviews.llvm.org/rL306040 ...but in this case, we use cmp X, 1 to set the carry bit as needed. Again, we can show that all of these are logically equivalent (although InstCombine currently canonicalizes to a form not seen here), and if we believe IACA, then this is the smallest/fastest code. Eg, with SNB: | Num Of | Ports pressure in cycles | | | Uops | 0 - DV | 1 | 2 - D | 3 - D | 4 | 5 | | --------------------------------------------------------------------- | 1 | 1.0 | | | | | | | cmp edi, 0x1 | 2 | | 1.0 | | | | 1.0 | CP | sbb eax, eax The larger motivation is to clean up all select-of-constants combining/lowering because we're missing some common cases. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306072 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelLowering.cpp | 22 +++++++++++++++++----- test/CodeGen/X86/sbb.ll | 9 +++------ 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 2b51137901f..b7e008c46a7 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -34900,12 +34900,13 @@ static SDValue combineAddOrSubToADCOrSBB(SDNode *N, SelectionDAG &DAG) { SDValue Z = Cmp.getOperand(0); SDVTList VTs = DAG.getVTList(N->getValueType(0), MVT::i32); - // If X is -1 or 0, then we have an opportunity to avoid constants required by - // the cmp transform below. 'neg' sets the carry flag when Z != 0, so create 0 - // or -1 using 'sbb' with fake operands: - // 0 - (Z != 0) --> sbb %eax, %eax, (neg Z) - // -1 + (Z == 0) --> sbb %eax, %eax, (neg Z) + // If X is -1 or 0, then we have an opportunity to avoid constants required in + // the general case below. if (auto *ConstantX = dyn_cast(X)) { + // 'neg' sets the carry flag when Z != 0, so create 0 or -1 using 'sbb' with + // fake operands: + // 0 - (Z != 0) --> sbb %eax, %eax, (neg Z) + // -1 + (Z == 0) --> sbb %eax, %eax, (neg Z) if ((IsSub && CC == X86::COND_NE && ConstantX->isNullValue()) || (!IsSub && CC == X86::COND_E && ConstantX->isAllOnesValue())) { SDValue Zero = DAG.getConstant(0, DL, VT); @@ -34914,6 +34915,17 @@ static SDValue combineAddOrSubToADCOrSBB(SDNode *N, SelectionDAG &DAG) { DAG.getConstant(X86::COND_B, DL, MVT::i8), SDValue(Neg.getNode(), 1)); } + // cmp with 1 sets the carry flag when Z == 0, so create 0 or -1 using 'sbb' + // with fake operands: + // 0 - (Z == 0) --> sbb %eax, %eax, (cmp Z, 1) + // -1 + (Z != 0) --> sbb %eax, %eax, (cmp Z, 1) + if ((IsSub && CC == X86::COND_E && ConstantX->isNullValue()) || + (!IsSub && CC == X86::COND_NE && ConstantX->isAllOnesValue())) { + SDValue One = DAG.getConstant(1, DL, Z.getValueType()); + SDValue Cmp1 = DAG.getNode(X86ISD::CMP, DL, MVT::i32, Z, One); + return DAG.getNode(X86ISD::SETCC_CARRY, DL, VT, + DAG.getConstant(X86::COND_B, DL, MVT::i8), Cmp1); + } } // (cmp Z, 1) sets the carry flag if Z is 0. diff --git a/test/CodeGen/X86/sbb.ll b/test/CodeGen/X86/sbb.ll index 61f639a7a95..409af00d3b2 100644 --- a/test/CodeGen/X86/sbb.ll +++ b/test/CodeGen/X86/sbb.ll @@ -75,9 +75,8 @@ define i64 @i64_select_neg1_or_0(i64 %x) { define i32 @i32_select_neg1_or_0_as_math(i32 %x) { ; CHECK-LABEL: i32_select_neg1_or_0_as_math: ; CHECK: # BB#0: -; CHECK-NEXT: xorl %eax, %eax ; CHECK-NEXT: cmpl $1, %edi -; CHECK-NEXT: sbbl $0, %eax +; CHECK-NEXT: sbbl %eax, %eax ; CHECK-NEXT: retq %cmp = icmp eq i32 %x, 0 %ext = zext i1 %cmp to i32 @@ -91,8 +90,7 @@ define i16 @i16_select_neg1_or_0_commuted(i16 %x) { ; CHECK-LABEL: i16_select_neg1_or_0_commuted: ; CHECK: # BB#0: ; CHECK-NEXT: cmpw $1, %di -; CHECK-NEXT: movw $-1, %ax -; CHECK-NEXT: sbbw $-1, %ax +; CHECK-NEXT: sbbw %ax, %ax ; CHECK-NEXT: retq %cmp = icmp ne i16 %x, 0 %sel = select i1 %cmp, i16 0, i16 -1 @@ -105,8 +103,7 @@ define i8 @i8_select_neg1_or_0_commuted_as_math(i8 %x) { ; CHECK-LABEL: i8_select_neg1_or_0_commuted_as_math: ; CHECK: # BB#0: ; CHECK-NEXT: cmpb $1, %dil -; CHECK-NEXT: movb $-1, %al -; CHECK-NEXT: sbbb $-1, %al +; CHECK-NEXT: sbbb %al, %al ; CHECK-NEXT: retq %cmp = icmp ne i8 %x, 0 %ext = zext i1 %cmp to i8 -- 2.40.0