Bug type: crash
Component: SLPVectorizer
Bug location: llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp: BoUpSLP::buildTree_rec
Issue title: [SLPVectorizer] Instruction does not dominate all uses! LLVM ERROR: Broken module found, compilation aborted!
Labels: llvm:SLPVectorizer
llvm:crash
Reported by: TatyanaDoubts

To reproduce run the test below with -passes slp-vectorizer -slp-threshold=-99999
```
; ModuleID = './reduced.ll'
source_filename = "./reduced.ll"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2"
target triple = "x86_64-unknown-linux-gnu"

define void @wombat() #0 gc "statepoint-example" {
bb:
  br label %bb1

bb1:                                              ; preds = %bb3, %bb
  %phi = phi i32 [ 0, %bb ], [ %add5, %bb3 ]
  %phi2 = phi i32 [ 0, %bb ], [ %add, %bb3 ]
  br i1 false, label %bb6, label %bb3

bb3:                                              ; preds = %bb1
  %add = add i32 0, 0
  %add4 = add i32 0, 0
  %add5 = add i32 %phi, 0
  br i1 false, label %bb6, label %bb1

bb6:                                              ; preds = %bb3, %bb1
  %phi7 = phi i32 [ %phi2, %bb1 ], [ %add4, %bb3 ]
  %phi8 = phi i32 [ %phi, %bb1 ], [ %add5, %bb3 ]
  ret void
}
```
Reproducer: https://godbolt.org/z/W96s5a1cb

```
Instruction does not dominate all uses!
  %2 = shufflevector <2 x i32> %0, <2 x i32> <i32 0, i32 poison>, <2 x i32> <i32 2, i32 1>
  %1 = add <2 x i32> zeroinitializer, %2
LLVM ERROR: Broken module found, compilation aborted!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes slp-vectorizer -slp-threshold=-99999 <source>
1.	Running pass "verify" on module "<source>"
 #0 0x0000000004f84b88 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4f84b88)
 #1 0x0000000004f822fc SignalHandler(int) Signals.cpp:0:0
 #2 0x000074dcb3642520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x000074dcb36969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x000074dcb3642476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x000074dcb36287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x00000000007b7cc5 llvm::json::operator==(llvm::json::Value const&, llvm::json::Value const&) (.cold) JSON.cpp:0:0
 #7 0x0000000004ebea18 (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4ebea18)
 #8 0x0000000004dbae20 llvm::VerifierPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4dbae20)
 #9 0x00000000008dbbde llvm::detail::PassModel<llvm::Module, llvm::VerifierPass, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8dbbde)
#10 0x0000000004d7ebb0 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4d7ebb0)
#11 0x00000000008e6912 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8e6912)
#12 0x00000000008d97ec optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8d97ec)
#13 0x000074dcb3629d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#14 0x000074dcb3629e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#15 0x00000000008d127e _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8d127e)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```

Comments: author: alexey-bataev
body: Yes

Fix patch:
commit e31252bf54dedadfe78b36d07ea6084156faa38a
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Wed Aug 21 11:47:00 2024 -0700

    [SLP]Fix PR105120: fix the order of phi nodes vectorization.
    
    The operands of the phi nodes should be vectorized in the same order, in
    which they were created, otherwise the compiler may crash when trying
    to correctly build dependency for nodes with non-schedulable
    instructions for gather/buildvector nodes.
    
    Fixes https://github.com/llvm/llvm-project/issues/105120

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index dee6d688b1b9..848e0de20e7b 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -7227,6 +7227,22 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
 
   unsigned ShuffleOrOp = S.isAltShuffle() ?
                 (unsigned) Instruction::ShuffleVector : S.getOpcode();
+  auto CreateOperandNodes = [&](TreeEntry *TE, const auto &Operands) {
+    // Postpone PHI nodes creation
+    SmallVector<unsigned> PHIOps;
+    for (unsigned I : seq<unsigned>(Operands.size())) {
+      ArrayRef<Value *> Op = Operands[I];
+      if (Op.empty())
+        continue;
+      InstructionsState S = getSameOpcode(Op, *TLI);
+      if (S.getOpcode() != Instruction::PHI || S.isAltShuffle())
+        buildTree_rec(Op, Depth + 1, {TE, I});
+      else
+        PHIOps.push_back(I);
+    }
+    for (unsigned I : PHIOps)
+      buildTree_rec(Operands[I], Depth + 1, {TE, I});
+  };
   switch (ShuffleOrOp) {
     case Instruction::PHI: {
       auto *PH = cast<PHINode>(VL0);
@@ -7238,10 +7254,12 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
       // Keeps the reordered operands to avoid code duplication.
       PHIHandler Handler(*DT, PH, VL);
       Handler.buildOperands();
-      for (unsigned I : seq<unsigned>(0, PH->getNumOperands()))
+      for (unsigned I : seq<unsigned>(PH->getNumOperands()))
         TE->setOperand(I, Handler.getOperands(I));
-      for (unsigned I : seq<unsigned>(0, PH->getNumOperands()))
-        buildTree_rec(Handler.getOperands(I), Depth + 1, {TE, I});
+      SmallVector<ArrayRef<Value *>> Operands(PH->getNumOperands());
+      for (unsigned I : seq<unsigned>(PH->getNumOperands()))
+        Operands[I] = Handler.getOperands(I);
+      CreateOperandNodes(TE, Operands);
       return;
     }
     case Instruction::ExtractValue:


Regression tests:
file: llvm/test/Transforms/SLPVectorizer/X86/phi-nodes-as-operand-reorder.ll
commands: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu -slp-threshold=-99999 < %s
tests: test_name: test
test_body: define void @test() {
bb:
  br label %bb1

bb1:                                              ; preds = %bb3, %bb
  %phi = phi i32 [ 0, %bb ], [ %add5, %bb3 ]
  %phi2 = phi i32 [ 0, %bb ], [ %add, %bb3 ]
  br i1 false, label %bb6, label %bb3

bb3:                                              ; preds = %bb1
  %add = add i32 0, 0
  %add4 = add i32 0, 0
  %add5 = add i32 %phi, 0
  br i1 false, label %bb6, label %bb1

bb6:                                              ; preds = %bb3, %bb1
  %phi7 = phi i32 [ %phi2, %bb1 ], [ %add4, %bb3 ]
  %phi8 = phi i32 [ %phi, %bb1 ], [ %add5, %bb3 ]
  ret void
}