[llvm] 2328cab - [X86] Prevent LowerSELECT from causing suboptimal codegen for __builtin_ffs(X) - 1.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 8 11:47:47 PDT 2020


Author: Craig Topper
Date: 2020-06-08T11:46:56-07:00
New Revision: 2328cab16ccd8f17fee782c29fb844662c089fbb

URL: https://github.com/llvm/llvm-project/commit/2328cab16ccd8f17fee782c29fb844662c089fbb
DIFF: https://github.com/llvm/llvm-project/commit/2328cab16ccd8f17fee782c29fb844662c089fbb.diff

LOG: [X86] Prevent LowerSELECT from causing suboptimal codegen for __builtin_ffs(X) - 1.

LowerSELECT sees the CMP with 0 and wants to use a trick with SUB
and SBB. But we can use the flags from the BSF/TZCNT.

Fixes PR46203.

Differential Revision: https://reviews.llvm.org/D81312

Added: 
    

Modified: 
    llvm/lib/Target/X86/X86ISelLowering.cpp
    llvm/test/CodeGen/X86/dagcombine-select.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index b194423a8371..fe06bb8b3e5f 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -22851,12 +22851,25 @@ SDValue X86TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
       Cond.getOperand(1).getOpcode() == X86ISD::CMP &&
       isNullConstant(Cond.getOperand(1).getOperand(1))) {
     SDValue Cmp = Cond.getOperand(1);
+    SDValue CmpOp0 = Cmp.getOperand(0);
     unsigned CondCode = Cond.getConstantOperandVal(0);
 
-    if ((isAllOnesConstant(Op1) || isAllOnesConstant(Op2)) &&
+    // Special handling for __builtin_ffs(X) - 1 pattern which looks like
+    // (select (seteq X, 0), -1, (cttz_zero_undef X)). Disable the special
+    // handle to keep the CMP with 0. This should be removed by
+    // optimizeCompareInst by using the flags from the BSR/TZCNT used for the
+    // cttz_zero_undef.
+    auto MatchFFSMinus1 = [&](SDValue Op1, SDValue Op2) {
+      return (Op1.getOpcode() == ISD::CTTZ_ZERO_UNDEF && Op1.hasOneUse() &&
+              Op1.getOperand(0) == CmpOp0 && isAllOnesConstant(Op2));
+    };
+    if (Subtarget.hasCMov() && (VT == MVT::i32 || VT == MVT::i64) &&
+        ((CondCode == X86::COND_NE && MatchFFSMinus1(Op1, Op2)) ||
+         (CondCode == X86::COND_E && MatchFFSMinus1(Op2, Op1)))) {
+      // Keep Cmp.
+    } else if ((isAllOnesConstant(Op1) || isAllOnesConstant(Op2)) &&
         (CondCode == X86::COND_E || CondCode == X86::COND_NE)) {
       SDValue Y = isAllOnesConstant(Op2) ? Op1 : Op2;
-      SDValue CmpOp0 = Cmp.getOperand(0);
 
       SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::i32);
       SDVTList CmpVTs = DAG.getVTList(CmpOp0.getValueType(), MVT::i32);
@@ -22886,7 +22899,6 @@ SDValue X86TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
     } else if (!Subtarget.hasCMov() && CondCode == X86::COND_E &&
                Cmp.getOperand(0).getOpcode() == ISD::AND &&
                isOneConstant(Cmp.getOperand(0).getOperand(1))) {
-      SDValue CmpOp0 = Cmp.getOperand(0);
       SDValue Src1, Src2;
       // true if Op2 is XOR or OR operator and one of its operands
       // is equal to Op1

diff  --git a/llvm/test/CodeGen/X86/dagcombine-select.ll b/llvm/test/CodeGen/X86/dagcombine-select.ll
index a6a81b975705..ff022c3bf0fa 100644
--- a/llvm/test/CodeGen/X86/dagcombine-select.ll
+++ b/llvm/test/CodeGen/X86/dagcombine-select.ll
@@ -436,19 +436,15 @@ define i32 @cttz_32_eq_select_ffs_m1(i32 %v) nounwind {
 ; NOBMI-LABEL: cttz_32_eq_select_ffs_m1:
 ; NOBMI:       # %bb.0:
 ; NOBMI-NEXT:    bsfl %edi, %ecx
-; NOBMI-NEXT:    xorl %eax, %eax
-; NOBMI-NEXT:    cmpl $1, %edi
-; NOBMI-NEXT:    sbbl %eax, %eax
-; NOBMI-NEXT:    orl %ecx, %eax
+; NOBMI-NEXT:    movl $-1, %eax
+; NOBMI-NEXT:    cmovnel %ecx, %eax
 ; NOBMI-NEXT:    retq
 ;
 ; BMI-LABEL: cttz_32_eq_select_ffs_m1:
 ; BMI:       # %bb.0:
 ; BMI-NEXT:    tzcntl %edi, %ecx
-; BMI-NEXT:    xorl %eax, %eax
-; BMI-NEXT:    cmpl $1, %edi
-; BMI-NEXT:    sbbl %eax, %eax
-; BMI-NEXT:    orl %ecx, %eax
+; BMI-NEXT:    movl $-1, %eax
+; BMI-NEXT:    cmovael %ecx, %eax
 ; BMI-NEXT:    retq
 
   %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
@@ -461,19 +457,15 @@ define i32 @cttz_32_ne_select_ffs_m1(i32 %v) nounwind {
 ; NOBMI-LABEL: cttz_32_ne_select_ffs_m1:
 ; NOBMI:       # %bb.0:
 ; NOBMI-NEXT:    bsfl %edi, %ecx
-; NOBMI-NEXT:    xorl %eax, %eax
-; NOBMI-NEXT:    cmpl $1, %edi
-; NOBMI-NEXT:    sbbl %eax, %eax
-; NOBMI-NEXT:    orl %ecx, %eax
+; NOBMI-NEXT:    movl $-1, %eax
+; NOBMI-NEXT:    cmovnel %ecx, %eax
 ; NOBMI-NEXT:    retq
 ;
 ; BMI-LABEL: cttz_32_ne_select_ffs_m1:
 ; BMI:       # %bb.0:
 ; BMI-NEXT:    tzcntl %edi, %ecx
-; BMI-NEXT:    xorl %eax, %eax
-; BMI-NEXT:    cmpl $1, %edi
-; BMI-NEXT:    sbbl %eax, %eax
-; BMI-NEXT:    orl %ecx, %eax
+; BMI-NEXT:    movl $-1, %eax
+; BMI-NEXT:    cmovael %ecx, %eax
 ; BMI-NEXT:    retq
 
   %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)


        


More information about the llvm-commits mailing list