[llvm] [AArch64] Combine truncate(buildvector) -> buildvector (PR #223787)
David Green via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 22 23:07:31 PDT 2026
https://github.com/davemgreen updated https://github.com/llvm/llvm-project/pull/223787
>From 4a7e370a5030e12264f1415cb8e1a649643179d9 Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Tue, 15 Sep 2026 20:11:41 +0100
Subject: [PATCH] [AArch64] Combine truncate(buildvector) -> buildvector
If late in the pipeline we are left with truncate(buildvector), we can generate
the buildvector directly. This helps remove the xtn and can lead to other
simplification.
---
.../Target/AArch64/AArch64ISelLowering.cpp | 7 ++++
llvm/test/CodeGen/AArch64/binopshuffles.ll | 2 +-
.../CodeGen/AArch64/fp-intrinsics-vector.ll | 36 +++++++++----------
llvm/test/CodeGen/AArch64/neon-truncstore.ll | 2 --
llvm/test/CodeGen/AArch64/store.ll | 5 ++-
.../sve-extract-vector-to-predicate-store.ll | 7 ++--
.../AArch64/vec3-loads-ext-trunc-stores.ll | 14 ++++----
7 files changed, 37 insertions(+), 36 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 2a50c0c474ab95..2ffc0069d6a1f4 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -24045,6 +24045,13 @@ static SDValue performTruncateCombine(SDNode *N, SelectionDAG &DAG,
DAG.getVectorIdxConstant(ExtractIndex * 2, DL));
}
+ // truncate(buildvector) -> buildvector if we still have it late in the
+ // pipeline. We do not truncate the operand types as the buildvector
+ // implicitly truncates.
+ if (!DCI.isBeforeLegalizeOps() && N0.getOpcode() == ISD::BUILD_VECTOR &&
+ N0.hasOneUse() && (VT == MVT::v8i8 || VT == MVT::v4i16))
+ return DAG.getBuildVector(VT, DL, N0->ops());
+
return SDValue();
}
diff --git a/llvm/test/CodeGen/AArch64/binopshuffles.ll b/llvm/test/CodeGen/AArch64/binopshuffles.ll
index 3ee9df3165c985..0f2fe1cabe2b66 100644
--- a/llvm/test/CodeGen/AArch64/binopshuffles.ll
+++ b/llvm/test/CodeGen/AArch64/binopshuffles.ll
@@ -173,7 +173,7 @@ define void @noncanonical(ptr %p0, ptr %p1, ptr %p2) {
; CHECK-LABEL: noncanonical:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: ldr d0, [x1]
-; CHECK-NEXT: xtn v0.8b, v0.8h
+; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b
; CHECK-NEXT: str s0, [x2]
; CHECK-NEXT: ret
entry:
diff --git a/llvm/test/CodeGen/AArch64/fp-intrinsics-vector.ll b/llvm/test/CodeGen/AArch64/fp-intrinsics-vector.ll
index 0b05e00a1b0db2..8e63ee39839be5 100644
--- a/llvm/test/CodeGen/AArch64/fp-intrinsics-vector.ll
+++ b/llvm/test/CodeGen/AArch64/fp-intrinsics-vector.ll
@@ -345,22 +345,22 @@ define <4 x i1> @fcmp_v4f32(<4 x float> %x, <4 x float> %y) #0 {
; CHECK-NEXT: mov s2, v1.s[1]
; CHECK-NEXT: mov s3, v0.s[1]
; CHECK-NEXT: fcmp s0, s1
+; CHECK-NEXT: mov s4, v0.s[2]
+; CHECK-NEXT: mov s0, v0.s[3]
; CHECK-NEXT: csetm w8, eq
; CHECK-NEXT: fcmp s3, s2
-; CHECK-NEXT: mov s2, v1.s[2]
-; CHECK-NEXT: mov s3, v0.s[2]
-; CHECK-NEXT: fmov s4, w8
+; CHECK-NEXT: mov s3, v1.s[2]
+; CHECK-NEXT: fmov s2, w8
; CHECK-NEXT: mov s1, v1.s[3]
-; CHECK-NEXT: mov s0, v0.s[3]
; CHECK-NEXT: csetm w8, eq
-; CHECK-NEXT: mov v4.s[1], w8
-; CHECK-NEXT: fcmp s3, s2
+; CHECK-NEXT: mov v2.h[1], w8
+; CHECK-NEXT: fcmp s4, s3
; CHECK-NEXT: csetm w8, eq
; CHECK-NEXT: fcmp s0, s1
-; CHECK-NEXT: mov v4.s[2], w8
+; CHECK-NEXT: mov v2.h[2], w8
; CHECK-NEXT: csetm w8, eq
-; CHECK-NEXT: mov v4.s[3], w8
-; CHECK-NEXT: xtn v0.4h, v4.4s
+; CHECK-NEXT: mov v2.h[3], w8
+; CHECK-NEXT: fmov d0, d2
; CHECK-NEXT: ret
entry:
%val = call <4 x i1> @llvm.experimental.constrained.fcmp.v4f64(<4 x float> %x, <4 x float> %y, metadata !"oeq", metadata !"fpexcept.strict")
@@ -373,22 +373,22 @@ define <4 x i1> @fcmps_v4f32(<4 x float> %x, <4 x float> %y) #0 {
; CHECK-NEXT: mov s2, v1.s[1]
; CHECK-NEXT: mov s3, v0.s[1]
; CHECK-NEXT: fcmpe s0, s1
+; CHECK-NEXT: mov s4, v0.s[2]
+; CHECK-NEXT: mov s0, v0.s[3]
; CHECK-NEXT: csetm w8, eq
; CHECK-NEXT: fcmpe s3, s2
-; CHECK-NEXT: mov s2, v1.s[2]
-; CHECK-NEXT: mov s3, v0.s[2]
-; CHECK-NEXT: fmov s4, w8
+; CHECK-NEXT: mov s3, v1.s[2]
+; CHECK-NEXT: fmov s2, w8
; CHECK-NEXT: mov s1, v1.s[3]
-; CHECK-NEXT: mov s0, v0.s[3]
; CHECK-NEXT: csetm w8, eq
-; CHECK-NEXT: mov v4.s[1], w8
-; CHECK-NEXT: fcmpe s3, s2
+; CHECK-NEXT: mov v2.h[1], w8
+; CHECK-NEXT: fcmpe s4, s3
; CHECK-NEXT: csetm w8, eq
; CHECK-NEXT: fcmpe s0, s1
-; CHECK-NEXT: mov v4.s[2], w8
+; CHECK-NEXT: mov v2.h[2], w8
; CHECK-NEXT: csetm w8, eq
-; CHECK-NEXT: mov v4.s[3], w8
-; CHECK-NEXT: xtn v0.4h, v4.4s
+; CHECK-NEXT: mov v2.h[3], w8
+; CHECK-NEXT: fmov d0, d2
; CHECK-NEXT: ret
entry:
%val = call <4 x i1> @llvm.experimental.constrained.fcmps.v4f32(<4 x float> %x, <4 x float> %y, metadata !"oeq", metadata !"fpexcept.strict")
diff --git a/llvm/test/CodeGen/AArch64/neon-truncstore.ll b/llvm/test/CodeGen/AArch64/neon-truncstore.ll
index 9666cd705cbf6a..88e1deff375c17 100644
--- a/llvm/test/CodeGen/AArch64/neon-truncstore.ll
+++ b/llvm/test/CodeGen/AArch64/neon-truncstore.ll
@@ -262,8 +262,6 @@ define void @extract_v4i8_v8i8(<8 x i8> %a, ptr %p) {
; CHECK-LABEL: extract_v4i8_v8i8:
; CHECK: // %bb.0:
; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0
-; CHECK-NEXT: zip1 v0.16b, v0.16b, v0.16b
-; CHECK-NEXT: xtn v0.8b, v0.8h
; CHECK-NEXT: str s0, [x0]
; CHECK-NEXT: ret
%c = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
diff --git a/llvm/test/CodeGen/AArch64/store.ll b/llvm/test/CodeGen/AArch64/store.ll
index 72f1cb5a0b22fc..5daf8c2317ca07 100644
--- a/llvm/test/CodeGen/AArch64/store.ll
+++ b/llvm/test/CodeGen/AArch64/store.ll
@@ -231,9 +231,8 @@ define void @store_v3i8(<3 x i8> %a, ptr %ptr){
; CHECK-SD-NEXT: .cfi_def_cfa_offset 16
; CHECK-SD-NEXT: fmov s0, w0
; CHECK-SD-NEXT: strb w2, [x3, #2]
-; CHECK-SD-NEXT: mov v0.h[1], w1
-; CHECK-SD-NEXT: mov v0.h[2], w2
-; CHECK-SD-NEXT: xtn v0.8b, v0.8h
+; CHECK-SD-NEXT: mov v0.b[1], w1
+; CHECK-SD-NEXT: mov v0.b[2], w2
; CHECK-SD-NEXT: ushll v0.4s, v0.4h, #0
; CHECK-SD-NEXT: str h0, [x3]
; CHECK-SD-NEXT: add sp, sp, #16
diff --git a/llvm/test/CodeGen/AArch64/sve-extract-vector-to-predicate-store.ll b/llvm/test/CodeGen/AArch64/sve-extract-vector-to-predicate-store.ll
index a432e9590ec3b6..0c7849ad40b28a 100644
--- a/llvm/test/CodeGen/AArch64/sve-extract-vector-to-predicate-store.ll
+++ b/llvm/test/CodeGen/AArch64/sve-extract-vector-to-predicate-store.ll
@@ -51,12 +51,11 @@ define void @pred_store_neg1(<vscale x 16 x i1> %pred, ptr %addr) #0 {
; CHECK-NEXT: mov w8, v0.s[2]
; CHECK-NEXT: mov z2.s, z0.s[4]
; CHECK-NEXT: mov z1.s, z0.s[6]
-; CHECK-NEXT: mov v0.h[1], w8
+; CHECK-NEXT: mov v0.b[1], w8
; CHECK-NEXT: fmov w8, s2
-; CHECK-NEXT: mov v0.h[2], w8
+; CHECK-NEXT: mov v0.b[2], w8
; CHECK-NEXT: fmov w8, s1
-; CHECK-NEXT: mov v0.h[3], w8
-; CHECK-NEXT: xtn v0.8b, v0.8h
+; CHECK-NEXT: mov v0.b[3], w8
; CHECK-NEXT: str s0, [x0]
; CHECK-NEXT: addvl sp, sp, #1
; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload
diff --git a/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll b/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll
index 538dbf94608c7f..b58af24483b254 100644
--- a/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll
+++ b/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll
@@ -897,11 +897,10 @@ define void @store_trunc_v3i64_to_v3i8(ptr %p, <3 x i64> %x) {
; CHECK-NEXT: xtn.2s v0, v0
; CHECK-NEXT: stur b1, [x0, #2]
; CHECK-NEXT: mov.s w8, v0[1]
-; CHECK-NEXT: mov.h v0[1], w8
+; CHECK-NEXT: mov.b v0[1], w8
; CHECK-NEXT: mov.s w8, v1[1]
-; CHECK-NEXT: mov.h v0[2], v1[0]
-; CHECK-NEXT: mov.h v0[3], w8
-; CHECK-NEXT: xtn.8b v0, v0
+; CHECK-NEXT: mov.b v0[2], v1[0]
+; CHECK-NEXT: mov.b v0[3], w8
; CHECK-NEXT: ushll.4s v0, v0, #0
; CHECK-NEXT: str h0, [x0]
; CHECK-NEXT: add sp, sp, #16
@@ -919,11 +918,10 @@ define void @store_trunc_v3i64_to_v3i8(ptr %p, <3 x i64> %x) {
; BE-NEXT: xtn v0.2s, v0.2d
; BE-NEXT: stur b1, [x0, #2]
; BE-NEXT: mov w8, v0.s[1]
-; BE-NEXT: mov v0.h[1], w8
+; BE-NEXT: mov v0.b[1], w8
; BE-NEXT: mov w8, v1.s[1]
-; BE-NEXT: mov v0.h[2], v1.h[0]
-; BE-NEXT: mov v0.h[3], w8
-; BE-NEXT: xtn v0.8b, v0.8h
+; BE-NEXT: mov v0.b[2], v1.b[0]
+; BE-NEXT: mov v0.b[3], w8
; BE-NEXT: rev32 v0.16b, v0.16b
; BE-NEXT: rev32 v0.4h, v0.4h
; BE-NEXT: ushll v0.4s, v0.4h, #0
More information about the llvm-commits
mailing list