@@ -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,26 @@ 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
+ // As we are looking for EQ/NE compares, the operands can be commuted ; can
3463
+ // we combine a (CMP (sub 0, op1), op2) into a CMN instruction ?
3464
+ std::swap(LHS, RHS);
3465
+ CC = ISD::getSetCCSwappedOperands(CC);
3466
+ Opcode = AArch64ISD::ADDS;
3467
+ RHS = RHS.getOperand(1);
3455
3468
} else if (isNullConstant(RHS) && !isUnsignedIntSetCC(CC)) {
3456
3469
if (LHS.getOpcode() == ISD::AND) {
3457
3470
// Similarly, (CMP (and X, Y), 0) can be implemented with a TST
@@ -3551,8 +3564,19 @@ static SDValue emitConditionalComparison(SDValue LHS, SDValue RHS,
3551
3564
}
3552
3565
} else if (RHS.getOpcode() == ISD::SUB) {
3553
3566
SDValue SubOp0 = RHS.getOperand(0);
3554
- if (isNullConstant(SubOp0) && (CC == ISD::SETEQ || CC == ISD::SETNE)) {
3567
+ if (isNullConstant(SubOp0) && (CC == ISD::SETEQ || CC == ISD::SETNE ||
3568
+ DAG.isKnownNeverZero(RHS.getOperand(1)))) {
3569
+ // See emitComparison() on why we can only do this for SETEQ and SETNE.
3570
+ Opcode = AArch64ISD::CCMN;
3571
+ RHS = RHS.getOperand(1);
3572
+ }
3573
+ } else if (LHS.getOpcode() == ISD::SUB) {
3574
+ SDValue SubOp0 = LHS.getOperand(0);
3575
+ if (isNullConstant(SubOp0) && (CC == ISD::SETEQ || CC == ISD::SETNE ||
3576
+ DAG.isKnownNeverZero(LHS.getOperand(1)))) {
3555
3577
// See emitComparison() on why we can only do this for SETEQ and SETNE.
3578
+ std::swap(LHS, RHS);
3579
+ CC = ISD::getSetCCSwappedOperands(CC);
3556
3580
Opcode = AArch64ISD::CCMN;
3557
3581
RHS = RHS.getOperand(1);
3558
3582
}
@@ -3871,10 +3895,17 @@ static SDValue getAArch64Cmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
3871
3895
// cmp w13, w12
3872
3896
// can be turned into:
3873
3897
// 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)) {
3898
+ if (!isa<ConstantSDNode>(RHS) || (!isLegalArithImmed(RHS->getAsZExtVal()) &&
3899
+ !isLegalArithImmed(-RHS->getAsZExtVal()))) {
3900
+ bool IsLHSCMN =
3901
+ (!isa<ConstantSDNode>(RHS) && isCMN(RHS, RHS.getOperand(1), CC, DAG));
3902
+ bool IsRHSCMN = isCMN(RHS, RHS.getOperand(1), CC, DAG);
3903
+ SDValue TheLHS = IsLHSCMN ? LHS.getOperand(1) : LHS;
3904
+ SDValue TheRHS = IsRHSCMN ? RHS.getOperand(1) : RHS;
3905
+ // We save a neg when we do cmn instead of cmp, so add 1 if that is what we
3906
+ // did.
3907
+ if ((getCmpOperandFoldingProfit(TheLHS) + (IsLHSCMN ? 1 : 0)) >
3908
+ getCmpOperandFoldingProfit(TheRHS) + (IsRHSCMN ? 1 : 0)) {
3878
3909
std::swap(LHS, RHS);
3879
3910
CC = ISD::getSetCCSwappedOperands(CC);
3880
3911
}
0 commit comments