Skip to content

Commit 44a9319

Browse files
committed
[AArch64] Use isKnownNonZero to optimize to cmn instead of cmp
1 parent 5b3bf4b commit 44a9319

File tree

4 files changed

+219
-149
lines changed

4 files changed

+219
-149
lines changed

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3396,9 +3396,11 @@ static bool isLegalArithImmed(uint64_t C) {
33963396
// So, finally, the only LLVM-native comparisons that don't mention C and V
33973397
// are SETEQ and SETNE. They're the only ones we can safely use CMN for in
33983398
// 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) {
34003401
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));
34023404
}
34033405

34043406
static SDValue emitStrictFPComparison(SDValue LHS, SDValue RHS, const SDLoc &dl,
@@ -3443,15 +3445,26 @@ static SDValue emitComparison(SDValue LHS, SDValue RHS, ISD::CondCode CC,
34433445
// register to WZR/XZR if it ends up being unused.
34443446
unsigned Opcode = AArch64ISD::SUBS;
34453447

3446-
if (isCMN(RHS, CC)) {
3448+
if (isCMN(RHS, RHS.getOperand(1), CC, DAG)) {
34473449
// Can we combine a (CMP op1, (sub 0, op2) into a CMN instruction ?
34483450
Opcode = AArch64ISD::ADDS;
34493451
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))) {
34513455
// As we are looking for EQ/NE compares, the operands can be commuted ; can
34523456
// 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);
34533459
Opcode = AArch64ISD::ADDS;
34543460
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);
34553468
} else if (isNullConstant(RHS) && !isUnsignedIntSetCC(CC)) {
34563469
if (LHS.getOpcode() == ISD::AND) {
34573470
// Similarly, (CMP (and X, Y), 0) can be implemented with a TST
@@ -3551,8 +3564,19 @@ static SDValue emitConditionalComparison(SDValue LHS, SDValue RHS,
35513564
}
35523565
} else if (RHS.getOpcode() == ISD::SUB) {
35533566
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)))) {
35553577
// See emitComparison() on why we can only do this for SETEQ and SETNE.
3578+
std::swap(LHS, RHS);
3579+
CC = ISD::getSetCCSwappedOperands(CC);
35563580
Opcode = AArch64ISD::CCMN;
35573581
RHS = RHS.getOperand(1);
35583582
}
@@ -3871,10 +3895,17 @@ static SDValue getAArch64Cmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
38713895
// cmp w13, w12
38723896
// can be turned into:
38733897
// 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)) {
38783909
std::swap(LHS, RHS);
38793910
CC = ISD::getSetCCSwappedOperands(CC);
38803911
}

llvm/test/CodeGen/AArch64/cmp-chains.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,7 @@ define i32 @neg_range_int_cmn(i32 %a, i32 %b, i32 %c) {
263263
; SDISEL-LABEL: neg_range_int_cmn:
264264
; SDISEL: // %bb.0:
265265
; SDISEL-NEXT: orr w8, w2, #0x1
266-
; SDISEL-NEXT: neg w8, w8
267-
; SDISEL-NEXT: cmp w8, w0
266+
; SDISEL-NEXT: cmn w0, w8
268267
; SDISEL-NEXT: ccmn w1, #3, #0, le
269268
; SDISEL-NEXT: csel w0, w1, w0, gt
270269
; SDISEL-NEXT: ret

llvm/test/CodeGen/AArch64/cmp-select-sign.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,7 @@ define i32 @or_neg(i32 %x, i32 %y) {
266266
; CHECK-LABEL: or_neg:
267267
; CHECK: // %bb.0:
268268
; CHECK-NEXT: orr w8, w0, #0x1
269-
; CHECK-NEXT: neg w8, w8
270-
; CHECK-NEXT: cmp w8, w1
269+
; CHECK-NEXT: cmn w1, w8
271270
; CHECK-NEXT: cset w0, gt
272271
; CHECK-NEXT: ret
273272
%3 = or i32 %x, 1

0 commit comments

Comments
 (0)