commit 0eaa69eb234798774a08743b64a9aa0cf71c5356
Author: Florian Hahn <flo@fhahn.com>
Date:   Tue Jan 7 21:26:40 2025 +0000

    [VPlan] Handle VPExpandSCEVRecipe in isUniformAfterVectorization.

    VPExpandSCEVRecipes must be placed in the entry and are alway uniform.
    This fixes a crash by always identifying them as uniform, even if the
    main vector loop region has been removed.

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

diff --git a/llvm/lib/Transforms/Vectorize/VPlanUtils.h b/llvm/lib/Transforms/Vectorize/VPlanUtils.h
index 965777002052..777944264f45 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanUtils.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanUtils.h
@@ -49,7 +49,8 @@ inline bool isUniformAfterVectorization(const VPValue *VPV) {
     return all_of(GEP->operands(), isUniformAfterVectorization);
   if (auto *VPI = dyn_cast<VPInstruction>(Def))
     return VPI->isSingleScalar() || VPI->isVectorToScalar();
-  return false;
+  // VPExpandSCEVRecipes must be placed in the entry and are alway uniform.
+  return isa<VPExpandSCEVRecipe>(Def);
 }

 /// Return true if \p V is a header mask in \p Plan.

opt -passes='loop-vectorize,verify<loops>' -force-vector-width=8 -force-vector-interleave=1 -S %s

opt -passes='loop-vectorize,verify<loops>' -force-vector-width=8 -force-vector-interleave=2 -S %s

opt -passes='loop-vectorize,verify<loops>' -force-vector-width=16 -force-vector-interleave=1 -S %s

target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #0

define void @scev_expand_step(i64 %x, ptr %dst) {
entry:
  %c = icmp eq i64 %x, 65536
  call void @llvm.assume(i1 %c)
  %fr = freeze i64 %x
  %step = add i64 %fr, -65534
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %iv.next = add i64 %iv, %step
  %gep.dst = getelementptr i8, ptr %dst, i64 %iv.next
  store i8 0, ptr %gep.dst, align 1
  %ec = icmp slt i64 %iv.next, 16
  br i1 %ec, label %loop, label %exit

exit:                                             ; preds = %loop
  ret void
}

attributes #0 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"

declare i1 @cond()

define void @remove_loop_region_outer_loop(i64 range(i64 8, 17) %N, ptr noalias %src, ptr %dst) {
entry:
  br label %outer.header

outer.header:                                     ; preds = %outer.latch, %entry
  %outer.iv = phi ptr [ %src, %entry ], [ %outer.iv.next, %outer.latch ]
  br label %inner

inner:                                            ; preds = %inner, %outer.header
  %inner.iv = phi i64 [ 0, %outer.header ], [ %iv.next, %inner ]
  %gep.src = getelementptr i8, ptr %outer.iv, i64 %inner.iv
  %l = load i8, ptr %gep.src, align 1
  %gep.dst = getelementptr i8, ptr %dst, i64 %inner.iv
  store i8 %l, ptr %gep.dst, align 1
  %iv.next = add i64 %inner.iv, 1
  %c.1 = icmp eq i64 %iv.next, %N
  br i1 %c.1, label %outer.latch, label %inner

outer.latch:                                      ; preds = %inner
  %outer.iv.next = getelementptr i8, ptr %outer.iv, i64 1
  %c.2 = call i1 @cond()
  br i1 %c.2, label %outer.header, label %exit

exit:                                             ; preds = %outer.latch
  ret void
}

target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"

define void @remove_loop_region_with_replicate_recipe(ptr %dst, i64 range(i64 5, 10) %N) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 2, %entry ], [ %iv.next, %loop ]
  %gep.dst = getelementptr i16, ptr %dst, i64 %iv
  store i16 0, ptr %gep.dst, align 2
  %iv.next = add i64 %iv, 1
  %ec = icmp eq i64 %iv.next, %N
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"

define void @test_tc_less_than_16(ptr %A, i64 %N) {
entry:
  %and = and i64 %N, 15
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ %and, %entry ], [ %iv.next, %loop ]
  %p.src = phi ptr [ %A, %entry ], [ %p.src.next, %loop ]
  %p.src.next = getelementptr inbounds i8, ptr %p.src, i64 1
  %l = load i8, ptr %p.src, align 1
  %add = add nsw i8 %l, 10
  store i8 %add, ptr %p.src, align 1
  %iv.next = add nsw i64 %iv, -1
  %cmp = icmp eq i64 %iv.next, 0
  br i1 %cmp, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

[clang] Crash at -O3: Assertion `hasVectorValue(Def)' failed.

This code crashes at `-O3`:

```c
int *a;
int b, d;
static int f = 65535;
char c[];
int h(int i) {
  int g = 1;
  for (; b;)
    if (a[0]) {
      g = 0;
      break;
    }
  if (g)
    a;
  else if (i)
    return 1;
  return 0;
}
void k() {
  int *e[10] = {&f};
  for (;;) {
    d = 0;
    for (; d < 8; d = f - 65535 + d + 1) {
      int j = h(f);
      c[j + f - 65534 + d] = 0;
    }
  }
}
void main() {}
```

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

Bisected to https://github.com/llvm/llvm-project/commit/f48884ded884d982a7fd13394b0e93e6588f4143, which was comitted by @fhahn

Crash:

```console
clang: /root/llvm-project/llvm/lib/Transforms/Vectorize/VPlan.cpp:236: llvm::Value* llvm::VPTransformState::get(llvm::VPValue*, const llvm::VPLane&): Assertion `hasVectorValue(Def)' failed.
```

Backtrace:

```console
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/clang -gdwarf-4 -g -o /app/output.s -mllvm --x86-asm-syntax=intel -fno-verbose-asm -S --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot -fcolor-diagnostics -fno-crash-diagnostics -O3 <source>
1.	<eof> parser at end of file
2.	Optimizer
3.	Running pass "function<eager-inv>(float2int,lower-constant-intrinsics,chr,loop(loop-rotate<header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,infer-alignment,loop-load-elim,instcombine<max-iterations=1;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,slp-vectorizer,vector-combine,instcombine<max-iterations=1;no-verify-fixpoint>,loop-unroll<O3>,transform-warning,sroa<preserve-cfg>,infer-alignment,instcombine<max-iterations=1;no-verify-fixpoint>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables>)" on module "<source>"
4.	Running pass "loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>" on function "k"
 #0 0x0000000003c71738 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3c71738)
 #1 0x0000000003c6f444 llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3c6f444)
 #2 0x0000000003bbc988 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x000077fbea242520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x000077fbea2969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #5 0x000077fbea242476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #6 0x000077fbea2287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #7 0x000077fbea22871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #8 0x000077fbea239e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #9 0x00000000058fd2be llvm::VPTransformState::get(llvm::VPValue*, llvm::VPLane const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x58fd2be)
#10 0x0000000005790d0d llvm::InnerLoopVectorizer::scalarizeInstruction(llvm::Instruction const*, llvm::VPReplicateRecipe*, llvm::VPLane const&, llvm::VPTransformState&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x5790d0d)
#11 0x00000000057916d0 llvm::VPReplicateRecipe::execute(llvm::VPTransformState&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x57916d0)
#12 0x00000000058e3ce7 llvm::VPBasicBlock::executeRecipes(llvm::VPTransformState*, llvm::BasicBlock*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x58e3ce7)
#13 0x00000000058ef282 llvm::VPBasicBlock::execute(llvm::VPTransformState*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x58ef282)
#14 0x00000000058f0ef1 llvm::VPRegionBlock::execute(llvm::VPTransformState*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x58f0ef1)
#15 0x00000000058fddb1 llvm::VPlan::execute(llvm::VPTransformState*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x58fddb1)
#16 0x00000000057be1eb llvm::LoopVectorizationPlanner::executePlan(llvm::ElementCount, unsigned int, llvm::VPlan&, llvm::InnerLoopVectorizer&, llvm::DominatorTree*, bool, llvm::DenseMap<llvm::SCEV const*, llvm::Value*, llvm::DenseMapInfo<llvm::SCEV const*, void>, llvm::detail::DenseMapPair<llvm::SCEV const*, llvm::Value*>> const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x57be1eb)
#17 0x00000000057d24c3 llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x57d24c3)
#18 0x00000000057d3e19 llvm::LoopVectorizePass::runImpl(llvm::Function&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x57d3e19)
#19 0x00000000057d4453 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x57d4453)
#20 0x00000000052f765e llvm::detail::PassModel<llvm::Function, llvm::LoopVectorizePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x52f765e)
#21 0x000000000361c6e0 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x361c6e0)
#22 0x00000000011305ce 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/clang+0x11305ce)
#23 0x000000000361affb llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x361affb)
#24 0x000000000112fc5e 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/clang+0x112fc5e)
#25 0x000000000361aa00 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x361aa00)
#26 0x0000000003f247bf (anonymous namespace)::EmitAssemblyHelper::RunOptimizationPipeline(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>&, std::unique_ptr<llvm::ToolOutputFile, std::default_delete<llvm::ToolOutputFile>>&, clang::BackendConsumer*) BackendUtil.cpp:0:0
#27 0x0000000003f28335 clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3f28335)
#28 0x000000000460209e clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x460209e)
#29 0x000000000660f9cc clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x660f9cc)
#30 0x0000000004602478 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4602478)
#31 0x00000000048be799 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x48be799)
#32 0x0000000004840e2e clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4840e2e)
#33 0x00000000049abb8e clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x49abb8e)
#34 0x0000000000ce93ef cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xce93ef)
#35 0x0000000000ce0e8a ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#36 0x0000000004647ae9 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#37 0x0000000003bbce34 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3bbce34)
#38 0x00000000046480df clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0
#39 0x000000000460c1ed clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x460c1ed)
#40 0x000000000460d26e clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x460d26e)
#41 0x0000000004614d95 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4614d95)
#42 0x0000000000ce6233 clang_main(int, char**, llvm::ToolContext const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xce6233)
#43 0x0000000000bb2524 main (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xbb2524)
#44 0x000077fbea229d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#45 0x000077fbea229e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#46 0x0000000000ce0935 _start (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xce0935)
```

Reduced repro:

```
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 void @k() {
entry:
  %.fr = freeze i32 65535
  %invariant.op = add i32 %.fr, -65534
  br label %for.cond.us

for.cond.us:                                      ; preds = %for.body.us.us, %entry
  br label %for.body.us.us

for.body.us.us:                                   ; preds = %for.body.us.us, %for.cond.us
  %storemerge7.us.us = phi i32 [ 0, %for.cond.us ], [ %sub.reass.us.us, %for.body.us.us ]
  %sub.reass.us.us = add i32 %storemerge7.us.us, %invariant.op
  %idxprom.us.us = sext i32 %sub.reass.us.us to i64
  %arrayidx.us.us = getelementptr [0 x i8], ptr null, i64 0, i64 %idxprom.us.us
  store i8 0, ptr %arrayidx.us.us, align 1
  %cmp.us.us = icmp slt i32 %sub.reass.us.us, 8
  br i1 %cmp.us.us, label %for.body.us.us, label %for.cond.us
}
```


commit 3512bcc2e9ab06b0ae2cab78744550b515e54184
Author: Nikita Popov <npopov@redhat.com>
Date:   Mon Aug 12 15:18:32 2024 +0200

    [SCEV] Fix incorrect extension in computeConstantDifference()

    The Mul factor was zero-extended here, resulting in incorrect
    results for integers larger than 64-bit.

    As we currently only multiply by 1 or -1, just split this into
    two cases -- there's no need for a full multiplication here.

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

diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 9ecdcbe2c5de..318a9d773dc2 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -11961,9 +11961,14 @@ ScalarEvolution::computeConstantDifference(const SCEV *More, const SCEV *Less) {
   SmallDenseMap<const SCEV *, int, 8> Multiplicity;
   APInt Diff(BW, 0);
   auto Add = [&](const SCEV *S, int Mul) {
-    if (auto *C = dyn_cast<SCEVConstant>(S))
-      Diff += C->getAPInt() * Mul;
-    else
+    if (auto *C = dyn_cast<SCEVConstant>(S)) {
+      if (Mul == 1) {
+        Diff += C->getAPInt();
+      } else {
+        assert(Mul == -1);
+        Diff -= C->getAPInt();
+      }
+    } else
       Multiplicity[S] += Mul;
   };
   auto Decompose = [&](const SCEV *S, int Mul) {

define void @test() {
entry:
  br label %loop

loop:                                             ; preds = %loop.latch, %entry
  %iv = phi i128 [ 3, %entry ], [ %iv.dec, %loop.latch ]
  %tobool = icmp ne i128 %iv, 0
  br i1 %tobool, label %loop.latch, label %if

if:                                               ; preds = %loop
  call void @foo()
  br label %loop.latch

loop.latch:                                       ; preds = %if, %loop
  %iv.dec = add nsw i128 %iv, -1
  %cmp = icmp sgt i128 %iv, 0
  br i1 %cmp, label %loop, label %exit

exit:                                             ; preds = %loop.latch
  ret void
}

declare void @foo()

[SCEV] WRONG code

```
int printf(const char *, ...);
__int128 a = 3, c;
char b;
int main() {
  c = 3;
  for (; c >= 0; c--) {
    b = 0;
    for (; b <= 3; b++) {
      if (c)
        break;
      a = 0;
    }
  }
  printf("%d\n", (int)a);
}

```

clang -march=z15 -O1 wrong0.i -o a.out

This program should print '0' as 'a' is set to zero inside the loop. It now prints '3' instead. A bisect leads to a recent commit: 79af689 " [SCEV] Handle more adds in computeConstantDifference() (#101339)".

Seems like IndVarSimplify has gone wrong with an i128:
GOOD <> BROKEN
```
; *** IR Dump After IndVarSimplifyPass on loo   ; *** IR Dump After IndVarSimplifyPass on loo

; Preheader:                                    ; Preheader:
entry:                                          entry:
  br label %for.cond1.preheader                   br label %for.cond1.preheader

; Loop:                                         ; Loop:
for.cond1.preheader:                            for.cond1.preheader:
  %storemerge11 = phi i128 [ 3, %entry ], [ %     %storemerge11 = phi i128 [ 3, %entry ], [ %
  %tobool = icmp ne i128 %storemerge11, 0     |   br i1 true, label %for.inc5, label %if.end.
  br i1 %tobool, label %for.inc5, label %if.e <

if.end.lr.ph:                                   if.end.lr.ph:
  store i128 0, ptr @a, align 8, !tbaa !4         store i128 0, ptr @a, align 8, !tbaa !4
  br label %if.end                                br label %if.end

if.end:                                         if.end:
  %storemerge89 = phi i8 [ 0, %if.end.lr.ph ]     %storemerge89 = phi i8 [ 0, %if.end.lr.ph ]
  %inc = add nuw nsw i8 %storemerge89, 1          %inc = add nuw nsw i8 %storemerge89, 1
  %cmp2 = icmp ugt i8 %storemerge89, 2            %cmp2 = icmp ugt i8 %storemerge89, 2
  %or.cond = or i1 %tobool, %cmp2             |   %or.cond = or i1 true, %cmp2
  br i1 %or.cond, label %for.inc5.loopexit, l     br i1 %or.cond, label %for.inc5.loopexit, l

for.inc5:                                       for.inc5:
  %storemerge8.lcssa = phi i8 [ 0, %for.cond1     %storemerge8.lcssa = phi i8 [ 0, %for.cond1
  %dec = add nsw i128 %storemerge11, -1           %dec = add nsw i128 %storemerge11, -1
  %cmp = icmp ugt i128 %storemerge11, 0           %cmp = icmp ugt i128 %storemerge11, 0
  br i1 %cmp, label %for.cond1.preheader, lab     br i1 %cmp, label %for.cond1.preheader, lab

for.inc5.loopexit:                              for.inc5.loopexit:
  %inc.lcssa = phi i8 [ %inc, %if.end ]           %inc.lcssa = phi i8 [ %inc, %if.end ]
  br label %for.inc5                              br label %for.inc5

; Exit blocks                                   ; Exit blocks
for.end6:                                       for.end6:
  %storemerge8.lcssa.lcssa = phi i8 [ %storem     %storemerge8.lcssa.lcssa = phi i8 [ %storem
  store i128 -1, ptr @c, align 8, !tbaa !4        store i128 -1, ptr @c, align 8, !tbaa !4
  store i8 %storemerge8.lcssa.lcssa, ptr @b,      store i8 %storemerge8.lcssa.lcssa, ptr @b,
  %0 = load i128, ptr @a, align 8, !tbaa !4       %0 = load i128, ptr @a, align 8, !tbaa !4
  %conv7 = trunc i128 %0 to i32                   %conv7 = trunc i128 %0 to i32
  %call = call signext i32 (ptr, ...) @printf     %call = call signext i32 (ptr, ...) @printf
  ret i32 0                                       ret i32 0

```

Classic mistake: https://github.com/llvm/llvm-project/blob/2f8f58dd17a11934e8c8ec212b6474f76fb18e61/llvm/lib/Analysis/ScalarEvolution.cpp#L11967 This `* Mul` doesn't do what I wanted it to do :)

I should really pick up https://github.com/llvm/llvm-project/pull/80309 again to prevent this kind of mistake in the first place.

Is this commit self-contained in the sense that I could revert it on my testing machines? Or will you revert / fix soon?


commit 4f32f5d5720fbef06672714a62376f236a36aef5
Author: Nikita Popov <npopov@redhat.com>
Date:   Wed Jan 31 15:23:53 2024 +0100

    [AA][JumpThreading] Don't use DomTree for AA in JumpThreading (#79294)

    JumpThreading may perform AA queries while the dominator tree is not up
    to date, which may result in miscompilations.

    Fix this by adding a new AAQI option to disable the use of the dominator
    tree in BasicAA.

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

diff --git a/llvm/include/llvm/Analysis/AliasAnalysis.h b/llvm/include/llvm/Analysis/AliasAnalysis.h
index d6f732d35fd4..e8e4f491be5a 100644
--- a/llvm/include/llvm/Analysis/AliasAnalysis.h
+++ b/llvm/include/llvm/Analysis/AliasAnalysis.h
@@ -287,6 +287,10 @@ public:
   ///   store %l, ...
   bool MayBeCrossIteration = false;

+  /// Whether alias analysis is allowed to use the dominator tree, for use by
+  /// passes that lazily update the DT while performing AA queries.
+  bool UseDominatorTree = true;
+
   AAQueryInfo(AAResults &AAR, CaptureInfo *CI) : AAR(AAR), CI(CI) {}
 };

@@ -668,6 +672,9 @@ public:
   void enableCrossIterationMode() {
     AAQI.MayBeCrossIteration = true;
   }
+
+  /// Disable the use of the dominator tree during alias analysis queries.
+  void disableDominatorTree() { AAQI.UseDominatorTree = false; }
 };

 /// Temporary typedef for legacy code that uses a generic \c AliasAnalysis
diff --git a/llvm/include/llvm/Analysis/BasicAliasAnalysis.h b/llvm/include/llvm/Analysis/BasicAliasAnalysis.h
index afc1811239f2..7eca82729430 100644
--- a/llvm/include/llvm/Analysis/BasicAliasAnalysis.h
+++ b/llvm/include/llvm/Analysis/BasicAliasAnalysis.h
@@ -43,20 +43,26 @@ class BasicAAResult : public AAResultBase {
   const Function &F;
   const TargetLibraryInfo &TLI;
   AssumptionCache &AC;
-  DominatorTree *DT;
+  /// Use getDT() instead of accessing this member directly, in order to
+  /// respect the AAQI.UseDominatorTree option.
+  DominatorTree *DT_;
+
+  DominatorTree *getDT(const AAQueryInfo &AAQI) const {
+    return AAQI.UseDominatorTree ? DT_ : nullptr;
+  }

 public:
   BasicAAResult(const DataLayout &DL, const Function &F,
                 const TargetLibraryInfo &TLI, AssumptionCache &AC,
                 DominatorTree *DT = nullptr)
-      : DL(DL), F(F), TLI(TLI), AC(AC), DT(DT) {}
+      : DL(DL), F(F), TLI(TLI), AC(AC), DT_(DT) {}

   BasicAAResult(const BasicAAResult &Arg)
       : AAResultBase(Arg), DL(Arg.DL), F(Arg.F), TLI(Arg.TLI), AC(Arg.AC),
-        DT(Arg.DT) {}
+        DT_(Arg.DT_) {}
   BasicAAResult(BasicAAResult &&Arg)
       : AAResultBase(std::move(Arg)), DL(Arg.DL), F(Arg.F), TLI(Arg.TLI),
-        AC(Arg.AC), DT(Arg.DT) {}
+        AC(Arg.AC), DT_(Arg.DT_) {}

   /// Handle invalidation events in the new pass manager.
   bool invalidate(Function &Fn, const PreservedAnalyses &PA,
diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index 3178e2d27816..1028b52a7912 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -89,7 +89,7 @@ bool BasicAAResult::invalidate(Function &Fn, const PreservedAnalyses &PA,
   // may be created without handles to some analyses and in that case don't
   // depend on them.
   if (Inv.invalidate<AssumptionAnalysis>(Fn, PA) ||
-      (DT && Inv.invalidate<DominatorTreeAnalysis>(Fn, PA)))
+      (DT_ && Inv.invalidate<DominatorTreeAnalysis>(Fn, PA)))
     return true;

   // Otherwise this analysis result remains valid.
@@ -1063,6 +1063,7 @@ AliasResult BasicAAResult::aliasGEP(
                                              : AliasResult::MayAlias;
   }

+  DominatorTree *DT = getDT(AAQI);
   DecomposedGEP DecompGEP1 = DecomposeGEPExpression(GEP1, DL, &AC, DT);
   DecomposedGEP DecompGEP2 = DecomposeGEPExpression(V2, DL, &AC, DT);

@@ -1556,6 +1557,7 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, LocationSize V1Size,
         const Value *HintO1 = getUnderlyingObject(Hint1);
         const Value *HintO2 = getUnderlyingObject(Hint2);

+        DominatorTree *DT = getDT(AAQI);
         auto ValidAssumeForPtrContext = [&](const Value *Ptr) {
           if (const Instruction *PtrI = dyn_cast<Instruction>(Ptr)) {
             return isValidAssumeForContext(Assume, PtrI, DT,
@@ -1735,7 +1737,7 @@ bool BasicAAResult::isValueEqualInPotentialCycles(const Value *V,
   if (!Inst || Inst->getParent()->isEntryBlock())
     return true;

-  return isNotInCycle(Inst, DT, /*LI*/ nullptr);
+  return isNotInCycle(Inst, getDT(AAQI), /*LI*/ nullptr);
 }

 /// Computes the symbolic difference between two de-composed GEPs.
diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
index b7cf02489631..bb33a5da288c 100644
--- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp
+++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
@@ -1261,6 +1261,8 @@ bool JumpThreadingPass::simplifyPartiallyRedundantLoad(LoadInst *LoadI) {
   BasicBlock::iterator BBIt(LoadI);
   bool IsLoadCSE;
   BatchAAResults BatchAA(*AA);
+  // The dominator tree is updated lazily and may not be valid at this point.
+  BatchAA.disableDominatorTree();
   if (Value *AvailableVal = FindAvailableLoadedValue(
           LoadI, LoadBB, BBIt, DefMaxInstsToScan, &BatchAA, &IsLoadCSE)) {
     // If the value of the load is locally available within the block, just use

@f = external global i32

define i32 @test(i64 %idx, i32 %val) {
entry:
  %cmp = icmp slt i64 %idx, 1
  br i1 %cmp, label %for.body, label %return

for.body:                                         ; preds = %entry
  %f = load i32, ptr @f, align 4
  %cmp1 = icmp eq i32 %f, 0
  br i1 %cmp1, label %cond.end, label %cond.false

cond.false:                                       ; preds = %for.body
  br label %cond.end

cond.end:                                         ; preds = %cond.false, %for.body
  %phi = phi i32 [ %val, %cond.false ], [ 1, %for.body ]
  %cmp.i = icmp sgt i32 %phi, 0
  %sel = select i1 %cmp.i, i32 0, i32 %phi
  %f.idx = getelementptr inbounds i32, ptr @f, i64 %idx
  store i32 %sel, ptr %f.idx, align 4
  %f.reload = load i32, ptr @f, align 4
  %cmp3 = icmp slt i32 %f.reload, 1
  br i1 %cmp3, label %return2, label %return

return:                                           ; preds = %cond.end, %entry
  ret i32 0

return2:                                          ; preds = %cond.end
  ret i32 1
}

WRONG code, likely JumpThreadingPass

[wrong0.tar.gz](https://github.com/llvm/llvm-project/files/14027750/wrong0.tar.gz)
(reduced c test case, should print 0)

runline:
clang -O3 -march=arch13 wrong0.i -o a.out -w -mllvm -available-load-scan-limit=12

The function n() below is called two times in the reduced test case. The first time f[0] has a value of 0 at the start of the function, and a value of 1 at the end. The second time n() is called, f[0] has a value of 1 at the top, while it is then set to 0 by k().
```
long k(long l, int m); // returns 0

const int *n() {
  for (; C <= 0;) {
    A = (f[0] == 0 ? 1 : A % f[0]);
    f[C] = k(A, 0);
    g = &f[0];
    f[C] = 1 > *g;
    if (f[C])
      return &e;
    break;
  }
  return 0;
}
```
This is the transformation of jump threading:

```
                                                                          >     *** IR Dump After JumpThreadingPass on n ***
                                                                          >     ; Function Attrs: nounwind
define dso_local ptr @n() local_unnamed_addr #1 {                               define dso_local ptr @n() local_unnamed_addr #1 {
entry:                                                                          entry:
  %0 = load i64, ptr @C, align 8, !tbaa !4                                        %0 = load i64, ptr @C, align 8, !tbaa !4
  %cmp = icmp slt i64 %0, 1                                                       %cmp = icmp slt i64 %0, 1
  br i1 %cmp, label %for.body, label %for.end                                     br i1 %cmp, label %for.body, label %for.end

for.body:                                         ; preds = %entry              for.body:                                         ; preds = %entry
  %1 = load i32, ptr @f, align 4, !tbaa !8                                        %1 = load i32, ptr @f, align 4, !tbaa !8
  %cmp1 = icmp eq i32 %1, 0                                                       %cmp1 = icmp eq i32 %1, 0
  br i1 %cmp1, label %cond.end, label %cond.false                         |       br i1 %cmp1, label %cond.end.thread, label %cond.end

cond.false:                                       ; preds = %for.body     |     cond.end.thread:                                  ; preds = %for.body
                                                                          >       store i64 1, ptr @A, align 8, !tbaa !4
                                                                          >       br label %3
                                                                          >
                                                                          >     cond.end:                                         ; preds = %for.body
  %2 = load i64, ptr @A, align 8, !tbaa !4                                        %2 = load i64, ptr @A, align 8, !tbaa !4
  %conv = sext i32 %1 to i64                                                      %conv = sext i32 %1 to i64
  %rem = srem i64 %2, %conv                                                       %rem = srem i64 %2, %conv
  br label %cond.end                                                      |       store i64 %rem, ptr @A, align 8, !tbaa !4
                                                                          >       %cmp.i = icmp sgt i64 %rem, 0
                                                                          >       %cond.fr = freeze i1 %cmp.i
                                                                          >       br i1 %cond.fr, label %3, label %4
                                                                          >
                                                                          >     3:                                                ; preds = %cond.end.
                                                                          >       %.pr = load i32, ptr @f, align 4, !tbaa !8
                                                                          >       br label %4

cond.end:                                         ; preds = %for.body,    |     4:                                                ; preds = %cond.end,
  %cond = phi i64 [ %rem, %cond.false ], [ 1, %for.body ]                 |       %5 = phi i32 [ %1, %cond.end ], [ %.pr, %3 ]
  store i64 %cond, ptr @A, align 8, !tbaa !4                              |       %6 = phi i64 [ 0, %3 ], [ %rem, %cond.end ]
  %cmp.i = icmp sgt i64 %cond, 0                                          |       %conv2 = trunc i64 %6 to i32
  %cond.i = select i1 %cmp.i, i64 0, i64 %cond                            <
  %conv2 = trunc i64 %cond.i to i32                                       <
  %arrayidx = getelementptr inbounds [1 x i32], ptr @f, i64 0, i64 %0             %arrayidx = getelementptr inbounds [1 x i32], ptr @f, i64 0, i64 %0
  store i32 %conv2, ptr %arrayidx, align 4, !tbaa !8                              store i32 %conv2, ptr %arrayidx, align 4, !tbaa !8
  store ptr @f, ptr @g, align 8, !tbaa !10                                        store ptr @f, ptr @g, align 8, !tbaa !10
  %3 = load i32, ptr @f, align 4, !tbaa !8                                |       %cmp3 = icmp slt i32 %5, 1
  %cmp3 = icmp slt i32 %3, 1                                              <
  %conv4 = zext i1 %cmp3 to i32                                                   %conv4 = zext i1 %cmp3 to i32
  store i32 %conv4, ptr %arrayidx, align 4, !tbaa !8                              store i32 %conv4, ptr %arrayidx, align 4, !tbaa !8
  br i1 %cmp3, label %return, label %for.end                                      br i1 %cmp3, label %return, label %for.end

for.end:                                          ; preds = %cond.end,    |     for.end:                                          ; preds = %4, %entry
  br label %return                                                                br label %return

return:                                           ; preds = %cond.end,    |     return:                                           ; preds = %4, %for.e
  %retval.0 = phi ptr [ null, %for.end ], [ @e, %cond.end ]               |       %retval.0 = phi ptr [ null, %for.end ], [ @e, %4 ]
  ret ptr %retval.0                                                               ret ptr %retval.0
}                                                                               }
~

```

Before (left), `@f `is reloaded for the final icmp in cond.end (%3), which is necessary as the store to %conv2 just above goes to the same address. However, to the right JumpThreading has changed the final icmp to use the %5 value, which does not reflect the stored value of %conv2. This seems wrong and maybe JT has missed the fact that %arrayidx aliases `@f`?

@jmorse @MatzeB @nikic

Here's a godbolt link seemingly showing the same thing: https://godbolt.org/z/dMPaP7161 . I can't replicate this at 6a7abea47 with just `opt --passes=jump-threading`, but can if it's part of clang and inspected with `print-after-all`.

Ah -- because it's sensitive to the `-available-load-scan-limit=12`, which defaults to six and needs to be at least ten for this problem to appear. Stepping through bits of opt, the AA trace believes something that's wrong:

```
Start   %arrayidx = getelementptr inbounds [1 x i32], ptr @f, i64 0, i64 %0 @ LocationSize::precise(4), @f = dso_local global [1 x i32] zeroinitializer, align 4 @ LocationSize::precise(4)
  Start @f = dso_local global [1 x i32] zeroinitializer, align 4 @ LocationSize::beforeOrAfterPointer, @f = dso_local global [1 x i32] zeroinitializer, align 4 @ LocationSize::beforeOrAfterPointer
  End @f = dso_local global [1 x i32] zeroinitializer, align 4 @ LocationSize::beforeOrAfterPointer, @f = dso_local global [1 x i32] zeroinitializer, align 4 @ LocationSize::beforeOrAfterPointer = MustAlias
End   %arrayidx = getelementptr inbounds [1 x i32], ptr @f, i64 0, i64 %0 @ LocationSize::precise(4), @f = dso_local global [1 x i32] zeroinitializer, align 4 @ LocationSize::precise(4) = NoAlias
```

Which I think is saying that the GEP is believed to not-alias the "f" variable, wheras it might alias depending on the value of %0. Stepping through other things during the alias query, I see `isKnownNonNullFromDominatingCondition` returning true for %0, i.e. the load from "C". I would imagine this means there's something wrong with the dominator tree that makes this code think it's only executing on a path where %0 is always-zero. (EDIT: actually it means always-non-zero).

(However this isn't my normal wheelhouse, so that might not be true!).

That sounds about right to me. JumpThreading performs lazy DT updates, so it's not legal to use DT during the transform.

BasicAA in principle already supports working without DT, but it may be a bit tricky to avoid the DT use just in JumpThreading, given how this is all wired up in the pass manager.

Somewhat reduced test case:
```llvm
; RUN: opt -S -passes=jump-threading < %s
@f = external global i32

define void @test(i64 %idx, i32 %val) {
entry:
  %cmp = icmp slt i64 %idx, 1
  br i1 %cmp, label %for.body, label %return

for.body:
  %f = load i32, ptr @f, align 4
  %cmp1 = icmp eq i32 %f, 0
  br i1 %cmp1, label %cond.end, label %cond.false

cond.false:
  br label %cond.end

cond.end:
  %phi = phi i32 [ %val, %cond.false ], [ 1, %for.body ]
  %cmp.i = icmp sgt i32 %phi, 0
  %sel = select i1 %cmp.i, i32 0, i32 %phi
  %f.idx = getelementptr inbounds i32, ptr @f, i64 %idx
  store i32 %sel, ptr %f.idx, align 4
  %f.reload = load i32, ptr @f, align 4
  %cmp3 = icmp slt i32 %f.reload, 1
  br i1 %cmp3, label %return, label %return

return:
  ret void
}
```

Not merged yet.

PR has been created, we will track the status there.


commit bec7181d5b9d1828129d78d440fd9e02d5cb63e8
Author: Nikita Popov <npopov@redhat.com>
Date:   Wed Feb 7 11:06:51 2024 +0100

    [SCEVExpander] Don't use recursive expansion for ptr IV inc

    Similar to the non-ptr case, directly create the getelementptr
    instruction. Going through expandAddToGEP() no longer makes sense
    with opaque pointers, where generating the necessary instruction
    is trivial.

    This avoids recursive expansion of (the SCEV of) StepV while the
    IR is in an inconsistent state, in particular with an incomplete
    IV phi node, which utilities may not be prepared to deal with.

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

diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
index 58dbac0e85fb..3a28909473d9 100644
--- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
+++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
@@ -795,7 +795,8 @@ Value *SCEVExpander::expandIVInc(PHINode *PN, Value *StepV, const Loop *L,
   Value *IncV;
   // If the PHI is a pointer, use a GEP, otherwise use an add or sub.
   if (PN->getType()->isPointerTy()) {
-    IncV = expandAddToGEP(SE.getSCEV(StepV), PN);
+    // TODO: Change name to IVName.iv.next.
+    IncV = Builder.CreatePtrAdd(PN, StepV, "scevgep");
   } else {
     IncV = useSubtract ?
       Builder.CreateSub(PN, StepV, Twine(IVName) + ".iv.next") :

define void @test(ptr %p, i8 %arg, i64 %arg1, i32 %arg2) {
entry:
  %sext = sext i8 %arg to i64
  %add = add i64 %arg1, -1
  br label %loop

loop:                                             ; preds = %latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]
  %phi = phi i32 [ %arg2, %entry ], [ %add9, %latch ]
  br label %loop2

loop2:                                            ; preds = %loop2, %loop
  %iv2 = phi i64 [ %iv2.next, %loop2 ], [ 0, %loop ]
  %gep = getelementptr [4 x i8], ptr %p, i64 %iv, i64 %iv2
  store i8 0, ptr %gep, align 1
  %iv2.next = add i64 %iv2, 1
  %icmp = icmp eq i64 %iv2.next, 0
  br i1 %icmp, label %latch, label %loop2

latch:                                            ; preds = %loop2
  %add9 = add nsw i32 %phi, 1
  %sext10 = sext i32 %phi to i64
  %add11 = add i64 %add, %sext10
  %add12 = add i64 %add11, %sext
  %iv.next = add i64 %add12, %iv
  br label %loop
}

llvm crash: Assertion `Idx >= 0 && "Invalid basic block argument!"' failed.

llvm crashes in `loop-idiom` pass.

Bisected to 1c6e6432ca0b6832e06b93a4bcf22ead1899c14d, which was committed by @nikic

Compiler explorer: https://godbolt.org/z/nxhnoE1Mb

**% cat reduced.ll**
```llvm
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define void @m(i8 %0, i64 %1, i32 %a.promoted) {
entry:
  %conv13 = sext i8 %0 to i64
  %add14 = add i64 %1, -1
  br label %for.cond5thread-pre-split.lr.ph.split.us.us

for.cond5thread-pre-split.lr.ph.split.us.us:      ; preds = %for.cond2.loopexit.us.us, %entry
  %inc.i1417.us = phi i32 [ %a.promoted, %entry ], [ %inc.i.us20, %for.cond2.loopexit.us.us ]
  %add161516.us = phi i64 [ 0, %entry ], [ %add16.us24, %for.cond2.loopexit.us.us ]
  br label %for.body7.us.us

for.body7.us.us:                                  ; preds = %for.body7.us.us, %for.cond5thread-pre-split.lr.ph.split.us.us
  %2 = phi i64 [ %add9.us.us, %for.body7.us.us ], [ 0, %for.cond5thread-pre-split.lr.ph.split.us.us ]
  %arrayidx8.us.us = getelementptr [1 x [5 x i8]], ptr null, i64 0, i64 %add161516.us, i64 %2
  store i8 0, ptr %arrayidx8.us.us, align 1
  %add9.us.us = add i64 %2, 1
  %tobool6.not.us.us = icmp eq i64 %add9.us.us, 0
  br i1 %tobool6.not.us.us, label %for.cond2.loopexit.us.us, label %for.body7.us.us

for.cond2.loopexit.us.us:                         ; preds = %for.body7.us.us
  %inc.i.us20 = add nsw i32 %inc.i1417.us, 1
  %conv.i.us21 = sext i32 %inc.i1417.us to i64
  %add15.us22 = add i64 %add14, %conv.i.us21
  %sub.us23 = add i64 %add15.us22, %conv13
  %add16.us24 = add i64 %sub.us23, %add161516.us
  br label %for.cond5thread-pre-split.lr.ph.split.us.us
}
```

**% opt -disable-output -passes=loop-idiom reduced.ll**
```console
opt: /tmp/tmpxmdtc3mt/tmpn8inmjh2/llvm/include/llvm/IR/Instructions.h:2910: llvm::Value* llvm::PHINode::getIncomingValueForBlock(const llvm::BasicBlock*) const: Assertion `Idx >= 0 && "Invalid basic block argument!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/opt -disable-output -passes=loop-idiom reduced.ll
 #0 0x00007fc24b876eaf llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x914eaf)
 #1 0x00007fc24b874414 SignalHandler(int) Signals.cpp:0:0
 #2 0x00007fc24ab77090 (/lib/x86_64-linux-gnu/libc.so.6+0x43090)
 #3 0x00007fc24ab7700b raise /build/glibc-wuryBv/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
 #4 0x00007fc24ab56859 abort /build/glibc-wuryBv/glibc-2.31/stdlib/abort.c:81:7
 #5 0x00007fc24ab56729 get_sysdep_segment_value /build/glibc-wuryBv/glibc-2.31/intl/loadmsgcat.c:509:8
 #6 0x00007fc24ab56729 _nl_load_domain /build/glibc-wuryBv/glibc-2.31/intl/loadmsgcat.c:970:34
 #7 0x00007fc24ab67fd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
 #8 0x00007fc24d68155f llvm::Loop::getCanonicalInductionVariable() const (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x271f55f)
 #9 0x00007fc24ca39df5 llvm::SCEVExpander::visitAddRecExpr(llvm::SCEVAddRecExpr const*) (.part.0) ScalarEvolutionExpander.cpp:0:0
#10 0x00007fc24ca36745 llvm::SCEVVisitor<llvm::SCEVExpander, llvm::Value*>::visit(llvm::SCEV const*) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x1ad4745)
#11 0x00007fc24ca3711b llvm::SCEVExpander::expand(llvm::SCEV const*) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x1ad511b)
#12 0x00007fc24ca37380 llvm::SCEVExpander::expandCodeForImpl(llvm::SCEV const*, llvm::Type*) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x1ad5380)
#13 0x00007fc24ca399ec llvm::SCEVExpander::expandAddToGEP(llvm::SCEV const*, llvm::Type*, llvm::Value*) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x1ad79ec)
#14 0x00007fc24ca3ab97 llvm::SCEVExpander::expandIVInc(llvm::PHINode*, llvm::Value*, llvm::Loop const*, llvm::Type*, llvm::Type*, bool) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x1ad8b97)
#15 0x00007fc24ca3bb6e llvm::SCEVExpander::getAddRecExprPHILiterally(llvm::SCEVAddRecExpr const*, llvm::Loop const*, llvm::Type*, llvm::Type*, llvm::Type*&, bool&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x1ad9b6e)
#16 0x00007fc24ca3c5d4 llvm::SCEVExpander::expandAddRecExprLiterally(llvm::SCEVAddRecExpr const*) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x1ada5d4)
#17 0x00007fc24ca36745 llvm::SCEVVisitor<llvm::SCEVExpander, llvm::Value*>::visit(llvm::SCEV const*) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x1ad4745)
#18 0x00007fc24ca3711b llvm::SCEVExpander::expand(llvm::SCEV const*) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x1ad511b)
#19 0x00007fc24ca37380 llvm::SCEVExpander::expandCodeForImpl(llvm::SCEV const*, llvm::Type*) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x1ad5380)
#20 0x00007fc24ce4bc8c (anonymous namespace)::LoopIdiomRecognize::processLoopStridedStore(llvm::Value*, llvm::SCEV const*, llvm::MaybeAlign, llvm::Value*, llvm::Instruction*, llvm::SmallPtrSetImpl<llvm::Instruction*>&, llvm::SCEVAddRecExpr const*, llvm::SCEV const*, bool, bool) LoopIdiomRecognize.cpp:0:0
#21 0x00007fc24ce539b7 (anonymous namespace)::LoopIdiomRecognize::processLoopStores(llvm::SmallVectorImpl<llvm::StoreInst*>&, llvm::SCEV const*, (anonymous namespace)::LoopIdiomRecognize::ForMemset) LoopIdiomRecognize.cpp:0:0
#22 0x00007fc24ce5494c (anonymous namespace)::LoopIdiomRecognize::runOnCountableLoop() LoopIdiomRecognize.cpp:0:0
#23 0x00007fc24ce561fd llvm::LoopIdiomRecognizePass::run(llvm::Loop&, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x1ef41fd)
#24 0x00007fc24e6ee6c6 llvm::detail::PassModel<llvm::Loop, llvm::LoopIdiomRecognizePass, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>::run(llvm::Loop&, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x378c6c6)
#25 0x00007fc24ce7544f std::optional<llvm::PreservedAnalyses> llvm::PassManager<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>::runSinglePass<llvm::Loop, std::unique_ptr<llvm::detail::PassConcept<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>, std::default_delete<llvm::detail::PassConcept<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>>>>(llvm::Loop&, std::unique_ptr<llvm::detail::PassConcept<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>, std::default_delete<llvm::detail::PassConcept<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>>>&, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&, llvm::PassInstrumentation&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x1f1344f)
#26 0x00007fc24ce756f6 llvm::PassManager<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>::runWithoutLoopNestPasses(llvm::Loop&, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x1f136f6)
#27 0x00007fc24ce76b0d llvm::PassManager<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>::run(llvm::Loop&, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x1f14b0d)
#28 0x00007fc24ce77d62 llvm::FunctionToLoopPassAdaptor::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x1f15d62)
#29 0x00007fc24e6eb0c6 llvm::detail::PassModel<llvm::Function, llvm::FunctionToLoopPassAdaptor, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x37890c6)
#30 0x00007fc24ba8a40d llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0xb2840d)
#31 0x00007fc24e6e41a6 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x37821a6)
#32 0x00007fc24ba88c9d llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0xb26c9d)
#33 0x00007fc24e6eb026 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0x3789026)
#34 0x00007fc24ba86c1d llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/../lib/libLLVM-18git.so+0xb24c1d)
#35 0x000055608ac0cc95 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/opt+0x25c95)
#36 0x000055608ac00876 main (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/opt+0x19876)
#37 0x00007fc24ab58083 __libc_start_main /build/glibc-wuryBv/glibc-2.31/csu/../csu/libc-start.c:342:3
#38 0x000055608ac0151e _start (/zdata/shaoli/compilers/ccbuilder-compilers/clang-1c6e6432ca0b6832e06b93a4bcf22ead1899c14d/bin/opt+0x1a51e)
[1]    1629345 abort       -disable-output -passes=loop-idiom reduced.ll
```

The IR is reduced from the following C code:
```C
int a, b;
long d, h, j;
short e;
char f;
static char *g = &f;
static long *i = &d;
char k[1][5];
long l() {
  long c = a++;
  return c;
}
void m() {
  for (; b;)
    for (;; j = l() + *g + *i - 1 + j) {
      e = 0;
      for (; *i + e; e = 1)
        for (; h; h = h + 1)
          k[j][h] = 4;
    }
}
int main() {}
```


commit b060661da8b3b53db55644e5e358bb2dca8b56d7
Author: Florian Hahn <flo@fhahn.com>
Date:   Thu Oct 17 13:55:20 2024 -0700

    [SCEVExpander] Expand UDiv avoiding UB when in seq_min/max. (#92177)

    Update SCEVExpander to introduce an SafeUDivMode, which is set
    when expanding operands of SCEVSequentialMinMaxExpr. In this mode,
    the expander will make sure that the divisor of the expanded UDiv is
    neither 0 nor poison.

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

    PR https://github.com/llvm/llvm-project/pull/92177

diff --git a/llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h b/llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h
index 5697d983c9ad..7dd754a2bc0d 100644
--- a/llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h
+++ b/llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h
@@ -126,6 +126,11 @@ class SCEVExpander : public SCEVVisitor<SCEVExpander, Value *> {
   /// "expanded" form.
   bool LSRMode;

+  /// When true, rewrite any divisors of UDiv expressions that may be 0 to
+  /// umax(Divisor, 1) to avoid introducing UB. If the divisor may be poison,
+  /// freeze it first.
+  bool SafeUDivMode = false;
+
   typedef IRBuilder<InstSimplifyFolder, IRBuilderCallbackInserter> BuilderType;
   BuilderType Builder;

diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
index c412d0398b95..39da38e49181 100644
--- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
+++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
@@ -681,7 +681,21 @@ Value *SCEVExpander::visitUDivExpr(const SCEVUDivExpr *S) {
                          SCEV::FlagAnyWrap, /*IsSafeToHoist*/ true);
   }

-  Value *RHS = expand(S->getRHS());
+  const SCEV *RHSExpr = S->getRHS();
+  Value *RHS = expand(RHSExpr);
+  if (SafeUDivMode) {
+    bool GuaranteedNotPoison =
+        ScalarEvolution::isGuaranteedNotToBePoison(RHSExpr);
+    if (!GuaranteedNotPoison)
+      RHS = Builder.CreateFreeze(RHS);
+
+    // We need an umax if either RHSExpr is not known to be zero, or if it is
+    // not guaranteed to be non-poison. In the later case, the frozen poison may
+    // be 0.
+    if (!SE.isKnownNonZero(RHSExpr) || !GuaranteedNotPoison)
+      RHS = Builder.CreateIntrinsic(RHS->getType(), Intrinsic::umax,
+                                    {RHS, ConstantInt::get(RHS->getType(), 1)});
+  }
   return InsertBinop(Instruction::UDiv, LHS, RHS, SCEV::FlagAnyWrap,
                      /*IsSafeToHoist*/ SE.isKnownNonZero(S->getRHS()));
 }
@@ -1376,11 +1390,14 @@ Value *SCEVExpander::visitSignExtendExpr(const SCEVSignExtendExpr *S) {
 Value *SCEVExpander::expandMinMaxExpr(const SCEVNAryExpr *S,
                                       Intrinsic::ID IntrinID, Twine Name,
                                       bool IsSequential) {
+  bool PrevSafeMode = SafeUDivMode;
+  SafeUDivMode |= IsSequential;
   Value *LHS = expand(S->getOperand(S->getNumOperands() - 1));
   Type *Ty = LHS->getType();
   if (IsSequential)
     LHS = Builder.CreateFreeze(LHS);
   for (int i = S->getNumOperands() - 2; i >= 0; --i) {
+    SafeUDivMode = (IsSequential && i != 0) || PrevSafeMode;
     Value *RHS = expand(S->getOperand(i));
     if (IsSequential && i != 0)
       RHS = Builder.CreateFreeze(RHS);
@@ -1395,6 +1412,7 @@ Value *SCEVExpander::expandMinMaxExpr(const SCEVNAryExpr *S,
     }
     LHS = Sel;
   }
+  SafeUDivMode = PrevSafeMode;
   return LHS;
 }

opt -p loop-vectorize -force-vector-width=4 -S %s

miscompilation due to LoopVectorize making a function vulnerable to integer divide-by-zero

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

this function:
```llvm
define i64 @f(i64 %0) {
  br label %2

2:                                                ; preds = %5, %1
  %3 = phi i64 [ 0, %1 ], [ %6, %5 ]
  %4 = icmp slt i64 %3, %0
  br i1 %4, label %5, label %9

5:                                                ; preds = %2
  %6 = add i64 %3, 1
  %7 = udiv i64 42, %0
  %8 = icmp slt i64 %3, %7
  br i1 %8, label %2, label %9

9:                                                ; preds = %5, %2
  %10 = phi i64 [ 1, %2 ], [ 0, %5 ]
  ret i64 %10
}
```
is getting optimized to:
```lllvm
define noundef i64 @f(i64 %0) local_unnamed_addr #0 {
  %smax = tail call i64 @llvm.smax.i64(i64 %0, i64 0)
  %2 = udiv i64 42, %0
  %umin = tail call i64 @llvm.umin.i64(i64 %smax, i64 %2)
  %min.iters.check = icmp ult i64 %umin, 4
  br i1 %min.iters.check, label %scalar.ph.preheader, label %vector.ph

vector.ph:                                        ; preds = %1
  %3 = add nuw nsw i64 %umin, 1
  %n.mod.vf = and i64 %3, 3
  %4 = icmp eq i64 %n.mod.vf, 0
  %5 = select i1 %4, i64 4, i64 %n.mod.vf
  %n.vec = sub nsw i64 %3, %5
  br label %vector.body

vector.body:                                      ; preds = %vector.body, %vector.ph
  %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
  %index.next = add nuw i64 %index, 4
  %6 = icmp eq i64 %index.next, %n.vec
  br i1 %6, label %scalar.ph.preheader, label %vector.body, !llvm.loop !0

scalar.ph.preheader:                              ; preds = %vector.body, %1
  %.ph = phi i64 [ 0, %1 ], [ %n.vec, %vector.body ]
  br label %scalar.ph

scalar.ph:                                        ; preds = %scalar.ph.preheader, %9
  %7 = phi i64 [ %10, %9 ], [ %.ph, %scalar.ph.preheader ]
  %8 = icmp slt i64 %7, %0
  br i1 %8, label %9, label %13

9:                                                ; preds = %scalar.ph
  %10 = add nuw nsw i64 %7, 1
  %11 = udiv i64 42, %0
  %12 = icmp ult i64 %7, %11
  br i1 %12, label %scalar.ph, label %13, !llvm.loop !3

13:                                               ; preds = %9, %scalar.ph
  %14 = phi i64 [ 1, %scalar.ph ], [ 0, %9 ]
  ret i64 %14
}

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

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

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

!0 = distinct !{!0, !1, !2}
!1 = !{!"llvm.loop.isvectorized", i32 1}
!2 = !{!"llvm.loop.unroll.runtime.disable"}
!3 = distinct !{!3, !2, !1}
```

the problem is that the optimized code can divide by zero even when the original code doesn't. to see this, pass 0 as an argument to `f`. I also independently verified on an x64-64 that the optimized code traps out with an FPE while the original code does not. it's LoopVectorize that's the culprit.

cc @nunoplopes @hatsunespica

cc @fhahn


commit 3cb82f49dc990dc20a765856c0e126193992fe44
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Mon Jul 22 12:45:28 2024 -0700

    [SLP]Fix PR99899: Use canonical type instead of original vector of ptr.

    Use adjusted canonical integer type instead of the original ptr type to
    fix the crash in the TTI.
    Fixes https://github.com/llvm/llvm-project/issues/99899

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 667c4eb311c2..cca9eeebaa53 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -9699,7 +9699,8 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals,
           CanonicalType = CanonicalType->getWithNewType(IntegerType::get(
               CanonicalType->getContext(),
               DL->getTypeSizeInBits(CanonicalType->getScalarType())));
-        IntrinsicCostAttributes CostAttrs(MinMaxID, VecTy, {VecTy, VecTy});
+        IntrinsicCostAttributes CostAttrs(MinMaxID, CanonicalType,
+                                          {CanonicalType, CanonicalType});
         InstructionCost IntrinsicCost =
             TTI->getIntrinsicInstrCost(CostAttrs, CostKind);
         // If the selects are the only uses of the compares, they will be

opt -S --passes=slp-vectorizer -mtriple=s390x-unknown-linux-gnu -mcpu=z16 -slp-threshold=-10 < %s

define i1 @test(i64 %0, i64 %1, ptr %2) {
;
entry:
  %gep44 = getelementptr i8, ptr null, i64 %0
  %gep45 = getelementptr i8, ptr null, i64 %1
  %4 = icmp ult ptr %gep44, %gep45
  %umin = select i1 %4, ptr %gep44, ptr %gep45
  %gep48 = getelementptr i8, ptr null, i64 %0
  %gep49 = getelementptr i8, ptr null, i64 %1
  %5 = icmp ult ptr %gep48, %gep49
  %umin50 = select i1 %5, ptr %gep48, ptr %gep49
  %b095 = icmp ult ptr %umin, %2
  %b196 = icmp ult ptr %umin50, %2
  %res = and i1 %b095, %b196
  ret i1 %res
}

[SLP] crash after 8ff233f

8ff233f "[SLP]Correctly detect minnum/maxnum patterns for select/cmp operations on floats." seems to have introduced a problem when building SPEC on SystemZ.

opt  -mtriple=s390x-linux-gnu -mcpu=z16 -O3 ./tc_slp.ll -o /dev/null
opt: /home/ijonpan/llvm-project/llvm/include/llvm/IR/DerivedTypes.h:704: llvm::Type* llvm::Type::getWithNewBitWidth(unsigned int) const: Assertion `isIntOrIntVectorTy() && "Original type expected to be a vector of integers or a scalar integer."' failed.
...
#15 0x000000000519c8f8 llvm::slpvectorizer::BoUpSLP::getEntryCost

[tc_slp.ll.tar.gz](https://github.com/user-attachments/files/16337301/tc_slp.ll.tar.gz)


commit d145f40963f15e94c4aefcc406a365fbe779e934
Author: David Green <david.green@arm.com>
Date:   Sun May 5 10:47:11 2024 +0100

    [VectorCombine] shuffleToIdentity - guard against call instructions.

    The shuffleToIdentity fold needs to be a bit more careful about the difference
    between call instructions and intrinsics. The second can be handled, but the
    first should result in bailing out. This patch also adds some extra intrinsic
    tests from #91000.

    Fixes #91078

diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index 04d2ff594bf5..bbb70134870a 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -1755,10 +1755,13 @@ bool VectorCombine::foldShuffleToIdentity(Instruction &I) {
             return false;
           if (IL.first->getValueID() != Item[0].first->getValueID())
             return false;
+          if (isa<CallInst>(IL.first) && !isa<IntrinsicInst>(IL.first))
+            return false;
           auto *II = dyn_cast<IntrinsicInst>(IL.first);
           return !II ||
-                 II->getIntrinsicID() ==
-                     cast<IntrinsicInst>(Item[0].first)->getIntrinsicID();
+                 (isa<IntrinsicInst>(Item[0].first) &&
+                  II->getIntrinsicID() ==
+                      cast<IntrinsicInst>(Item[0].first)->getIntrinsicID());
         }))
       return false;

target triple = "aarch64"

define <8 x half> @callinst(<8 x half> %a) {
  %ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = call <4 x half> @othercall(<4 x half> %at)
  %abb = call <4 x half> @llvm.fabs.v4f16(<4 x half> %ab)
  %r = shufflevector <4 x half> %abt, <4 x half> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x half> %r
}

declare <4 x half> @othercall(<4 x half>)

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x half> @llvm.fabs.v4f16(<4 x half>) #0

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

target triple = "aarch64"

define <8 x half> @callinst2(<8 x half> %a) {
  %ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = call <4 x half> @llvm.fabs.v4f16(<4 x half> %at)
  %abb = call <4 x half> @othercall(<4 x half> %ab)
  %r = shufflevector <4 x half> %abt, <4 x half> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x half> %r
}

declare <4 x half> @othercall(<4 x half>)

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x half> @llvm.fabs.v4f16(<4 x half>) #0

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

target triple = "aarch64"

define <8 x i32> @lrint(<8 x half> %a) {
  %ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = call <4 x i32> @llvm.lrint.v4i32.v4f16(<4 x half> %at)
  %abb = call <4 x i32> @llvm.lrint.v4i32.v4f16(<4 x half> %ab)
  %r = shufflevector <4 x i32> %abt, <4 x i32> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x i32> %r
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x i32> @llvm.lrint.v4i32.v4f16(<4 x half>) #0

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

target triple = "aarch64"

define <8 x i8> @abs_different(<8 x i8> %a) {
  %ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = call <4 x i8> @llvm.abs.v4i8(<4 x i8> %at, i1 true)
  %abb = call <4 x i8> @llvm.abs.v4i8(<4 x i8> %ab, i1 false)
  %r = shufflevector <4 x i8> %abt, <4 x i8> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x i8> %r
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x i8> @llvm.abs.v4i8(<4 x i8>, i1 immarg) #0

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

target triple = "aarch64"

define <8 x half> @powi(<8 x half> %a) {
  %ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = call <4 x half> @llvm.powi.v4f16.i32(<4 x half> %at, i32 10)
  %abb = call <4 x half> @llvm.powi.v4f16.i32(<4 x half> %ab, i32 10)
  %r = shufflevector <4 x half> %abt, <4 x half> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x half> %r
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x half> @llvm.powi.v4f16.i32(<4 x half>, i32) #0

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

target triple = "aarch64"

define <8 x i8> @abs(<8 x i8> %a) {
  %ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = call <4 x i8> @llvm.abs.v4i8(<4 x i8> %at, i1 false)
  %abb = call <4 x i8> @llvm.abs.v4i8(<4 x i8> %ab, i1 false)
  %r = shufflevector <4 x i8> %abt, <4 x i8> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x i8> %r
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x i8> @llvm.abs.v4i8(<4 x i8>, i1 immarg) #0

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

A/F: isa<To>(Val) && "cast<Ty>() argument of incompatible type!" after commit a4d1026

A few of our internal tests started hitting an assertion failure which I bisected back to commit a4d10266d20bfe5930dfed77e17832af341ed66e.

Consider the following code:
```c++
template <typename a> a b(a);
typedef float c __attribute__((__vector_size__(32)));
typedef float __attribute__((ext_vector_type(8))) d;
typedef float __attribute__((ext_vector_type(4))) e;
c f;
#define g(h) (b(h))
d i;
void j() {
  c k = __builtin_ia32_rsqrtps256(f);
  d l(k);
  d m g(i);
  volatile e n = __builtin_shufflevector(l, m, 15, 2, 0, 1);
}
```
When compiled with optimizations and `-mavx` it hits an assertion failure:
```
$ ~/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang -c -O2 -mavx repro2.cpp
clang: /home/dyung/src/upstream/llvm_clean_git/llvm/include/llvm/Support/Casting.h:578: decltype(auto) llvm::cast(From*) [with To = llvm::IntrinsicInst; From = llvm::Value]: Assertion `isa<To>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.      Program arguments: /home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang -c -O2 -mavx repro2.cpp
1.      <eof> parser at end of file
2.      Optimizer
 #0 0x0000557d533cfe2f llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x4055e2f)
 #1 0x0000557d533cd96c llvm::sys::CleanupOnSignal(unsigned long) (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x405396c)
 #2 0x0000557d5331a4e8 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x00007f0ccbb8b420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #4 0x00007f0ccb65800b raise /build/glibc-e2p3jK/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
 #5 0x00007f0ccb637859 abort /build/glibc-e2p3jK/glibc-2.31/stdlib/abort.c:81:7
 #6 0x00007f0ccb637729 get_sysdep_segment_value /build/glibc-e2p3jK/glibc-2.31/intl/loadmsgcat.c:509:8
 #7 0x00007f0ccb637729 _nl_load_domain /build/glibc-e2p3jK/glibc-2.31/intl/loadmsgcat.c:970:34
 #8 0x00007f0ccb648fd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
 #9 0x0000557d54cd0f88 (anonymous namespace)::VectorCombine::foldShuffleToIdentity(llvm::Instruction&)::'lambda3'(std::pair<llvm::Value*, int>)::operator()(std::pair<llvm::Value*, int>) const (.isra.0) VectorCombine.cpp:0:0
#10 0x0000557d54cdac11 (anonymous namespace)::VectorCombine::foldShuffleToIdentity(llvm::Instruction&) VectorCombine.cpp:0:0
#11 0x0000557d54ce56f1 (anonymous namespace)::VectorCombine::run()::'lambda'(llvm::Instruction&)::operator()(llvm::Instruction&) const (.isra.0) VectorCombine.cpp:0:0
#12 0x0000557d54ce695d llvm::VectorCombinePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x596c95d)
#13 0x0000557d547ca386 llvm::detail::PassModel<llvm::Function, llvm::VectorCombinePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x5450386)
#14 0x0000557d50a03b4c 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/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x1689b4c)
#15 0x0000557d52d96d0d llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x3a1cd0d)
#16 0x0000557d509e66d6 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x166c6d6)
#17 0x0000557d52d94b9d llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x3a1ab9d)
#18 0x0000557d5366aa28 (anonymous namespace)::EmitAssemblyHelper::RunOptimizationPipeline(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>&, std::unique_ptr<llvm::ToolOutputFile, std::default_delete<llvm::ToolOutputFile>>&, clang::BackendConsumer*) BackendUtil.cpp:0:0
#19 0x0000557d5366dd85 (anonymous namespace)::EmitAssemblyHelper::EmitAssembly(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) BackendUtil.cpp:0:0
#20 0x0000557d5366e449 clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x42f4449)
#21 0x0000557d53cc97ca clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x494f7ca)
#22 0x0000557d55a3f65c clang::ParseAST(clang::Sema&, bool, bool) (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x66c565c)
#23 0x0000557d53cc8278 clang::CodeGenAction::ExecuteAction() (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x494e278)
#24 0x0000557d53f56729 clang::FrontendAction::Execute() (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x4bdc729)
#25 0x0000557d53edc48e clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x4b6248e)
#26 0x0000557d54040e86 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x4cc6e86)
#27 0x0000557d505e1bbc cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x1267bbc)
#28 0x0000557d505dacca ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#29 0x0000557d53d0d8ed void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#30 0x0000557d5331a9f0 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x3fa09f0)
#31 0x0000557d53d0df0f clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0
#32 0x0000557d53cd2a4c clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x4958a4c)
#33 0x0000557d53cd34dd clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x49594dd)
#34 0x0000557d53cdb8f5 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x49618f5)
#35 0x0000557d505defab clang_main(int, char**, llvm::ToolContext const&) (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x1264fab)
#36 0x0000557d504db96b main (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x116196b)
#37 0x00007f0ccb639083 __libc_start_main /build/glibc-e2p3jK/glibc-2.31/csu/../csu/libc-start.c:342:3
#38 0x0000557d505da79e _start (/home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin/clang+0x126079e)
clang: error: clang frontend command failed with exit code 134 (use -v to see invocation)
clang version 19.0.0 (https://github.com/llvm/llvm-project.git a4d10266d20bfe5930dfed77e17832af341ed66e)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/dyung/src/upstream/a4d10266d20bfe5930dfed77e17832af341ed66e-linux/bin
Build config: +assertions
```


commit eb8f379567e8d014194faefe02ce92813e237afc
Author: Florian Hahn <flo@fhahn.com>
Date:   Wed Mar 6 20:08:00 2024 +0000

    [DSE] Remove malloc from EarliestEscapeInfo before removing. (#84157)

    Not removing the malloc from earliest escape info leaves stale entries
    in the cache.

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

    PR: https://github.com/llvm/llvm-project/pull/84157

diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
index 3d1dac5ea17e..392e6ad5a66b 100644
--- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -1908,15 +1908,15 @@ struct DSEState {
                               Malloc->getArgOperand(0), IRB, TLI);
     if (!Calloc)
       return false;
+
     MemorySSAUpdater Updater(&MSSA);
     auto *NewAccess =
       Updater.createMemoryAccessAfter(cast<Instruction>(Calloc), nullptr,
                                       MallocDef);
     auto *NewAccessMD = cast<MemoryDef>(NewAccess);
     Updater.insertDef(NewAccessMD, /*RenameUses=*/true);
-    Updater.removeMemoryAccess(Malloc);
     Malloc->replaceAllUsesWith(Calloc);
-    Malloc->eraseFromParent();
+    deleteDeadInstruction(Malloc);
     return true;
   }

target datalayout = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"

define void @widget(ptr %a) {
bb:
  %call = tail call ptr @malloc(i64 1)
  tail call void @llvm.memset.p0.i64(ptr %call, i8 0, i64 1, i1 false)
  %call1 = tail call noalias ptr @malloc(i64 0)
  store ptr %call1, ptr %a, align 8
  %load = load ptr, ptr %a, align 8
  %load2 = load i32, ptr %load, align 8
  %getelementptr = getelementptr i8, ptr %call1, i64 0
  %getelementptr3 = getelementptr i8, ptr %getelementptr, i64 1
  store i8 0, ptr %call1, align 1
  %getelementptr4 = getelementptr i8, ptr %getelementptr, i64 8
  store i16 0, ptr %getelementptr4, align 4
  %getelementptr5 = getelementptr i8, ptr %getelementptr, i64 12
  store i32 0, ptr %call1, align 4
  %load6 = load i32, ptr inttoptr (i64 4 to ptr), align 4
  br label %bb48

bb7:                                              ; No predecessors!
  br label %bb9

bb8:                                              ; No predecessors!
  br label %bb53

bb9:                                              ; preds = %bb43, %bb7
  %phi = phi ptr [ %call1, %bb7 ], [ %a, %bb43 ]
  %getelementptr10 = getelementptr i8, ptr %phi, i64 0
  %getelementptr11 = getelementptr i8, ptr %phi, i64 0
  %getelementptr12 = getelementptr i8, ptr %phi, i64 0
  %getelementptr13 = getelementptr i8, ptr %getelementptr12, i64 1
  store i8 0, ptr %call1, align 1
  br label %bb29

bb14:                                             ; No predecessors!
  %getelementptr15 = getelementptr i8, ptr %getelementptr10, i64 8
  %load16 = load i16, ptr %call1, align 4
  br i1 false, label %bb22, label %bb17

bb17:                                             ; preds = %bb14
  %getelementptr18 = getelementptr i8, ptr %getelementptr11, i64 8
  %load19 = load i16, ptr %call1, align 4
  %getelementptr20 = getelementptr i8, ptr %getelementptr12, i64 8
  store i16 0, ptr %call1, align 4
  %getelementptr21 = getelementptr i8, ptr %phi, i64 0
  br label %bb25

bb22:                                             ; preds = %bb14
  %getelementptr23 = getelementptr i8, ptr %phi, i64 0
  %getelementptr24 = getelementptr i8, ptr %getelementptr23, i64 12
  br label %bb25

bb25:                                             ; preds = %bb22, %bb17
  %phi26 = phi ptr [ %a, %bb17 ], [ %call1, %bb22 ]
  %phi27 = phi ptr [ %call1, %bb17 ], [ %call1, %bb22 ]
  %phi28 = phi ptr [ %call1, %bb17 ], [ %call1, %bb22 ]
  store i32 0, ptr %call1, align 4
  br label %bb29

bb29:                                             ; preds = %bb25, %bb9
  %phi30 = phi ptr [ %call1, %bb9 ], [ %call1, %bb25 ]
  %phi31 = phi ptr [ %call1, %bb9 ], [ %call1, %bb25 ]
  %load32 = load i8, ptr %call1, align 4
  %load33 = load i8, ptr %call1, align 4
  %getelementptr34 = getelementptr i8, ptr %phi31, i64 12
  %getelementptr35 = getelementptr i8, ptr %getelementptr12, i64 12
  br label %bb86

bb36:                                             ; No predecessors!
  %getelementptr37 = getelementptr i8, ptr %phi30, i64 12
  br label %bb38

bb38:                                             ; preds = %bb38, %bb36
  %getelementptr39 = getelementptr [0 x i32], ptr %getelementptr34, i64 0, i64 0
  %load40 = load i32, ptr %call1, align 4
  %getelementptr41 = getelementptr [0 x i32], ptr %getelementptr37, i64 0, i64 0
  %load42 = load i32, ptr %call1, align 4
  br label %bb38

bb43:                                             ; No predecessors!
  %getelementptr44 = getelementptr i8, ptr %getelementptr12, i64 8
  %load45 = load i16, ptr %call1, align 4
  store i16 0, ptr %call1, align 4
  store i8 0, ptr %call1, align 4
  %getelementptr46 = getelementptr i8, ptr %getelementptr12, i64 12
  store i32 0, ptr %call1, align 4
  %getelementptr47 = getelementptr i8, ptr %getelementptr12, i64 16
  store i32 0, ptr %call1, align 4
  br label %bb9

bb48:                                             ; preds = %bb48, %bb
  %getelementptr49 = getelementptr i8, ptr %call1, i64 0
  %getelementptr50 = getelementptr i8, ptr %getelementptr49, i64 1
  store i8 0, ptr %call1, align 1
  %getelementptr51 = getelementptr i8, ptr %getelementptr49, i64 8
  store i16 0, ptr %call1, align 4
  %getelementptr52 = getelementptr i8, ptr %getelementptr49, i64 12
  store i32 0, ptr %call1, align 4
  br label %bb48

bb53:                                             ; preds = %bb71, %bb8
  %phi54 = phi ptr [ %call1, %bb8 ], [ %a, %bb71 ]
  %getelementptr55 = getelementptr i8, ptr %phi54, i64 0
  %getelementptr56 = getelementptr i8, ptr %phi54, i64 0
  %getelementptr57 = getelementptr i8, ptr %phi54, i64 0
  %getelementptr58 = getelementptr i8, ptr %getelementptr57, i64 1
  br label %bb71

bb59:                                             ; No predecessors!
  %getelementptr60 = getelementptr i8, ptr %phi54, i64 0
  %getelementptr61 = getelementptr i8, ptr %getelementptr60, i64 12
  br label %bb67

bb62:                                             ; No predecessors!
  %getelementptr63 = getelementptr i8, ptr %getelementptr56, i64 8
  %load64 = load i16, ptr %call1, align 4
  %getelementptr65 = getelementptr i8, ptr %getelementptr57, i64 8
  store i16 0, ptr %call1, align 4
  %getelementptr66 = getelementptr i8, ptr %phi54, i64 0
  br label %bb67

bb67:                                             ; preds = %bb62, %bb59
  %phi68 = phi ptr [ %a, %bb62 ], [ %call1, %bb59 ]
  %phi69 = phi ptr [ %call1, %bb62 ], [ %call1, %bb59 ]
  %phi70 = phi ptr [ %call1, %bb62 ], [ %call1, %bb59 ]
  store i32 0, ptr %call1, align 4
  br label %bb71

bb71:                                             ; preds = %bb67, %bb53
  %phi72 = phi ptr [ %call1, %bb53 ], [ %call1, %bb67 ]
  %phi73 = phi ptr [ %call1, %bb53 ], [ %call1, %bb67 ]
  %load74 = load i8, ptr %call1, align 4
  %load75 = load i8, ptr %call1, align 4
  %getelementptr76 = getelementptr i8, ptr %phi72, i64 12
  %getelementptr77 = getelementptr i8, ptr %getelementptr57, i64 12
  %getelementptr78 = getelementptr [0 x i32], ptr %getelementptr76, i64 0, i64 0
  %load79 = load i32, ptr %call1, align 4
  %getelementptr80 = getelementptr [0 x i32], ptr %getelementptr77, i64 0, i64 0
  store i32 0, ptr %call1, align 4
  %load81 = load i8, ptr %call1, align 4
  %getelementptr82 = getelementptr i8, ptr %getelementptr57, i64 8
  %load83 = load i16, ptr %call1, align 4
  store i16 0, ptr %call1, align 4
  store i8 0, ptr %call1, align 4
  %getelementptr84 = getelementptr i8, ptr %getelementptr57, i64 12
  store i32 0, ptr %call1, align 4
  %getelementptr85 = getelementptr i8, ptr %getelementptr57, i64 16
  store i32 0, ptr %call1, align 4
  br label %bb53

bb86:                                             ; preds = %bb86, %bb29
  %getelementptr87 = getelementptr [0 x i32], ptr %getelementptr34, i64 0, i64 0
  %load88 = load i32, ptr %call1, align 4
  %getelementptr89 = getelementptr [0 x i32], ptr %getelementptr35, i64 0, i64 0
  store i32 0, ptr %call1, align 4
  br label %bb86
}

declare ptr @malloc(i64)

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }

[DSE] crash

Reduced test case:
[tc_dse.tar.gz](https://github.com/llvm/llvm-project/files/14499403/tc_dse.tar.gz)

opt -mtriple=s390x-unknown-linux -mcpu=z16 -O3 -S ./tc_dse.ll

#6 0x0000000005287456 llvm::BasicAAResult::aliasCheck
#11 0x00000000048f0646 (anonymous namespace)::DSEState::isReadClobber
14 0x00000000049004d8 llvm::DSEPass::run
Segmentation fault (core dumped)

This is reported by user on F37 with clang-15, and is still failing on trunk.

@fhahn @BK1603 @nikic

llvm-reduce result for `-passes=dse`: https://gist.github.com/nikic/d52c888425c5d4ff3fbd37b4f84778b6

valgrind reports a use-after-free. Probably not invalidating EII correctly somewhere.

Also reproduces with ASAn, looking now