[llvm] [CodeGenPrepare][RISCV] Combine (X ^ Y) and (X == Y) where appropriate (PR #130922)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 13 12:50:14 PDT 2025
================
@@ -17194,12 +17194,58 @@ static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL,
return true;
}
+ // If XOR is reused and has an immediate that will fit in XORI,
+ // do not fold.
+ auto IsXorImmediate = [](const SDValue &Op) -> bool {
+ if (const auto XorCnst = dyn_cast<ConstantSDNode>(Op))
+ return isInt<12>(XorCnst->getSExtValue());
+ return false;
+ };
+ // Fold (X(i1) ^ 1) == 0 -> X != 0
+ auto SingleBitOp = [&DAG](const SDValue &VarOp,
+ const SDValue &ConstOp) -> bool {
+ if (const auto XorCnst = dyn_cast<ConstantSDNode>(ConstOp)) {
+ const APInt Mask = APInt::getBitsSetFrom(VarOp.getValueSizeInBits(), 1);
+ return (XorCnst->getSExtValue() == 1) &&
+ DAG.MaskedValueIsZero(VarOp, Mask);
+ }
+ return false;
+ };
+ auto OnlyUsedBySelectOrBR = [](const SDValue &Op) -> bool {
+ for (const SDNode *UserNode : Op->users()) {
+ const unsigned Opcode = UserNode->getOpcode();
+ if (Opcode != RISCVISD::SELECT_CC && Opcode != RISCVISD::BR_CC)
+ return false;
+ }
+ return true;
+ };
+ auto IsFoldableXorEq = [IsXorImmediate, SingleBitOp, OnlyUsedBySelectOrBR](
+ const SDValue &LHS, const SDValue &RHS) -> bool {
+ return LHS.getOpcode() == ISD::XOR && isNullConstant(RHS) &&
+ (!IsXorImmediate(LHS.getOperand(1)) ||
+ SingleBitOp(LHS.getOperand(0), LHS.getOperand(1)) ||
+ OnlyUsedBySelectOrBR(LHS));
+ };
// Fold ((xor X, Y), 0, eq/ne) -> (X, Y, eq/ne)
- if (LHS.getOpcode() == ISD::XOR && isNullConstant(RHS)) {
+ if (IsFoldableXorEq(LHS, RHS)) {
RHS = LHS.getOperand(1);
LHS = LHS.getOperand(0);
return true;
}
+ // Fold ((sext (xor X, C)), 0, eq/ne) -> ((sext(X), C, eq/ne)
+ if (LHS.getOpcode() == ISD::SIGN_EXTEND_INREG) {
+ const SDValue LHS0 = LHS.getOperand(0);
+ if (IsFoldableXorEq(LHS0, RHS) && isa<ConstantSDNode>(LHS0.getOperand(1))) {
+ // SEXT(XOR(X, Y)) -> XOR(SEXT(X), SEXT(Y)))
+ RHS = DAG.getNode(
+ ISD::SIGN_EXTEND_INREG, DL, LHS.getValueType(), LHS0.getOperand(1),
+ DAG.getValueType(cast<VTSDNode>(LHS.getOperand(1))->getVT()));
----------------
topperc wrote:
You can pass `LHS.getOperand(1)` directly for the last operand of the getNode. You don't need to extract the VT from it and re-create the VTSDNode.
https://github.com/llvm/llvm-project/pull/130922
More information about the llvm-commits
mailing list