commit f564a48f0ea4d2100c0cadfa6e6f20f97244025e
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Mon Sep 16 09:19:42 2024 -0700

    [SLP]Fix PR108700: correctly identify id of the operand node

    If the operand node for truncs is not created during construction, but
    one of the previous ones is reused instead, need to correctly identify
    its index, to correctly emit the code.

    Fixes https://github.com/llvm/llvm-project/issues/108700

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 5f2bf082fb87..282bb8eac7e2 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -7481,7 +7481,16 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
                 PrevMaxBW),
             std::min<unsigned>(DL->getTypeSizeInBits(VL0->getType()),
                                PrevMinBW));
-        ExtraBitWidthNodes.insert(VectorizableTree.size() + 1);
+      }
+      TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
+                                   ReuseShuffleIndices);
+      LLVM_DEBUG(dbgs() << "SLP: added a vector of casts.\n");
+
+      TE->setOperandsInOrder();
+      for (unsigned I : seq<unsigned>(0, VL0->getNumOperands()))
+        buildTree_rec(TE->getOperand(I), Depth + 1, {TE, I});
+      if (ShuffleOrOp == Instruction::Trunc) {
+        ExtraBitWidthNodes.insert(getOperandEntry(TE, 0)->Idx);
       } else if (ShuffleOrOp == Instruction::SIToFP ||
                  ShuffleOrOp == Instruction::UIToFP) {
         unsigned NumSignBits =
@@ -7492,15 +7501,8 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
         }
         if (NumSignBits * 2 >=
             DL->getTypeSizeInBits(VL0->getOperand(0)->getType()))
-          ExtraBitWidthNodes.insert(VectorizableTree.size() + 1);
+          ExtraBitWidthNodes.insert(getOperandEntry(TE, 0)->Idx);
       }
-      TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
-                                   ReuseShuffleIndices);
-      LLVM_DEBUG(dbgs() << "SLP: added a vector of casts.\n");
-
-      TE->setOperandsInOrder();
-      for (unsigned I : seq<unsigned>(0, VL0->getNumOperands()))
-        buildTree_rec(TE->getOperand(I), Depth + 1, {TE, I});
       return;
     }
     case Instruction::ICmp:

opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s

define void @test(ptr %block, ptr noalias %pixels, i1 %b) {
entry:
  %0 = load i16, ptr %block, align 2
  %tobool.not.i78 = icmp ult i16 %0, 0
  %conv.i80 = sext i1 true to i8
  %conv1.i81 = trunc i16 %0 to i8
  %retval.0.i82 = select i1 %tobool.not.i78, i8 %conv1.i81, i8 %conv.i80
  store i8 %retval.0.i82, ptr %pixels, align 1
  %arrayidx2 = getelementptr i8, ptr %block, i64 2
  %1 = load i16, ptr %arrayidx2, align 2
  %tobool.not.i73 = icmp ult i16 %1, 0
  %conv.i75 = sext i1 %b to i8
  %conv1.i76 = trunc i16 %1 to i8
  %retval.0.i77 = select i1 %tobool.not.i73, i8 %conv1.i76, i8 %conv.i75
  %arrayidx5 = getelementptr i8, ptr %pixels, i64 1
  store i8 %retval.0.i77, ptr %arrayidx5, align 1
  %arrayidx6 = getelementptr i8, ptr %block, i64 4
  %2 = load i16, ptr %arrayidx6, align 2
  %tobool.not.i68 = icmp ult i16 %2, 0
  %conv.i70 = sext i1 false to i8
  %conv1.i71 = trunc i16 %2 to i8
  %retval.0.i72 = select i1 %tobool.not.i68, i8 %conv1.i71, i8 %conv.i70
  %arrayidx9 = getelementptr i8, ptr %pixels, i64 2
  store i8 %retval.0.i72, ptr %arrayidx9, align 1
  %arrayidx10 = getelementptr i8, ptr %block, i64 6
  %3 = load i16, ptr %arrayidx10, align 2
  %tobool.not.i63 = icmp ult i16 %3, 0
  %conv.i65 = sext i1 false to i8
  %conv1.i66 = trunc i16 %3 to i8
  %retval.0.i67 = select i1 %tobool.not.i63, i8 %conv1.i66, i8 %conv.i65
  %arrayidx13 = getelementptr i8, ptr %pixels, i64 3
  store i8 %retval.0.i67, ptr %arrayidx13, align 1
  ret void
}

define i16 @test() {
entry:
  %conv73 = xor i64 0, 0
  %and.i = and i64 0, 0
  %xor2.i = or i64 %and.i, 0
  %sub.i = or i64 %xor2.i, 0
  %xor3.i = xor i64 %sub.i, %conv73
  %and4.i = and i64 %xor3.i, 0
  %cmp.i = icmp slt i64 %and4.i, 0
  %0 = trunc i64 %conv73 to i16
  %1 = or i16 0, %0
  %conv73i = xor i64 0, 0
  %andi.i = and i64 0, 0
  %xor2i.i = or i64 %andi.i, 0
  %subi.i = or i64 %xor2i.i, 0
  %xor3i.i = xor i64 %subi.i, %conv73i
  %and4i.i = and i64 %xor3i.i, 0
  %cmpi.i = icmp slt i64 %and4i.i, 0
  %2 = trunc i64 %conv73i to i16
  %3 = or i16 0, %2
  %4 = select i1 %cmpi.i, i16 0, i16 %3
  %5 = select i1 %cmp.i, i16 0, i16 %1
  %6 = zext i32 0 to i64
  %add.ip = or i64 %6, 0
  %orp = or i64 %add.ip, 0
  %conv72p = shl i64 %orp, 0
  %sextp = ashr i64 %conv72p, 0
  %conv73p = xor i64 %sextp, 0
  %and.ip = and i64 0, 0
  %xor2.ip = or i64 %and.ip, 0
  %sub.ip = or i64 %xor2.ip, 0
  %xor3.ip = xor i64 %sub.ip, %conv73p
  %and4.ip = and i64 %xor3.ip, 0
  %cmp.ip = icmp slt i64 %and4.ip, 0
  %7 = trunc i64 %conv73p to i16
  %8 = or i16 0, %7
  %9 = select i1 %cmp.ip, i16 0, i16 %8
  %conv76i = and i16 %4, %5
  %conv76p = and i16 %conv76i, %9
  %10 = zext i32 0 to i64
  %add.ip1 = or i64 %10, 0
  %orp1 = or i64 %add.ip1, 0
  %conv72p1 = shl i64 %orp1, 0
  %sextp1 = ashr i64 %conv72p1, 0
  %conv73p1 = xor i64 %sextp1, 0
  %and.ip1 = and i64 0, 0
  %xor2.ip1 = or i64 %and.ip1, 0
  %sub.ip1 = or i64 %xor2.ip1, 0
  %xor3.ip1 = xor i64 %sub.ip1, %conv73p1
  %and4.ip1 = and i64 %xor3.ip1, 0
  %cmp.ip1 = icmp slt i64 %and4.ip1, 0
  %11 = trunc i64 %conv73p1 to i16
  %12 = or i16 0, %11
  %13 = select i1 %cmp.ip1, i16 0, i16 %12
  %conv76p2 = and i16 %conv76p, %13
  ret i16 %conv76p2
}

[SLPVectorizer] Assertion `OpIdx < Operands.size() && "Off bounds"' failed.

Reproducer: https://godbolt.org/z/8Es17cqcW
```
; bin/opt -passes=slp-vectorizer reduced.ll -S
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"
target triple = "x86_64-unknown-linux-gnu"

define i16 @main() {
entry:
  %conv73.i.peel.i.i.i.i.i = xor i64 0, 0
  %and.i.i.peel.i.i.i.i.i = and i64 0, 0
  %xor2.i.i.peel.i.i.i.i.i = or i64 %and.i.i.peel.i.i.i.i.i, 0
  %sub.i.i.peel.i.i.i.i.i = or i64 %xor2.i.i.peel.i.i.i.i.i, 0
  %xor3.i.i.peel.i.i.i.i.i = xor i64 %sub.i.i.peel.i.i.i.i.i, %conv73.i.peel.i.i.i.i.i
  %and4.i.i.peel.i.i.i.i.i = and i64 %xor3.i.i.peel.i.i.i.i.i, 0
  %cmp.i.i.peel.i.i.i.i.i = icmp slt i64 %and4.i.i.peel.i.i.i.i.i, 0
  %0 = trunc i64 %conv73.i.peel.i.i.i.i.i to i16
  %1 = or i16 0, %0
  %conv73.i.i.i.i.i.i = xor i64 0, 0
  %and.i.i.i.i.i.i.i = and i64 0, 0
  %xor2.i.i.i.i.i.i.i = or i64 %and.i.i.i.i.i.i.i, 0
  %sub.i.i.i.i.i.i.i = or i64 %xor2.i.i.i.i.i.i.i, 0
  %xor3.i.i.i.i.i.i.i = xor i64 %sub.i.i.i.i.i.i.i, %conv73.i.i.i.i.i.i
  %and4.i.i.i.i.i.i.i = and i64 %xor3.i.i.i.i.i.i.i, 0
  %cmp.i.i.i.i.i.i.i = icmp slt i64 %and4.i.i.i.i.i.i.i, 0
  %2 = trunc i64 %conv73.i.i.i.i.i.i to i16
  %3 = or i16 0, %2
  %4 = select i1 %cmp.i.i.i.i.i.i.i, i16 0, i16 %3
  %5 = select i1 %cmp.i.i.peel.i.i.i.i.i, i16 0, i16 %1
  %6 = zext i32 0 to i64
  %add.i.i.peel.i369.i.i.i.i = or i64 %6, 0
  %or.i.peel.i371.i.i.i.i = or i64 %add.i.i.peel.i369.i.i.i.i, 0
  %conv72.i.peel.i372.i.i.i.i = shl i64 %or.i.peel.i371.i.i.i.i, 0
  %sext.i.peel.i373.i.i.i.i = ashr i64 %conv72.i.peel.i372.i.i.i.i, 0
  %conv73.i.peel.i374.i.i.i.i = xor i64 %sext.i.peel.i373.i.i.i.i, 0
  %and.i.i.peel.i376.i.i.i.i = and i64 0, 0
  %xor2.i.i.peel.i377.i.i.i.i = or i64 %and.i.i.peel.i376.i.i.i.i, 0
  %sub.i.i.peel.i378.i.i.i.i = or i64 %xor2.i.i.peel.i377.i.i.i.i, 0
  %xor3.i.i.peel.i379.i.i.i.i = xor i64 %sub.i.i.peel.i378.i.i.i.i, %conv73.i.peel.i374.i.i.i.i
  %and4.i.i.peel.i380.i.i.i.i = and i64 %xor3.i.i.peel.i379.i.i.i.i, 0
  %cmp.i.i.peel.i381.i.i.i.i = icmp slt i64 %and4.i.i.peel.i380.i.i.i.i, 0
  %7 = trunc i64 %conv73.i.peel.i374.i.i.i.i to i16
  %8 = or i16 0, %7
  %9 = select i1 %cmp.i.i.peel.i381.i.i.i.i, i16 0, i16 %8
  %conv76.i.i.i.i.i.i = and i16 %4, %5
  %conv76.i.peel.i384.i.i.i.i = and i16 %conv76.i.i.i.i.i.i, %9
  %10 = zext i32 0 to i64
  %add.i.i.peel.i417.i.i.i.i = or i64 %10, 0
  %or.i.peel.i419.i.i.i.i = or i64 %add.i.i.peel.i417.i.i.i.i, 0
  %conv72.i.peel.i420.i.i.i.i = shl i64 %or.i.peel.i419.i.i.i.i, 0
  %sext.i.peel.i421.i.i.i.i = ashr i64 %conv72.i.peel.i420.i.i.i.i, 0
  %conv73.i.peel.i422.i.i.i.i = xor i64 %sext.i.peel.i421.i.i.i.i, 0
  %and.i.i.peel.i424.i.i.i.i = and i64 0, 0
  %xor2.i.i.peel.i425.i.i.i.i = or i64 %and.i.i.peel.i424.i.i.i.i, 0
  %sub.i.i.peel.i426.i.i.i.i = or i64 %xor2.i.i.peel.i425.i.i.i.i, 0
  %xor3.i.i.peel.i427.i.i.i.i = xor i64 %sub.i.i.peel.i426.i.i.i.i, %conv73.i.peel.i422.i.i.i.i
  %and4.i.i.peel.i428.i.i.i.i = and i64 %xor3.i.i.peel.i427.i.i.i.i, 0
  %cmp.i.i.peel.i429.i.i.i.i = icmp slt i64 %and4.i.i.peel.i428.i.i.i.i, 0
  %11 = trunc i64 %conv73.i.peel.i422.i.i.i.i to i16
  %12 = or i16 0, %11
  %13 = select i1 %cmp.i.i.peel.i429.i.i.i.i, i16 0, i16 %12
  %conv76.i.peel.i432.i.i.i.i = and i16 %conv76.i.peel.i384.i.i.i.i, %13
  ret i16 %conv76.i.peel.i432.i.i.i.i
}
```
```
opt: /root/llvm-project/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp:3180: llvm::slpvectorizer::BoUpSLP::ValueList& llvm::slpvectorizer::BoUpSLP::TreeEntry::getOperand(unsigned int): Assertion `OpIdx < Operands.size() && "Off bounds"' failed.
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 <source>
1.	Running pass "function(slp-vectorizer)" on module "<source>"
2.	Running pass "slp-vectorizer" on function "main"
 #0 0x0000000005016bb8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5016bb8)
 #1 0x00000000050142fc SignalHandler(int) Signals.cpp:0:0
 #2 0x00007955e2242520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x00007955e22969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x00007955e2242476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x00007955e22287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x00007955e222871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x00007955e2239e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x000000000406f2b8 llvm::slpvectorizer::BoUpSLP::TreeEntry::getOperand(unsigned int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x406f2b8)
 #9 0x00000000040f675e llvm::slpvectorizer::BoUpSLP::getEntryCost(llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::ArrayRef<llvm::Value*>, llvm::SmallPtrSetImpl<llvm::Value*>&)::'lambda0'(llvm::function_ref<llvm::InstructionCost (unsigned int)>, llvm::function_ref<llvm::InstructionCost (llvm::InstructionCost)>)::operator()(llvm::function_ref<llvm::InstructionCost (unsigned int)>, llvm::function_ref<llvm::InstructionCost (llvm::InstructionCost)>) const SLPVectorizer.cpp:0:0
#10 0x00000000040f74aa llvm::slpvectorizer::BoUpSLP::getEntryCost(llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::ArrayRef<llvm::Value*>, llvm::SmallPtrSetImpl<llvm::Value*>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x40f74aa)
#11 0x0000000004114641 llvm::slpvectorizer::BoUpSLP::getTreeCost(llvm::ArrayRef<llvm::Value*>) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4114641)
#12 0x00000000041198c8 (anonymous namespace)::HorizontalReduction::tryToReduce(llvm::slpvectorizer::BoUpSLP&, llvm::DataLayout const&, llvm::TargetTransformInfo*, llvm::TargetLibraryInfo const&) SLPVectorizer.cpp:0:0
#13 0x000000000411bfe1 llvm::SLPVectorizerPass::vectorizeHorReduction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&, llvm::TargetTransformInfo*, llvm::SmallVectorImpl<llvm::WeakTrackingVH>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x411bfe1)
#14 0x0000000004120876 llvm::SLPVectorizerPass::vectorizeRootInstruction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&, llvm::TargetTransformInfo*) (.constprop.0) SLPVectorizer.cpp:0:0
#15 0x0000000004124e16 llvm::SLPVectorizerPass::vectorizeChainsInBlock(llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4124e16)
#16 0x000000000412b2e1 llvm::SLPVectorizerPass::runImpl(llvm::Function&, llvm::ScalarEvolution*, llvm::TargetTransformInfo*, llvm::TargetLibraryInfo*, llvm::AAResults*, llvm::LoopInfo*, llvm::DominatorTree*, llvm::AssumptionCache*, llvm::DemandedBits*, llvm::OptimizationRemarkEmitter*) (.part.0) SLPVectorizer.cpp:0:0
#17 0x000000000412bf6b llvm::SLPVectorizerPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x412bf6b)
#18 0x0000000002f0034e llvm::detail::PassModel<llvm::Function, llvm::SLPVectorizerPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x2f0034e)
#19 0x0000000004e18ff8 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e18ff8)
#20 0x0000000000e06a0e llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xe06a0e)
#21 0x0000000004e17a1e llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e17a1e)
#22 0x0000000000e0621e llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xe0621e)
#23 0x0000000004e17450 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e17450)
#24 0x00000000008fce52 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+0x8fce52)
#25 0x00000000008efcdc optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8efcdc)
#26 0x00007955e2229d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#27 0x00007955e2229e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#28 0x00000000008e77ae _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8e77ae)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```


commit c05599966cd594c15834378f57669719d221c4d4
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Mon Jan 6 16:23:46 2025 +0800

    [InstCombine] Fix FMF propagation in `copysign Mag, (copysign ?, X) -> copysign Mag, X` (#121574)

    Closes https://github.com/llvm/llvm-project/issues/121432.

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index cdb2c11ef046..5494c70b34b1 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2673,8 +2673,12 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
     // Propagate sign argument through nested calls:
     // copysign Mag, (copysign ?, X) --> copysign Mag, X
     Value *X;
-    if (match(Sign, m_Intrinsic<Intrinsic::copysign>(m_Value(), m_Value(X))))
-      return replaceOperand(*II, 1, X);
+    if (match(Sign, m_Intrinsic<Intrinsic::copysign>(m_Value(), m_Value(X)))) {
+      Value *CopySign = Builder.CreateCopySign(
+          Mag, X,
+          II->getFastMathFlags() & cast<Instruction>(Sign)->getFastMathFlags());
+      return replaceInstUsesWith(*II, CopySign);
+    }

     // Clear sign-bit of constant magnitude:
     // copysign -MagC, X --> copysign MagC, X

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

define float @copysign_sign_arg_mixed(float %x, float %y, float %z) {
  %s = call ninf nsz float @llvm.copysign.f32(float %y, float %z)
  %r = call nnan nsz float @llvm.copysign.f32(float %x, float %s)
  ret float %r
}

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

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

define float @copysign_sign_arg(float %x, float %y, float %z) {
  %s = call float @llvm.copysign.f32(float %y, float %z)
  %r = call ninf float @llvm.copysign.f32(float %x, float %s)
  ret float %r
}

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

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

define float @fneg_mag(float %x, float %y) {
  %n = fneg float %x
  %r = call float @llvm.copysign.f32(float %n, float %y)
  ret float %r
}

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

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

define float @copysign_sign_arg_nnan(float %x, float %y, float %z) {
  %s = call nnan float @llvm.copysign.f32(float %y, float %z)
  %r = call nnan float @llvm.copysign.f32(float %x, float %s)
  ret float %r
}

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

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

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

define float @not_known_positive_sign_arg(float %x, float %y) {
  %max = call float @llvm.maxnum.f32(float %x, float 0.000000e+00)
  %r = call ninf float @llvm.copysign.f32(float %y, float %max)
  ret float %r
}

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

[InstCombine] FMF flags should not be propagated

Alive2: https://alive2.llvm.org/ce/z/ajCxTh
```
define float @src1(float noundef %x, float noundef %y, float noundef %z) {
  %s = call float @llvm.copysign.f32(float %y, float %z)
  %r = call nnan float @llvm.copysign.f32(float %x, float %s)
  ret float %r
}

define float @tgt1(float noundef %x, float noundef %y, float noundef %z) {
  %r = call nnan float @llvm.copysign.f32(float %x, float %z)
  ret float %r
}

define float @src2(float noundef %x, float noundef %y, float noundef %z) {
  %s = call float @llvm.copysign.f32(float %y, float %z)
  %r = call ninf float @llvm.copysign.f32(float %x, float %s)
  ret float %r
}

define float @tgt2(float noundef %x, float noundef %y, float noundef %z) {
  %r = call ninf float @llvm.copysign.f32(float %x, float %z)
  ret float %r
}

define float @src3(float noundef %x, float noundef %y, float noundef %z) {
  %s = call float @llvm.copysign.f32(float %y, float %z)
  %r = call nsz float @llvm.copysign.f32(float %x, float %s)
  ret float %r
}

define float @tgt3(float noundef %x, float noundef %y, float noundef %z) {
  %r = call nsz float @llvm.copysign.f32(float %x, float %z)
  ret float %r
}
```


commit 18311093abe6481388a0d963d58438d743b47569
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Tue Oct 29 10:39:07 2024 +0800

    [InstCombine] Do not fold `shufflevector(select)` if the select condition is a vector (#113993)

    Since `shufflevector` is not element-wise, we cannot do fold it into
    select when the select condition is a vector.
    For shufflevector that doesn't change the length, it doesn't crash, but
    it is still a miscompilation: https://alive2.llvm.org/ce/z/s8saCx

    Fixes https://github.com/llvm/llvm-project/issues/113986.

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
index 75e7c1c97018..454fe5a91d37 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
@@ -2902,8 +2902,12 @@ Instruction *InstCombinerImpl::visitShuffleVectorInst(ShuffleVectorInst &SVI) {

   if (match(RHS, m_Constant())) {
     if (auto *SI = dyn_cast<SelectInst>(LHS)) {
-      if (Instruction *I = FoldOpIntoSelect(SVI, SI))
-        return I;
+      // We cannot do this fold for elementwise select since ShuffleVector is
+      // not elementwise.
+      if (SI->getCondition()->getType()->isIntegerTy()) {
+        if (Instruction *I = FoldOpIntoSelect(SVI, SI))
+          return I;
+      }
     }
     if (auto *PN = dyn_cast<PHINode>(LHS)) {
       if (Instruction *I = foldOpIntoPhi(SVI, PN))

define <4 x float> @shuf_larger_length_vec_select(<2 x i1> %cond) {
  %sel = select <2 x i1> %cond, <2 x float> zeroinitializer, <2 x float> splat (float 1.000000e+00)
  %shuf = shufflevector <2 x float> %sel, <2 x float> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
  ret <4 x float> %shuf
}

[InstCombine] Assertion `!areInvalidOperands(C, S1, S2) && "Invalid operands for select"' failed.

Reproducer:
```
; bin/opt -passes=instcombine reduced.ll -S
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"
target triple = "x86_64-pc-linux-gnu"

define <32 x float> @process(<8 x i1> %0) {
  %3 = select <8 x i1> %0, <8 x float> zeroinitializer, <8 x float> <float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>
  %4 = shufflevector <8 x float> %3, <8 x float> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
  %5 = shufflevector <16 x float> %4, <16 x float> zeroinitializer, <32 x i32> <i32 0, i32 8, i32 16, i32 24, i32 1, i32 9, i32 17, i32 25, i32 2, i32 10, i32 18, i32 26, i32 3, i32 11, i32 19, i32 27, i32 4, i32 12, i32 20, i32 28, i32 5, i32 13, i32 21, i32 29, i32 6, i32 14, i32 22, i32 30, i32 7, i32 15, i32 23, i32 31>
  ret <32 x float> %5
}
```
```
opt: /home/dtcxzyw/WorkSpace/Projects/compilers/llvm-project/llvm/include/llvm/IR/Instructions.h:1614: void llvm::SelectInst::init(llvm::Value*, llvm::Value*, llvm::Value*): Assertion `!areInvalidOperands(C, S1, S2) && "Invalid operands for select"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: bin/opt -passes=instcombine reduced.ll
1.      Running pass "function(instcombine<max-iterations=1;verify-fixpoint>)" on module "reduced.ll"
2.      Running pass "instcombine<max-iterations=1;verify-fixpoint>" on function "process"
 #0 0x00007ffff7e15b02 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMSupport.so.20.0git+0x215b02)
 #1 0x00007ffff7e129af llvm::sys::RunSignalHandlers() (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMSupport.so.20.0git+0x2129af)
 #2 0x00007ffff7e12af5 SignalHandler(int) Signals.cpp:0:0
 #3 0x00007ffff7842520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x00007ffff78969fc __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x00007ffff78969fc __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #6 0x00007ffff78969fc pthread_kill ./nptl/pthread_kill.c:89:10
 #7 0x00007ffff7842476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
 #8 0x00007ffff78287f3 abort ./stdlib/abort.c:81:7
 #9 0x00007ffff782871b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#10 0x00007ffff7839e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#11 0x00007ffff1272963 llvm::InstCombinerImpl::FoldOpIntoSelect(llvm::Instruction&, llvm::SelectInst*, bool) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMInstCombine.so.20.0git+0x60963)
#12 0x00007ffff13a09d1 llvm::InstCombinerImpl::visitShuffleVectorInst(llvm::ShuffleVectorInst&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMInstCombine.so.20.0git+0x18e9d1)
#13 0x00007ffff1275da8 llvm::InstCombinerImpl::run() (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMInstCombine.so.20.0git+0x63da8)
#14 0x00007ffff1276f09 combineInstructionsOverFunction(llvm::Function&, llvm::InstructionWorklist&, llvm::AAResults*, llvm::AssumptionCache&, llvm::TargetLibraryInfo&, llvm::TargetTransformInfo&, llvm::DominatorTree&, llvm::OptimizationRemarkEmitter&, llvm::BlockFrequencyInfo*, llvm::BranchProbabilityInfo*, llvm::ProfileSummaryInfo*, llvm::InstCombineOptions const&) InstructionCombining.cpp:0:0
#15 0x00007ffff1277dfb llvm::InstCombinePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMInstCombine.so.20.0git+0x65dfb)
#16 0x00007ffff30d9955 llvm::detail::PassModel<llvm::Function, llvm::InstCombinePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMPasses.so.20.0git+0xd9955)
#17 0x00007ffff01678bd llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMCore.so.20.0git+0x3678bd)
#18 0x00007ffff68d9e65 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMX86CodeGen.so.20.0git+0xd9e65)
#19 0x00007ffff01659f6 llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMCore.so.20.0git+0x3659f6)
#20 0x00007ffff68da825 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMX86CodeGen.so.20.0git+0xda825)
#21 0x00007ffff016657a llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMCore.so.20.0git+0x36657a)
#22 0x00007ffff7f95051 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) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMOptDriver.so.20.0git+0x2d051)
#23 0x00007ffff7fa073f optMain (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMOptDriver.so.20.0git+0x3873f)
#24 0x00007ffff7829d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#25 0x00007ffff7829e40 call_init ./csu/../csu/libc-start.c:128:20
#26 0x00007ffff7829e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#27 0x0000555555555095 _start (bin/opt+0x1095)
Aborted (core dumped)
```

It is caused by https://github.com/llvm/llvm-project/pull/113746. We cannot do this fold if the output and input operands don't have the exact same type. It was reported by llvm-opt-benchmark pre-commit test https://github.com/dtcxzyw/llvm-opt-benchmark/pull/1543. I am sorry I didn't notice about this. Fortunately this issue was captured by a post-commit test https://github.com/dtcxzyw/llvm-opt-benchmark/issues/1560.

cc @MatzeB @RKSimon @goldsteinn

I will post a fix later.


commit 67aec0cd62d607b4e5b7198769be061454ce67b3
Author: Peter Rong <peterrong96@gmail.com>
Date:   Mon May 27 10:58:22 2024 -0700

    [LowerSwitch] Use unsigned integer for range comparison (#93237)

    Commit 1db51d8eb2 switched from int64_t to `APInt` to prevent high precision integer overflow.
    However, when comparing the "range" of switch cases, we should switch to unsigned integer to prevent overflow.
    This patch fixes https://github.com/llvm/llvm-project/issues/93152.
    Some test cases are added.

    Signed-off-by: Peter Rong <PeterRong96@gmail.com>

diff --git a/llvm/lib/Transforms/Utils/LowerSwitch.cpp b/llvm/lib/Transforms/Utils/LowerSwitch.cpp
index f5921e5ccb09..f4ef6d02abf0 100644
--- a/llvm/lib/Transforms/Utils/LowerSwitch.cpp
+++ b/llvm/lib/Transforms/Utils/LowerSwitch.cpp
@@ -208,7 +208,7 @@ BasicBlock *NewLeafBlock(CaseRange &Leaf, Value *Val, ConstantInt *LowerBound,
     PHINode *PN = cast<PHINode>(I);
     // Remove all but one incoming entries from the cluster
     APInt Range = Leaf.High->getValue() - Leaf.Low->getValue();
-    for (APInt j(Range.getBitWidth(), 0, true); j.slt(Range); ++j) {
+    for (APInt j(Range.getBitWidth(), 0, false); j.ult(Range); ++j) {
       PN->removeIncomingValue(OrigBlock);
     }

llvm commit: 4cc6d0f4dfb26d
Reproduce with:
```opt -passes="lower-switch" -verify-each bbi-95731.ll -o /dev/null```
Result:
```
PHINode should have one entry for each predecessor of its parent basic block!
  %tmp = phi i3 [ 0, %LeafBlock ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ]
LLVM ERROR: Broken function found after pass "LowerSwitchPass", compilation aborted!
```
If we look at what lower-switch actually produces (-print-after-all) we see
```
; *** IR Dump After LowerSwitchPass on v_257_0 ***
define void @v_257_0(i3 %0) {
bb.0:
  br label %LeafBlock

LeafBlock:                                        ; preds = %bb.0
  %.off = add i3 %0, 2
  %SwitchLeaf = icmp ule i3 %.off, -4
  br i1 %SwitchLeaf, label %bb.1, label %bb.2

bb.1:                                             ; preds = %LeafBlock
  %tmp = phi i3 [ 0, %LeafBlock ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ]
  br label %bb.2

bb.2:                                             ; preds = %LeafBlock, %bb.1
  ret void
}
PHINode should have one entry for each predecessor of its parent basic block!
  %tmp = phi i3 [ 0, %LeafBlock ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ]
```
So it has removed the switch instruction but it only updated one of the five phi operands for %bb.0.
The input looked like
```
define void @v_257_0(i3 %0) {
bb.0:
  switch i3 %0, label %bb.2 [
    i3 -1, label %bb.1
    i3 -2, label %bb.1
    i3 2, label %bb.1
    i3 1, label %bb.1
    i3 0, label %bb.1
  ]

bb.1:                                             ; preds = %bb.0, %bb.0, %bb.0, %bb.0, %bb.0
  %tmp = phi i3 [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ]
  br label %bb.2

bb.2:                                             ; preds = %bb.1, %bb.0
  ret void
}
```
So there is one phi operand for each of the values that makes it jump from %bb.0 to %bb.1 and lower-switch only updated one of them when it changed things.
[bbi-95731.ll.gz](https://github.com/llvm/llvm-project/files/15414163/bbi-95731.ll.gz)

This starts happening with 1db51d8eb2d
```
[Transform] Rewrite LowerSwitch using APInt

This rewrite fixes https://github.com/llvm/llvm-project/issues/59316.

Previously LowerSwitch uses int64_t, which will crash on case branches using integers with more than 64 bits.
Using APInt fixes this problem. This patch also includes a test

Reviewed By: RKSimon

Differential Revision: https://reviews.llvm.org/D140747
```

I am taking a look. Some initial thoughts:

- https://github.com/llvm/llvm-project/commit/1db51d8eb2d220a4f0000555ada310990098cf5b didn't attempt to change how it optimizes the switch. Maybe we forgot to change the API in that optimization.
- `i3` is playing a role here: if you switch it to `i32`, [it'll pass](https://godbolt.org/z/c5Yveb8Kf).

I found the problem. Fixing it now. Will push a patch shortly


commit 4d2ae88d1617a910ec3a1436ce53579523ac2f97
Author: Nikita Popov <npopov@redhat.com>
Date:   Wed Jul 3 10:58:38 2024 +0200

    [InstCombine] Fix invalid scalarization of div

    If the binop is not speculatable, and the extract index is out of
    range, then scalarizing will perform the operation on a poison
    operand, resulting in immediate UB, instead of the previous
    poison result.

    Fixes https://github.com/llvm/llvm-project/issues/97053.

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
index 3de56a403803..753ed55523c8 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
@@ -419,6 +419,7 @@ Instruction *InstCombinerImpl::visitExtractElementInst(ExtractElementInst &EI) {
   // If extracting a specified index from the vector, see if we can recursively
   // find a previously computed scalar that was inserted into the vector.
   auto *IndexC = dyn_cast<ConstantInt>(Index);
+  bool HasKnownValidIndex = false;
   if (IndexC) {
     // Canonicalize type of constant indices to i64 to simplify CSE
     if (auto *NewIdx = getPreferredVectorIndex(IndexC))
@@ -426,6 +427,7 @@ Instruction *InstCombinerImpl::visitExtractElementInst(ExtractElementInst &EI) {

     ElementCount EC = EI.getVectorOperandType()->getElementCount();
     unsigned NumElts = EC.getKnownMinValue();
+    HasKnownValidIndex = IndexC->getValue().ult(NumElts);

     if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(SrcVec)) {
       Intrinsic::ID IID = II->getIntrinsicID();
@@ -471,8 +473,11 @@ Instruction *InstCombinerImpl::visitExtractElementInst(ExtractElementInst &EI) {
     return UnaryOperator::CreateWithCopiedFlags(UO->getOpcode(), E, UO);
   }

+  // If the binop is not speculatable, we cannot hoist the extractelement if
+  // it may make the operand poison.
   BinaryOperator *BO;
-  if (match(SrcVec, m_BinOp(BO)) && cheapToScalarize(SrcVec, Index)) {
+  if (match(SrcVec, m_BinOp(BO)) && cheapToScalarize(SrcVec, Index) &&
+      (HasKnownValidIndex || isSafeToSpeculativelyExecute(BO))) {
     // extelt (binop X, Y), Index --> binop (extelt X, Index), (extelt Y, Index)
     Value *X = BO->getOperand(0), *Y = BO->getOperand(1);
     Value *E0 = Builder.CreateExtractElement(X, Index);

define i8 @extract_element_binop_splat_variable_index_may_trap(<4 x i8> %x, <4 x i8> %y, i32 %z) {
  %b = sdiv <4 x i8> splat (i8 42), %y
  %r = extractelement <4 x i8> %b, i32 %z
  ret i8 %r
}

define i8 @extract_element_binop_splat_variable_index(<4 x i8> %x, i32 %y) {
  %b = sdiv <4 x i8> %x, splat (i8 42)
  %r = extractelement <4 x i8> %b, i32 %y
  ret i8 %r
}

Wrong swap between `sdiv` and `extractelement` by InstCombine

https://alive2.llvm.org/ce/z/mGNeLx

```ll
----------------------------------------
define i8 @fun0(<4 x i8> %val0, i32 %val1) {
#0:
  %val2 = sdiv <4 x i8> { 42, 42, 42, 42 }, %val0
  %val3 = extractelement <4 x i8> %val2, i32 %val1
  ret i8 %val3
}
=>
define i8 @fun0(<4 x i8> %val0, i32 %val1) {
#0:
  %#1 = extractelement <4 x i8> %val0, i32 %val1
  %val3 = sdiv i8 42, %#1
  ret i8 %val3
}
Transformation doesn't verify!

ERROR: Source is more defined than target

Example:
<4 x i8> %val0 = < #x01 (1), #x08 (8), #x02 (2), #x04 (4) >
i32 %val1 = #x20000000 (536870912)

Source:
<4 x i8> %val2 = < #x2a (42), #x05 (5), #x15 (21), #x0a (10) >
i8 %val3 = poison

Target:
i8 %#1 = poison
i8 %val3 = UB triggered!

Summary:
  0 correct transformations
  1 incorrect transformations
  0 failed-to-prove transformations
  0 Alive2 errors
```

`sdiv` and `extractelement` cannot be swapped for vector operands as it can trigger UB, diving an integer by `poison`.


commit 9725595f3acc0c1aaa354e15ac4ee2b1f8ff4cc9
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Sat Feb 1 20:41:15 2025 +0800

    [InstCombine] Check nowrap flags when folding comparison of GEPs with the same base pointer (#121892)

    Alive2: https://alive2.llvm.org/ce/z/P5XbMx
    Closes https://github.com/llvm/llvm-project/issues/121890

    TODO: It is still safe to perform this transform without nowrap flags if
    the corresponding scale factor is 1 byte:
    https://alive2.llvm.org/ce/z/J-JCJd

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9e9739ac2440..a8a5cb2b20d7 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -834,8 +834,9 @@ Instruction *InstCombinerImpl::foldGEPICmp(GEPOperator *GEPLHS, Value *RHS,
         return replaceInstUsesWith(
             I, // No comparison is needed here.
             ConstantInt::get(I.getType(), ICmpInst::isTrueWhenEqual(Cond)));
-
-      else if (NumDifferences == 1 && CanFold(NW)) {
+      // If two GEPs only differ by an index, compare them.
+      // Note that nowrap flags are always needed when comparing two indices.
+      else if (NumDifferences == 1 && NW != GEPNoWrapFlags::none()) {
         Value *LHSV = GEPLHS->getOperand(DiffOperand);
         Value *RHSV = GEPRHS->getOperand(DiffOperand);
         return NewICmp(NW, LHSV, RHSV);

opt -S -passes='instcombine<no-verify-fixpoint>' < %s

target datalayout = "p:8:8:8"
define i1 @cmp_gep_same_base_same_type_nusw(ptr %ptr, i8%idx1, i8%idx2) {
  %gep1 = getelementptr nusw i32, ptr %ptr, i8%idx1
  %gep2 = getelementptr nusw i32, ptr %ptr, i8%idx2
  %cmp = icmp eq ptr %gep1, %gep2
  ret i1 %cmp
}

target datalayout = "p:8:8:8"
define i1 @cmp_gep_same_base_same_type_maywrap(ptr %ptr, i8%idx1, i8%idx2) {
  %gep1 = getelementptr i32, ptr %ptr, i8%idx1
  %gep2 = getelementptr i32, ptr %ptr, i8%idx2
  %cmp = icmp eq ptr %gep1, %gep2
  ret i1 %cmp
}

target datalayout = "p:8:8:8"
define i1 @cmp_gep_same_base_same_type_nuw(ptr %ptr, i8%idx1, i8%idx2) {
  %gep1 = getelementptr nuw i32, ptr %ptr, i8%idx1
  %gep2 = getelementptr nuw i32, ptr %ptr, i8%idx2
  %cmp = icmp eq ptr %gep1, %gep2
  ret i1 %cmp
}

target datalayout = "p:8:8:8"
define i1 @cmp_gep_same_base_different_type(ptr %ptr, i8%idx1, i8%idx2) {
  %gep1 = getelementptr inbounds i32, ptr %ptr, i8%idx1
  %gep2 = getelementptr inbounds i64, ptr %ptr, i8%idx2
  %cmp = icmp ult ptr %gep1, %gep2
  ret i1 %cmp
}

target datalayout = "p:8:8:8"
define i1 @cmp_gep_same_base_same_type(ptr %ptr, i8%idx1, i8%idx2) {
  %gep1 = getelementptr inbounds i32, ptr %ptr, i8%idx1
  %gep2 = getelementptr inbounds i32, ptr %ptr, i8%idx2
  %cmp = icmp ult ptr %gep1, %gep2
  ret i1 %cmp
}

[InstCombine] Missing flag check when folding comparison of geps with the same base pointer

Alive2: https://alive2.llvm.org/ce/z/P5XbMx
```

----------------------------------------
define i1 @src(ptr %ptr, i8 %idx1, i8 %idx2) {
#0:
  %gep1 = gep ptr %ptr, 4 x i8 %idx1
  %gep2 = gep ptr %ptr, 4 x i8 %idx2
  %cmp = icmp eq ptr %gep1, %gep2, offsetonly
  ret i1 %cmp
}
=>
define i1 @tgt(ptr %ptr, i8 %idx1, i8 %idx2) {
#0:
  %cmp = icmp eq i8 %idx1, %idx2
  ret i1 %cmp
}
Transformation doesn't verify!

ERROR: Value mismatch

Example:
ptr %ptr = null
i8 %idx1 = #x00 (0)
i8 %idx2 = #x40 (64)

Source:
ptr %gep1 = null
ptr %gep2 = null
i1 %cmp = #x1 (1)

SOURCE MEMORY STATE
===================
NON-LOCAL BLOCKS:
Block 0 >	size: 0	align: 1	alloc type: 0	alive: false	address: 0
Block 1 >	size: 0	align: 1	alloc type: 0	alive: true	address: 1

Target:
i1 %cmp = #x0 (0)
Source value: #x1 (1)
Target value: #x0 (0)

----------------------------------------
define i1 @src1(ptr %ptr, i8 %idx1, i8 %idx2) {
#0:
  %gep1 = gep nuw ptr %ptr, 4 x i8 %idx1
  %gep2 = gep nuw ptr %ptr, 4 x i8 %idx2
  %cmp = icmp eq ptr %gep1, %gep2, offsetonly
  ret i1 %cmp
}
=>
define i1 @tgt1(ptr %ptr, i8 %idx1, i8 %idx2) {
#0:
  %cmp = icmp eq i8 %idx1, %idx2
  ret i1 %cmp
}
Transformation seems to be correct!

----------------------------------------
define i1 @src2(ptr %ptr, i8 %idx1, i8 %idx2) {
#0:
  %gep1 = gep nusw ptr %ptr, 4 x i8 %idx1
  %gep2 = gep nusw ptr %ptr, 4 x i8 %idx2
  %cmp = icmp eq ptr %gep1, %gep2, offsetonly
  ret i1 %cmp
}
=>
define i1 @tgt2(ptr %ptr, i8 %idx1, i8 %idx2) {
#0:
  %cmp = icmp eq i8 %idx1, %idx2
  ret i1 %cmp
}
Transformation seems to be correct!

Summary:
  2 correct transformations
  1 incorrect transformations
  0 failed-to-prove transformations
  0 Alive2 errors
```

miscompilation
llvm:instcombine
generated by fuzzer


commit c2fba023475fddb893eac29dc9f34dfbdb221cd5
Author: goldsteinn <35538541+goldsteinn@users.noreply.github.com>
Date:   Tue Jan 28 15:54:00 2025 -0600

    [ValueTracking] Fix bug of using wrong condition for deducing KnownBits (#124481)

    - **[ValueTracking] Add test for issue 124275**
    - **[ValueTracking] Fix bug of using wrong condition for deducing
    KnownBits**

    Fixes https://github.com/llvm/llvm-project/issues/124275

    Bug was introduced by https://github.com/llvm/llvm-project/pull/114689

    Now that computeKnownBits supports breaking out of recursive Phi
    nodes, `IncValue` can be an operand of a different Phi than `P`. This
    breaks the previous assumptions we had when using the possibly
    condition at `CxtI` to constrain `IncValue`.

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index eba728c7c8c3..b63a0a07f7de 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -593,11 +593,14 @@ static bool cmpExcludesZero(CmpInst::Predicate Pred, const Value *RHS) {
 }

 static void breakSelfRecursivePHI(const Use *U, const PHINode *PHI,
-                                  Value *&ValOut, Instruction *&CtxIOut) {
+                                  Value *&ValOut, Instruction *&CtxIOut,
+                                  const PHINode **PhiOut = nullptr) {
   ValOut = U->get();
   if (ValOut == PHI)
     return;
   CtxIOut = PHI->getIncomingBlock(*U)->getTerminator();
+  if (PhiOut)
+    *PhiOut = PHI;
   Value *V;
   // If the Use is a select of this phi, compute analysis on other arm to break
   // recursion.
@@ -610,11 +613,13 @@ static void breakSelfRecursivePHI(const Use *U, const PHINode *PHI,
   // incoming value to break recursion.
   // TODO: We could handle any number of incoming edges as long as we only have
   // two unique values.
-  else if (auto *IncPhi = dyn_cast<PHINode>(ValOut);
-           IncPhi && IncPhi->getNumIncomingValues() == 2) {
+  if (auto *IncPhi = dyn_cast<PHINode>(ValOut);
+      IncPhi && IncPhi->getNumIncomingValues() == 2) {
     for (int Idx = 0; Idx < 2; ++Idx) {
       if (IncPhi->getIncomingValue(Idx) == PHI) {
         ValOut = IncPhi->getIncomingValue(1 - Idx);
+        if (PhiOut)
+          *PhiOut = IncPhi;
         CtxIOut = IncPhi->getIncomingBlock(1 - Idx)->getTerminator();
         break;
       }
@@ -1673,8 +1678,9 @@ static void computeKnownBitsFromOperator(const Operator *I,
       Known.One.setAllBits();
       for (const Use &U : P->operands()) {
         Value *IncValue;
+        const PHINode *CxtPhi;
         Instruction *CxtI;
-        breakSelfRecursivePHI(&U, P, IncValue, CxtI);
+        breakSelfRecursivePHI(&U, P, IncValue, CxtI, &CxtPhi);
         // Skip direct self references.
         if (IncValue == P)
           continue;
@@ -1705,9 +1711,10 @@ static void computeKnownBitsFromOperator(const Operator *I,
                     m_Br(m_c_ICmp(Pred, m_Specific(IncValue), m_APInt(RHSC)),
                          m_BasicBlock(TrueSucc), m_BasicBlock(FalseSucc)))) {
             // Check for cases of duplicate successors.
-            if ((TrueSucc == P->getParent()) != (FalseSucc == P->getParent())) {
+            if ((TrueSucc == CxtPhi->getParent()) !=
+                (FalseSucc == CxtPhi->getParent())) {
               // If we're using the false successor, invert the predicate.
-              if (FalseSucc == P->getParent())
+              if (FalseSucc == CxtPhi->getParent())
                 Pred = CmpInst::getInversePredicate(Pred);
               // Get the knownbits implied by the incoming phi condition.
               auto CR = ConstantRange::makeExactICmpRegion(Pred, *RHSC);

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"
target triple = "x86_64-unknown-linux-gnu"

@c = dso_local global i32 1, align 4
@a = dso_local global i32 0, align 4
@b = dso_local global i32 0, align 4

define dso_local i32 @main() #0 {
entry:
  %retval = alloca i32, align 4
  %d = alloca i32, align 4
  store i32 0, ptr %retval, align 4
  store i32 -1, ptr @a, align 4
  %0 = load i32, ptr @a, align 4
  %cmp = icmp ult i32 %0, 1
  br i1 %cmp, label %if.then, label %if.end

if.then:
  br label %e

if.end:
  %1 = load i32, ptr @c, align 4
  store i32 %1, ptr %d, align 4
  %2 = load i32, ptr %d, align 4
  %tobool = icmp ne i32 %2, 0
  br i1 %tobool, label %if.then1, label %if.end2

if.then1:
  br label %e

e:
  br label %if.end2

if.end2:
  %3 = load i32, ptr %d, align 4
  %tobool3 = icmp ne i32 %3, 0
  br i1 %tobool3, label %if.end5, label %if.then4

if.then4:
  unreachable

if.end5:
  %4 = load i32, ptr @b, align 4
  %tobool6 = icmp ne i32 %4, 0
  br i1 %tobool6, label %if.then7, label %if.end8

if.then7:
  br label %e

if.end8:
  ret i32 0
}

attributes #0 = { noinline nounwind uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }

!llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
!llvm.ident = !{!6}

!0 = !{i32 7, !"Dwarf Version", i32 4}
!1 = !{i32 1, !"wchar_size", i32 4}
!2 = !{i32 8, !"PIC Level", i32 2}
!3 = !{i32 7, !"PIE Level", i32 2}
!4 = !{i32 7, !"uwtable", i32 2}
!5 = !{i32 7, !"frame-pointer", i32 2}
!6 = !{!"clang version 21.0.0git (https://github.com/llvm/llvm-project.git 5c3c0a8cec9205efba78583bd0b8a646270968a1)"}

wrong code at -O1 and above on x86_64-linux-gnu

It appears to be a recent regression from 19.1.0.

Compiler Explorer: https://godbolt.org/z/haMfGoo6h

```
[548] % clangtk -v
clang version 20.0.0git (https://github.com/llvm/llvm-project.git ddd2f57b29661f21308eec0400fa92a6d075b0c6)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/home/suz/suz-local/software/local/clang-trunk/bin
Build config: +assertions
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/12
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/12
Candidate multilib: .;@m64
Selected multilib: .;@m64
Found CUDA installation: /usr/local/cuda, version 12.1
[549] %
[549] % clangtk -O1 small.c
[550] % ./a.out
Aborted
[551] %
[551] % cat small.c
int printf(const char *, ...);
unsigned a;
int b, c = 1;
int main() {
  int d;
  a = -1;
  if (a < 1)
    goto e;
  d = c;
  if (d) {
  e:;
  }
  if (!d)
    __builtin_abort();
  if (b)
    goto e;
  return 0;
}
```

Another likely related test:
```
[552] % clangtk -v
clang version 20.0.0git (https://github.com/llvm/llvm-project.git ddd2f57b29661f21308eec0400fa92a6d075b0c6)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/home/suz/suz-local/software/local/clang-trunk/bin
Build config: +assertions
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/12
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/12
Candidate multilib: .;@m64
Selected multilib: .;@m64
Found CUDA installation: /usr/local/cuda, version 12.1
[553] %
[553] % clangtk -O0 small.c
[554] % ./a.out
[555] %
[555] % clangtk -O1 small.c
[556] % timeout -s 9 5 ./a.out
Killed
[557] % cat small.c
int a, b;
int main() {
  {
    int c;
    if (a && 0)
      goto d;
  }
  int e = -~b;
  if (e) {
  d:;
  }
  while (!e)
    goto d;
  return 0;
}
```

Reduced to:

```llvm
; opt -p instcombine small.ll
define i32 @small(i32 noundef %0) {
  %2 = xor i32 %0, 1
  %3 = sub i32 0, %2
  %4 = icmp ne i32 %3, 0
  br i1 %4, label %5, label %6

5:                                                ; preds = %6, %1
  %.0 = phi i32 [ %.1, %6 ], [ %3, %1 ]
  br label %6

6:                                                ; preds = %5, %1
  %.1 = phi i32 [ %.0, %5 ], [ 0, %1 ]
  %7 = icmp ne i32 %.1, 0
  %8 = xor i1 %7, true
  br i1 %8, label %5, label %9

9:                                                ; preds = %6
  ret i32 0
}
```

Fix at: https://github.com/llvm/llvm-project/pull/124481


commit d4a38c8ff5c993e14c42895b51a47272fb03a857
Author: Usman Nadeem <mnadeem@quicinc.com>
Date:   Tue Sep 24 08:54:36 2024 -0700

    [DFAJumpThreading] Handle select unfolding when user phi is not a dir… (#109511)

    …ect successor

    Previously the code assumed that the select instruction is defined in a
    block that is a direct predecessor of the block where the PHINode uses
    it. So, we were hitting an assertion when we tried to access the def
    block as an incoming block for the user phi node.

    This patch handles that case by using the correct end block and creating
    a new phi node that aggregates both the values of the select in that end
    block, and then using that new unfolded phi to overwrite the original
    user phi node.

    Fixes #106083

    Change-Id: Ie471994cca232318f74a6e6438efa21e561c2dc0

diff --git a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp
index ef9c264482a6..0e2b5c925a6a 100644
--- a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp
+++ b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp
@@ -194,7 +194,6 @@ void unfold(DomTreeUpdater *DTU, LoopInfo *LI, SelectInstToUnfold SIToUnfold,
   SelectInst *SI = SIToUnfold.getInst();
   PHINode *SIUse = SIToUnfold.getUse();
   BasicBlock *StartBlock = SI->getParent();
-  BasicBlock *EndBlock = SIUse->getParent();
   BranchInst *StartBlockTerm =
       dyn_cast<BranchInst>(StartBlock->getTerminator());

@@ -202,6 +201,7 @@ void unfold(DomTreeUpdater *DTU, LoopInfo *LI, SelectInstToUnfold SIToUnfold,
   assert(SI->hasOneUse());

   if (StartBlockTerm->isUnconditional()) {
+    BasicBlock *EndBlock = StartBlock->getUniqueSuccessor();
     // Arbitrarily choose the 'false' side for a new input value to the PHI.
     BasicBlock *NewBlock = BasicBlock::Create(
         SI->getContext(), Twine(SI->getName(), ".si.unfold.false"),
@@ -223,32 +223,44 @@ void unfold(DomTreeUpdater *DTU, LoopInfo *LI, SelectInstToUnfold SIToUnfold,
                                       NewBlock->getFirstInsertionPt());
     NewPhi->addIncoming(SIOp2, StartBlock);

-    if (auto *OpSi = dyn_cast<SelectInst>(SIOp1))
-      NewSIsToUnfold->push_back(SelectInstToUnfold(OpSi, SIUse));
-    if (auto *OpSi = dyn_cast<SelectInst>(SIOp2))
-      NewSIsToUnfold->push_back(SelectInstToUnfold(OpSi, NewPhi));
-
-    // Update the phi node of SI.
-    for (unsigned Idx = 0; Idx < SIUse->getNumIncomingValues(); ++Idx) {
-      if (SIUse->getIncomingBlock(Idx) == StartBlock)
-        SIUse->setIncomingValue(Idx, SIOp1);
+    // Update any other PHI nodes in EndBlock.
+    for (PHINode &Phi : EndBlock->phis()) {
+      if (SIUse == &Phi)
+        continue;
+      Phi.addIncoming(Phi.getIncomingValueForBlock(StartBlock), NewBlock);
     }
-    SIUse->addIncoming(NewPhi, NewBlock);

-    // Update any other PHI nodes in EndBlock.
-    for (auto II = EndBlock->begin(); PHINode *Phi = dyn_cast<PHINode>(II);
-         ++II) {
-      if (Phi != SIUse)
-        Phi->addIncoming(Phi->getIncomingValueForBlock(StartBlock), NewBlock);
+    // Update the phi node of SI, which is its only use.
+    if (EndBlock == SIUse->getParent()) {
+      SIUse->addIncoming(NewPhi, NewBlock);
+      SIUse->replaceUsesOfWith(SI, SIOp1);
+    } else {
+      PHINode *EndPhi = PHINode::Create(SIUse->getType(), pred_size(EndBlock),
+                                        Twine(SI->getName(), ".si.unfold.phi"),
+                                        EndBlock->getFirstInsertionPt());
+      for (BasicBlock *Pred : predecessors(EndBlock)) {
+        if (Pred != StartBlock && Pred != NewBlock)
+          EndPhi->addIncoming(EndPhi, Pred);
+      }
+
+      EndPhi->addIncoming(SIOp1, StartBlock);
+      EndPhi->addIncoming(NewPhi, NewBlock);
+      SIUse->replaceUsesOfWith(SI, EndPhi);
+      SIUse = EndPhi;
     }

-    StartBlockTerm->eraseFromParent();
+    if (auto *OpSi = dyn_cast<SelectInst>(SIOp1))
+      NewSIsToUnfold->push_back(SelectInstToUnfold(OpSi, SIUse));
+    if (auto *OpSi = dyn_cast<SelectInst>(SIOp2))
+      NewSIsToUnfold->push_back(SelectInstToUnfold(OpSi, NewPhi));

     // Insert the real conditional branch based on the original condition.
+    StartBlockTerm->eraseFromParent();
     BranchInst::Create(EndBlock, NewBlock, SI->getCondition(), StartBlock);
     DTU->applyUpdates({{DominatorTree::Insert, StartBlock, EndBlock},
                        {DominatorTree::Insert, StartBlock, NewBlock}});
   } else {
+    BasicBlock *EndBlock = SIUse->getParent();
     BasicBlock *NewBlockT = BasicBlock::Create(
         SI->getContext(), Twine(SI->getName(), ".si.unfold.true"),
         EndBlock->getParent(), EndBlock);

define i32 @test2(i32 %init) {
entry:
  %cmp = icmp eq i32 %init, 0
  %sel = select i1 %cmp, i32 0, i32 2
  br label %loop.1

loop.1:                                           ; preds = %loop.1.backedge, %entry
  %state.1 = phi i32 [ %sel, %entry ], [ %state.1.be2, %loop.1.backedge ]
  br label %loop.2

loop.2:                                           ; preds = %loop.2.backedge, %loop.1
  %state.2 = phi i32 [ %state.1, %loop.1 ], [ %state.2.be, %loop.2.backedge ]
  br label %loop.3

loop.3:                                           ; preds = %case2, %loop.2
  %state = phi i32 [ %state.2, %loop.2 ], [ 3, %case2 ]
  switch i32 %state, label %infloop.i [
    i32 2, label %case2
    i32 3, label %case3
    i32 4, label %case4
    i32 0, label %case0
    i32 1, label %case1
  ]

case2:                                            ; preds = %loop.3
  br i1 %cmp, label %loop.3, label %loop.1.backedge

case3:                                            ; preds = %loop.3
  br i1 %cmp, label %loop.2.backedge, label %case4

case4:                                            ; preds = %case3, %loop.3
  br i1 %cmp, label %loop.2.backedge, label %loop.1.backedge

loop.1.backedge:                                  ; preds = %case4, %case2
  %state.1.be = phi i32 [ 2, %case4 ], [ 4, %case2 ]
  %state.1.be2 = select i1 %cmp, i32 1, i32 %state.1.be
  br label %loop.1

loop.2.backedge:                                  ; preds = %case4, %case3
  %state.2.be = phi i32 [ 3, %case4 ], [ 0, %case3 ]
  br label %loop.2

case0:                                            ; preds = %loop.3
  br label %exit

case1:                                            ; preds = %loop.3
  br label %exit

infloop.i:                                        ; preds = %infloop.i, %loop.3
  br label %infloop.i

exit:                                             ; preds = %case1, %case0
  ret i32 0
}

define void @pr106083_select_dead_uses(i1 %cmp1, i1 %not, ptr %p) {
bb:
  %spec.select = select i1 %cmp1, i32 0, i32 1
  br label %.loopexit6

.loopexit6:                                       ; preds = %select.unfold, %bb
  br i1 %not, label %select.unfold, label %bb1

bb1:                                              ; preds = %.loopexit6
  %i = load i32, ptr %p, align 4
  %not2 = icmp eq i32 0, 0
  %spec.select7 = select i1 %not2, i32 %spec.select, i32 0
  br label %select.unfold

select.unfold:                                    ; preds = %bb1, %.loopexit6
  %_2 = phi i32 [ 0, %.loopexit6 ], [ %spec.select7, %bb1 ]
  switch i32 %_2, label %bb2 [
    i32 0, label %.preheader.preheader
    i32 1, label %.loopexit6
  ]

.preheader.preheader:                             ; preds = %select.unfold
  ret void

bb2:                                              ; preds = %select.unfold
  unreachable
}

define i32 @test1(i32 %num) {
entry:
  br label %for.body

for.body:                                         ; preds = %for.inc, %entry
  %count = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
  %state = phi i32 [ 1, %entry ], [ %state.next, %for.inc ]
  switch i32 %state, label %for.inc [
    i32 1, label %case1
    i32 2, label %case2
  ]

case1:                                            ; preds = %for.body
  br label %for.inc

case2:                                            ; preds = %for.body
  %cmp = icmp eq i32 %count, 50
  %sel = select i1 %cmp, i32 1, i32 2
  br label %for.inc

for.inc:                                          ; preds = %case2, %case1, %for.body
  %state.next = phi i32 [ %sel, %case2 ], [ 1, %for.body ], [ 2, %case1 ]
  %inc = add nsw i32 %count, 1
  %cmp.exit = icmp slt i32 %inc, %num
  br i1 %cmp.exit, label %for.body, label %for.end

for.end:                                          ; preds = %for.inc
  ret i32 0
}

define void @pr106083_invalidBBarg_fold(i1 %cmp1, i1 %cmp2, i1 %not, ptr %d) {
bb:
  %sel = select i1 %cmp1, i32 0, i32 1
  br label %BB1

BB1:                                              ; preds = %BB1.backedge, %BB7, %bb
  %i = phi i16 [ 0, %BB1.backedge ], [ 0, %bb ], [ 1, %BB7 ]
  br i1 %not, label %BB7, label %BB2

BB2:                                              ; preds = %BB1
  store i16 0, ptr %d, align 2
  %spec.select = select i1 %cmp2, i32 %sel, i32 0
  br label %BB7

BB7:                                              ; preds = %BB2, %BB1
  %d.promoted4 = phi i16 [ 0, %BB1 ], [ 1, %BB2 ]
  %_3 = phi i32 [ 0, %BB1 ], [ %spec.select, %BB2 ]
  switch i32 %_3, label %BB1.backedge [
    i32 0, label %BB1
    i32 1, label %BB8
  ]

BB1.backedge:                                     ; preds = %BB7
  br label %BB1

BB8:                                              ; preds = %BB7
  ret void
}

define void @pr78059_bitwidth() {
.split.preheader:
  br label %.split

.split:                                           ; preds = %.split, %.split.preheader
  %0 = phi i128 [ 0, %.split.preheader ], [ -1, %.split ]
  switch i128 %0, label %end [
    i128 -1, label %end
    i128 0, label %.split
  ]

end:                                              ; preds = %.split, %.split
  ret void
}

[DFAJumpThreading] crash since b167ada

Seeing many assertions that go away if I revert b167ada "[DFAJumpThreading] Rewrite the way paths are enumerated (#96127)".

```
clang-20 -cc1 -triple s390x-unknown-linux-gnu -target-cpu z15 -O3 -w -mllvm -enable-dfa-jump-thread -o /dev/null -emit-llvm -x ir  tc_dfa-jt_invalidbbarg.ll
...
10 0x000002aa0a73e544 (anonymous namespace)::DFAJumpThreading::run
...
```

```
clang-20 -cc1 -triple s390x-unknown-linux-gnu   -target-cpu z16 -O3 -w -mllvm -enable-dfa-jump-thread -o /dev/null -emit-llvm -x ir  tc_select_mustbedeadnow.ll
...
#10 0x000002aa1b0c0968 llvm::DFAJumpThreadingPass::run
...

```
[tcs_dfa-jt.tar.gz](https://github.com/user-attachments/files/16750050/tcs_dfa-jt.tar.gz)

Perhaps the same assertion I reported here:
 https://github.com/llvm/llvm-project/pull/96127#issuecomment-2303862037
?

> Perhaps the same assertion I reported here: [#96127 (comment)](https://github.com/llvm/llvm-project/pull/96127#issuecomment-2303862037) ?

Yes, same assertion, and in addition my second test case above triggered another assertion.


commit 7152bf3bc805b8d9b1873058ab0a084d7b6079d6
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Mon Oct 28 06:37:24 2024 -0700

    [SLP]Do not create new vector node if scalars fully overlap with the existing one

    If the list of scalars vectorized as the part of the same vector node,
    no need to generate vector node again, it will be handled as part of
    overlapping matching.

    Fixes #113810

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 2afd02dae3a8..268546fe99e1 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -7947,8 +7947,13 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
           Nodes.insert(E);
         SmallPtrSet<Value *, 8> Values(VL.begin(), VL.end());
         if (any_of(Nodes, [&](const TreeEntry *E) {
-              return all_of(E->Scalars,
-                            [&](Value *V) { return Values.contains(V); });
+              if (all_of(E->Scalars,
+                         [&](Value *V) { return Values.contains(V); }))
+                return true;
+              SmallPtrSet<Value *, 8> EValues(E->Scalars.begin(),
+                                              E->Scalars.end());
+              return (
+                  all_of(VL, [&](Value *V) { return EValues.contains(V); }));
             })) {
           LLVM_DEBUG(dbgs() << "SLP: Gathering due to full overlap.\n");
           if (TryToFindDuplicates(S))

define void @test(ptr %p1, ptr %0, i32 %1, i1 %c1, ptr %p2) {
top:
  %2 = getelementptr i8, ptr %0, i64 8
  %3 = getelementptr i8, ptr %0, i64 12
  %4 = getelementptr i8, ptr %0, i64 16
  %5 = getelementptr i8, ptr %0, i64 20
  br i1 %c1, label %L42, label %L41

L41:                                              ; preds = %top
  %.not276 = icmp eq ptr %2, null
  %6 = load i32, ptr %2, align 4
  %7 = select i1 %.not276, i32 0, i32 %6
  %.not277 = icmp eq ptr %3, null
  %8 = load i32, ptr %3, align 4
  %9 = select i1 %.not277, i32 0, i32 %8
  %.not278 = icmp eq ptr %4, null
  %10 = load i32, ptr %4, align 4
  %11 = select i1 %.not278, i32 0, i32 %10
  %.not279 = icmp eq ptr %5, null
  %12 = load i32, ptr %5, align 4
  %13 = select i1 %.not279, i32 0, i32 %12
  br label %L112

L42:                                              ; preds = %top
  %14 = load i32, ptr %2, align 4
  %.not280 = icmp eq i32 %14, 0
  br i1 %.not280, label %L112, label %L47

L47:                                              ; preds = %L42
  %15 = load i32, ptr %3, align 4
  %.not282 = icmp eq ptr %4, null
  %16 = load i32, ptr %4, align 4
  %17 = select i1 %.not282, i32 0, i32 %16
  %.not283 = icmp eq ptr %5, null
  %18 = load i32, ptr %5, align 4
  %19 = select i1 %.not283, i32 0, i32 %18
  br label %L112

L112:                                             ; preds = %L47, %L42, %L41
  %value_phi13336 = phi i32 [ %19, %L47 ], [ %13, %L41 ], [ 0, %L42 ]
  %value_phi12335 = phi i32 [ %17, %L47 ], [ %11, %L41 ], [ %1, %L42 ]
  %value_phi11334 = phi i32 [ %15, %L47 ], [ %9, %L41 ], [ 0, %L42 ]
  %value_phi10333 = phi i32 [ 0, %L47 ], [ %7, %L41 ], [ 0, %L42 ]
  store i32 %value_phi10333, ptr %p2, align 4
  store i32 %value_phi11334, ptr %p1, align 4
  store i32 %value_phi12335, ptr %p2, align 4
  store i32 %value_phi13336, ptr %p1, align 4
  ret void
}

SLPVectorizer miscompilation

This IR
```llvm
; Function Attrs: alignstack(16)
define swiftcc { ptr addrspace(10), i8 } @julia__zip_iterate_all_17381(ptr noalias nocapture noundef nonnull align 4 dereferenceable(96) %union_bytes_return, ptr nonnull swiftself %pgcstack_arg, ptr addrspace(11) nocapture noundef nonnull readonly align 4 dereferenceable(48) %0, ptr addrspace(11) nocapture noundef nonnull readonly align 4 dereferenceable(48) %1) #0 {
top:
  %pgcstack = call ptr @julia.get_pgcstack()
  %ptls_field = getelementptr inbounds i8, ptr %pgcstack, i32 8
  %ptls_load = load ptr, ptr %ptls_field, align 4
  %2 = getelementptr inbounds i8, ptr %ptls_load, i32 16
  %safepoint = load ptr, ptr %2, align 4
  fence syncscope("singlethread") seq_cst
  call void @julia.safepoint(ptr %safepoint)
  fence syncscope("singlethread") seq_cst
  %3 = load i32, ptr addrspace(11) %1, align 4
  %4 = load i32, ptr addrspace(11) %0, align 4
  %.not = icmp eq i32 %3, %4
  br i1 %.not, label %L26, label %L20

L20:                                              ; preds = %top
  %5 = add i32 %3, 1
  %6 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 4
  %7 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 8
  %8 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 12
  %9 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 16
  %10 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 20
  %.not265 = icmp eq ptr addrspace(11) %6, null
  %11 = load i32, ptr addrspace(11) %6, align 4
  %12 = select i1 %.not265, i32 undef, i32 %11
  %.not266 = icmp eq ptr addrspace(11) %7, null
  %13 = load i32, ptr addrspace(11) %7, align 4
  %14 = select i1 %.not266, i32 undef, i32 %13
  %.not267 = icmp eq ptr addrspace(11) %8, null
  %15 = load i32, ptr addrspace(11) %8, align 4
  %16 = select i1 %.not267, i32 undef, i32 %15
  %.not268 = icmp eq ptr addrspace(11) %9, null
  %17 = load i32, ptr addrspace(11) %9, align 4
  %18 = select i1 %.not268, i32 undef, i32 %17
  %.not269 = icmp eq ptr addrspace(11) %10, null
  %19 = load i32, ptr addrspace(11) %10, align 4
  %20 = select i1 %.not269, i32 undef, i32 %19
  br label %L112

L26:                                              ; preds = %top
  %21 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 4
  %22 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 8
  %23 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 12
  %24 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 16
  %25 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 20
  %26 = getelementptr inbounds i8, ptr addrspace(11) %0, i32 4
  %27 = getelementptr inbounds i8, ptr addrspace(11) %0, i32 12
  %28 = getelementptr inbounds i8, ptr addrspace(11) %0, i32 16
  %29 = getelementptr inbounds i8, ptr addrspace(11) %0, i32 20
  %30 = load i32, ptr addrspace(11) %21, align 4
  %31 = load i32, ptr addrspace(11) %26, align 4
  %.not275 = icmp eq i32 %30, %31
  br i1 %.not275, label %L42, label %L41

L41:                                              ; preds = %L26
  %32 = add i32 %30, 1
  %.not276 = icmp eq ptr addrspace(11) %22, null
  %33 = load i32, ptr addrspace(11) %22, align 4
  %34 = select i1 %.not276, i32 undef, i32 %33
  %.not277 = icmp eq ptr addrspace(11) %23, null
  %35 = load i32, ptr addrspace(11) %23, align 4
  %36 = select i1 %.not277, i32 undef, i32 %35
  %.not278 = icmp eq ptr addrspace(11) %24, null
  %37 = load i32, ptr addrspace(11) %24, align 4
  %38 = select i1 %.not278, i32 undef, i32 %37
  %.not279 = icmp eq ptr addrspace(11) %25, null
  %39 = load i32, ptr addrspace(11) %25, align 4
  %40 = select i1 %.not279, i32 undef, i32 %39
  br label %L112

L42:                                              ; preds = %L26
  %41 = getelementptr inbounds i8, ptr addrspace(11) %0, i32 8
  %42 = load i32, ptr addrspace(11) %22, align 4
  %43 = load i32, ptr addrspace(11) %41, align 4
  %.not280 = icmp eq i32 %42, %43
  br i1 %.not280, label %L48, label %L47

L47:                                              ; preds = %L42
  %44 = add i32 %42, 1
  %.not281 = icmp eq ptr addrspace(11) %23, null
  %45 = load i32, ptr addrspace(11) %23, align 4
  %46 = select i1 %.not281, i32 undef, i32 %45
  %.not282 = icmp eq ptr addrspace(11) %24, null
  %47 = load i32, ptr addrspace(11) %24, align 4
  %48 = select i1 %.not282, i32 undef, i32 %47
  %.not283 = icmp eq ptr addrspace(11) %25, null
  %49 = load i32, ptr addrspace(11) %25, align 4
  %50 = select i1 %.not283, i32 undef, i32 %49
  br label %L112

L48:                                              ; preds = %L42
  %51 = load i32, ptr addrspace(11) %23, align 4
  %52 = load i32, ptr addrspace(11) %27, align 4
  %.not284 = icmp eq i32 %51, %52
  br i1 %.not284, label %L54, label %L53

L53:                                              ; preds = %L48
  %53 = add i32 %51, 1
  %.not285 = icmp eq ptr addrspace(11) %24, null
  %54 = load i32, ptr addrspace(11) %24, align 4
  %55 = select i1 %.not285, i32 undef, i32 %54
  %.not286 = icmp eq ptr addrspace(11) %25, null
  %56 = load i32, ptr addrspace(11) %25, align 4
  %57 = select i1 %.not286, i32 undef, i32 %56
  br label %L112

L54:                                              ; preds = %L48
  %58 = load i32, ptr addrspace(11) %24, align 4
  %59 = load i32, ptr addrspace(11) %28, align 4
  %.not287 = icmp eq i32 %58, %59
  br i1 %.not287, label %L87, label %L59

L59:                                              ; preds = %L54
  %60 = add i32 %58, 1
  %.not288 = icmp eq ptr addrspace(11) %25, null
  %61 = load i32, ptr addrspace(11) %25, align 4
  %62 = select i1 %.not288, i32 undef, i32 %61
  br label %L112

L87:                                              ; preds = %L54
  %63 = load i32, ptr addrspace(11) %25, align 4
  %64 = add i32 %63, 1
  %65 = load i32, ptr addrspace(11) %29, align 4
  %66 = icmp eq i32 %63, %65
  br i1 %66, label %common.ret, label %L112

L112:                                             ; preds = %L87, %L20, %L41, %L47, %L53, %L59
  %value_phi13336 = phi i32 [ %64, %L87 ], [ %62, %L59 ], [ %57, %L53 ], [ %50, %L47 ], [ %40, %L41 ], [ %20, %L20 ]
  %value_phi12335 = phi i32 [ 1, %L87 ], [ %60, %L59 ], [ %55, %L53 ], [ %48, %L47 ], [ %38, %L41 ], [ %18, %L20 ]
  %value_phi11334 = phi i32 [ 1, %L87 ], [ 1, %L59 ], [ %53, %L53 ], [ %46, %L47 ], [ %36, %L41 ], [ %16, %L20 ]
  %value_phi10333 = phi i32 [ 1, %L87 ], [ 1, %L59 ], [ 1, %L53 ], [ %44, %L47 ], [ %34, %L41 ], [ %14, %L20 ]
  %value_phi9332 = phi i32 [ 1, %L87 ], [ 1, %L59 ], [ 1, %L53 ], [ 1, %L47 ], [ %32, %L41 ], [ %12, %L20 ]
  %value_phi2326 = phi i32 [ 1, %L87 ], [ 1, %L59 ], [ 1, %L53 ], [ 1, %L47 ], [ 1, %L41 ], [ %5, %L20 ]
  %67 = getelementptr inbounds i8, ptr addrspace(11) %0, i32 24
  %68 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 24
  %69 = load i32, ptr addrspace(11) %68, align 4
  %70 = load i32, ptr addrspace(11) %67, align 4
  %.not289 = icmp eq i32 %69, %70
  br i1 %.not289, label %L134, label %L128

L128:                                             ; preds = %L112
  %71 = add i32 %69, 1
  %72 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 28
  %73 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 32
  %74 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 36
  %75 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 40
  %76 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 44
  %.not290 = icmp eq ptr addrspace(11) %72, null
  %77 = load i32, ptr addrspace(11) %72, align 4
  %78 = select i1 %.not290, i32 undef, i32 %77
  %.not291 = icmp eq ptr addrspace(11) %73, null
  %79 = load i32, ptr addrspace(11) %73, align 4
  %80 = select i1 %.not291, i32 undef, i32 %79
  %.not292 = icmp eq ptr addrspace(11) %74, null
  %81 = load i32, ptr addrspace(11) %74, align 4
  %82 = select i1 %.not292, i32 undef, i32 %81
  %.not293 = icmp eq ptr addrspace(11) %75, null
  %83 = load i32, ptr addrspace(11) %75, align 4
  %84 = select i1 %.not293, i32 undef, i32 %83
  %.not294 = icmp eq ptr addrspace(11) %76, null
  %85 = load i32, ptr addrspace(11) %76, align 4
  %86 = select i1 %.not294, i32 undef, i32 %85
  br label %L230

L134:                                             ; preds = %L112
  %87 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 28
  %88 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 32
  %89 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 36
  %90 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 40
  %91 = getelementptr inbounds i8, ptr addrspace(11) %1, i32 44
  %92 = getelementptr inbounds i8, ptr addrspace(11) %0, i32 28
  %93 = getelementptr inbounds i8, ptr addrspace(11) %0, i32 36
  %94 = getelementptr inbounds i8, ptr addrspace(11) %0, i32 40
  %95 = getelementptr inbounds i8, ptr addrspace(11) %0, i32 44
  %96 = load i32, ptr addrspace(11) %87, align 4
  %97 = load i32, ptr addrspace(11) %92, align 4
  %.not300 = icmp eq i32 %96, %97
  br i1 %.not300, label %L150, label %L149

L149:                                             ; preds = %L134
  %98 = add i32 %96, 1
  %.not301 = icmp eq ptr addrspace(11) %88, null
  %99 = load i32, ptr addrspace(11) %88, align 4
  %100 = select i1 %.not301, i32 undef, i32 %99
  %.not302 = icmp eq ptr addrspace(11) %89, null
  %101 = load i32, ptr addrspace(11) %89, align 4
  %102 = select i1 %.not302, i32 undef, i32 %101
  %.not303 = icmp eq ptr addrspace(11) %90, null
  %103 = load i32, ptr addrspace(11) %90, align 4
  %104 = select i1 %.not303, i32 undef, i32 %103
  %.not304 = icmp eq ptr addrspace(11) %91, null
  %105 = load i32, ptr addrspace(11) %91, align 4
  %106 = select i1 %.not304, i32 undef, i32 %105
  br label %L230

L150:                                             ; preds = %L134
  %107 = getelementptr inbounds i8, ptr addrspace(11) %0, i32 32
  %108 = load i32, ptr addrspace(11) %88, align 4
  %109 = load i32, ptr addrspace(11) %107, align 4
  %.not305 = icmp eq i32 %108, %109
  br i1 %.not305, label %L156, label %L155

L155:                                             ; preds = %L150
  %110 = add i32 %108, 1
  %.not306 = icmp eq ptr addrspace(11) %89, null
  %111 = load i32, ptr addrspace(11) %89, align 4
  %112 = select i1 %.not306, i32 undef, i32 %111
  %.not307 = icmp eq ptr addrspace(11) %90, null
  %113 = load i32, ptr addrspace(11) %90, align 4
  %114 = select i1 %.not307, i32 undef, i32 %113
  %.not308 = icmp eq ptr addrspace(11) %91, null
  %115 = load i32, ptr addrspace(11) %91, align 4
  %116 = select i1 %.not308, i32 undef, i32 %115
  br label %L230

L156:                                             ; preds = %L150
  %117 = load i32, ptr addrspace(11) %89, align 4
  %118 = load i32, ptr addrspace(11) %93, align 4
  %.not309 = icmp eq i32 %117, %118
  br i1 %.not309, label %L162, label %L161

L161:                                             ; preds = %L156
  %119 = add i32 %117, 1
  %.not310 = icmp eq ptr addrspace(11) %90, null
  %120 = load i32, ptr addrspace(11) %90, align 4
  %121 = select i1 %.not310, i32 undef, i32 %120
  %.not311 = icmp eq ptr addrspace(11) %91, null
  %122 = load i32, ptr addrspace(11) %91, align 4
  %123 = select i1 %.not311, i32 undef, i32 %122
  br label %L230

L162:                                             ; preds = %L156
  %124 = load i32, ptr addrspace(11) %90, align 4
  %125 = load i32, ptr addrspace(11) %94, align 4
  %.not312 = icmp eq i32 %124, %125
  br i1 %.not312, label %L195, label %L167

L167:                                             ; preds = %L162
  %126 = add i32 %124, 1
  %.not313 = icmp eq ptr addrspace(11) %91, null
  %127 = load i32, ptr addrspace(11) %91, align 4
  %128 = select i1 %.not313, i32 undef, i32 %127
  br label %L230

L195:                                             ; preds = %L162
  %129 = load i32, ptr addrspace(11) %91, align 4
  %130 = add i32 %129, 1
  %131 = load i32, ptr addrspace(11) %95, align 4
  %132 = icmp eq i32 %129, %131
  br i1 %132, label %common.ret, label %L230

common.ret:                                       ; preds = %L87, %L195, %L230
  %common.ret.op = phi { ptr addrspace(10), i8 } [ { ptr addrspace(10) null, i8 2 }, %L230 ], [ { ptr addrspace(10) null, i8 1 }, %L195 ], [ { ptr addrspace(10) null, i8 1 }, %L87 ]
  ret { ptr addrspace(10), i8 } %common.ret.op

L230:                                             ; preds = %L195, %L128, %L149, %L155, %L161, %L167
  %value_phi29359 = phi i32 [ %130, %L195 ], [ %128, %L167 ], [ %123, %L161 ], [ %116, %L155 ], [ %106, %L149 ], [ %86, %L128 ]
  %value_phi28358 = phi i32 [ 1, %L195 ], [ %126, %L167 ], [ %121, %L161 ], [ %114, %L155 ], [ %104, %L149 ], [ %84, %L128 ]
  %value_phi27357 = phi i32 [ 1, %L195 ], [ 1, %L167 ], [ %119, %L161 ], [ %112, %L155 ], [ %102, %L149 ], [ %82, %L128 ]
  %value_phi26356 = phi i32 [ 1, %L195 ], [ 1, %L167 ], [ 1, %L161 ], [ %110, %L155 ], [ %100, %L149 ], [ %80, %L128 ]
  %value_phi25355 = phi i32 [ 1, %L195 ], [ 1, %L167 ], [ 1, %L161 ], [ 1, %L155 ], [ %98, %L149 ], [ %78, %L128 ]
  %value_phi18349 = phi i32 [ 1, %L195 ], [ 1, %L167 ], [ 1, %L161 ], [ 1, %L155 ], [ 1, %L149 ], [ %71, %L128 ]
  store i32 %value_phi2326, ptr %union_bytes_return, align 4
  %.sroa.0429.sroa.0.sroa.2.0.union_bytes_return.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 4
  store i32 %value_phi9332, ptr %.sroa.0429.sroa.0.sroa.2.0.union_bytes_return.sroa_idx, align 4
  %.sroa.0429.sroa.0.sroa.3.0.union_bytes_return.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 8
  store i32 %value_phi10333, ptr %.sroa.0429.sroa.0.sroa.3.0.union_bytes_return.sroa_idx, align 4
  %.sroa.0429.sroa.0.sroa.4.0.union_bytes_return.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 12
  store i32 %value_phi11334, ptr %.sroa.0429.sroa.0.sroa.4.0.union_bytes_return.sroa_idx, align 4
  %.sroa.0429.sroa.0.sroa.5.0.union_bytes_return.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 16
  store i32 %value_phi12335, ptr %.sroa.0429.sroa.0.sroa.5.0.union_bytes_return.sroa_idx, align 4
  %.sroa.0429.sroa.0.sroa.6.0.union_bytes_return.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 20
  store i32 %value_phi13336, ptr %.sroa.0429.sroa.0.sroa.6.0.union_bytes_return.sroa_idx, align 4
  %.sroa.0429.sroa.2.0.union_bytes_return.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 24
  store i32 %value_phi18349, ptr %.sroa.0429.sroa.2.0.union_bytes_return.sroa_idx, align 4
  %.sroa.0429.sroa.3.0.union_bytes_return.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 28
  store i32 %value_phi25355, ptr %.sroa.0429.sroa.3.0.union_bytes_return.sroa_idx, align 4
  %.sroa.0429.sroa.4.0.union_bytes_return.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 32
  store i32 %value_phi26356, ptr %.sroa.0429.sroa.4.0.union_bytes_return.sroa_idx, align 4
  %.sroa.0429.sroa.5.0.union_bytes_return.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 36
  store i32 %value_phi27357, ptr %.sroa.0429.sroa.5.0.union_bytes_return.sroa_idx, align 4
  %.sroa.0429.sroa.6.0.union_bytes_return.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 40
  store i32 %value_phi28358, ptr %.sroa.0429.sroa.6.0.union_bytes_return.sroa_idx, align 4
  %.sroa.0429.sroa.7.0.union_bytes_return.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 44
  store i32 %value_phi29359, ptr %.sroa.0429.sroa.7.0.union_bytes_return.sroa_idx, align 4
  %.sroa.0429.sroa.8.0.union_bytes_return.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 48
  store i32 %value_phi2326, ptr %.sroa.0429.sroa.8.0.union_bytes_return.sroa_idx, align 4
  %.sroa.0429.sroa.8.sroa.2.0..sroa.0429.sroa.8.0.union_bytes_return.sroa_idx.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 52
  store i32 %value_phi9332, ptr %.sroa.0429.sroa.8.sroa.2.0..sroa.0429.sroa.8.0.union_bytes_return.sroa_idx.sroa_idx, align 4
  %.sroa.0429.sroa.8.sroa.3.0..sroa.0429.sroa.8.0.union_bytes_return.sroa_idx.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 56
  store i32 %value_phi10333, ptr %.sroa.0429.sroa.8.sroa.3.0..sroa.0429.sroa.8.0.union_bytes_return.sroa_idx.sroa_idx, align 4
  %.sroa.0429.sroa.8.sroa.4.0..sroa.0429.sroa.8.0.union_bytes_return.sroa_idx.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 60
  store i32 %value_phi11334, ptr %.sroa.0429.sroa.8.sroa.4.0..sroa.0429.sroa.8.0.union_bytes_return.sroa_idx.sroa_idx, align 4
  %.sroa.0429.sroa.8.sroa.5.0..sroa.0429.sroa.8.0.union_bytes_return.sroa_idx.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 64
  store i32 %value_phi12335, ptr %.sroa.0429.sroa.8.sroa.5.0..sroa.0429.sroa.8.0.union_bytes_return.sroa_idx.sroa_idx, align 4
  %.sroa.0429.sroa.8.sroa.6.0..sroa.0429.sroa.8.0.union_bytes_return.sroa_idx.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 68
  store i32 %value_phi13336, ptr %.sroa.0429.sroa.8.sroa.6.0..sroa.0429.sroa.8.0.union_bytes_return.sroa_idx.sroa_idx, align 4
  %.sroa.4430.0.union_bytes_return.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 72
  store i32 %value_phi18349, ptr %.sroa.4430.0.union_bytes_return.sroa_idx, align 4
  %.sroa.5431.0.union_bytes_return.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 76
  store i32 %value_phi25355, ptr %.sroa.5431.0.union_bytes_return.sroa_idx, align 4
  %.sroa.6432.0.union_bytes_return.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 80
  store i32 %value_phi26356, ptr %.sroa.6432.0.union_bytes_return.sroa_idx, align 4
  %.sroa.7433.0.union_bytes_return.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 84
  store i32 %value_phi27357, ptr %.sroa.7433.0.union_bytes_return.sroa_idx, align 4
  %.sroa.8434.0.union_bytes_return.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 88
  store i32 %value_phi28358, ptr %.sroa.8434.0.union_bytes_return.sroa_idx, align 4
  %.sroa.9435.0.union_bytes_return.sroa_idx = getelementptr inbounds i8, ptr %union_bytes_return, i32 92
  store i32 %value_phi29359, ptr %.sroa.9435.0.union_bytes_return.sroa_idx, align 4
  br label %common.ret
}

declare ptr @julia.get_pgcstack()

; Function Attrs: memory(argmem: readwrite, inaccessiblemem: readwrite)
declare void @julia.safepoint(ptr) #2

; Function Attrs: willreturn memory(argmem: read, inaccessiblemem: readwrite)
declare nonnull align 16 dereferenceable(16) ptr addrspace(10) @jl_alloc_genericmemory(ptr addrspace(10), i32) #3

; Function Attrs: nounwind willreturn allockind("alloc") allocsize(1) memory(argmem: read, inaccessiblemem: readwrite)
declare noalias nonnull ptr addrspace(10) @julia.gc_alloc_obj(ptr, i32, ptr addrspace(10)) #4

; Function Attrs: norecurse nosync nounwind speculatable willreturn memory(none)
declare noundef nonnull ptr addrspace(13) @julia.gc_loaded(ptr addrspace(10) nocapture noundef nonnull readnone, ptr noundef nonnull readnone) #5

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #6

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #6
```
gives error
```
Instruction does not dominate all uses!
  %20 = shufflevector <4 x ptr addrspace(11)> %19, <4 x ptr addrspace(11)> poison, <4 x i32> zeroinitializer
  %17 = shufflevector <4 x ptr addrspace(11)> %20, <4 x ptr addrspace(11)> poison, <2 x i32> zeroinitializer
Instruction does not dominate all uses!
  %90 = shufflevector <4 x ptr addrspace(11)> %89, <4 x ptr addrspace(11)> poison, <4 x i32> zeroinitializer
  %87 = shufflevector <4 x ptr addrspace(11)> %90, <4 x ptr addrspace(11)> poison, <2 x i32> zeroinitializer
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 <source>
1.	Running pass "verify" on module "<source>"
 #0 0x00000000050e6958 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x50e6958)
 #1 0x00000000050e434c SignalHandler(int) Signals.cpp:0:0
 #2 0x00007508e6a42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x00007508e6a969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x00007508e6a42476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x00007508e6a287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x00000000007d7105 llvm::json::operator==(llvm::json::Value const&, llvm::json::Value const&) (.cold) JSON.cpp:0:0
 #7 0x00000000050254d8 (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x50254d8)
 #8 0x0000000004f23440 llvm::VerifierPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4f23440)
 #9 0x00000000009000ae 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+0x9000ae)
#10 0x0000000004ee6850 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4ee6850)
#11 0x000000000090adda 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+0x90adda)
#12 0x00000000008fdd2a optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8fdd2a)
#13 0x00007508e6a29d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#14 0x00007508e6a29e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#15 0x00000000008f57ae _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8f57ae)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```
https://godbolt.org/z/sah34KE77

Reduced IR:
```llvm
define swiftcc { ptr addrspace(10), i8 } @julia__zip_iterate_all_17381(ptr addrspace(11) %0, i32 %1) {
top:
  %2 = getelementptr i8, ptr addrspace(11) %0, i32 8
  %3 = getelementptr i8, ptr addrspace(11) %0, i32 12
  %4 = getelementptr i8, ptr addrspace(11) %0, i32 16
  %5 = getelementptr i8, ptr addrspace(11) %0, i32 20
  br i1 false, label %L42, label %L41

L41:                                              ; preds = %top
  %.not276 = icmp eq ptr addrspace(11) %2, null
  %6 = select i1 %.not276, i32 0, i32 0
  %.not277 = icmp eq ptr addrspace(11) %3, null
  %7 = select i1 %.not277, i32 0, i32 0
  %.not278 = icmp eq ptr addrspace(11) %4, null
  %8 = select i1 %.not278, i32 0, i32 0
  %.not279 = icmp eq ptr addrspace(11) %5, null
  %9 = select i1 %.not279, i32 0, i32 0
  br label %common.ret

L42:                                              ; preds = %top
  %.not282 = icmp eq ptr addrspace(11) %4, null
  %10 = select i1 %.not282, i32 0, i32 0
  %.not283 = icmp eq ptr addrspace(11) %5, null
  %11 = select i1 %.not283, i32 0, i32 0
  br label %common.ret

L59:                                              ; No predecessors!
  %12 = select i1 false, i32 0, i32 0
  br label %common.ret

common.ret:                                       ; preds = %L59, %L42, %L41
  %value_phi13336 = phi i32 [ %12, %L59 ], [ %11, %L42 ], [ %9, %L41 ]
  %value_phi12335 = phi i32 [ 0, %L59 ], [ %10, %L42 ], [ %8, %L41 ]
  %value_phi11334 = phi i32 [ 0, %L59 ], [ %1, %L42 ], [ %7, %L41 ]
  %value_phi10333 = phi i32 [ 0, %L59 ], [ 0, %L42 ], [ %6, %L41 ]
  ret { ptr addrspace(10), i8 } zeroinitializer
}
```
https://godbolt.org/z/a8xzqGYo9

Bisected to 69332bb8995aef60d830406de12cb79a5039026 and f3d2609af3031ddb54030548e86335f295cf49ca, @alexey-bataev