Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -17283,24 +17283,47 @@ SDValue RHS = N->getOperand(1); ISD::CondCode Cond = cast(N->getOperand(2))->get(); - // setcc (csel 0, 1, cond, X), 1, ne ==> csel 0, 1, !cond, X - if (Cond == ISD::SETNE && isOneConstant(RHS) && - LHS->getOpcode() == AArch64ISD::CSEL && - isNullConstant(LHS->getOperand(0)) && isOneConstant(LHS->getOperand(1)) && - LHS->hasOneUse()) { + if (Cond == ISD::SETNE) { SDLoc DL(N); + EVT VT = N->getValueType(0); + + // setcc (csel 0, 1, cond, X), 1, ne ==> csel 0, 1, !cond, X + if (isOneConstant(RHS) && LHS->getOpcode() == AArch64ISD::CSEL && + isNullConstant(LHS->getOperand(0)) && + isOneConstant(LHS->getOperand(1)) && LHS->hasOneUse()) { + // Invert CSEL's condition. + auto *OpCC = cast(LHS.getOperand(2)); + auto OldCond = static_cast(OpCC->getZExtValue()); + auto NewCond = getInvertedCondCode(OldCond); + + // csel 0, 1, !cond, X + SDValue CSEL = DAG.getNode(AArch64ISD::CSEL, DL, LHS.getValueType(), + LHS.getOperand(0), LHS.getOperand(1), + DAG.getConstant(NewCond, DL, MVT::i32), + LHS.getOperand(3)); + return DAG.getZExtOrTrunc(CSEL, DL, N->getValueType(0)); + } - // Invert CSEL's condition. - auto *OpCC = cast(LHS.getOperand(2)); - auto OldCond = static_cast(OpCC->getZExtValue()); - auto NewCond = getInvertedCondCode(OldCond); - - // csel 0, 1, !cond, X - SDValue CSEL = - DAG.getNode(AArch64ISD::CSEL, DL, LHS.getValueType(), LHS.getOperand(0), - LHS.getOperand(1), DAG.getConstant(NewCond, DL, MVT::i32), - LHS.getOperand(3)); - return DAG.getZExtOrTrunc(CSEL, DL, N->getValueType(0)); + // setcc (srl x, imm), 0, ne ==> csel, 0, 1, eq, (tst x, (-1 << imm)) + if (isNullConstant(RHS) && LHS->getOpcode() == ISD::SRL && + LHS->hasOneUse() && isa(LHS->getOperand(1))) { + EVT TstVT = LHS->getOperand(0)->getValueType(0); + if (TstVT == MVT::i32 || TstVT == MVT::i64) { + auto *SrlImmOp = dyn_cast(LHS->getOperand(1)); + uint64_t TstImm = -1ULL << SrlImmOp->getZExtValue(); + SDVTList VTs = DAG.getVTList(TstVT, MVT_CC); + SDValue TST = DAG.getNode(AArch64ISD::ANDS, DL, VTs, LHS->getOperand(0), + DAG.getConstant(TstImm, DL, TstVT)) + .getValue(1); + + SDValue CSEL = DAG.getNode( + AArch64ISD::CSEL, DL, MVT::i32, DAG.getConstant(0, DL, MVT::i32), + DAG.getConstant(1, DL, MVT::i32), + DAG.getConstant(AArch64CC::EQ, DL, MVT::i32), TST); + + return DAG.getZExtOrTrunc(CSEL, DL, VT); + } + } } return SDValue(); Index: llvm/test/CodeGen/AArch64/arm64-xaluo.ll =================================================================== --- llvm/test/CodeGen/AArch64/arm64-xaluo.ll +++ llvm/test/CodeGen/AArch64/arm64-xaluo.ll @@ -1847,9 +1847,8 @@ ; SDAG-NEXT: and w8, w1, #0xff ; SDAG-NEXT: and w9, w0, #0xff ; SDAG-NEXT: mul w8, w9, w8 -; SDAG-NEXT: lsr w9, w8, #8 -; SDAG-NEXT: cmp w9, #0 ; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: tst w8, #0xffffff00 ; SDAG-NEXT: csel w0, w8, w9, ne ; SDAG-NEXT: ret ; @@ -1858,9 +1857,8 @@ ; FAST-NEXT: and w8, w1, #0xff ; FAST-NEXT: and w9, w0, #0xff ; FAST-NEXT: mul w8, w9, w8 -; FAST-NEXT: lsr w9, w8, #8 -; FAST-NEXT: cmp w9, #0 ; FAST-NEXT: mov w9, #10 +; FAST-NEXT: tst w8, #0xffffff00 ; FAST-NEXT: csel w0, w8, w9, ne ; FAST-NEXT: ret ; @@ -1925,9 +1923,8 @@ ; SDAG-NEXT: and w8, w1, #0xffff ; SDAG-NEXT: and w9, w0, #0xffff ; SDAG-NEXT: mul w8, w9, w8 -; SDAG-NEXT: lsr w9, w8, #16 -; SDAG-NEXT: cmp w9, #0 ; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: tst w8, #0xffff0000 ; SDAG-NEXT: csel w0, w8, w9, ne ; SDAG-NEXT: ret ; @@ -1936,9 +1933,8 @@ ; FAST-NEXT: and w8, w1, #0xffff ; FAST-NEXT: and w9, w0, #0xffff ; FAST-NEXT: mul w8, w9, w8 -; FAST-NEXT: lsr w9, w8, #16 -; FAST-NEXT: cmp w9, #0 ; FAST-NEXT: mov w9, #10 +; FAST-NEXT: tst w8, #0xffff0000 ; FAST-NEXT: csel w0, w8, w9, ne ; FAST-NEXT: ret ;