Bug type: crash
Component: SLPVectorizer
Bug location: llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp: BoUpSLP::isGatherShuffledSingleRegisterEntry
Issue title: SLP: Instruction does not dominate all uses (insertelement/shufflevector)
Labels: llvm:SLPVectorizer
crash
Reported by: vzakhari

[slp.ll.gz](https://github.com/user-attachments/files/18972113/slp.ll.gz)

Reproducer: `opt -passes=slp-vectorizer slp.ll -mcpu=skylake`

@alexey-bataev can you please take a look?


Fix patch:
commit 418a9872851ef5342b29baa36dd672129f129953
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Wed Feb 26 12:59:27 2025 -0800

    [SLP]Do not use node, if it is a subvector or buildvector node
    
    If the buildvector has some matches with another node, which is
    a subvector of another buildvector node, need to check for this and
    cancel matching to avoid incorrect ordering of the nodes.
    
    Fixes #128770

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 02fea2eaf9d4..b25b09306aca 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -13353,6 +13353,14 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry(
       return EdgeInfo(const_cast<TreeEntry *>(TE), 0);
     return TE->UserTreeIndex;
   };
+  auto HasGatherUser = [&](const TreeEntry *TE) {
+    while (TE->Idx != 0 && TE->UserTreeIndex) {
+      if (TE->UserTreeIndex.EdgeIdx == UINT_MAX)
+        return true;
+      TE = TE->UserTreeIndex.UserTE;
+    }
+    return false;
+  };
   const EdgeInfo TEUseEI = GetUserEntry(TE);
   if (!TEUseEI)
     return std::nullopt;
@@ -13453,7 +13461,8 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry(
         // If the user instruction is used for some reason in different
         // vectorized nodes - make it depend on index.
         if (TEUseEI.UserTE != UseEI.UserTE &&
-            TEUseEI.UserTE->Idx < UseEI.UserTE->Idx)
+            (TEUseEI.UserTE->Idx < UseEI.UserTE->Idx ||
+             HasGatherUser(TEUseEI.UserTE)))
           continue;
       }
 


Regression tests:
file: llvm/test/Transforms/SLPVectorizer/X86/buildvector-reused-with-bv-subvector.ll
commands: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu -mcpu=skylake < %s
tests: test_name: <module>
test_body: 
define void @test(ptr %0, i64 %1, i64 %2) {
;
  %4 = ptrtoint ptr %0 to i64
  %5 = ptrtoint ptr %0 to i64
  %6 = ptrtoint ptr %0 to i64
  %7 = ptrtoint ptr %0 to i64
  %8 = ptrtoint ptr %0 to i64
  br label %.preheader.lr.ph

.preheader.lr.ph:
  br label %.preheader.us.us.preheader

.preheader.us.us.preheader:
  %9 = or i64 %1, %7
  %10 = or i64 %2, %7
  %11 = or i64 %1, %4
  %12 = or i64 %1, %8
  %13 = or i64 %5, %8
  %14 = or i64 %8, %4
  %15 = or i64 %5, %6
  %16 = or i64 %6, %4
  br label %.preheader.us.us

.preheader.us.us:
  %diff.check1 = icmp ult i64 %9, 32
  %diff.check2 = icmp ult i64 %10, 32
  %conflict.rdx3 = or i1 %diff.check1, %diff.check2
  %diff.check4 = icmp ult i64 %11, 32
  %conflict.rdx5 = or i1 %conflict.rdx3, %diff.check4
  %diff.check6 = icmp ult i64 %12, 32
  %conflict.rdx7 = or i1 %conflict.rdx5, %diff.check6
  %diff.check8 = icmp ult i64 %13, 32
  %conflict.rdx9 = or i1 %conflict.rdx7, %diff.check8
  %diff.check10 = icmp ult i64 %14, 32
  %conflict.rdx11 = or i1 %conflict.rdx9, %diff.check10
  %diff.check12 = icmp ult i64 %15, 32
  %conflict.rdx13 = or i1 %conflict.rdx11, %diff.check12
  %diff.check14 = icmp ult i64 %16, 32
  %conflict.rdx15 = or i1 %conflict.rdx13, %diff.check14
  br i1 %conflict.rdx15, label %scalar.ph, label %.preheader.us.us

scalar.ph:
  ret void
}