Bug type: crash
Component: SLPVectorizer
Bug location: llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp: BoUpSLP::getLastInstructionInBundle
BoUpSLP::setInsertPointAfterBundle
BoUpSLP::vectorizeTree
Issue title: Instruction does not dominate all uses! LLVM ERROR: Broken module found, compilation aborted! Yet another case.
Labels: llvm:SLPVectorizer
crash-on-valid
Reported by: TatyanaDoubts

To reproduce run opt with the test below using -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 i64 @wombat() #0 gc "statepoint-example" {
bb:
  br label %bb1

bb1:                                              ; preds = %bb5, %bb
  %phi = phi i32 [ 0, %bb ], [ %or, %bb5 ]
  %phi2 = phi i32 [ 0, %bb ], [ %or4, %bb5 ]
  %or = or i32 %phi, 0
  %add = add i32 0, 0
  %or3 = or i32 %add, %phi2
  %or4 = or i32 %or3, 0
  br label %bb5

bb5:                                              ; preds = %bb1
  br i1 false, label %bb6, label %bb1

bb6:                                              ; preds = %bb5
  %phi7 = phi i32 [ %or, %bb5 ]
  %phi8 = phi i32 [ %or3, %bb5 ]
  ret i64 0
}

attributes #0 = { "target-features"="+prfchw,-cldemote,+avx,+aes,+sahf,+pclmul,-xop,+crc32,-amx-fp8,+xsaves,-avx512fp16,-usermsr,-sm4,-egpr,+sse4.1,-avx512ifma,+xsave,+sse4.2,-tsxldtrk,-sm3,-ptwrite,-widekl,-movrs,+invpcid,+64bit,+xsavec,-avx10.1-512,-avx512vpopcntdq,+cmov,-avx512vp2intersect,+avx512cd,+movbe,-avxvnniint8,-ccmp,-amx-int8,-kl,-avx10.1-256,+evex512,-avxvnni,+rtm,+adx,+avx2,-hreset,-movdiri,-serialize,-sha512,-vpclmulqdq,+avx512vl,-uintr,-cf,+clflushopt,-raoint,-cmpccxadd,+bmi,-amx-tile,+sse,-avx10.2-256,-gfni,-avxvnniint16,-amx-fp16,-zu,-ndd,+xsaveopt,+rdrnd,+avx512f,-amx-bf16,-avx512bf16,-avx512vnni,-push2pop2,+cx8,+avx512bw,+sse3,+pku,-nf,-amx-tf32,-amx-avx512,+fsgsbase,-clzero,-mwaitx,-lwp,+lzcnt,-sha,-movdir64b,-ppx,-wbnoinvd,-enqcmd,-amx-transpose,-avx10.2-512,-avxneconvert,-tbm,-pconfig,-amx-complex,+ssse3,+cx16,+bmi2,+fma,+popcnt,-avxifma,+f16c,-avx512bitalg,-rdpru,+clwb,+mmx,+sse2,+rdseed,-avx512vbmi2,-prefetchi,-amx-movrs,-rdpid,-fma4,-avx512vbmi,-shstk,-vaes,-waitpkg,-sgx,+fxsr,+avx512dq,-sse4a,-avx512f" }
```

Reproducer: https://godbolt.org/z/xh9xjfEKc

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 0x00000000055a8748 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x55a8748)
 #1 0x00000000055a60d4 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #2 0x00007479c4242520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x00007479c42969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x00007479c4242476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x00007479c42287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x000000000080bfcd llvm::json::operator==(llvm::json::Value const&, llvm::json::Value const&) (.cold) JSON.cpp:0:0
 #7 0x00000000054e4741 (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x54e4741)
 #8 0x00000000053e0e38 (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x53e0e38)
 #9 0x0000000000940c0e 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+0x940c0e)
#10 0x000000000539ff70 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x539ff70)
#11 0x000000000094b05a 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+0x94b05a)
#12 0x000000000093e82c optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x93e82c)
#13 0x00007479c4229d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#14 0x00007479c4229e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#15 0x0000000000936465 _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x936465)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```


Fix patch:
commit d79d9b8fbfc7e8411aeaf2f5e1be9d4247594fee
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Fri May 16 12:52:27 2025 -0400

    [SLP]Change the insertion point for outside-block-used nodes and prevec phi operand gathers
    
    Need to set the insertion point for (non-schedulable) vector node after
    the last instruction in the node to avoid def-use breakage. But it also
    causes miscompilation with gather/buildvector operands of the phi nodes,
    used in the same phi only in the block.
    These nodes supposed to be inserted at the end of the block and after
    changing the insertion point for the non-schedulable vec block, it also
    may break def-use dependencies. Need to prevector such nodes, to emit
    them as early as possible, so the vectorized nodes are inserted before
    these nodes.
    
    Fixes #139728
    
    Reviewers: hiraditya, HanKuanChen, RKSimon
    
    Reviewed By: RKSimon
    
    Pull Request: https://github.com/llvm/llvm-project/pull/139917

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index eb339282fdae..19d19946ea23 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -16142,16 +16142,10 @@ Instruction &BoUpSLP::getLastInstructionInBundle(const TreeEntry *E) {
                 [](Value *V) {
                   return !isa<GetElementPtrInst>(V) && isa<Instruction>(V);
                 })) ||
-        all_of(E->Scalars,
-               [](Value *V) {
-                 return isa<PoisonValue>(V) ||
-                        (!isVectorLikeInstWithConstOps(V) &&
-                         isUsedOutsideBlock(V));
-               }) ||
-        (E->isGather() && E->Idx == 0 && all_of(E->Scalars, [](Value *V) {
-           return isa<ExtractElementInst, UndefValue>(V) ||
-                  areAllOperandsNonInsts(V);
-         })))
+        all_of(E->Scalars, [](Value *V) {
+          return isa<PoisonValue>(V) ||
+                 (!isVectorLikeInstWithConstOps(V) && isUsedOutsideBlock(V));
+        }))
       Res = FindLastInst();
     else
       Res = FindFirstInst();
@@ -16210,7 +16204,7 @@ void BoUpSLP::setInsertPointAfterBundle(const TreeEntry *E) {
   }
   if (IsPHI ||
       (!E->isGather() && E->State != TreeEntry::SplitVectorize &&
-       doesNotNeedToSchedule(E->Scalars)) ||
+       all_of(E->Scalars, areAllOperandsNonInsts)) ||
       (GatheredLoadsEntriesFirst.has_value() &&
        E->Idx >= *GatheredLoadsEntriesFirst && !E->isGather() &&
        E->getOpcode() == Instruction::Load)) {
@@ -17799,17 +17793,27 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E) {
           Value *VecOp = NewPhi->getIncomingValueForBlock(IBB);
           NewPhi->addIncoming(VecOp, IBB);
           TreeEntry *OpTE = getOperandEntry(E, I);
+          assert(!OpTE->VectorizedValue && "Expected no vectorized value.");
           OpTE->VectorizedValue = VecOp;
           continue;
         }
 
         Builder.SetInsertPoint(IBB->getTerminator());
         Builder.SetCurrentDebugLocation(PH->getDebugLoc());
-        Value *Vec = vectorizeOperand(E, I);
+        const TreeEntry *OpE = getOperandEntry(E, I);
+        Value *Vec;
+        if (OpE->isGather()) {
+          assert(OpE->VectorizedValue && "Expected vectorized value.");
+          Vec = OpE->VectorizedValue;
+          if (auto *IVec = dyn_cast<Instruction>(Vec))
+            Builder.SetInsertPoint(IVec->getNextNonDebugInstruction());
+        } else {
+          Vec = vectorizeOperand(E, I);
+        }
         if (VecTy != Vec->getType()) {
-          assert((It != MinBWs.end() || getOperandEntry(E, I)->isGather() ||
-                  MinBWs.contains(getOperandEntry(E, I))) &&
-                 "Expected item in MinBWs.");
+          assert(
+              (It != MinBWs.end() || OpE->isGather() || MinBWs.contains(OpE)) &&
+              "Expected item in MinBWs.");
           Vec = Builder.CreateIntCast(Vec, VecTy, GetOperandSignedness(I));
         }
         NewPhi->addIncoming(Vec, IBB);
@@ -18696,6 +18700,28 @@ Value *BoUpSLP::vectorizeTree(
   else
     Builder.SetInsertPoint(&F->getEntryBlock(), F->getEntryBlock().begin());
 
+  // Vectorize gather operands of the PHI nodes.
+  for (const std::unique_ptr<TreeEntry> &TE : reverse(VectorizableTree)) {
+    if (TE->isGather() && TE->UserTreeIndex.UserTE &&
+        TE->UserTreeIndex.UserTE->hasState() &&
+        !TE->UserTreeIndex.UserTE->isAltShuffle() &&
+        TE->UserTreeIndex.UserTE->State == TreeEntry::Vectorize &&
+        TE->UserTreeIndex.UserTE->getOpcode() == Instruction::PHI &&
+        !TE->VectorizedValue) {
+      auto *PH = cast<PHINode>(TE->UserTreeIndex.UserTE->getMainOp());
+      BasicBlock *IBB = PH->getIncomingBlock(TE->UserTreeIndex.EdgeIdx);
+      // If there is the same incoming block earlier - skip, it will be handled
+      // in PHI node.
+      if (TE->UserTreeIndex.EdgeIdx > 0 &&
+          any_of(seq<unsigned>(TE->UserTreeIndex.EdgeIdx), [&](unsigned Idx) {
+            return PH->getIncomingBlock(Idx) == IBB;
+          }))
+        continue;
+      Builder.SetInsertPoint(IBB->getTerminator());
+      Builder.SetCurrentDebugLocation(PH->getDebugLoc());
+      (void)vectorizeTree(TE.get());
+    }
+  }
   // Emit gathered loads first to emit better code for the users of those
   // gathered loads.
   for (const std::unique_ptr<TreeEntry> &TE : VectorizableTree) {


Regression tests:
file: llvm/test/Transforms/SLPVectorizer/AArch64/reused-scalar-repeated-in-node.ll
commands: opt -S --passes=slp-vectorizer -mtriple=aarch64-unknown-linux-gnu < %s
tests: test_name: test
test_body: define void @test() {
entry:
  br label %bb61

bb61:                                             ; preds = %entry
  br label %bb64

bb62:                                             ; No predecessors!
  br i1 poison, label %bb63, label %bb64

bb63:                                             ; preds = %bb62
  br label %bb64

bb64:                                             ; preds = %bb63, %bb62, %bb61
  %i = phi nsz float [ poison, %bb61 ], [ poison, %bb63 ], [ poison, %bb62 ]
  %i65 = phi nsz float [ poison, %bb61 ], [ poison, %bb63 ], [ poison, %bb62 ]
  %i66 = load float, ptr poison, align 16
  %i67 = load float, ptr poison, align 4
  %i68 = load float, ptr poison, align 8
  %i69 = load float, ptr poison, align 4
  %i70 = load float, ptr poison, align 4
  %i71 = load float, ptr poison, align 16
  %i72 = load float, ptr poison, align 4
  %i73 = load float, ptr poison, align 8
  %i74 = load float, ptr poison, align 4
  %i75 = load float, ptr poison, align 16
  %i76 = load float, ptr poison, align 4
  br i1 poison, label %bb167, label %bb77

bb77:                                             ; preds = %bb64
  br label %bb78

bb78:                                             ; preds = %bb78, %bb77
  %i79 = phi nsz float [ %i66, %bb77 ], [ %i103, %bb78 ]
  %i80 = phi nsz float [ %i67, %bb77 ], [ %i104, %bb78 ]
  %i81 = phi nsz float [ %i68, %bb77 ], [ %i105, %bb78 ]
  %i82 = phi nsz float [ poison, %bb77 ], [ %i106, %bb78 ]
  %i83 = phi nsz float [ poison, %bb77 ], [ %i123, %bb78 ]
  %i84 = phi nsz float [ %i69, %bb77 ], [ %i124, %bb78 ]
  %i85 = phi nsz float [ poison, %bb77 ], [ %i125, %bb78 ]
  %i86 = phi nsz float [ %i70, %bb77 ], [ %i126, %bb78 ]
  %i87 = fmul fast float %i79, poison
  %i88 = fmul fast float %i80, poison
  %i89 = fmul fast float %i81, poison
  %i90 = fmul fast float %i82, poison
  %i91 = fmul fast float %i83, poison
  %i92 = fadd fast float %i91, %i87
  %i93 = fmul fast float %i84, poison
  %i94 = fadd fast float %i93, %i88
  %i95 = fmul fast float %i85, poison
  %i96 = fadd fast float %i95, %i89
  %i97 = fmul fast float %i86, poison
  %i98 = fadd fast float %i97, %i90
  %i99 = fadd fast float %i92, poison
  %i100 = fadd fast float %i94, poison
  %i101 = fadd fast float %i96, poison
  %i102 = fadd fast float %i98, poison
  %i103 = fadd fast float %i99, poison
  %i104 = fadd fast float %i100, poison
  %i105 = fadd fast float %i101, poison
  %i106 = fadd fast float %i102, poison
  %i107 = fmul fast float %i79, poison
  %i108 = fmul fast float %i80, poison
  %i109 = fmul fast float %i81, poison
  %i110 = fmul fast float %i82, poison
  %i111 = fmul fast float %i83, poison
  %i112 = fadd fast float %i111, %i107
  %i113 = fmul fast float %i84, poison
  %i114 = fadd fast float %i113, %i108
  %i115 = fmul fast float %i85, poison
  %i116 = fadd fast float %i115, %i109
  %i117 = fmul fast float %i86, poison
  %i118 = fadd fast float %i117, %i110
  %i119 = fadd fast float %i112, poison
  %i120 = fadd fast float %i114, poison
  %i121 = fadd fast float %i116, poison
  %i122 = fadd fast float %i118, poison
  %i123 = fadd fast float %i119, poison
  %i124 = fadd fast float %i120, poison
  %i125 = fadd fast float %i121, poison
  %i126 = fadd fast float %i122, poison
  %i127 = fmul fast float %i79, %i
  %i128 = fmul fast float %i80, %i
  %i129 = fmul fast float %i81, %i
  %i130 = fmul fast float %i82, %i
  %i131 = fmul fast float %i83, %i65
  %i132 = fadd fast float %i131, %i127
  %i133 = fmul fast float %i84, %i65
  %i134 = fadd fast float %i133, %i128
  %i135 = fmul fast float %i85, %i65
  %i136 = fadd fast float %i135, %i129
  %i137 = fmul fast float %i86, %i65
  %i138 = fadd fast float %i137, %i130
  %i139 = fadd fast float %i132, poison
  %i140 = fadd fast float %i134, poison
  %i141 = fadd fast float %i136, poison
  %i142 = fadd fast float %i138, poison
  %i143 = fadd fast float %i139, poison
  %i144 = fadd fast float %i140, poison
  %i145 = fadd fast float %i141, poison
  %i146 = fadd fast float %i142, poison
  %i147 = fmul fast float %i79, poison
  %i148 = fmul fast float %i80, poison
  %i149 = fmul fast float %i81, poison
  %i150 = fmul fast float %i82, poison
  %i151 = fmul fast float %i83, poison
  %i152 = fadd fast float %i151, %i147
  %i153 = fmul fast float %i84, poison
  %i154 = fadd fast float %i153, %i148
  %i155 = fmul fast float %i85, poison
  %i156 = fadd fast float %i155, %i149
  %i157 = fmul fast float %i86, poison
  %i158 = fadd fast float %i157, %i150
  %i159 = fadd fast float %i152, poison
  %i160 = fadd fast float %i154, poison
  %i161 = fadd fast float %i156, poison
  %i162 = fadd fast float %i158, poison
  %i163 = fadd fast float %i159, poison
  %i164 = fadd fast float %i160, poison
  %i165 = fadd fast float %i161, poison
  %i166 = fadd fast float %i162, poison
  br i1 poison, label %bb78, label %bb167

bb167:                                            ; preds = %bb78, %bb64
  %i168 = phi nsz float [ %i76, %bb64 ], [ %i166, %bb78 ]
  %i169 = phi nsz float [ poison, %bb64 ], [ %i165, %bb78 ]
  %i170 = phi nsz float [ poison, %bb64 ], [ %i164, %bb78 ]
  %i171 = phi nsz float [ %i75, %bb64 ], [ %i163, %bb78 ]
  %i172 = phi nsz float [ %i74, %bb64 ], [ %i146, %bb78 ]
  %i173 = phi nsz float [ %i73, %bb64 ], [ %i145, %bb78 ]
  %i174 = phi nsz float [ %i72, %bb64 ], [ %i144, %bb78 ]
  %i175 = phi nsz float [ %i71, %bb64 ], [ %i143, %bb78 ]
  %i176 = phi nsz float [ %i70, %bb64 ], [ %i126, %bb78 ]
  %i177 = phi nsz float [ poison, %bb64 ], [ %i125, %bb78 ]
  %i178 = phi nsz float [ %i69, %bb64 ], [ %i124, %bb78 ]
  %i179 = phi nsz float [ poison, %bb64 ], [ %i123, %bb78 ]
  %i180 = phi nsz float [ poison, %bb64 ], [ %i106, %bb78 ]
  %i181 = phi nsz float [ %i68, %bb64 ], [ %i105, %bb78 ]
  %i182 = phi nsz float [ %i67, %bb64 ], [ %i104, %bb78 ]
  %i183 = phi nsz float [ %i66, %bb64 ], [ %i103, %bb78 ]
  store float %i182, ptr poison, align 1
  store float %i174, ptr poison, align 1
  br i1 poison, label %bb186, label %bb184

bb184:                                            ; preds = %bb167
  br label %bb185

bb185:                                            ; preds = %bb185, %bb184
  br i1 poison, label %bb185, label %bb186

bb186:                                            ; preds = %bb185, %bb167
  %i187 = phi nsz float [ %i178, %bb167 ], [ poison, %bb185 ]
  ret void
}

file: llvm/test/Transforms/SLPVectorizer/X86/buildvectors-parent-phi-nodes.ll
commands: opt -S --passes=slp-vectorizer -mtriple=x86_64-generic-linux-gnu -mattr=+avx < %s
tests: test_name: test
test_body: define void @test(ptr %0, float %1) {
  %3 = load float, ptr %0, align 4
  br label %4

4:                                                ; preds = %4, %2
  %5 = phi float [ %1, %4 ], [ %3, %2 ]
  %6 = phi float [ %1, %4 ], [ 0.000000e+00, %2 ]
  %7 = phi float [ %28, %4 ], [ 0.000000e+00, %2 ]
  %8 = phi float [ %26, %4 ], [ 0.000000e+00, %2 ]
  %9 = phi float [ %26, %4 ], [ %3, %2 ]
  %10 = phi float [ %24, %4 ], [ 0.000000e+00, %2 ]
  %11 = fmul float %9, 0.000000e+00
  %12 = fadd float %11, 0.000000e+00
  %13 = fmul float %7, 0.000000e+00
  %14 = fadd float %13, 0.000000e+00
  %15 = fmul float %10, 0.000000e+00
  %16 = fadd float %15, 0.000000e+00
  %17 = fmul float %8, 0.000000e+00
  %18 = fadd float %17, 0.000000e+00
  %19 = insertelement <4 x float> zeroinitializer, float %12, i64 0
  %20 = insertelement <4 x float> %19, float %14, i64 1
  %21 = insertelement <4 x float> %20, float %16, i64 2
  %22 = insertelement <4 x float> %21, float %18, i64 3
  store <4 x float> %22, ptr %0, align 16
  %23 = fmul float %6, 0.000000e+00
  %24 = fadd float %23, 0.000000e+00
  %25 = fmul float %6, 0.000000e+00
  %26 = fadd float %25, 0.000000e+00
  %27 = fmul float %5, 0.000000e+00
  %28 = fadd float %27, 0.000000e+00
  br label %4
}

file: llvm/test/Transforms/SLPVectorizer/X86/full-matched-bv-with-subvectors.ll
commands: opt -S --passes=slp-vectorizer -slp-threshold=-9999 -mtriple=x86_64-unknown-linux-gnu < %s
tests: test_name: test
test_body: define i32 @test(i64 %l.549) {
entry:
  %conv3 = sext i32 0 to i64
  br label %if.then19

p:                                                ; preds = %if.end29, %if.end25
  %l.0 = phi i64 [ %xor, %if.end29 ], [ %l.5493, %if.end25 ]
  %m.0 = phi i64 [ %not21, %if.end29 ], [ %m.550, %if.end25 ]
  br i1 false, label %s, label %q

q:                                                ; preds = %land.lhs.true, %p
  %xor39 = phi i64 [ 0, %p ], [ 0, %land.lhs.true ]
  %l.1 = phi i64 [ 0, %p ], [ 0, %land.lhs.true ]
  %m.1 = phi i64 [ 0, %p ], [ 0, %land.lhs.true ]
  br i1 false, label %lor.lhs.false, label %r

lor.lhs.false:                                    ; preds = %q
  br i1 false, label %land.lhs.true, label %s

r:                                                ; preds = %if.then19, %q
  %xor38 = phi i64 [ %xor39, %q ], [ %xor, %if.then19 ]
  %j.0 = phi i64 [ %conv3, %q ], [ %not21, %if.then19 ]
  %l.2 = phi i64 [ %l.1, %q ], [ %l.549, %if.then19 ]
  %m.2 = phi i64 [ %m.1, %q ], [ %m.550, %if.then19 ]
  br i1 false, label %s, label %land.lhs.true

land.lhs.true:                                    ; preds = %r, %lor.lhs.false
  %xor37 = phi i64 [ %xor38, %r ], [ 0, %lor.lhs.false ]
  %j.1 = phi i64 [ %j.0, %r ], [ 0, %lor.lhs.false ]
  %l.3 = phi i64 [ %l.2, %r ], [ 0, %lor.lhs.false ]
  %m.3 = phi i64 [ %m.2, %r ], [ 0, %lor.lhs.false ]
  br i1 false, label %q, label %s

s:                                                ; preds = %land.lhs.true, %r, %lor.lhs.false, %p
  %xor36 = phi i64 [ %xor37, %land.lhs.true ], [ %xor38, %r ], [ %xor39, %lor.lhs.false ], [ %l.0, %p ]
  %j.2 = phi i64 [ %j.1, %land.lhs.true ], [ %j.0, %r ], [ %conv3, %lor.lhs.false ], [ %m.0, %p ]
  %l.4 = phi i64 [ %l.3, %land.lhs.true ], [ %l.2, %r ], [ %l.1, %lor.lhs.false ], [ %l.0, %p ]
  %m.4 = phi i64 [ %m.3, %land.lhs.true ], [ %m.2, %r ], [ %m.1, %lor.lhs.false ], [ %m.0, %p ]
  br label %if.then19

if.then19:                                        ; preds = %s, %entry
  %m.550 = phi i64 [ 0, %entry ], [ %m.4, %s ]
  %l.5493 = phi i64 [ 0, %entry ], [ %l.4, %s ]
  %xor = xor i64 0, 0
  %not21 = xor i64 0, 0
  br i1 false, label %r, label %if.end25

if.end25:                                         ; preds = %if.then19
  br i1 false, label %if.end29, label %p

if.end29:                                         ; preds = %if.end25
  br label %p
}

file: llvm/test/Transforms/SLPVectorizer/X86/matched-bv-schedulable.ll
commands: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s -slp-threshold=-99999
tests: test_name: test
test_body: define void @test() {
bb:
  br i1 false, label %bb1, label %bb5

bb1:                                              ; preds = %bb1, %bb
  %phi = phi i32 [ %or4, %bb1 ], [ 0, %bb ]
  %phi2 = phi i32 [ %add, %bb1 ], [ 0, %bb ]
  %add = add i32 1, 0
  %or = or i32 0, %phi2
  %or3 = or i32 %or, 0
  %mul = mul i32 0, 0
  %or4 = or i32 %phi, %mul
  br i1 false, label %bb1, label %bb5

bb5:                                              ; preds = %bb1, %bb
  %phi6 = phi i32 [ 0, %bb ], [ %or4, %bb1 ]
  %phi7 = phi i32 [ 0, %bb ], [ %or, %bb1 ]
  ret void
}

file: llvm/test/Transforms/SLPVectorizer/X86/matched-nodes-updated.ll
commands: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu -slp-threshold=-9999 < %s
tests: test_name: test
test_body: define i32 @test(i32 %s.0) {
entry:
  br label %k

k:                                                ; preds = %t, %entry
  %.pre = phi i32 [ 0, %entry ], [ %.pre4053, %t ]
  br label %o

if.end3:                                          ; No predecessors!
  br label %if.end6

if.end6:                                          ; preds = %o, %if.end3
  %.pre43 = phi i32 [ 0, %if.end3 ], [ 0, %o ]
  %0 = phi i32 [ 0, %if.end3 ], [ 0, %o ]
  %1 = phi i32 [ 0, %if.end3 ], [ 0, %o ]
  %h.4 = phi i32 [ 0, %if.end3 ], [ %h.6, %o ]
  %i.4 = phi i32 [ 0, %if.end3 ], [ %i.7, %o ]
  %j.4 = phi i32 [ 0, %if.end3 ], [ %j.5, %o ]
  %l.4 = phi i32 [ 0, %if.end3 ], [ 0, %o ]
  %not8 = xor i32 %i.4, 0
  %not9 = xor i32 %h.4, 0
  br i1 false, label %if.end24, label %if.then11

if.then11:                                        ; preds = %if.end6
  br label %if.end24

if.then18:                                        ; No predecessors!
  br label %t

t:                                                ; preds = %o, %if.then18
  %.pre40 = phi i32 [ %.pre4053, %o ], [ 0, %if.then18 ]
  %i.5 = phi i32 [ 0, %o ], [ 0, %if.then18 ]
  %l.5 = phi i32 [ %l.7, %o ], [ 0, %if.then18 ]
  %r.2 = phi i32 [ %r.4, %o ], [ 0, %if.then18 ]
  %s.2 = phi i32 [ %s.4, %o ], [ 0, %if.then18 ]
  br i1 false, label %if.end24, label %k

if.end24:                                         ; preds = %t, %if.then11, %if.end6
  %.pre4050 = phi i32 [ 0, %if.then11 ], [ 0, %if.end6 ], [ %.pre40, %t ]
  %.pre42 = phi i32 [ 0, %if.then11 ], [ %.pre43, %if.end6 ], [ %.pre40, %t ]
  %2 = phi i32 [ 0, %if.then11 ], [ %0, %if.end6 ], [ %.pre40, %t ]
  %3 = phi i32 [ 0, %if.then11 ], [ %1, %if.end6 ], [ %.pre40, %t ]
  %i.6 = phi i32 [ %i.4, %if.then11 ], [ %i.7, %if.end6 ], [ %i.5, %t ]
  %l.6 = phi i32 [ 0, %if.then11 ], [ %l.4, %if.end6 ], [ %l.5, %t ]
  %r.3 = phi i32 [ %j.4, %if.then11 ], [ %not8, %if.end6 ], [ %r.2, %t ]
  %s.3 = phi i32 [ 0, %if.then11 ], [ %not9, %if.end6 ], [ %s.2, %t ]
  br label %o

o:                                                ; preds = %if.end24, %k
  %.pre4053 = phi i32 [ 0, %k ], [ %.pre4050, %if.end24 ]
  %.pre46 = phi i32 [ 0, %k ], [ %.pre42, %if.end24 ]
  %4 = phi i32 [ 0, %k ], [ %2, %if.end24 ]
  %5 = phi i32 [ 0, %k ], [ %3, %if.end24 ]
  %h.6 = phi i32 [ 0, %k ], [ %r.3, %if.end24 ]
  %i.7 = phi i32 [ 0, %k ], [ %i.6, %if.end24 ]
  %j.5 = phi i32 [ 0, %k ], [ %s.3, %if.end24 ]
  %l.7 = phi i32 [ %.pre, %k ], [ %l.6, %if.end24 ]
  %r.4 = phi i32 [ 0, %k ], [ %r.3, %if.end24 ]
  %s.4 = phi i32 [ %s.0, %k ], [ %s.3, %if.end24 ]
  br i1 false, label %t, label %if.end6
}

file: llvm/test/Transforms/SLPVectorizer/X86/node-outside-used-only.ll
commands: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu -slp-threshold=-99999 < %s
tests: test_name: <module>
test_body: 
define i64 @test() {
;
bb:
  br label %bb1

bb1:
  %phi = phi i32 [ 0, %bb ], [ %or, %bb5 ]
  %phi2 = phi i32 [ 0, %bb ], [ %or4, %bb5 ]
  %or = or i32 %phi, 0
  %add = add i32 0, 0
  %or3 = or i32 %add, %phi2
  %or4 = or i32 %or3, 0
  br label %bb5

bb5:
  br i1 false, label %bb6, label %bb1

bb6:
  %phi7 = phi i32 [ %or, %bb5 ]
  %phi8 = phi i32 [ %or3, %bb5 ]
  ret i64 0
}
file: llvm/test/Transforms/SLPVectorizer/X86/reduced-val-vectorized-in-transform.ll
commands: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu -slp-threshold=-10 < %s
tests: test_name: test
test_body: define i32 @test(i1 %cond) {
entry:
  br label %bb

bb:                                               ; preds = %bb, %entry
  %p1 = phi i32 [ %or92, %bb ], [ 0, %entry ]
  %p2 = phi i32 [ %0, %bb ], [ 0, %entry ]
  %p3 = phi i32 [ %4, %bb ], [ 0, %entry ]
  %0 = or i32 1, 0
  %or8.i = or i32 0, 0
  %or9.i = or i32 0, 0
  %or91 = or i32 %p1, 0
  %or12.i = or i32 %p2, 0
  %or92 = or i32 1, 0
  %1 = xor i32 %or91, %or12.i
  %2 = xor i32 %1, %or9.i
  %3 = xor i32 %2, %or8.i
  %4 = xor i32 %3, %or92
  br i1 %cond, label %exit, label %bb

exit:                                             ; preds = %bb
  ret i32 %4
}

file: llvm/test/Transforms/SLPVectorizer/X86/split-node-num-operands.ll
commands: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu -mattr=+avx -slp-threshold=-1000 < %s
tests: test_name: Foo
test_body: define i64 @Foo(ptr align 8 dereferenceable(344) %0, i64 %1) {
  %3 = getelementptr i8, ptr %0, i64 104
  %4 = getelementptr i8, ptr %0, i64 112
  %5 = getelementptr i8, ptr %0, i64 24
  %6 = load i64, ptr %3, align 8
  %7 = load i64, ptr %4, align 8
  %8 = load i64, ptr %5, align 8
  %9 = load i64, ptr %0, align 8
  br label %10

10:                                               ; preds = %18, %2
  %11 = phi i64 [ %9, %2 ], [ 0, %18 ]
  %12 = phi i64 [ %8, %2 ], [ %12, %18 ]
  %13 = phi i64 [ %7, %2 ], [ 0, %18 ]
  %14 = phi i64 [ %6, %2 ], [ 0, %18 ]
  switch i32 0, label %15 [
    i32 0, label %18
  ]

15:                                               ; preds = %10
  %16 = tail call i64 @llvm.umin.i64(i64 0, i64 0)
  %17 = tail call i64 @llvm.umax.i64(i64 0, i64 0)
  br label %18

18:                                               ; preds = %15, %10
  %19 = phi i64 [ %17, %15 ], [ 0, %10 ]
  %20 = phi i64 [ %16, %15 ], [ 0, %10 ]
  %21 = phi i64 [ %11, %15 ], [ 0, %10 ]
  %22 = phi i64 [ %12, %15 ], [ 0, %10 ]
  %23 = phi i64 [ %13, %15 ], [ %1, %10 ]
  %24 = phi i64 [ %14, %15 ], [ 0, %10 ]
  br i1 false, label %.loopexit206, label %10

.loopexit206:                                     ; preds = %18
  switch i32 0, label %26 [
    i32 0, label %.cont174
    i32 1, label %25
  ]

25:                                               ; preds = %.loopexit206
  br label %.cont174

26:                                               ; preds = %.loopexit206
  %27 = tail call i64 @llvm.umin.i64(i64 0, i64 0)
  %28 = tail call i64 @llvm.umax.i64(i64 0, i64 0)
  br label %.cont174

.cont174:                                         ; preds = %26, %25, %.loopexit206
  %.sroa.139.1 = phi i64 [ %28, %26 ], [ %19, %25 ], [ %19, %.loopexit206 ]
  %.sroa.133.1 = phi i64 [ %27, %26 ], [ 0, %25 ], [ %20, %.loopexit206 ]
  %.sroa.81.1 = phi i64 [ %23, %26 ], [ 0, %25 ], [ %23, %.loopexit206 ]
  %.sroa.75.1 = phi i64 [ %24, %26 ], [ 0, %25 ], [ %24, %.loopexit206 ]
  %.sroa.21.1 = phi i64 [ %21, %26 ], [ 0, %25 ], [ %21, %.loopexit206 ]
  %.sroa.15.1 = phi i64 [ %22, %26 ], [ 0, %25 ], [ %22, %.loopexit206 ]
  %29 = phi i64 [ %28, %26 ], [ 0, %25 ], [ %19, %.loopexit206 ]
  %30 = phi i64 [ %27, %26 ], [ 0, %25 ], [ %20, %.loopexit206 ]
  ret i64 0
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i64 @llvm.umax.i64(i64, i64) #0

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i64 @llvm.umin.i64(i64, i64) #0

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

file: llvm/test/Transforms/SLPVectorizer/revec.ll
commands: opt -passes=slp-vectorizer -S -slp-revec -slp-max-reg-size=1024 -slp-threshold=-100 %s
tests: test_name: test8
test_body: define void @test8() {
entry:
  br i1 false, label %for0, label %for.body

for0:                                             ; preds = %for.body, %entry
  %0 = phi <2 x float> [ zeroinitializer, %entry ], [ %4, %for.body ]
  %1 = phi <2 x float> [ zeroinitializer, %entry ], [ %5, %for.body ]
  %2 = phi <2 x float> [ zeroinitializer, %entry ], [ %4, %for.body ]
  %3 = phi <2 x float> [ zeroinitializer, %entry ], [ %5, %for.body ]
  ret void

for.body:                                         ; preds = %for.body, %entry
  %4 = phi <2 x float> [ %4, %for.body ], [ zeroinitializer, %entry ]
  %5 = phi <2 x float> [ %5, %for.body ], [ zeroinitializer, %entry ]
  br i1 false, label %for0, label %for.body
}

test_name: test7
test_body: define void @test7() {
  %1 = getelementptr i8, ptr null, i64 16
  %2 = trunc <8 x i64> zeroinitializer to <8 x i16>
  store <8 x i16> %2, ptr %1, align 2
  %3 = trunc <8 x i64> zeroinitializer to <8 x i16>
  store <8 x i16> %3, ptr null, align 2
  ret void
}