@@ -3396,9 +3396,11 @@ static bool isLegalArithImmed(uint64_t C) {
3396
3396
// So, finally, the only LLVM-native comparisons that don't mention C and V
3397
3397
// are SETEQ and SETNE. They're the only ones we can safely use CMN for in
3398
3398
// the absence of information about op2.
3399
- static bool isCMN(SDValue Op, ISD::CondCode CC) {
3399
+ static bool isCMN(SDValue Op, SDValue CheckedVal, ISD::CondCode CC,
3400
+ SelectionDAG &DAG) {
3400
3401
return Op.getOpcode() == ISD::SUB && isNullConstant(Op.getOperand(0)) &&
3401
- (CC == ISD::SETEQ || CC == ISD::SETNE);
3402
+ (CC == ISD::SETEQ || CC == ISD::SETNE ||
3403
+ DAG.isKnownNeverZero(CheckedVal));
3402
3404
}
3403
3405
3404
3406
static SDValue emitStrictFPComparison(SDValue LHS, SDValue RHS, const SDLoc &dl,
@@ -3443,15 +3445,27 @@ static SDValue emitComparison(SDValue LHS, SDValue RHS, ISD::CondCode CC,
3443
3445
// register to WZR/XZR if it ends up being unused.
3444
3446
unsigned Opcode = AArch64ISD::SUBS;
3445
3447
3446
- if (isCMN(RHS, CC )) {
3448
+ if (isCMN(RHS, RHS.getOperand(1), CC, DAG )) {
3447
3449
// Can we combine a (CMP op1, (sub 0, op2) into a CMN instruction ?
3448
3450
Opcode = AArch64ISD::ADDS;
3449
3451
RHS = RHS.getOperand(1);
3450
- } else if (isCMN(LHS, CC)) {
3452
+ } else if (isCMN(LHS, RHS, CC, DAG) &&
3453
+ (!isUnsignedIntSetCC(CC) ||
3454
+ isCMN(LHS, LHS.getOperand(1), CC, DAG))) {
3451
3455
// As we are looking for EQ/NE compares, the operands can be commuted ; can
3452
3456
// we combine a (CMP (sub 0, op1), op2) into a CMN instruction ?
3457
+ // Not swapping operands, but negation requires inversion
3458
+ CC = ISD::getSetCCSwappedOperands(CC);
3453
3459
Opcode = AArch64ISD::ADDS;
3454
3460
LHS = LHS.getOperand(1);
3461
+ } else if (isCMN(LHS, LHS.getOperand(1), CC, DAG) &&
3462
+ (!isUnsignedIntSetCC(CC) || isCMN(LHS, RHS, CC, DAG))) {
3463
+ // As we are looking for EQ/NE compares, the operands can be commuted ; can
3464
+ // we combine a (CMP (sub 0, op1), op2) into a CMN instruction ?
3465
+ std::swap(LHS, RHS);
3466
+ CC = ISD::getSetCCSwappedOperands(CC);
3467
+ Opcode = AArch64ISD::ADDS;
3468
+ RHS = RHS.getOperand(1);
3455
3469
} else if (isNullConstant(RHS) && !isUnsignedIntSetCC(CC)) {
3456
3470
if (LHS.getOpcode() == ISD::AND) {
3457
3471
// Similarly, (CMP (and X, Y), 0) can be implemented with a TST
@@ -3551,11 +3565,24 @@ static SDValue emitConditionalComparison(SDValue LHS, SDValue RHS,
3551
3565
}
3552
3566
} else if (RHS.getOpcode() == ISD::SUB) {
3553
3567
SDValue SubOp0 = RHS.getOperand(0);
3554
- if (isNullConstant(SubOp0) && (CC == ISD::SETEQ || CC == ISD::SETNE)) {
3568
+ if (isNullConstant(SubOp0) && (CC == ISD::SETEQ || CC == ISD::SETNE ||
3569
+ DAG.isKnownNeverZero(RHS.getOperand(1)))) {
3555
3570
// See emitComparison() on why we can only do this for SETEQ and SETNE.
3556
3571
Opcode = AArch64ISD::CCMN;
3557
3572
RHS = RHS.getOperand(1);
3558
3573
}
3574
+ } else if (LHS.getOpcode() == ISD::SUB) {
3575
+ SDValue SubOp0 = RHS.getOperand(0);
3576
+ if (isNullConstant(SubOp0) &&
3577
+ (CC == ISD::SETEQ || CC == ISD::SETNE ||
3578
+ (DAG.isKnownNeverZero(LHS.getOperand(1)) &&
3579
+ (!isUnsignedIntSetCC(CC) || DAG.isKnownNeverZero(RHS))))) {
3580
+ // See emitComparison() on why we can only do this for SETEQ and SETNE.
3581
+ std::swap(LHS, RHS);
3582
+ CC = ISD::getSetCCSwappedOperands(CC);
3583
+ Opcode = AArch64ISD::CCMN;
3584
+ RHS = RHS.getOperand(1);
3585
+ }
3559
3586
}
3560
3587
if (Opcode == 0)
3561
3588
Opcode = AArch64ISD::CCMP;
@@ -3872,8 +3899,8 @@ static SDValue getAArch64Cmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
3872
3899
// can be turned into:
3873
3900
// cmp w12, w11, lsl #1
3874
3901
if (!isa<ConstantSDNode>(RHS) || !isLegalArithImmed(RHS->getAsZExtVal())) {
3875
- SDValue TheLHS = isCMN(LHS, CC) ? LHS.getOperand(1) : LHS;
3876
-
3902
+ SDValue TheLHS =
3903
+ isCMN(LHS, LHS.getOperand(1), CC, DAG) ? LHS.getOperand(1) : LHS;
3877
3904
if (getCmpOperandFoldingProfit(TheLHS) > getCmpOperandFoldingProfit(RHS)) {
3878
3905
std::swap(LHS, RHS);
3879
3906
CC = ISD::getSetCCSwappedOperands(CC);
0 commit comments