[llvm] r306072 - [x86] add/sub (X==0) --> sbb(cmp X, 1)

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 22 16:47:16 PDT 2017


Author: spatel
Date: Thu Jun 22 18:47:15 2017
New Revision: 306072

URL: http://llvm.org/viewvc/llvm-project?rev=306072&view=rev
Log:
[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.


Modified:
    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
    llvm/trunk/test/CodeGen/X86/sbb.ll

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=306072&r1=306071&r2=306072&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Thu Jun 22 18:47:15 2017
@@ -34900,12 +34900,13 @@ static SDValue combineAddOrSubToADCOrSBB
   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<ConstantSDNode>(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
                          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.

Modified: llvm/trunk/test/CodeGen/X86/sbb.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/sbb.ll?rev=306072&r1=306071&r2=306072&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/sbb.ll (original)
+++ llvm/trunk/test/CodeGen/X86/sbb.ll Thu Jun 22 18:47:15 2017
@@ -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_commute
 ; 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_
 ; 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




More information about the llvm-commits mailing list