[llvm] [AArch64] Prefer comparison with 0 with checking sign flag only (PR #153511)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 14 08:44:40 PDT 2025


https://github.com/AZero13 updated https://github.com/llvm/llvm-project/pull/153511

>From ef68bd733028b8531fda919a978d323ee0acbf7f Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Wed, 13 Aug 2025 20:21:40 -0400
Subject: [PATCH] [AArch64] Prefer comparison with 0 with checking sign flag
 only

The peephole optimizer prefers this.
---
 llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 17 ++++++++++++-----
 .../AArch64/check-sign-bit-before-extension.ll  | 12 ++++++------
 .../test/CodeGen/AArch64/select-constant-xor.ll |  4 ++--
 llvm/test/CodeGen/AArch64/signbit-shift.ll      |  8 ++++----
 llvm/test/CodeGen/AArch64/signbit-test.ll       |  4 ++--
 .../CodeGen/AArch64/typepromotion-signed.ll     |  8 ++++----
 6 files changed, 30 insertions(+), 23 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 2072e48914ae6..7606e06ba21d5 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -3960,16 +3960,23 @@ static unsigned getCmpOperandFoldingProfit(SDValue Op) {
 // works.
 static bool shouldBeAdjustedToZero(SDValue LHS, APInt C, ISD::CondCode &CC) {
   // Only works for ANDS and AND.
-  if (LHS.getOpcode() != ISD::AND && LHS.getOpcode() != AArch64ISD::ANDS)
+
+  // TODO: Is this too restrictive? This is just to prevent CSE with other
+  // comparisons.
+  if (LHS.getOpcode() != ISD::AND && LHS.getOpcode() != AArch64ISD::ANDS &&
+      !LHS.hasOneUse())
     return false;
 
-  if (C.isOne() && (CC == ISD::SETLT || CC == ISD::SETGE)) {
-    CC = (CC == ISD::SETLT) ? ISD::SETLE : ISD::SETGT;
+  if (C.isAllOnes() && (CC == ISD::SETLE || CC == ISD::SETGT)) {
+    CC = (CC == ISD::SETLE) ? ISD::SETLT : ISD::SETGE;
     return true;
   }
 
-  if (C.isAllOnes() && (CC == ISD::SETLE || CC == ISD::SETGT)) {
-    CC = (CC == ISD::SETLE) ? ISD::SETLT : ISD::SETGE;
+  if (LHS.getOpcode() != ISD::AND && LHS.getOpcode() != AArch64ISD::ANDS)
+    return false;
+
+  if (C.isOne() && (CC == ISD::SETLT || CC == ISD::SETGE)) {
+    CC = (CC == ISD::SETLT) ? ISD::SETLE : ISD::SETGT;
     return true;
   }
 
diff --git a/llvm/test/CodeGen/AArch64/check-sign-bit-before-extension.ll b/llvm/test/CodeGen/AArch64/check-sign-bit-before-extension.ll
index 0960c4c2a3342..04675c68afd52 100644
--- a/llvm/test/CodeGen/AArch64/check-sign-bit-before-extension.ll
+++ b/llvm/test/CodeGen/AArch64/check-sign-bit-before-extension.ll
@@ -14,8 +14,8 @@ define i32 @f_i8_sign_extend_inreg(i8 %in, i32 %a, i32 %b) nounwind {
 ; CHECK-LABEL: f_i8_sign_extend_inreg:
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    sxtb w8, w0
-; CHECK-NEXT:    cmn w8, #1
-; CHECK-NEXT:    csel w8, w1, w2, gt
+; CHECK-NEXT:    cmp w8, #0
+; CHECK-NEXT:    csel w8, w1, w2, pl
 ; CHECK-NEXT:    add w0, w8, w0, uxtb
 ; CHECK-NEXT:    ret
 entry:
@@ -36,8 +36,8 @@ define i32 @f_i16_sign_extend_inreg(i16 %in, i32 %a, i32 %b) nounwind {
 ; CHECK-LABEL: f_i16_sign_extend_inreg:
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    sxth w8, w0
-; CHECK-NEXT:    cmn w8, #1
-; CHECK-NEXT:    csel w8, w1, w2, gt
+; CHECK-NEXT:    cmp w8, #0
+; CHECK-NEXT:    csel w8, w1, w2, pl
 ; CHECK-NEXT:    add w0, w8, w0, uxth
 ; CHECK-NEXT:    ret
 entry:
@@ -145,8 +145,8 @@ define i64 @f_i32_sign_extend_i64(i32 %in, i64 %a, i64 %b) nounwind {
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
 ; CHECK-NEXT:    sxtw x8, w0
-; CHECK-NEXT:    cmn x8, #1
-; CHECK-NEXT:    csel x8, x1, x2, gt
+; CHECK-NEXT:    cmp x8, #0
+; CHECK-NEXT:    csel x8, x1, x2, pl
 ; CHECK-NEXT:    add x0, x8, w0, uxtw
 ; CHECK-NEXT:    ret
 entry:
diff --git a/llvm/test/CodeGen/AArch64/select-constant-xor.ll b/llvm/test/CodeGen/AArch64/select-constant-xor.ll
index 97ad579a39f78..95a3a035e3456 100644
--- a/llvm/test/CodeGen/AArch64/select-constant-xor.ll
+++ b/llvm/test/CodeGen/AArch64/select-constant-xor.ll
@@ -168,8 +168,8 @@ define i32 @icmpasreq(i32 %input, i32 %a, i32 %b) {
 define i32 @icmpasrne(i32 %input, i32 %a, i32 %b) {
 ; CHECK-SD-LABEL: icmpasrne:
 ; CHECK-SD:       // %bb.0:
-; CHECK-SD-NEXT:    cmn w0, #1
-; CHECK-SD-NEXT:    csel w0, w1, w2, gt
+; CHECK-SD-NEXT:    cmp w0, #0
+; CHECK-SD-NEXT:    csel w0, w1, w2, pl
 ; CHECK-SD-NEXT:    ret
 ;
 ; CHECK-GI-LABEL: icmpasrne:
diff --git a/llvm/test/CodeGen/AArch64/signbit-shift.ll b/llvm/test/CodeGen/AArch64/signbit-shift.ll
index ce8a96386d04c..0f64e7f485a5e 100644
--- a/llvm/test/CodeGen/AArch64/signbit-shift.ll
+++ b/llvm/test/CodeGen/AArch64/signbit-shift.ll
@@ -43,8 +43,8 @@ define i32 @sel_ifpos_tval_bigger(i32 %x) {
 ; CHECK-LABEL: sel_ifpos_tval_bigger:
 ; CHECK:       // %bb.0:
 ; CHECK-NEXT:    mov w8, #41 // =0x29
-; CHECK-NEXT:    cmn w0, #1
-; CHECK-NEXT:    cinc w0, w8, gt
+; CHECK-NEXT:    cmp w0, #0
+; CHECK-NEXT:    cinc w0, w8, pl
 ; CHECK-NEXT:    ret
   %c = icmp sgt i32 %x, -1
   %r = select i1 %c, i32 42, i32 41
@@ -91,8 +91,8 @@ define i32 @sel_ifpos_fval_bigger(i32 %x) {
 ; CHECK-LABEL: sel_ifpos_fval_bigger:
 ; CHECK:       // %bb.0:
 ; CHECK-NEXT:    mov w8, #41 // =0x29
-; CHECK-NEXT:    cmn w0, #1
-; CHECK-NEXT:    cinc w0, w8, le
+; CHECK-NEXT:    cmp w0, #0
+; CHECK-NEXT:    cinc w0, w8, mi
 ; CHECK-NEXT:    ret
   %c = icmp sgt i32 %x, -1
   %r = select i1 %c, i32 41, i32 42
diff --git a/llvm/test/CodeGen/AArch64/signbit-test.ll b/llvm/test/CodeGen/AArch64/signbit-test.ll
index c74a934ee09d8..bda2b299e6ea5 100644
--- a/llvm/test/CodeGen/AArch64/signbit-test.ll
+++ b/llvm/test/CodeGen/AArch64/signbit-test.ll
@@ -5,8 +5,8 @@ define i64 @test_clear_mask_i64_i32(i64 %x) nounwind {
 ; CHECK-LABEL: test_clear_mask_i64_i32:
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    mov w8, #42 // =0x2a
-; CHECK-NEXT:    cmn w0, #1
-; CHECK-NEXT:    csel x0, x8, x0, gt
+; CHECK-NEXT:    cmp w0, #0
+; CHECK-NEXT:    csel x0, x8, x0, pl
 ; CHECK-NEXT:    ret
 entry:
   %a = and i64 %x, 2147483648
diff --git a/llvm/test/CodeGen/AArch64/typepromotion-signed.ll b/llvm/test/CodeGen/AArch64/typepromotion-signed.ll
index 0feac24062647..ded6a1de2677d 100644
--- a/llvm/test/CodeGen/AArch64/typepromotion-signed.ll
+++ b/llvm/test/CodeGen/AArch64/typepromotion-signed.ll
@@ -60,9 +60,9 @@ define i32 @test_signext_b(ptr nocapture readonly %ptr, i8 signext %arg) {
 ; CHECK-NEXT:    mov w8, #20894 // =0x519e
 ; CHECK-NEXT:    add w9, w9, w1
 ; CHECK-NEXT:    sxtb w9, w9
-; CHECK-NEXT:    cmn w9, #1
+; CHECK-NEXT:    cmp w9, #0
 ; CHECK-NEXT:    mov w9, #42 // =0x2a
-; CHECK-NEXT:    csel w0, w9, w8, gt
+; CHECK-NEXT:    csel w0, w9, w8, pl
 ; CHECK-NEXT:    ret
 entry:
   %0 = load i8, ptr %ptr, align 1
@@ -100,9 +100,9 @@ define i32 @test_signext_h(ptr nocapture readonly %ptr, i16 signext %arg) {
 ; CHECK-NEXT:    mov w8, #20894 // =0x519e
 ; CHECK-NEXT:    add w9, w9, w1
 ; CHECK-NEXT:    sxth w9, w9
-; CHECK-NEXT:    cmn w9, #1
+; CHECK-NEXT:    cmp w9, #0
 ; CHECK-NEXT:    mov w9, #42 // =0x2a
-; CHECK-NEXT:    csel w0, w9, w8, gt
+; CHECK-NEXT:    csel w0, w9, w8, pl
 ; CHECK-NEXT:    ret
 entry:
   %0 = load i16, ptr %ptr, align 1



More information about the llvm-commits mailing list