[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
This commit is contained in:
Craig Topper 2020-06-08 11:26:11 -07:00
parent f3d8a93970
commit 2328cab16c
2 changed files with 23 additions and 19 deletions

View File

@ -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

View File

@ -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)