@@ -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,8 +3565,21 @@ 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)))) {
3570
+ // See emitComparison() on why we can only do this for SETEQ and SETNE.
3571
+ Opcode = AArch64ISD::CCMN;
3572
+ RHS = RHS.getOperand(1);
3573
+ }
3574
+ } else if (LHS.getOpcode() == ISD::SUB) {
3575
+ SDValue SubOp0 = LHS.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))))) {
3555
3580
// See emitComparison() on why we can only do this for SETEQ and SETNE.
3581
+ std::swap(LHS, RHS);
3582
+ CC = ISD::getSetCCSwappedOperands(CC);
3556
3583
Opcode = AArch64ISD::CCMN;
3557
3584
RHS = RHS.getOperand(1);
3558
3585
}
@@ -3871,10 +3898,16 @@ static SDValue getAArch64Cmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
3871
3898
// cmp w13, w12
3872
3899
// can be turned into:
3873
3900
// cmp w12, w11, lsl #1
3874
- if (!isa<ConstantSDNode>(RHS) || !isLegalArithImmed(RHS->getAsZExtVal())) {
3875
- SDValue TheLHS = isCMN(LHS, CC) ? LHS.getOperand(1) : LHS;
3876
-
3877
- if (getCmpOperandFoldingProfit(TheLHS) > getCmpOperandFoldingProfit(RHS)) {
3901
+ if (!isa<ConstantSDNode>(RHS) || (!isLegalArithImmed(RHS->getAsZExtVal()) &&
3902
+ !isLegalArithImmed(-RHS->getAsZExtVal()))) {
3903
+ SDValue TheLHS =
3904
+ isCMN(LHS, LHS.getOperand(1), CC, DAG) ? LHS.getOperand(1) : LHS;
3905
+ SDValue TheRHS =
3906
+ (!isa<ConstantSDNode>(RHS) && isCMN(RHS, RHS.getOperand(1), CC, DAG))
3907
+ ? RHS.getOperand(1)
3908
+ : RHS;
3909
+ if (getCmpOperandFoldingProfit(TheLHS) >
3910
+ getCmpOperandFoldingProfit(TheRHS)) {
3878
3911
std::swap(LHS, RHS);
3879
3912
CC = ISD::getSetCCSwappedOperands(CC);
3880
3913
}
0 commit comments