[llvm] [AArch64][SelectionDAG] Only fold into ands directly if AND is one-use (PR #167371)
via llvm-commits
llvm-commits at lists.llvm.org
Sun May 24 14:03:12 PDT 2026
https://github.com/LumioseSil updated https://github.com/llvm/llvm-project/pull/167371
>From c1e6846608ccbefbb941e636bc12e192aa53f2cd 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 08f3d4e0d30ac..558cda54f13b8 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