diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -17363,14 +17363,14 @@ SDValue LHS = N->getOperand(0); SDValue RHS = N->getOperand(1); ISD::CondCode Cond = cast(N->getOperand(2))->get(); + SDLoc DL(N); + EVT VT = N->getValueType(0); // 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()) { - SDLoc DL(N); - // Invert CSEL's condition. auto *OpCC = cast(LHS.getOperand(2)); auto OldCond = static_cast(OpCC->getZExtValue()); @@ -17381,7 +17381,21 @@ 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)); + return DAG.getZExtOrTrunc(CSEL, DL, VT); + } + + // setcc (srl x, imm), 0, ne ==> setcc (and x, (-1 << imm)), 0, ne + if (Cond == ISD::SETNE && isNullConstant(RHS) && + LHS->getOpcode() == ISD::SRL && isa(LHS->getOperand(1)) && + LHS->hasOneUse()) { + EVT TstVT = LHS->getValueType(0); + if (TstVT.isScalarInteger() && TstVT.getFixedSizeInBits() <= 64) { + // this pattern will get better opt in emitComparison + uint64_t TstImm = -1ULL << LHS->getConstantOperandVal(1); + SDValue TST = DAG.getNode(ISD::AND, DL, TstVT, LHS->getOperand(0), + DAG.getConstant(TstImm, DL, TstVT)); + return DAG.getNode(ISD::SETCC, DL, VT, TST, RHS, N->getOperand(2)); + } } return SDValue(); diff --git a/llvm/test/CodeGen/AArch64/arm64-xaluo.ll b/llvm/test/CodeGen/AArch64/arm64-xaluo.ll --- a/llvm/test/CodeGen/AArch64/arm64-xaluo.ll +++ b/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, #0xff00 ; 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, #0xff00 ; 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 ;