@@ -17194,12 +17194,58 @@ static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL,
17194
17194
return true;
17195
17195
}
17196
17196
17197
+ // If XOR is reused and has an immediate that will fit in XORI,
17198
+ // do not fold.
17199
+ auto IsXorImmediate = [](const SDValue &Op) -> bool {
17200
+ if (const auto XorCnst = dyn_cast<ConstantSDNode>(Op))
17201
+ return isInt<12>(XorCnst->getSExtValue());
17202
+ return false;
17203
+ };
17204
+ // Fold (X(i1) ^ 1) == 0 -> X != 0
17205
+ auto SingleBitOp = [&DAG](const SDValue &VarOp,
17206
+ const SDValue &ConstOp) -> bool {
17207
+ if (const auto XorCnst = dyn_cast<ConstantSDNode>(ConstOp)) {
17208
+ const APInt Mask = APInt::getBitsSetFrom(VarOp.getValueSizeInBits(), 1);
17209
+ return (XorCnst->getSExtValue() == 1) &&
17210
+ DAG.MaskedValueIsZero(VarOp, Mask);
17211
+ }
17212
+ return false;
17213
+ };
17214
+ auto OnlyUsedBySelectOrBR = [](const SDValue &Op) -> bool {
17215
+ for (const SDNode *UserNode : Op->users()) {
17216
+ const unsigned Opcode = UserNode->getOpcode();
17217
+ if (Opcode != RISCVISD::SELECT_CC && Opcode != RISCVISD::BR_CC)
17218
+ return false;
17219
+ }
17220
+ return true;
17221
+ };
17222
+ auto IsFoldableXorEq = [IsXorImmediate, SingleBitOp, OnlyUsedBySelectOrBR](
17223
+ const SDValue &LHS, const SDValue &RHS) -> bool {
17224
+ return LHS.getOpcode() == ISD::XOR && isNullConstant(RHS) &&
17225
+ (!IsXorImmediate(LHS.getOperand(1)) ||
17226
+ SingleBitOp(LHS.getOperand(0), LHS.getOperand(1)) ||
17227
+ OnlyUsedBySelectOrBR(LHS));
17228
+ };
17197
17229
// Fold ((xor X, Y), 0, eq/ne) -> (X, Y, eq/ne)
17198
- if (LHS.getOpcode() == ISD::XOR && isNullConstant( RHS)) {
17230
+ if (IsFoldableXorEq(LHS, RHS)) {
17199
17231
RHS = LHS.getOperand(1);
17200
17232
LHS = LHS.getOperand(0);
17201
17233
return true;
17202
17234
}
17235
+ // Fold ((sext (xor X, C)), 0, eq/ne) -> ((sext(X), C, eq/ne)
17236
+ if (LHS.getOpcode() == ISD::SIGN_EXTEND_INREG) {
17237
+ const SDValue LHS0 = LHS.getOperand(0);
17238
+ if (IsFoldableXorEq(LHS0, RHS) && isa<ConstantSDNode>(LHS0.getOperand(1))) {
17239
+ // SEXT(XOR(X, Y)) -> XOR(SEXT(X), SEXT(Y)))
17240
+ RHS = DAG.getNode(
17241
+ ISD::SIGN_EXTEND_INREG, DL, LHS.getValueType(), LHS0.getOperand(1),
17242
+ DAG.getValueType(cast<VTSDNode>(LHS.getOperand(1))->getVT()));
17243
+ LHS = DAG.getNode(
17244
+ ISD::SIGN_EXTEND_INREG, DL, LHS.getValueType(), LHS0.getOperand(0),
17245
+ DAG.getValueType(cast<VTSDNode>(LHS.getOperand(1))->getVT()));
17246
+ return true;
17247
+ }
17248
+ }
17203
17249
17204
17250
// Fold ((srl (and X, 1<<C), C), 0, eq/ne) -> ((shl X, XLen-1-C), 0, ge/lt)
17205
17251
if (isNullConstant(RHS) && LHS.getOpcode() == ISD::SRL && LHS.hasOneUse() &&
0 commit comments