[llvm] [AArch64][SelectionDAG] Only fold into ands directly if AND is one-use (PR #167371)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 29 08:05:53 PST 2026


https://github.com/SiliconA-Z updated https://github.com/llvm/llvm-project/pull/167371

>From 5aa0a8b9e1fe7000c7e46152bc138d31096714ca Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Mon, 10 Nov 2025 21:12:46 -0500
Subject: [PATCH] [AArch64][SelectionDAG] Only fold into ands directly if AND
 is one-use

Otherwise, we can be too aggressive, and when it comes time to split along edges, we can end up duplicating more than we bargained for.

This works well for one-use because it works even if the cmp and and end up in different basic blocks.

Peephole will catch the extra stray cases.

Fixes: #175453
---
 .../lib/Target/AArch64/AArch64ISelLowering.cpp | 18 ++++++------------
 llvm/test/CodeGen/AArch64/arm64-ccmp.ll        |  4 ++--
 llvm/test/CodeGen/AArch64/peephole-and-tst.ll  | 14 +++++++-------
 llvm/test/CodeGen/AArch64/sshl_sat.ll          |  7 +++----
 4 files changed, 18 insertions(+), 25 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 3b53b91d9f798..25aa97f68415b 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -3844,19 +3844,13 @@ static SDValue emitComparison(SDValue LHS, SDValue RHS, ISD::CondCode CC,
     Opcode = AArch64ISD::ADDS;
     LHS = LHS.getOperand(1);
   } else if (isNullConstant(RHS) && !isUnsignedIntSetCC(CC)) {
-    if (LHS.getOpcode() == ISD::AND) {
+    if (LHS.getOpcode() == ISD::AND && LHS.hasOneUse()) {
       // Similarly, (CMP (and X, Y), 0) can be implemented with a TST
-      // (a.k.a. ANDS) except that the flags are only guaranteed to work for one
-      // of the signed comparisons.
-      const SDValue ANDSNode =
-          DAG.getNode(AArch64ISD::ANDS, DL, DAG.getVTList(VT, FlagsVT),
-                      LHS.getOperand(0), LHS.getOperand(1));
-      // Replace all users of (and X, Y) with newly generated (ands X, Y)
-      DAG.ReplaceAllUsesWith(LHS, ANDSNode);
-      return ANDSNode.getValue(1);
-    } else if (LHS.getOpcode() == AArch64ISD::ANDS) {
-      // Use result of ANDS
-      return LHS.getValue(1);
+      // (a.k.a. ANDS) except that the flags are only guaranteed to work for
+      // signed comparisons.
+      Opcode = AArch64ISD::ANDS;
+      RHS = LHS.getOperand(1);
+      LHS = LHS.getOperand(0);
     }
   }
 
diff --git a/llvm/test/CodeGen/AArch64/arm64-ccmp.ll b/llvm/test/CodeGen/AArch64/arm64-ccmp.ll
index 71d26d25c0515..4058820789656 100644
--- a/llvm/test/CodeGen/AArch64/arm64-ccmp.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-ccmp.ll
@@ -1053,10 +1053,10 @@ define i32 @multiccmp(i32 %s0, i32 %s1, i32 %s2, i32 %s3, i32 %x, i32 %y) #0 {
 ; CHECK-SD-NEXT:    mov x19, x5
 ; CHECK-SD-NEXT:    cmp w0, w1
 ; CHECK-SD-NEXT:    ccmp w2, w3, #4, gt
-; CHECK-SD-NEXT:    mrs x20, NZCV
+; CHECK-SD-NEXT:    cset w20, ne
 ; CHECK-SD-NEXT:    csel w0, w5, w4, ne
 ; CHECK-SD-NEXT:    bl _callee
-; CHECK-SD-NEXT:    msr NZCV, x20
+; CHECK-SD-NEXT:    cmp w20, #0
 ; CHECK-SD-NEXT:    csel w0, w0, w19, ne
 ; CHECK-SD-NEXT:    bl _callee
 ; CHECK-SD-NEXT:    ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
diff --git a/llvm/test/CodeGen/AArch64/peephole-and-tst.ll b/llvm/test/CodeGen/AArch64/peephole-and-tst.ll
index 74b0e69d1b05b..7ad8251b0bc89 100644
--- a/llvm/test/CodeGen/AArch64/peephole-and-tst.ll
+++ b/llvm/test/CodeGen/AArch64/peephole-and-tst.ll
@@ -219,12 +219,12 @@ define i64 @test_and3(i64 %x, i64 %y) {
 ; CHECK-SD-NEXT:    .cfi_offset w19, -8
 ; CHECK-SD-NEXT:    .cfi_offset w20, -16
 ; CHECK-SD-NEXT:    .cfi_offset w30, -32
-; CHECK-SD-NEXT:    mov x20, x0
+; CHECK-SD-NEXT:    and x20, x0, #0x3
 ; CHECK-SD-NEXT:    mov x0, xzr
 ; CHECK-SD-NEXT:    mov x19, x1
 ; CHECK-SD-NEXT:    bl callee
-; CHECK-SD-NEXT:    ands x8, x20, #0x3
-; CHECK-SD-NEXT:    csel x0, x8, x19, eq
+; CHECK-SD-NEXT:    cmp x20, #0
+; CHECK-SD-NEXT:    csel x0, x20, x19, eq
 ; CHECK-SD-NEXT:    ldp x20, x19, [sp, #16] // 16-byte Folded Reload
 ; CHECK-SD-NEXT:    ldr x30, [sp], #32 // 8-byte Folded Reload
 ; CHECK-SD-NEXT:    ret
@@ -262,11 +262,11 @@ define i64 @test_and_4(i64 %x, i64 %y) {
 ; CHECK-SD-NEXT:    .cfi_def_cfa_offset 16
 ; CHECK-SD-NEXT:    .cfi_offset w19, -8
 ; CHECK-SD-NEXT:    .cfi_offset w30, -16
-; CHECK-SD-NEXT:    mov x19, x0
-; CHECK-SD-NEXT:    ands x0, x0, #0x3
+; CHECK-SD-NEXT:    and x19, x0, #0x3
+; CHECK-SD-NEXT:    mov x0, x19
 ; CHECK-SD-NEXT:    bl callee
-; CHECK-SD-NEXT:    ands x8, x19, #0x3
-; CHECK-SD-NEXT:    csel x0, x8, x0, eq
+; CHECK-SD-NEXT:    cmp x19, #0
+; CHECK-SD-NEXT:    csel x0, x19, x0, eq
 ; CHECK-SD-NEXT:    ldp x30, x19, [sp], #16 // 16-byte Folded Reload
 ; CHECK-SD-NEXT:    ret
 ;
diff --git a/llvm/test/CodeGen/AArch64/sshl_sat.ll b/llvm/test/CodeGen/AArch64/sshl_sat.ll
index be2b3e763733b..34f233135f002 100644
--- a/llvm/test/CodeGen/AArch64/sshl_sat.ll
+++ b/llvm/test/CodeGen/AArch64/sshl_sat.ll
@@ -142,12 +142,11 @@ define i16 @combine_shlsat_to_shl(i16 %x) nounwind {
 define i16 @combine_shlsat_to_shl_no_fold(i16 %x) nounwind {
 ; CHECK-LABEL: combine_shlsat_to_shl_no_fold:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    sxth w8, w0
-; CHECK-NEXT:    mov w9, #-65536 // =0xffff0000
+; CHECK-NEXT:    sbfiz w8, w0, #14, #16
 ; CHECK-NEXT:    mov w10, #-2147483648 // =0x80000000
-; CHECK-NEXT:    ands w8, w9, w8, lsl #14
-; CHECK-NEXT:    cinv w10, w10, pl
+; CHECK-NEXT:    ands w8, w8, #0xffff0000
 ; CHECK-NEXT:    lsl w9, w8, #3
+; CHECK-NEXT:    cinv w10, w10, pl
 ; CHECK-NEXT:    cmp w8, w9, asr #3
 ; CHECK-NEXT:    csel w8, w10, w9, ne
 ; CHECK-NEXT:    asr w0, w8, #16



More information about the llvm-commits mailing list