[llvm] [AArch64] Fold addv(ctpop) to ctpop if the operand is known to be 8-bit (PR #159086)
Hongyu Chen via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 16 06:08:34 PDT 2025
https://github.com/XChy created https://github.com/llvm/llvm-project/pull/159086
Fixes https://github.com/llvm/llvm-project/issues/158741
>From 29ee2e21cf2e68ec26fae56fc131acc83a780baf Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Tue, 16 Sep 2025 19:41:21 +0800
Subject: [PATCH 1/2] Precommit tests
---
llvm/test/CodeGen/AArch64/ctpop.ll | 97 ++++++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
diff --git a/llvm/test/CodeGen/AArch64/ctpop.ll b/llvm/test/CodeGen/AArch64/ctpop.ll
index c739be95cd243..4cfab83f5c1a8 100644
--- a/llvm/test/CodeGen/AArch64/ctpop.ll
+++ b/llvm/test/CodeGen/AArch64/ctpop.ll
@@ -505,3 +505,100 @@ entry:
%s = call <4 x i128> @llvm.ctpop(<4 x i128> %d)
ret <4 x i128> %s
}
+
+define i8 @i8(i8 %x) {
+; CHECK-SD-LABEL: i8:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: and w8, w0, #0xff
+; CHECK-SD-NEXT: fmov s0, w8
+; CHECK-SD-NEXT: cnt v0.8b, v0.8b
+; CHECK-SD-NEXT: addv b0, v0.8b
+; CHECK-SD-NEXT: fmov w0, s0
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: i8:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: // kill: def $w0 killed $w0 def $x0
+; CHECK-GI-NEXT: and x8, x0, #0xff
+; CHECK-GI-NEXT: fmov d0, x8
+; CHECK-GI-NEXT: cnt v0.8b, v0.8b
+; CHECK-GI-NEXT: uaddlv h0, v0.8b
+; CHECK-GI-NEXT: fmov w0, s0
+; CHECK-GI-NEXT: ret
+entry:
+ %s = call i8 @llvm.ctpop.i8(i8 %x)
+ ret i8 %s
+}
+
+define i16 @i16_mask(i16 %x) {
+; CHECK-SD-LABEL: i16_mask:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: and w8, w0, #0xff
+; CHECK-SD-NEXT: fmov s0, w8
+; CHECK-SD-NEXT: cnt v0.8b, v0.8b
+; CHECK-SD-NEXT: addv b0, v0.8b
+; CHECK-SD-NEXT: fmov w0, s0
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: i16_mask:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: and w8, w0, #0xff
+; CHECK-GI-NEXT: and x8, x8, #0xffff
+; CHECK-GI-NEXT: fmov d0, x8
+; CHECK-GI-NEXT: cnt v0.8b, v0.8b
+; CHECK-GI-NEXT: uaddlv h0, v0.8b
+; CHECK-GI-NEXT: fmov w0, s0
+; CHECK-GI-NEXT: ret
+entry:
+ %and = and i16 %x, 255
+ %s = call i16 @llvm.ctpop.i16(i16 %and)
+ ret i16 %s
+}
+
+define i32 @i32_mask(i32 %x) {
+; CHECK-SD-LABEL: i32_mask:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: and w8, w0, #0xff
+; CHECK-SD-NEXT: fmov s0, w8
+; CHECK-SD-NEXT: cnt v0.8b, v0.8b
+; CHECK-SD-NEXT: addv b0, v0.8b
+; CHECK-SD-NEXT: fmov w0, s0
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: i32_mask:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: and w8, w0, #0xff
+; CHECK-GI-NEXT: fmov s0, w8
+; CHECK-GI-NEXT: cnt v0.8b, v0.8b
+; CHECK-GI-NEXT: uaddlv h0, v0.8b
+; CHECK-GI-NEXT: fmov w0, s0
+; CHECK-GI-NEXT: ret
+entry:
+ %and = and i32 %x, 255
+ %s = call i32 @llvm.ctpop.i32(i32 %and)
+ ret i32 %s
+}
+
+define i32 @i32_mask_negative(i32 %x) {
+; CHECK-SD-LABEL: i32_mask_negative:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: and w8, w0, #0xffff
+; CHECK-SD-NEXT: fmov s0, w8
+; CHECK-SD-NEXT: cnt v0.8b, v0.8b
+; CHECK-SD-NEXT: addv b0, v0.8b
+; CHECK-SD-NEXT: fmov w0, s0
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: i32_mask_negative:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: and w8, w0, #0xffff
+; CHECK-GI-NEXT: fmov s0, w8
+; CHECK-GI-NEXT: cnt v0.8b, v0.8b
+; CHECK-GI-NEXT: uaddlv h0, v0.8b
+; CHECK-GI-NEXT: fmov w0, s0
+; CHECK-GI-NEXT: ret
+entry:
+ %and = and i32 %x, 65535
+ %s = call i32 @llvm.ctpop.i32(i32 %and)
+ ret i32 %s
+}
>From 4824f1399f507d4afad68f4beee9b37155b523bb Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Tue, 16 Sep 2025 20:38:48 +0800
Subject: [PATCH 2/2] [AArch64] Fold addv(ctpop) to ctpop if the operand is
known to be 8-bit
---
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 12 ++++++++++++
llvm/test/CodeGen/AArch64/ctpop.ll | 3 ---
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 5ffaf2c49b4c0..32962c70d1d3c 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -18988,6 +18988,7 @@ static SDValue performUADDVZextCombine(SDValue A, SelectionDAG &DAG) {
}
static SDValue performUADDVCombine(SDNode *N, SelectionDAG &DAG) {
+ MVT VT = N->getSimpleValueType(0);
SDValue A = N->getOperand(0);
if (A.getOpcode() == ISD::ADD) {
if (SDValue R = performUADDVAddCombine(A, DAG))
@@ -18995,6 +18996,17 @@ static SDValue performUADDVCombine(SDNode *N, SelectionDAG &DAG) {
else if (SDValue R = performUADDVZextCombine(A, DAG))
return R;
}
+
+ // uaddv(ctpop(a)) --> ctpop(a) if a is known as 8-bit number.
+ if (VT == MVT::v8i8 && A.getOpcode() == ISD::CTPOP) {
+ SDValue Counted = peekThroughBitcasts(A.getOperand(0));
+ if (Counted.getSimpleValueType() == MVT::i64) {
+ KnownBits KnownCounted = DAG.computeKnownBits(Counted);
+ if (KnownCounted.countMaxActiveBits() <= 8)
+ return A;
+ }
+ }
+
return SDValue();
}
diff --git a/llvm/test/CodeGen/AArch64/ctpop.ll b/llvm/test/CodeGen/AArch64/ctpop.ll
index 4cfab83f5c1a8..ecd15380cc7b6 100644
--- a/llvm/test/CodeGen/AArch64/ctpop.ll
+++ b/llvm/test/CodeGen/AArch64/ctpop.ll
@@ -512,7 +512,6 @@ define i8 @i8(i8 %x) {
; CHECK-SD-NEXT: and w8, w0, #0xff
; CHECK-SD-NEXT: fmov s0, w8
; CHECK-SD-NEXT: cnt v0.8b, v0.8b
-; CHECK-SD-NEXT: addv b0, v0.8b
; CHECK-SD-NEXT: fmov w0, s0
; CHECK-SD-NEXT: ret
;
@@ -536,7 +535,6 @@ define i16 @i16_mask(i16 %x) {
; CHECK-SD-NEXT: and w8, w0, #0xff
; CHECK-SD-NEXT: fmov s0, w8
; CHECK-SD-NEXT: cnt v0.8b, v0.8b
-; CHECK-SD-NEXT: addv b0, v0.8b
; CHECK-SD-NEXT: fmov w0, s0
; CHECK-SD-NEXT: ret
;
@@ -561,7 +559,6 @@ define i32 @i32_mask(i32 %x) {
; CHECK-SD-NEXT: and w8, w0, #0xff
; CHECK-SD-NEXT: fmov s0, w8
; CHECK-SD-NEXT: cnt v0.8b, v0.8b
-; CHECK-SD-NEXT: addv b0, v0.8b
; CHECK-SD-NEXT: fmov w0, s0
; CHECK-SD-NEXT: ret
;
More information about the llvm-commits
mailing list