[llvm] [AArch64] Fix the assertion failure on `RegisterVT == PartVT && "Part… (PR #170632)

Cheng Lingfei via llvm-commits llvm-commits at lists.llvm.org
Sat Jan 31 23:44:21 PST 2026


https://github.com/clingfei updated https://github.com/llvm/llvm-project/pull/170632

>From a9dab7a24ae56f53b9e2ca446885556faf5fe912 Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Thu, 4 Dec 2025 17:27:02 +0800
Subject: [PATCH 1/4] [AArch64] Fix the assertion failure on `RegisterVT ==
 PartVT && "Part type doesn't match vector breakdown'

---
 .../SelectionDAG/SelectionDAGBuilder.cpp      | 19 ++++++++
 .../AArch64/sve-breakdown-fixed-vectortype.ll | 46 +++++++++++++++++++
 2 files changed, 65 insertions(+)
 create mode 100644 llvm/test/CodeGen/AArch64/sve-breakdown-fixed-vectortype.ll

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 53d73ad618bd1..edfddeec4030e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -359,6 +359,15 @@ static SDValue getCopyFromPartsVector(SelectionDAG &DAG, const SDLoc &DL,
           *DAG.getContext(), *CallConv, ValueVT, IntermediateVT,
           NumIntermediates, RegisterVT);
     } else {
+      if (!ValueVT.isScalableVector() && PartVT.isVector() &&
+          !PartVT.isScalableVector()) {
+        if (ValueVT.getSizeInBits() % PartVT.getSizeInBits() == 0) {
+          MVT NewEltVT = PartVT.getVectorElementType();
+          unsigned NewNumElts =
+              ValueVT.getSizeInBits() / NewEltVT.getSizeInBits();
+          ValueVT = MVT::getVectorVT(NewEltVT, NewNumElts);
+        }
+      }
       NumRegs =
           TLI.getVectorTypeBreakdown(*DAG.getContext(), ValueVT, IntermediateVT,
                                      NumIntermediates, RegisterVT);
@@ -763,6 +772,16 @@ static void getCopyToPartsVector(SelectionDAG &DAG, const SDLoc &DL,
         *DAG.getContext(), *CallConv, ValueVT, IntermediateVT, NumIntermediates,
         RegisterVT);
   } else {
+    if (!ValueVT.isScalableVector() && PartVT.isVector() &&
+        !PartVT.isScalableVector()) {
+      if (ValueVT.getSizeInBits() % PartVT.getSizeInBits() == 0) {
+        MVT NewEltVT = PartVT.getVectorElementType();
+        unsigned NewNumElts =
+            ValueVT.getSizeInBits() / NewEltVT.getSizeInBits();
+        ValueVT = MVT::getVectorVT(NewEltVT, NewNumElts);
+        Val = DAG.getNode(ISD::BITCAST, DL, ValueVT, Val);
+      }
+    }
     NumRegs =
         TLI.getVectorTypeBreakdown(*DAG.getContext(), ValueVT, IntermediateVT,
                                    NumIntermediates, RegisterVT);
diff --git a/llvm/test/CodeGen/AArch64/sve-breakdown-fixed-vectortype.ll b/llvm/test/CodeGen/AArch64/sve-breakdown-fixed-vectortype.ll
new file mode 100644
index 0000000000000..57d3b9172b9cd
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/sve-breakdown-fixed-vectortype.ll
@@ -0,0 +1,46 @@
+; RUN: llc -mtriple=aarch64--linux-gnu < %s | FileCheck %s
+
+define dso_local void @_Z3fooi(i32 noundef %val) #0 {
+; CHECK-LABEL: _Z3fooi:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    sub	sp, sp, #144
+; CHECK-NEXT:    .cfi_def_cfa_offset 144
+; CHECK-NEXT:    movi	v4.2d, #0xffffffff00000000
+; CHECK-NEXT:    str	w0, [sp, #140]
+; CHECK-NEXT:    adrp	x8, .LCPI0_0
+; CHECK-NEXT:    //APP
+; CHECK-NEXT:    //NO_APP
+; CHECK-NEXT:    ldp	q6, q0, [sp, #32]
+; CHECK-NEXT:    ldr	q5, [x8, :lo12:.LCPI0_0]
+; CHECK-NEXT:    stp	q1, q2, [sp, #64]
+; CHECK-NEXT:    mov	v3.16b, v4.16b
+; CHECK-NEXT:    stp	q5, q4, [sp]
+; CHECK-NEXT:    bsl	v3.16b, v0.16b, v2.16b
+; CHECK-NEXT:    mov	v0.16b, v5.16b
+; CHECK-NEXT:    bsl	v0.16b, v6.16b, v1.16b
+; CHECK-NEXT:    mov	v1.16b, v3.16b
+; CHECK-NEXT:    stp	q0, q3, [sp, #96]
+; CHECK-NEXT:    //APP
+; CHECK-NEXT:    //NO_APP
+; CHECK-NEXT:    add	sp, sp, #144
+; CHECK-NEXT:    ret
+entry:
+  %val.addr = alloca i32, align 4
+  %x = alloca <8 x i32>, align 16
+  %y = alloca <8 x i32>, align 16
+  %z = alloca <8 x i32>, align 16
+  %.compoundliteral = alloca <8 x i32>, align 16
+  store i32 %val, ptr %val.addr, align 4
+  %0 = call <8 x i32> asm sideeffect "", "={z1}"()
+  store <8 x i32> %0, ptr %y, align 16
+  store <8 x i32> <i32 -1, i32 0, i32 0, i32 -1, i32 0, i32 -1, i32 0, i32 -1>, ptr %.compoundliteral, align 16
+  %10 = load <8 x i32>, ptr %.compoundliteral, align 16
+  %11 = load <8 x i32>, ptr %z, align 16
+  %12 = load <8 x i32>, ptr %y, align 16
+  %vector_cond = icmp ne <8 x i32> %10, zeroinitializer
+  %vector_select = select <8 x i1> %vector_cond, <8 x i32> %11, <8 x i32> %12
+  store <8 x i32> %vector_select, ptr %x, align 16
+  %13 = load <8 x i32>, ptr %x, align 16
+  call void asm sideeffect "", "{z0}"(<8 x i32> %13)
+  ret void
+}
\ No newline at end of file

>From d0233f13908a0f69fbb3c91d985282e43d3b7c38 Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Fri, 5 Dec 2025 14:04:19 +0800
Subject: [PATCH 2/4] reduce the test case

---
 .../AArch64/sve-breakdown-fixed-vectortype.ll | 35 +++----------------
 1 file changed, 4 insertions(+), 31 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/sve-breakdown-fixed-vectortype.ll b/llvm/test/CodeGen/AArch64/sve-breakdown-fixed-vectortype.ll
index 57d3b9172b9cd..aa6983451058a 100644
--- a/llvm/test/CodeGen/AArch64/sve-breakdown-fixed-vectortype.ll
+++ b/llvm/test/CodeGen/AArch64/sve-breakdown-fixed-vectortype.ll
@@ -1,46 +1,19 @@
 ; RUN: llc -mtriple=aarch64--linux-gnu < %s | FileCheck %s
 
-define dso_local void @_Z3fooi(i32 noundef %val) #0 {
+define dso_local void @_Z3fooi(ptr %x, ptr %y) #0 {
 ; CHECK-LABEL: _Z3fooi:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    sub	sp, sp, #144
-; CHECK-NEXT:    .cfi_def_cfa_offset 144
-; CHECK-NEXT:    movi	v4.2d, #0xffffffff00000000
-; CHECK-NEXT:    str	w0, [sp, #140]
-; CHECK-NEXT:    adrp	x8, .LCPI0_0
 ; CHECK-NEXT:    //APP
 ; CHECK-NEXT:    //NO_APP
-; CHECK-NEXT:    ldp	q6, q0, [sp, #32]
-; CHECK-NEXT:    ldr	q5, [x8, :lo12:.LCPI0_0]
-; CHECK-NEXT:    stp	q1, q2, [sp, #64]
-; CHECK-NEXT:    mov	v3.16b, v4.16b
-; CHECK-NEXT:    stp	q5, q4, [sp]
-; CHECK-NEXT:    bsl	v3.16b, v0.16b, v2.16b
-; CHECK-NEXT:    mov	v0.16b, v5.16b
-; CHECK-NEXT:    bsl	v0.16b, v6.16b, v1.16b
-; CHECK-NEXT:    mov	v1.16b, v3.16b
-; CHECK-NEXT:    stp	q0, q3, [sp, #96]
+; CHECK-NEXT:    stp	q1, q2, [x1]
+; CHECK-NEXT:    ldp	q0, q1, [x0]
 ; CHECK-NEXT:    //APP
 ; CHECK-NEXT:    //NO_APP
-; CHECK-NEXT:    add	sp, sp, #144
 ; CHECK-NEXT:    ret
 entry:
-  %val.addr = alloca i32, align 4
-  %x = alloca <8 x i32>, align 16
-  %y = alloca <8 x i32>, align 16
-  %z = alloca <8 x i32>, align 16
-  %.compoundliteral = alloca <8 x i32>, align 16
-  store i32 %val, ptr %val.addr, align 4
   %0 = call <8 x i32> asm sideeffect "", "={z1}"()
   store <8 x i32> %0, ptr %y, align 16
-  store <8 x i32> <i32 -1, i32 0, i32 0, i32 -1, i32 0, i32 -1, i32 0, i32 -1>, ptr %.compoundliteral, align 16
-  %10 = load <8 x i32>, ptr %.compoundliteral, align 16
-  %11 = load <8 x i32>, ptr %z, align 16
-  %12 = load <8 x i32>, ptr %y, align 16
-  %vector_cond = icmp ne <8 x i32> %10, zeroinitializer
-  %vector_select = select <8 x i1> %vector_cond, <8 x i32> %11, <8 x i32> %12
-  store <8 x i32> %vector_select, ptr %x, align 16
   %13 = load <8 x i32>, ptr %x, align 16
   call void asm sideeffect "", "{z0}"(<8 x i32> %13)
   ret void
-}
\ No newline at end of file
+}

>From 7ee0c6e216379f2df173eaa8647c52321b6c04bd Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Sun, 1 Feb 2026 14:50:22 +0800
Subject: [PATCH 3/4] update

---
 .../CodeGen/SelectionDAG/SelectionDAGBuilder.cpp   | 14 ++++++++++----
 .../AArch64/sve-breakdown-fixed-vectortype.ll      | 12 ++++++------
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index edfddeec4030e..b6bc4e01f2f4e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -361,10 +361,13 @@ static SDValue getCopyFromPartsVector(SelectionDAG &DAG, const SDLoc &DL,
     } else {
       if (!ValueVT.isScalableVector() && PartVT.isVector() &&
           !PartVT.isScalableVector()) {
-        if (ValueVT.getSizeInBits() % PartVT.getSizeInBits() == 0) {
+        TypeSize ValueSize = ValueVT.getSizeInBits();
+        TypeSize PartSize = PartVT.getSizeInBits();
+        if (ValueSize.isKnownMultipleOf(PartSize)) {
           MVT NewEltVT = PartVT.getVectorElementType();
+          TypeSize NewEltSize = NewEltVT.getSizeInBits();
           unsigned NewNumElts =
-              ValueVT.getSizeInBits() / NewEltVT.getSizeInBits();
+              ValueSize.getKnownMinValue() / NewEltSize.getKnownMinValue();
           ValueVT = MVT::getVectorVT(NewEltVT, NewNumElts);
         }
       }
@@ -774,10 +777,13 @@ static void getCopyToPartsVector(SelectionDAG &DAG, const SDLoc &DL,
   } else {
     if (!ValueVT.isScalableVector() && PartVT.isVector() &&
         !PartVT.isScalableVector()) {
-      if (ValueVT.getSizeInBits() % PartVT.getSizeInBits() == 0) {
+      TypeSize ValueSize = ValueVT.getSizeInBits();
+      TypeSize PartSize = PartVT.getSizeInBits();
+      if (ValueSize.isKnownMultipleOf(PartSize)) {
         MVT NewEltVT = PartVT.getVectorElementType();
+        TypeSize NewEltSize = NewEltVT.getSizeInBits();
         unsigned NewNumElts =
-            ValueVT.getSizeInBits() / NewEltVT.getSizeInBits();
+            ValueSize.getKnownMinValue() / NewEltSize.getKnownMinValue();
         ValueVT = MVT::getVectorVT(NewEltVT, NewNumElts);
         Val = DAG.getNode(ISD::BITCAST, DL, ValueVT, Val);
       }
diff --git a/llvm/test/CodeGen/AArch64/sve-breakdown-fixed-vectortype.ll b/llvm/test/CodeGen/AArch64/sve-breakdown-fixed-vectortype.ll
index aa6983451058a..ac57e5fb1811d 100644
--- a/llvm/test/CodeGen/AArch64/sve-breakdown-fixed-vectortype.ll
+++ b/llvm/test/CodeGen/AArch64/sve-breakdown-fixed-vectortype.ll
@@ -1,6 +1,6 @@
-; RUN: llc -mtriple=aarch64--linux-gnu < %s | FileCheck %s
+; RUN: llc -mtriple=aarch64--linux < %s | FileCheck %s
 
-define dso_local void @_Z3fooi(ptr %x, ptr %y) #0 {
+define void @_Z3fooi(ptr %x, ptr %y) #0 {
 ; CHECK-LABEL: _Z3fooi:
 ; CHECK:       // %bb.0:
 ; CHECK-NEXT:    //APP
@@ -11,9 +11,9 @@ define dso_local void @_Z3fooi(ptr %x, ptr %y) #0 {
 ; CHECK-NEXT:    //NO_APP
 ; CHECK-NEXT:    ret
 entry:
-  %0 = call <8 x i32> asm sideeffect "", "={z1}"()
-  store <8 x i32> %0, ptr %y, align 16
-  %13 = load <8 x i32>, ptr %x, align 16
-  call void asm sideeffect "", "{z0}"(<8 x i32> %13)
+  %y.y = call <8 x i32> asm sideeffect "", "={z1}"()
+  store <8 x i32> %y.y, ptr %y, align 16
+  %x.x = load <8 x i32>, ptr %x, align 16
+  call void asm sideeffect "", "{z0}"(<8 x i32> %x.x)
   ret void
 }

>From 431cf4a57fdfe22dba212908b70f94d02e2c3ac7 Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Sun, 1 Feb 2026 15:44:04 +0800
Subject: [PATCH 4/4] update

---
 .../AArch64/sve-breakdown-fixed-vectortype.ll | 60 +++++++++++++++----
 1 file changed, 49 insertions(+), 11 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/sve-breakdown-fixed-vectortype.ll b/llvm/test/CodeGen/AArch64/sve-breakdown-fixed-vectortype.ll
index ac57e5fb1811d..a69ee06299b2b 100644
--- a/llvm/test/CodeGen/AArch64/sve-breakdown-fixed-vectortype.ll
+++ b/llvm/test/CodeGen/AArch64/sve-breakdown-fixed-vectortype.ll
@@ -1,15 +1,17 @@
-; RUN: llc -mtriple=aarch64--linux < %s | FileCheck %s
+; RUN: llc -mtriple=aarch64--linux < %s | FileCheck %s --check-prefix=SVE-ABI
 
-define void @_Z3fooi(ptr %x, ptr %y) #0 {
-; CHECK-LABEL: _Z3fooi:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    //APP
-; CHECK-NEXT:    //NO_APP
-; CHECK-NEXT:    stp	q1, q2, [x1]
-; CHECK-NEXT:    ldp	q0, q1, [x0]
-; CHECK-NEXT:    //APP
-; CHECK-NEXT:    //NO_APP
-; CHECK-NEXT:    ret
+; Fixed-length vectors forced into SVE Z registers still need ABI copies
+; broken down into Q register pairs when lowering fixed-width memory ops.
+define void @sve_fixed_vector_breakdown_v8i32(ptr %x, ptr %y) {
+; SVE-ABI-LABEL: sve_fixed_vector_breakdown_v8i32:
+; SVE-ABI:       // %bb.0:
+; SVE-ABI-NEXT:    //APP
+; SVE-ABI-NEXT:    //NO_APP
+; SVE-ABI-NEXT:    stp	q1, q2, [x1]
+; SVE-ABI-NEXT:    ldp	q0, q1, [x0]
+; SVE-ABI-NEXT:    //APP
+; SVE-ABI-NEXT:    //NO_APP
+; SVE-ABI-NEXT:    ret
 entry:
   %y.y = call <8 x i32> asm sideeffect "", "={z1}"()
   store <8 x i32> %y.y, ptr %y, align 16
@@ -17,3 +19,39 @@ entry:
   call void asm sideeffect "", "{z0}"(<8 x i32> %x.x)
   ret void
 }
+
+define void @sve_fixed_vector_breakdown_v4i64(ptr %x, ptr %y) {
+; SVE-ABI-LABEL: sve_fixed_vector_breakdown_v4i64:
+; SVE-ABI:       // %bb.0:
+; SVE-ABI-NEXT:    //APP
+; SVE-ABI-NEXT:    //NO_APP
+; SVE-ABI-NEXT:    stp	q1, q2, [x1]
+; SVE-ABI-NEXT:    ldp	q0, q1, [x0]
+; SVE-ABI-NEXT:    //APP
+; SVE-ABI-NEXT:    //NO_APP
+; SVE-ABI-NEXT:    ret
+entry:
+  %y.y = call <4 x i64> asm sideeffect "", "={z1}"()
+  store <4 x i64> %y.y, ptr %y, align 16
+  %x.x = load <4 x i64>, ptr %x, align 16
+  call void asm sideeffect "", "{z0}"(<4 x i64> %x.x)
+  ret void
+}
+
+define void @sve_fixed_vector_breakdown_v16i8(ptr %x, ptr %y) {
+; SVE-ABI-LABEL: sve_fixed_vector_breakdown_v16i8:
+; SVE-ABI:       // %bb.0:
+; SVE-ABI-NEXT:    //APP
+; SVE-ABI-NEXT:    //NO_APP
+; SVE-ABI-NEXT:    str q1, [x1]
+; SVE-ABI-NEXT:    ldr q0, [x0]
+; SVE-ABI-NEXT:    //APP
+; SVE-ABI-NEXT:    //NO_APP
+; SVE-ABI-NEXT:    ret
+entry:
+  %y.y = call <16 x i8> asm sideeffect "", "={z1}"()
+  store <16 x i8> %y.y, ptr %y, align 16
+  %x.x = load <16 x i8>, ptr %x, align 16
+  call void asm sideeffect "", "{z0}"(<16 x i8> %x.x)
+  ret void
+}



More information about the llvm-commits mailing list