[llvm] [AArch64] Factor in the possible cmn commute by emitComparison (PR #144234)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Jun 14 12:44:27 PDT 2025
https://github.com/AZero13 created https://github.com/llvm/llvm-project/pull/144234
Basically, we were failing to take into account the possibility of commuting the cmn, which meant that we failed to counter-act the cmn if it could go on the right-side anyway.
>From 917e676bf1495bae4a477766707688b90a66bd87 Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Sat, 14 Jun 2025 13:40:14 -0400
Subject: [PATCH 1/2] Factor in the possible cmn commute by emitComparison
---
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 7519ac5260a64..6cbab040a68a4 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -3436,6 +3436,12 @@ static bool isCMN(SDValue Op, ISD::CondCode CC, SelectionDAG &DAG) {
(isSignedIntSetCC(CC) && isSafeSignedCMN(Op, DAG)));
}
+static bool canBeCommutedToCMN(SDValue LHS, SDValue RHS, ISD::CondCode CC) {
+ if (LHS.getOpcode() != ISD::SUB || !isNullConstant(LHS.getOperand(0)))
+ return false;
+ return isIntEqualitySetCC(CC);
+}
+
static SDValue emitStrictFPComparison(SDValue LHS, SDValue RHS, const SDLoc &dl,
SelectionDAG &DAG, SDValue Chain,
bool IsSignaling) {
@@ -3480,8 +3486,7 @@ static SDValue emitComparison(SDValue LHS, SDValue RHS, ISD::CondCode CC,
// Can we combine a (CMP op1, (sub 0, op2) into a CMN instruction ?
Opcode = AArch64ISD::ADDS;
RHS = RHS.getOperand(1);
- } else if (LHS.getOpcode() == ISD::SUB && isNullConstant(LHS.getOperand(0)) &&
- isIntEqualitySetCC(CC)) {
+ } else if (canBeCommutedToCMN(LHS, RHS, CC)) {
// As we are looking for EQ/NE compares, the operands can be commuted ; can
// we combine a (CMP (sub 0, op1), op2) into a CMN instruction ?
Opcode = AArch64ISD::ADDS;
@@ -3932,8 +3937,9 @@ static SDValue getAArch64Cmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
// can be turned into:
// cmp w12, w11, lsl #1
if (!isa<ConstantSDNode>(RHS) || !isLegalCmpImmed(RHS->getAsAPIntVal())) {
- bool LHSIsCMN = isCMN(LHS, CC, DAG);
- bool RHSIsCMN = isCMN(RHS, CC, DAG);
+ // Do not count twice if the CMN can be commuted, hence OR.
+ bool LHSIsCMN = isCMN(LHS, CC, DAG) || canBeCommutedToCMN(RHS, LHS, CC);
+ bool RHSIsCMN = isCMN(RHS, CC, DAG) || canBeCommutedToCMN(LHS, RHS, CC);
SDValue TheLHS = LHSIsCMN ? LHS.getOperand(1) : LHS;
SDValue TheRHS = RHSIsCMN ? RHS.getOperand(1) : RHS;
>From e7271aa89522fc2532818e5ce9414b2cc0ffb66b Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Sat, 14 Jun 2025 15:43:37 -0400
Subject: [PATCH 2/2] [AArch64] Do not count cmn twice if the cmn can be
commuted
Basically, we were failing to take into account the possibility of commuting the cmn, which meant that we failed to counter-act the cmn if it could go on the right-side anyway.
---
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 9 ++++++---
llvm/test/CodeGen/AArch64/cmp-to-cmn.ll | 8 ++++----
2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 6cbab040a68a4..4da51fbcfcb83 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -3937,12 +3937,15 @@ static SDValue getAArch64Cmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
// can be turned into:
// cmp w12, w11, lsl #1
if (!isa<ConstantSDNode>(RHS) || !isLegalCmpImmed(RHS->getAsAPIntVal())) {
- // Do not count twice if the CMN can be commuted, hence OR.
- bool LHSIsCMN = isCMN(LHS, CC, DAG) || canBeCommutedToCMN(RHS, LHS, CC);
- bool RHSIsCMN = isCMN(RHS, CC, DAG) || canBeCommutedToCMN(LHS, RHS, CC);
+ bool LHSIsCMN = isCMN(LHS, CC, DAG);
+ bool RHSIsCMN = isCMN(RHS, CC, DAG);
SDValue TheLHS = LHSIsCMN ? LHS.getOperand(1) : LHS;
SDValue TheRHS = RHSIsCMN ? RHS.getOperand(1) : RHS;
+ // Do not count twice if the CMN can be commuted, hence OR.
+ LHSIsCMN |= canBeCommutedToCMN(RHS, LHS, CC);
+ RHSIsCMN |= canBeCommutedToCMN(LHS, RHS, CC);
+
if (getCmpOperandFoldingProfit(TheLHS) + (LHSIsCMN ? 1 : 0) >
getCmpOperandFoldingProfit(TheRHS) + (RHSIsCMN ? 1 : 0)) {
std::swap(LHS, RHS);
diff --git a/llvm/test/CodeGen/AArch64/cmp-to-cmn.ll b/llvm/test/CodeGen/AArch64/cmp-to-cmn.ll
index 5765e0acae269..73b7f5b6ebf8e 100644
--- a/llvm/test/CodeGen/AArch64/cmp-to-cmn.ll
+++ b/llvm/test/CodeGen/AArch64/cmp-to-cmn.ll
@@ -6,7 +6,7 @@ target triple = "arm64"
define i1 @test_EQ_IllEbT(i64 %a, i64 %b) {
; CHECK-LABEL: test_EQ_IllEbT:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: cmn x0, x1
+; CHECK-NEXT: cmn x1, x0
; CHECK-NEXT: cset w0, eq
; CHECK-NEXT: ret
entry:
@@ -70,7 +70,7 @@ entry:
define i1 @test_EQ_IiiEbT(i32 %a, i32 %b) {
; CHECK-LABEL: test_EQ_IiiEbT:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: cmn w0, w1
+; CHECK-NEXT: cmn w1, w0
; CHECK-NEXT: cset w0, eq
; CHECK-NEXT: ret
entry:
@@ -220,7 +220,7 @@ entry:
define i1 @test_NE_IllEbT(i64 %a, i64 %b) {
; CHECK-LABEL: test_NE_IllEbT:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: cmn x0, x1
+; CHECK-NEXT: cmn x1, x0
; CHECK-NEXT: cset w0, ne
; CHECK-NEXT: ret
entry:
@@ -284,7 +284,7 @@ entry:
define i1 @test_NE_IiiEbT(i32 %a, i32 %b) {
; CHECK-LABEL: test_NE_IiiEbT:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: cmn w0, w1
+; CHECK-NEXT: cmn w1, w0
; CHECK-NEXT: cset w0, ne
; CHECK-NEXT: ret
entry:
More information about the llvm-commits
mailing list