[llvm] 71cbaac - [AArch64] Combine truncate(buildvector) -> buildvector (#223787)

via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 28 04:47:21 PDT 2026


Author: David Green
Date: 2026-09-28T11:47:14Z
New Revision: 71cbaace075d39f87063afa9d0da165ee04345b3

URL: https://github.com/llvm/llvm-project/commit/71cbaace075d39f87063afa9d0da165ee04345b3
DIFF: https://github.com/llvm/llvm-project/commit/71cbaace075d39f87063afa9d0da165ee04345b3.diff

LOG: [AArch64] Combine truncate(buildvector) -> buildvector (#223787)

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.

Added: 
    

Modified: 
    llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
    llvm/test/CodeGen/AArch64/binopshuffles.ll
    llvm/test/CodeGen/AArch64/fp-intrinsics-vector.ll
    llvm/test/CodeGen/AArch64/neon-truncstore.ll
    llvm/test/CodeGen/AArch64/store.ll
    llvm/test/CodeGen/AArch64/sve-extract-vector-to-predicate-store.ll
    llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index e159aea0868d5..99be309f6bc9d 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -23999,6 +23999,12 @@ static SDValue performTruncateCombine(SDNode *N, SelectionDAG &DAG,
     return DAG.getExtractVectorElt(DL, VT, Op, ExtractIndex * 2);
   }
 
+  // truncate(buildvector) -> buildvector if we 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 3ee9df3165c98..0f2fe1cabe2b6 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 0b05e00a1b0db..8e63ee39839be 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 9666cd705cbf6..88e1deff375c1 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 72f1cb5a0b22f..5daf8c2317ca0 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 a432e9590ec3b..0c7849ad40b28 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 538dbf94608c7..b58af24483b25 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