Author: Florian Hahn
Date: 2026-07-28T11:43:45+02:00
New Revision: 8eddfe681bae133c1c396220638abd9636c171e1

URL: 
https://github.com/llvm/llvm-project/commit/8eddfe681bae133c1c396220638abd9636c171e1
DIFF: 
https://github.com/llvm/llvm-project/commit/8eddfe681bae133c1c396220638abd9636c171e1.diff

LOG: [SLP] Only consider BuildVector inserts into the same object. (#212269)

When following insertelement instruction for a BuildVector sequence, we
may discover a user that inserts into a different vector.

Bail out when that happens instead of crashing.

PR: https://github.com/llvm/llvm-project/pull/212269
(cherry picked from commit 07aa3b710f2622f662cab7a53ddf1288c725a9be)

Added: 
    
llvm/test/Transforms/SLPVectorizer/AArch64/buildvector-used-by-insertvalue.ll

Modified: 
    llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp 
b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 7e22ba3bd149c..80091308116f7 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -23694,6 +23694,7 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E) {
           // Follow all insert element instructions from the current 
buildvector
           // sequence.
           Instruction *Ins = VL0;
+          Instruction *Op;
           do {
             std::optional<unsigned> InsertIdx = getElementIndex(Ins);
             if (!InsertIdx)
@@ -23702,9 +23703,10 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E) {
               InsertMask[*InsertIdx] = *InsertIdx;
             if (!Ins->hasOneUse())
               break;
+            Op = Ins;
             Ins =
                 dyn_cast_or_null<Instruction>(Ins->getUniqueUndroppableUser());
-          } while (Ins);
+          } while (Ins && Ins->getOperand(0) == Op);
           SmallBitVector UseMask =
               buildUseMask(NumElts, InsertMask, UseMask::UndefsAsMask);
           SmallBitVector IsFirstPoison =

diff  --git 
a/llvm/test/Transforms/SLPVectorizer/AArch64/buildvector-used-by-insertvalue.ll 
b/llvm/test/Transforms/SLPVectorizer/AArch64/buildvector-used-by-insertvalue.ll
new file mode 100644
index 0000000000000..ac7dd2c00e8a7
--- /dev/null
+++ 
b/llvm/test/Transforms/SLPVectorizer/AArch64/buildvector-used-by-insertvalue.ll
@@ -0,0 +1,59 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 
UTC_ARGS: --version 6
+; RUN: opt -passes=slp-vectorizer -S %s | FileCheck %s
+
+target triple = "aarch64-unknown-linux-gnu"
+
+%struct.f4x3 = type { [4 x <3 x float>] }
+
+; The buildvector for <3 x float> is consumed by an insertvalue that places it
+; at aggregate index 3.
+define %struct.f4x3 @buildvector_used_by_insertvalue(ptr %p, float %c) {
+; CHECK-LABEL: define %struct.f4x3 @buildvector_used_by_insertvalue(
+; CHECK-SAME: ptr [[P:%.*]], float [[C:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x double>, ptr [[P]], align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc <2 x double> [[TMP0]] to <2 x float>
+; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x 
float> poison, <3 x i32> <i32 0, i32 1, i32 poison>
+; CHECK-NEXT:    [[INS_11:%.*]] = shufflevector <3 x float> zeroinitializer, 
<3 x float> [[TMP2]], <3 x i32> <i32 3, i32 4, i32 2>
+; CHECK-NEXT:    [[INS_2:%.*]] = insertelement <3 x float> [[INS_11]], float 
[[C]], i32 0
+; CHECK-NEXT:    [[RES:%.*]] = insertvalue [[STRUCT_F4X3:%.*]] 
zeroinitializer, <3 x float> [[INS_2]], 0, 3
+; CHECK-NEXT:    ret [[STRUCT_F4X3]] [[RES]]
+;
+entry:
+  %p.1 = getelementptr inbounds i8, ptr %p, i64 8
+  %l.0 = load double, ptr %p, align 8
+  %l.1 = load double, ptr %p.1, align 8
+  %conv.0 = fptrunc double %l.0 to float
+  %ins.0 = insertelement <3 x float> zeroinitializer, float %conv.0, i32 0
+  %conv.1 = fptrunc double %l.1 to float
+  %ins.1 = insertelement <3 x float> %ins.0, float %conv.1, i32 1
+  %ins.2 = insertelement <3 x float> %ins.1, float %c, i32 0
+  %res = insertvalue %struct.f4x3 zeroinitializer, <3 x float> %ins.2, 0, 3
+  ret %struct.f4x3 %res
+}
+
+; Same buildvector, but stored instead of placed into an aggregate.
+define void @buildvector_used_by_store(ptr %p, float %c, ptr %q) {
+; CHECK-LABEL: define void @buildvector_used_by_store(
+; CHECK-SAME: ptr [[P:%.*]], float [[C:%.*]], ptr [[Q:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x double>, ptr [[P]], align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc <2 x double> [[TMP0]] to <2 x float>
+; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x 
float> poison, <3 x i32> <i32 0, i32 1, i32 poison>
+; CHECK-NEXT:    [[INS_11:%.*]] = shufflevector <3 x float> zeroinitializer, 
<3 x float> [[TMP2]], <3 x i32> <i32 3, i32 4, i32 2>
+; CHECK-NEXT:    [[INS_2:%.*]] = insertelement <3 x float> [[INS_11]], float 
[[C]], i32 0
+; CHECK-NEXT:    store <3 x float> [[INS_2]], ptr [[Q]], align 16
+; CHECK-NEXT:    ret void
+;
+entry:
+  %p.1 = getelementptr inbounds i8, ptr %p, i64 8
+  %l.0 = load double, ptr %p, align 8
+  %l.1 = load double, ptr %p.1, align 8
+  %conv.0 = fptrunc double %l.0 to float
+  %ins.0 = insertelement <3 x float> zeroinitializer, float %conv.0, i32 0
+  %conv.1 = fptrunc double %l.1 to float
+  %ins.1 = insertelement <3 x float> %ins.0, float %conv.1, i32 1
+  %ins.2 = insertelement <3 x float> %ins.1, float %c, i32 0
+  store <3 x float> %ins.2, ptr %q, align 16
+  ret void
+}


        
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to