[X86] Canonicalize the pattern for __builtin_ffs in a similar way to '__builtin_ffs...
authorCraig Topper <craig.topper@intel.com>
Wed, 1 Aug 2018 18:38:46 +0000 (18:38 +0000)
committerCraig Topper <craig.topper@intel.com>
Wed, 1 Aug 2018 18:38:46 +0000 (18:38 +0000)
We now emit a move of -1 before the cmov and do the addition after the cmov just like the case with an extra addition.

This may be slightly worse for code size, but is more consistent with other compilers. And we might be able to hoist the mov -1 outside of loops.

llvm-svn: 338613

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

index 6c49e24..f77a716 100644 (file)
@@ -33395,10 +33395,13 @@ static SDValue combineCMov(SDNode *N, SelectionDAG &DAG,
     SDValue Add = TrueOp;
     SDValue Const = FalseOp;
     // Canonicalize the condition code for easier matching and output.
-    if (CC == X86::COND_E) {
+    if (CC == X86::COND_E)
       std::swap(Add, Const);
-      CC = X86::COND_NE;
-    }
+
+    // We might have replaced the constant in the cmov with the LHS of the
+    // compare. If so change it to the RHS of the compare.
+    if (Const == Cond.getOperand(0))
+      Const = Cond.getOperand(1);
 
     // Ok, now make sure that Add is (add (cttz X), C2) and Const is a constant.
     if (isa<ConstantSDNode>(Const) && Add.getOpcode() == ISD::ADD &&
@@ -33410,7 +33413,8 @@ static SDValue combineCMov(SDNode *N, SelectionDAG &DAG,
       // This should constant fold.
       SDValue Diff = DAG.getNode(ISD::SUB, DL, VT, Const, Add.getOperand(1));
       SDValue CMov = DAG.getNode(X86ISD::CMOV, DL, VT, Diff, Add.getOperand(0),
-                                 DAG.getConstant(CC, DL, MVT::i8), Cond);
+                                 DAG.getConstant(X86::COND_NE, DL, MVT::i8),
+                                 Cond);
       return DAG.getNode(ISD::ADD, DL, VT, CMov, Add.getOperand(1));
     }
   }
index 50d2809..45d8324 100644 (file)
@@ -383,18 +383,18 @@ define i32 @cttz_32_ne_select(i32 %v) nounwind {
 define i32 @cttz_32_eq_select_ffs(i32 %v) nounwind {
 ; NOBMI-LABEL: cttz_32_eq_select_ffs:
 ; NOBMI:       # %bb.0:
-; NOBMI-NEXT:    bsfl %edi, %eax
+; NOBMI-NEXT:    bsfl %edi, %ecx
+; NOBMI-NEXT:    movl $-1, %eax
+; NOBMI-NEXT:    cmovnel %ecx, %eax
 ; NOBMI-NEXT:    incl %eax
-; NOBMI-NEXT:    testl %edi, %edi
-; NOBMI-NEXT:    cmovel %edi, %eax
 ; NOBMI-NEXT:    retq
 ;
 ; BMI-LABEL: cttz_32_eq_select_ffs:
 ; BMI:       # %bb.0:
-; BMI-NEXT:    tzcntl %edi, %eax
+; BMI-NEXT:    tzcntl %edi, %ecx
+; BMI-NEXT:    movl $-1, %eax
+; BMI-NEXT:    cmovael %ecx, %eax
 ; BMI-NEXT:    incl %eax
-; BMI-NEXT:    testl %edi, %edi
-; BMI-NEXT:    cmovel %edi, %eax
 ; BMI-NEXT:    retq
 
   %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
@@ -407,18 +407,18 @@ define i32 @cttz_32_eq_select_ffs(i32 %v) nounwind {
 define i32 @cttz_32_ne_select_ffs(i32 %v) nounwind {
 ; NOBMI-LABEL: cttz_32_ne_select_ffs:
 ; NOBMI:       # %bb.0:
-; NOBMI-NEXT:    bsfl %edi, %eax
+; NOBMI-NEXT:    bsfl %edi, %ecx
+; NOBMI-NEXT:    movl $-1, %eax
+; NOBMI-NEXT:    cmovnel %ecx, %eax
 ; NOBMI-NEXT:    incl %eax
-; NOBMI-NEXT:    testl %edi, %edi
-; NOBMI-NEXT:    cmovel %edi, %eax
 ; NOBMI-NEXT:    retq
 ;
 ; BMI-LABEL: cttz_32_ne_select_ffs:
 ; BMI:       # %bb.0:
-; BMI-NEXT:    tzcntl %edi, %eax
+; BMI-NEXT:    tzcntl %edi, %ecx
+; BMI-NEXT:    movl $-1, %eax
+; BMI-NEXT:    cmovael %ecx, %eax
 ; BMI-NEXT:    incl %eax
-; BMI-NEXT:    testl %edi, %edi
-; BMI-NEXT:    cmovel %edi, %eax
 ; BMI-NEXT:    retq
 
   %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)