Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -18860,6 +18860,62 @@ return DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, newSelect, zeroConst); } + // (select (and (x , 0x1) == 0), y, (z ^ y) ) -> (-(and (x , 0x1)) & z ) ^ y + // (select (and (x , 0x1) == 0), y, (z | y) ) -> (-(and (x , 0x1)) & z ) | y + // (select (and (x , 0x1)), (z ^ y), y ) -> (-(and (x , 0x1)) & z ) ^ y + // (select (and (x , 0x1)), (z | y), y ) -> (-(and (x , 0x1)) & z ) | y + // We have to handle two cases of condition, setcc or a and used directly. + if (!Subtarget.hasCMov() && + (Cond.getOpcode() == ISD::AND || + (Cond.getOpcode() == ISD::SETCC && + cast(Cond.getOperand(2))->get() == ISD::SETEQ && + isNullConstant(Cond.getOperand(1))))) { + SDValue And = Cond; + SDValue TrueVal = Op1; + SDValue FalseVal = Op2; + // If we matched a SETCC, look through it. + if (Cond.getOpcode() == ISD::SETCC) { + And = Cond.getOperand(0); + std::swap(TrueVal, FalseVal); + } + + if (And.getOpcode() == ISD::AND && isOneConstant(And.getOperand(1))) { + // true if FalseVal is XOR or OR operator and one of its operands + // is equal to TrueVal + // ( a op b, a) || ( a op b, b) + auto isOrXorPattern = [](SDValue TrueVal, SDValue FalseVal, + SDValue &Src1, SDValue &Src2) { + if ((TrueVal.getOpcode() == ISD::XOR || + TrueVal.getOpcode() == ISD::OR) && + (TrueVal.getOperand(0) == FalseVal || + TrueVal.getOperand(1) == FalseVal)) { + Src1 = TrueVal.getOperand(0) == FalseVal ? TrueVal.getOperand(1) + : TrueVal.getOperand(0); + Src2 = FalseVal; + return true; + } + return false; + }; + + SDValue Src1, Src2; + if (isOrXorPattern(TrueVal, FalseVal, Src1, Src2)) { + unsigned CmpSz = And.getSimpleValueType().getSizeInBits(); + // we need mask of all zeros or ones with same size of the other + // operands. + if (CmpSz > VT.getSizeInBits()) + And = DAG.getNode(ISD::TRUNCATE, DL, VT, And); + else if (CmpSz < VT.getSizeInBits()) + And = DAG.getNode(ISD::AND, DL, VT, + DAG.getNode(ISD::ANY_EXTEND, DL, VT, And.getOperand(0)), + DAG.getConstant(1, DL, VT)); + SDValue Mask = DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), + And); // -(and (x, 0x1)) + Mask = DAG.getNode(ISD::AND, DL, VT, Mask, Src1); // Mask & z + return DAG.getNode(TrueVal.getOpcode(), DL, VT, Mask, Src2); // And Op y + } + } + } + if (Cond.getOpcode() == ISD::SETCC) { if (SDValue NewCond = LowerSETCC(Cond, DAG)) { Cond = NewCond; @@ -18875,8 +18931,6 @@ // (select (x == 0), y, -1) -> ~(sign_bit (x - 1)) | y // (select (x != 0), y, -1) -> (sign_bit (x - 1)) | y // (select (x != 0), -1, y) -> ~(sign_bit (x - 1)) | y - // (select (and (x , 0x1) == 0), y, (z ^ y) ) -> (-(and (x , 0x1)) & z ) ^ y - // (select (and (x , 0x1) == 0), y, (z | y) ) -> (-(and (x , 0x1)) & z ) | y if (Cond.getOpcode() == X86ISD::SETCC && Cond.getOperand(1).getOpcode() == X86ISD::CMP && isNullConstant(Cond.getOperand(1).getOperand(1))) { @@ -18917,43 +18971,6 @@ if (!isNullConstant(Op2)) Res = DAG.getNode(ISD::OR, DL, Res.getValueType(), Res, Y); return Res; - } 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 - // ( a , a op b) || ( b , a op b) - auto isOrXorPattern = [&]() { - if ((Op2.getOpcode() == ISD::XOR || Op2.getOpcode() == ISD::OR) && - (Op2.getOperand(0) == Op1 || Op2.getOperand(1) == Op1)) { - Src1 = - Op2.getOperand(0) == Op1 ? Op2.getOperand(1) : Op2.getOperand(0); - Src2 = Op1; - return true; - } - return false; - }; - - if (isOrXorPattern()) { - SDValue Neg; - unsigned int CmpSz = CmpOp0.getSimpleValueType().getSizeInBits(); - // we need mask of all zeros or ones with same size of the other - // operands. - if (CmpSz > VT.getSizeInBits()) - Neg = DAG.getNode(ISD::TRUNCATE, DL, VT, CmpOp0); - else if (CmpSz < VT.getSizeInBits()) - Neg = DAG.getNode(ISD::AND, DL, VT, - DAG.getNode(ISD::ANY_EXTEND, DL, VT, CmpOp0.getOperand(0)), - DAG.getConstant(1, DL, VT)); - else - Neg = CmpOp0; - SDValue Mask = DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), - Neg); // -(and (x, 0x1)) - SDValue And = DAG.getNode(ISD::AND, DL, VT, Mask, Src1); // Mask & z - return DAG.getNode(Op2.getOpcode(), DL, VT, And, Src2); // And Op y - } } } Index: test/CodeGen/X86/select.ll =================================================================== --- test/CodeGen/X86/select.ll +++ test/CodeGen/X86/select.ll @@ -1118,11 +1118,10 @@ ; ; MCU-LABEL: select_xor_1b: ; MCU: # %bb.0: # %entry -; MCU-NEXT: testb $1, %dl -; MCU-NEXT: je .LBB26_2 -; MCU-NEXT: # %bb.1: -; MCU-NEXT: xorl $43, %eax -; MCU-NEXT: .LBB26_2: # %entry +; MCU-NEXT: andl $1, %edx +; MCU-NEXT: negl %edx +; MCU-NEXT: andl $43, %edx +; MCU-NEXT: xorl %edx, %eax ; MCU-NEXT: # kill: def $ax killed $ax killed $eax ; MCU-NEXT: retl entry: @@ -1170,11 +1169,10 @@ ; ; MCU-LABEL: select_xor_2b: ; MCU: # %bb.0: # %entry -; MCU-NEXT: testb $1, %cl -; MCU-NEXT: je .LBB28_2 -; MCU-NEXT: # %bb.1: -; MCU-NEXT: xorl %edx, %eax -; MCU-NEXT: .LBB28_2: # %entry +; MCU-NEXT: andl $1, %ecx +; MCU-NEXT: negl %ecx +; MCU-NEXT: andl %edx, %ecx +; MCU-NEXT: xorl %ecx, %eax ; MCU-NEXT: retl entry: %and = and i8 %cond, 1 @@ -1221,11 +1219,10 @@ ; ; MCU-LABEL: select_or_b: ; MCU: # %bb.0: # %entry -; MCU-NEXT: testb $1, %cl -; MCU-NEXT: je .LBB30_2 -; MCU-NEXT: # %bb.1: -; MCU-NEXT: orl %edx, %eax -; MCU-NEXT: .LBB30_2: # %entry +; MCU-NEXT: andl $1, %ecx +; MCU-NEXT: negl %ecx +; MCU-NEXT: andl %edx, %ecx +; MCU-NEXT: orl %ecx, %eax ; MCU-NEXT: retl entry: %and = and i8 %cond, 1 @@ -1272,11 +1269,10 @@ ; ; MCU-LABEL: select_or_1b: ; MCU: # %bb.0: # %entry -; MCU-NEXT: testb $1, %cl -; MCU-NEXT: je .LBB32_2 -; MCU-NEXT: # %bb.1: -; MCU-NEXT: orl %edx, %eax -; MCU-NEXT: .LBB32_2: # %entry +; MCU-NEXT: andl $1, %ecx +; MCU-NEXT: negl %ecx +; MCU-NEXT: andl %edx, %ecx +; MCU-NEXT: orl %ecx, %eax ; MCU-NEXT: retl entry: %and = and i32 %cond, 1