[llvm] [SLP]Fix crash on short interleaved gathered-load remainder (PR #210965)
Alexey Bataev via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 21 05:31:14 PDT 2026
https://github.com/alexey-bataev created https://github.com/llvm/llvm-project/pull/210965
A trailing, undersized chunk could keep an InterleaveFactor too
large for it, so RISCVTTIImpl::getInterleavedMemoryOpCost divided
by it and built a zero-element vector type.
Fixes #210849
>From f2ec0b767934e9646a6dde4b3dc581c6b60ff594 Mon Sep 17 00:00:00 2001
From: Alexey Bataev <a.bataev at outlook.com>
Date: Tue, 21 Jul 2026 05:31:01 -0700
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
=?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.7
---
.../Transforms/Vectorize/SLPVectorizer.cpp | 6 +-
...hered-loads-interleave-factor-remainder.ll | 142 ++++++++++++++++++
2 files changed, 147 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/Transforms/SLPVectorizer/RISCV/gathered-loads-interleave-factor-remainder.ll
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 9650415998142..9f8c85cb8e7b3 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -10123,7 +10123,11 @@ void BoUpSLP::tryToVectorizeGatheredLoads(
}))
continue;
unsigned Sz = VectorizableTree.size();
- buildTreeRec(SubSlice, 0, EdgeInfo(), InterleaveFactor);
+ // A chunk smaller than InterleaveFactor cannot form an
+ // interleave group; keep it non-interleaved instead.
+ buildTreeRec(
+ SubSlice, 0, EdgeInfo(),
+ SubSlice.size() >= InterleaveFactor ? InterleaveFactor : 0);
if (Sz == VectorizableTree.size()) {
IsVectorized = false;
// Try non-interleaved vectorization with smaller vector
diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/gathered-loads-interleave-factor-remainder.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/gathered-loads-interleave-factor-remainder.ll
new file mode 100644
index 0000000000000..0ec1672a2ddf5
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/RISCV/gathered-loads-interleave-factor-remainder.ll
@@ -0,0 +1,142 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -passes=slp-vectorizer -mtriple=riscv64-unknown-fuchsia -mattr=+zve64x -S | FileCheck %s
+
+; The trailing, less-than-full-width chunk of gathered loads must not be
+; tagged with the interleave factor computed for the full-width chunks,
+; otherwise the cost model divides the chunk size by the factor and gets 0,
+; tripping the FixedVectorType::get NumElts > 0 assertion.
+
+define void @_Z8keccak_fv() {
+; CHECK-LABEL: define void @_Z8keccak_fv(
+; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: [[ARRAYIDX12_PHI_TRANS_INSERT:%.*]] = getelementptr i8, ptr null, i64 120
+; CHECK-NEXT: [[DOTPRE105:%.*]] = load i64, ptr [[ARRAYIDX12_PHI_TRANS_INSERT]], align 8
+; CHECK-NEXT: [[ARRAYIDX16_PHI_TRANS_INSERT:%.*]] = getelementptr i8, ptr null, i64 160
+; CHECK-NEXT: [[DOTPRE106:%.*]] = load i64, ptr [[ARRAYIDX16_PHI_TRANS_INSERT]], align 8
+; CHECK-NEXT: [[ARRAYIDX_2_PHI_TRANS_INSERT:%.*]] = getelementptr i8, ptr null, i64 16
+; CHECK-NEXT: [[DOTPRE107:%.*]] = load i64, ptr [[ARRAYIDX_2_PHI_TRANS_INSERT]], align 8
+; CHECK-NEXT: [[ARRAYIDX5_2_PHI_TRANS_INSERT:%.*]] = getelementptr i8, ptr null, i64 56
+; CHECK-NEXT: [[DOTPRE109:%.*]] = load i64, ptr [[ARRAYIDX5_2_PHI_TRANS_INSERT]], align 8
+; CHECK-NEXT: [[ARRAYIDX8_2_PHI_TRANS_INSERT:%.*]] = getelementptr i8, ptr null, i64 96
+; CHECK-NEXT: [[DOTPRE111:%.*]] = load i64, ptr [[ARRAYIDX8_2_PHI_TRANS_INSERT]], align 8
+; CHECK-NEXT: [[ARRAYIDX12_2_PHI_TRANS_INSERT:%.*]] = getelementptr i8, ptr null, i64 136
+; CHECK-NEXT: [[DOTPRE113:%.*]] = load i64, ptr [[ARRAYIDX12_2_PHI_TRANS_INSERT]], align 8
+; CHECK-NEXT: [[ARRAYIDX16_2_PHI_TRANS_INSERT:%.*]] = getelementptr i8, ptr null, i64 176
+; CHECK-NEXT: [[DOTPRE115:%.*]] = load i64, ptr [[ARRAYIDX16_2_PHI_TRANS_INSERT]], align 8
+; CHECK-NEXT: [[ARRAYIDX_3_PHI_TRANS_INSERT:%.*]] = getelementptr i8, ptr null, i64 24
+; CHECK-NEXT: [[DOTPRE116:%.*]] = load i64, ptr [[ARRAYIDX_3_PHI_TRANS_INSERT]], align 8
+; CHECK-NEXT: [[DOTPRE120:%.*]] = load i64, ptr null, align 8
+; CHECK-NEXT: [[ARRAYIDX12_3_PHI_TRANS_INSERT:%.*]] = getelementptr i8, ptr null, i64 144
+; CHECK-NEXT: [[DOTPRE122:%.*]] = load i64, ptr [[ARRAYIDX12_3_PHI_TRANS_INSERT]], align 8
+; CHECK-NEXT: [[ARRAYIDX16_3_PHI_TRANS_INSERT:%.*]] = getelementptr i8, ptr null, i64 184
+; CHECK-NEXT: [[DOTPRE124:%.*]] = load i64, ptr [[ARRAYIDX16_3_PHI_TRANS_INSERT]], align 8
+; CHECK-NEXT: [[ARRAYIDX8_4_PHI_TRANS_INSERT:%.*]] = getelementptr i8, ptr null, i64 112
+; CHECK-NEXT: [[DOTPRE127:%.*]] = load i64, ptr [[ARRAYIDX8_4_PHI_TRANS_INSERT]], align 8
+; CHECK-NEXT: [[ARRAYIDX12_4_PHI_TRANS_INSERT:%.*]] = getelementptr i8, ptr null, i64 152
+; CHECK-NEXT: [[DOTPRE128:%.*]] = load i64, ptr [[ARRAYIDX12_4_PHI_TRANS_INSERT]], align 8
+; CHECK-NEXT: [[ARRAYIDX16_4_PHI_TRANS_INSERT:%.*]] = getelementptr i8, ptr null, i64 192
+; CHECK-NEXT: [[DOTPRE129:%.*]] = load i64, ptr [[ARRAYIDX16_4_PHI_TRANS_INSERT]], align 8
+; CHECK-NEXT: [[ARRAYIDX12_1:%.*]] = getelementptr i8, ptr null, i64 128
+; CHECK-NEXT: [[ARRAYIDX12_1_PROMOTED:%.*]] = load i64, ptr [[ARRAYIDX12_1]], align 8
+; CHECK-NEXT: [[ARRAYIDX16_1:%.*]] = getelementptr i8, ptr null, i64 168
+; CHECK-NEXT: [[ARRAYIDX16_1_PROMOTED:%.*]] = load i64, ptr [[ARRAYIDX16_1]], align 8
+; CHECK-NEXT: br label %[[FOR_BODY:.*]]
+; CHECK: [[FOR_BODY]]:
+; CHECK-NEXT: [[TMP0:%.*]] = phi i64 [ [[ARRAYIDX16_1_PROMOTED]], %[[ENTRY]] ], [ 0, %[[FOR_BODY]] ]
+; CHECK-NEXT: [[TMP1:%.*]] = phi i64 [ [[ARRAYIDX12_1_PROMOTED]], %[[ENTRY]] ], [ 0, %[[FOR_BODY]] ]
+; CHECK-NEXT: [[TMP2:%.*]] = phi i64 [ [[DOTPRE129]], %[[ENTRY]] ], [ 0, %[[FOR_BODY]] ]
+; CHECK-NEXT: [[TMP3:%.*]] = phi i64 [ [[DOTPRE128]], %[[ENTRY]] ], [ 0, %[[FOR_BODY]] ]
+; CHECK-NEXT: [[TMP4:%.*]] = phi i64 [ [[DOTPRE124]], %[[ENTRY]] ], [ [[AND_4:%.*]], %[[FOR_BODY]] ]
+; CHECK-NEXT: [[TMP5:%.*]] = phi i64 [ [[DOTPRE122]], %[[ENTRY]] ], [ [[XOR60_3:%.*]], %[[FOR_BODY]] ]
+; CHECK-NEXT: [[TMP6:%.*]] = phi i64 [ [[DOTPRE120]], %[[ENTRY]] ], [ 0, %[[FOR_BODY]] ]
+; CHECK-NEXT: [[TMP7:%.*]] = phi i64 [ [[DOTPRE115]], %[[ENTRY]] ], [ 0, %[[FOR_BODY]] ]
+; CHECK-NEXT: [[TMP8:%.*]] = phi i64 [ [[DOTPRE109]], %[[ENTRY]] ], [ [[XOR37_499:%.*]], %[[FOR_BODY]] ]
+; CHECK-NEXT: [[TMP9:%.*]] = phi i64 [ [[DOTPRE107]], %[[ENTRY]] ], [ [[OP_RDX1:%.*]], %[[FOR_BODY]] ]
+; CHECK-NEXT: [[TMP10:%.*]] = xor i64 [[DOTPRE111]], [[DOTPRE113]]
+; CHECK-NEXT: [[TMP11:%.*]] = xor i64 [[TMP10]], [[TMP7]]
+; CHECK-NEXT: [[TMP12:%.*]] = xor i64 [[TMP11]], [[TMP9]]
+; CHECK-NEXT: [[XOR17_2:%.*]] = xor i64 [[TMP12]], [[TMP8]]
+; CHECK-NEXT: [[XOR_3:%.*]] = xor i64 0, [[DOTPRE116]]
+; CHECK-NEXT: [[XOR9_3:%.*]] = xor i64 [[XOR_3]], [[TMP6]]
+; CHECK-NEXT: [[XOR13_3:%.*]] = xor i64 [[XOR9_3]], [[TMP5]]
+; CHECK-NEXT: [[XOR17_3:%.*]] = xor i64 [[XOR13_3]], [[TMP4]]
+; CHECK-NEXT: [[XOR29_4:%.*]] = xor i64 [[XOR17_2]], [[XOR17_3]]
+; CHECK-NEXT: [[XOR37_499]] = xor i64 [[XOR29_4]], [[DOTPRE106]]
+; CHECK-NEXT: [[OP_RDX:%.*]] = xor i64 0, [[TMP1]]
+; CHECK-NEXT: [[OP_RDX1]] = xor i64 [[OP_RDX]], [[TMP0]]
+; CHECK-NEXT: [[XOR17_4:%.*]] = xor i64 [[TMP3]], [[TMP2]]
+; CHECK-NEXT: [[XOR37_3:%.*]] = xor i64 [[XOR17_4]], [[DOTPRE105]]
+; CHECK-NEXT: [[AND_3:%.*]] = and i64 [[XOR37_3]], 0
+; CHECK-NEXT: [[XOR60_3]] = xor i64 0, [[AND_3]]
+; CHECK-NEXT: [[XOR37_4:%.*]] = xor i64 [[DOTPRE127]], 0
+; CHECK-NEXT: [[AND_4]] = and i64 [[XOR37_4]], 0
+; CHECK-NEXT: br label %[[FOR_BODY]]
+;
+entry:
+ %arrayidx12.phi.trans.insert = getelementptr i8, ptr null, i64 120
+ %.pre105 = load i64, ptr %arrayidx12.phi.trans.insert, align 8
+ %arrayidx16.phi.trans.insert = getelementptr i8, ptr null, i64 160
+ %.pre106 = load i64, ptr %arrayidx16.phi.trans.insert, align 8
+ %arrayidx.2.phi.trans.insert = getelementptr i8, ptr null, i64 16
+ %.pre107 = load i64, ptr %arrayidx.2.phi.trans.insert, align 8
+ %arrayidx5.2.phi.trans.insert = getelementptr i8, ptr null, i64 56
+ %.pre109 = load i64, ptr %arrayidx5.2.phi.trans.insert, align 8
+ %arrayidx8.2.phi.trans.insert = getelementptr i8, ptr null, i64 96
+ %.pre111 = load i64, ptr %arrayidx8.2.phi.trans.insert, align 8
+ %arrayidx12.2.phi.trans.insert = getelementptr i8, ptr null, i64 136
+ %.pre113 = load i64, ptr %arrayidx12.2.phi.trans.insert, align 8
+ %arrayidx16.2.phi.trans.insert = getelementptr i8, ptr null, i64 176
+ %.pre115 = load i64, ptr %arrayidx16.2.phi.trans.insert, align 8
+ %arrayidx.3.phi.trans.insert = getelementptr i8, ptr null, i64 24
+ %.pre116 = load i64, ptr %arrayidx.3.phi.trans.insert, align 8
+ %.pre120 = load i64, ptr null, align 8
+ %arrayidx12.3.phi.trans.insert = getelementptr i8, ptr null, i64 144
+ %.pre122 = load i64, ptr %arrayidx12.3.phi.trans.insert, align 8
+ %arrayidx16.3.phi.trans.insert = getelementptr i8, ptr null, i64 184
+ %.pre124 = load i64, ptr %arrayidx16.3.phi.trans.insert, align 8
+ %arrayidx8.4.phi.trans.insert = getelementptr i8, ptr null, i64 112
+ %.pre127 = load i64, ptr %arrayidx8.4.phi.trans.insert, align 8
+ %arrayidx12.4.phi.trans.insert = getelementptr i8, ptr null, i64 152
+ %.pre128 = load i64, ptr %arrayidx12.4.phi.trans.insert, align 8
+ %arrayidx16.4.phi.trans.insert = getelementptr i8, ptr null, i64 192
+ %.pre129 = load i64, ptr %arrayidx16.4.phi.trans.insert, align 8
+ %arrayidx12.1 = getelementptr i8, ptr null, i64 128
+ %arrayidx12.1.promoted = load i64, ptr %arrayidx12.1, align 8
+ %arrayidx16.1 = getelementptr i8, ptr null, i64 168
+ %arrayidx16.1.promoted = load i64, ptr %arrayidx16.1, align 8
+ br label %for.body
+
+for.body:
+ %0 = phi i64 [ %arrayidx16.1.promoted, %entry ], [ 0, %for.body ]
+ %1 = phi i64 [ %arrayidx12.1.promoted, %entry ], [ 0, %for.body ]
+ %2 = phi i64 [ %.pre129, %entry ], [ 0, %for.body ]
+ %3 = phi i64 [ %.pre128, %entry ], [ 0, %for.body ]
+ %4 = phi i64 [ %.pre124, %entry ], [ %and.4, %for.body ]
+ %5 = phi i64 [ %.pre122, %entry ], [ %xor60.3, %for.body ]
+ %6 = phi i64 [ %.pre120, %entry ], [ 0, %for.body ]
+ %7 = phi i64 [ %.pre115, %entry ], [ 0, %for.body ]
+ %8 = phi i64 [ %.pre109, %entry ], [ %xor37.499, %for.body ]
+ %9 = phi i64 [ %.pre107, %entry ], [ %xor54, %for.body ]
+ %10 = xor i64 %.pre111, %.pre113
+ %11 = xor i64 %10, %7
+ %12 = xor i64 %11, %9
+ %xor17.2 = xor i64 %12, %8
+ %xor.3 = xor i64 0, %.pre116
+ %xor9.3 = xor i64 %xor.3, %6
+ %xor13.3 = xor i64 %xor9.3, %5
+ %xor17.3 = xor i64 %xor13.3, %4
+ %xor29.4 = xor i64 %xor17.2, %xor17.3
+ %xor37.499 = xor i64 %xor29.4, %.pre106
+ %xor17.1 = xor i64 %1, %0
+ %xor37.295 = xor i64 %xor17.1, 0
+ %13 = xor i64 0, %xor37.295
+ %xor54 = xor i64 %13, 0
+ %xor17.4 = xor i64 %3, %2
+ %xor37.3 = xor i64 %xor17.4, %.pre105
+ %and.3 = and i64 %xor37.3, 0
+ %xor60.3 = xor i64 0, %and.3
+ %xor37.4 = xor i64 %.pre127, 0
+ %and.4 = and i64 %xor37.4, 0
+ br label %for.body
+}
More information about the llvm-commits
mailing list