Bug type: crash
Component: ScalarEvolution
Bug location: llvm/lib/Analysis/ScalarEvolution.cpp: ScalarEvolution::LoopGuards::collectFromBlock
Issue title: [SCEV] Segfault in SCEV LoopGuards
Labels: llvm:SCEV
crash-on-valid
Reported by: danilaml

For the following IR:
```llvm
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2"
target triple = "x86_64-unknown-linux-gnu"

define void @foo() {
.split.us120:
  br label %.split.us120.split.split.us.split.split.us.split.split.us.split

.split.us120.split.split.us.split.split.us.split.split.us.split: ; preds = %.noexc7.us.us.us.us.us, %.split.us120
  br label %.noexc7.us.us.us.us.us

.lr.ph.us.us.us.us407:                            ; No predecessors!
  switch i32 0, label %.split142.us.split.us.split.us [
    i32 0, label %.split160.us.split.us.split.us
    i32 1, label %.noexc7.us.us.us.us.us
  ]

.noexc7.us.us.us.us.us:                           ; preds = %.noexc7.us.us.us.us.us, %.lr.ph.us.us.us.us407, %.split.us120.split.split.us.split.split.us.split.split.us.split
  %0 = phi i32 [ %1, %.noexc7.us.us.us.us.us ], [ 0, %.lr.ph.us.us.us.us407 ], [ 0, %.split.us120.split.split.us.split.split.us.split.split.us.split ]
  %1 = add i32 %0, 1
  %.not.i3.us.us.us.us384.us = icmp slt i32 %0, 0
  br i1 %.not.i3.us.us.us.us384.us, label %.noexc7.us.us.us.us.us, label %.split.us120.split.split.us.split.split.us.split.split.us.split

.split142.us.split.us.split.us:                   ; preds = %.lr.ph.us.us.us.us407
  ret void

.split160.us.split.us.split.us:                   ; preds = %.lr.ph.us.us.us.us407
  ret void
}
```
`opt` crashes when run using `-passes=nary-reassociate --scalar-evolution-use-expensive-range-sharpening`

godbolt: https://godbolt.org/z/xPv4TMMo8

Backtrace (truncated due to length limits):
```
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=nary-reassociate --scalar-evolution-use-expensive-range-sharpening <source>
1.	Running pass "function(nary-reassociate)" on module "<source>"
2.	Running pass "nary-reassociate" on function "foo"
  #0 0x0000000005257198 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5257198)
  #1 0x0000000005254b9c SignalHandler(int) Signals.cpp:0:0
  #2 0x00007f9ab9c42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
  #3 0x00000000051640cb llvm::hash_value(llvm::APInt const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x51640cb)
  #4 0x00000000051641a9 llvm::DenseMapInfo<llvm::APInt, void>::getHashValue(llvm::APInt const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x51641a9)
  #5 0x0000000004ed726b bool llvm::DenseMapBase<llvm::DenseMap<llvm::APInt, std::unique_ptr<llvm::ConstantInt, std::default_delete<llvm::ConstantInt>>, llvm::DenseMapInfo<llvm::APInt, void>, llvm::detail::DenseMapPair<llvm::APInt, std::unique_ptr<llvm::ConstantInt, std::default_delete<llvm::ConstantInt>>>>, llvm::APInt, std::unique_ptr<llvm::ConstantInt, std::default_delete<llvm::ConstantInt>>, llvm::DenseMapInfo<llvm::APInt, void>, llvm::detail::DenseMapPair<llvm::APInt, std::unique_ptr<llvm::ConstantInt, std::default_delete<llvm::ConstantInt>>>>::LookupBucketFor<llvm::APInt>(llvm::APInt const&, llvm::detail::DenseMapPair<llvm::APInt, std::unique_ptr<llvm::ConstantInt, std::default_delete<llvm::ConstantInt>>>*&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4ed726b)
  #6 0x0000000004edb996 llvm::ConstantInt::get(llvm::LLVMContext&, llvm::APInt const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4edb996)
  #7 0x0000000004eeba30 llvm::ConstantInt::get(llvm::Type*, llvm::APInt const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4eeba30)
  #8 0x0000000004eb6172 llvm::ConstantFoldBinaryInstruction(unsigned int, llvm::Constant*, llvm::Constant*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4eb6172)
  #9 0x0000000004ee9f2e llvm::ConstantExpr::get(unsigned int, llvm::Constant*, llvm::Constant*, unsigned int, llvm::Type*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4ee9f2e)
 #10 0x00000000049427fb llvm::ScalarEvolution::getNegativeSCEV(llvm::SCEV const*, llvm::SCEV::NoWrapFlags) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x49427fb)
 #11 0x00000000049429c4 llvm::ScalarEvolution::getMinusSCEV(llvm::SCEV const*, llvm::SCEV const*, llvm::SCEV::NoWrapFlags, unsigned int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x49429c4)
 #12 0x0000000004950e7a llvm::ScalarEvolution::LoopGuards::collectFromBlock(llvm::ScalarEvolution&, llvm::ScalarEvolution::LoopGuards&, llvm::BasicBlock const*, llvm::BasicBlock const*, llvm::SmallPtrSetImpl<llvm::BasicBlock const*>&, unsigned int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4950e7a)
 #13 0x00000000049524c2 llvm::ScalarEvolution::LoopGuards::collectFromPHI(llvm::ScalarEvolution&, llvm::ScalarEvolution::LoopGuards&, llvm::PHINode const&, llvm::SmallPtrSetImpl<llvm::BasicBlock const*>&, llvm::SmallDenseMap<llvm::BasicBlock const*, llvm::ScalarEvolution::LoopGuards, 4u, llvm::DenseMapInfo<llvm::BasicBlock const*, void>, llvm::detail::DenseMapPair<llvm::BasicBlock const*, llvm::ScalarEvolution::LoopGuards>>&, unsigned int)::'lambda'(unsigned int)::operator()(unsigned int) const ScalarEvolution.cpp:0:0
 #14 0x0000000004952702 llvm::ScalarEvolution::LoopGuards::collectFromPHI(llvm::ScalarEvolution&, llvm::ScalarEvolution::LoopGuards&, llvm::PHINode const&, llvm::SmallPtrSetImpl<llvm::BasicBlock const*>&, llvm::SmallDenseMap<llvm::BasicBlock const*, llvm::ScalarEvolution::LoopGuards, 4u, llvm::DenseMapInfo<llvm::BasicBlock const*, void>, llvm::detail::DenseMapPair<llvm::BasicBlock const*, llvm::ScalarEvolution::LoopGuards>>&, unsigned int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4952702)
 #15 0x0000000004951839 llvm::ScalarEvolution::LoopGuards::collectFromBlock(llvm::ScalarEvolution&, llvm::ScalarEvolution::LoopGuards&, llvm::BasicBlock const*, llvm::BasicBlock const*, llvm::SmallPtrSetImpl<llvm::BasicBlock const*>&, unsigned int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4951839)
 #16 0x0000000004952c7d llvm::ScalarEvolution::applyLoopGuards(llvm::SCEV const*, llvm::Loop const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4952c7d)
 #17 0x0000000004952fb0 llvm::ScalarEvolution::getRangeForAffineNoSelfWrappingAR(llvm::SCEVAddRecExpr const*, llvm::SCEV const*, unsigned int, llvm::ScalarEvolution::RangeSignHint) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4952fb0)
 #18 0x000000000492888d llvm::ScalarEvolution::getRangeRef(llvm::SCEV const*, llvm::ScalarEvolution::RangeSignHint, unsigned int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x492888d)
 #19 0x0000000004942b52 llvm::ScalarEvolution::isKnownPredicateViaConstantRanges(llvm::CmpInst::Predicate, llvm::SCEV const*, llvm::SCEV const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4942b52)
 #20 0x0000000004942e18 llvm::ScalarEvolution::isKnownViaNonRecursiveReasoning(llvm::CmpInst::Predicate, llvm::SCEV const*, llvm::SCEV const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4942e18)
 #21 0x0000000004943799 llvm::ScalarEvolution::getMinMaxExpr(llvm::SCEVTypes, llvm::SmallVectorImpl<llvm::SCEV const*>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4943799)
 #22 0x0000000004943f1a llvm::ScalarEvolution::getSMinExpr(llvm::SCEV const*, llvm::SCEV const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4943f1a)
 #23 0x0000000004951128 llvm::ScalarEvolution::LoopGuards::collectFromBlock(llvm::ScalarEvolution&, llvm::ScalarEvolution::LoopGuards&, llvm::BasicBlock const*, llvm::BasicBlock const*, llvm::SmallPtrSetImpl<llvm::BasicBlock const*>&, unsigned int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4951128)
...
#255 0x00000000049524c2 llvm::ScalarEvolution::LoopGuards::collectFromPHI(llvm::ScalarEvolution&, llvm::ScalarEvolution::LoopGuards&, llvm::PHINode const&, llvm::SmallPtrSetImpl<llvm::BasicBlock const*>&, llvm::SmallDenseMap<llvm::BasicBlock const*, llvm::ScalarEvolution::LoopGuards, 4u, llvm::DenseMapInfo<llvm::BasicBlock const*, void>, llvm::detail::DenseMapPair<llvm::BasicBlock const*, llvm::ScalarEvolution::LoopGuards>>&, unsigned int)::'lambda'(unsigned int)::operator()(unsigned int) const ScalarEvolution.cpp:0:0
Program terminated with signal: SIGSEGV
Compiler returned: 139
```

Stack exhaustion via some recursion error maybe?

Comments: author: danilaml
body: @juliannagele possibly due to https://github.com/llvm/llvm-project/pull/113915 (from backtrace)
author: fhahn
body: Likely the same as https://github.com/llvm/llvm-project/issues/120237
author: juliannagele
body: Related, but slightly different, should be fixed here https://github.com/llvm/llvm-project/pull/120749.

Fix patch:
commit f035351af785b7349ab7bcd55149c781ceca24cb
Author: Julian Nagele <j.nagele@apple.com>
Date:   Tue Dec 31 10:24:48 2024 +0100

    [SCEV] Make sure starting block is marked as visited when recursively collecting loop guards. (#120749)
    
    When `collectFromBlock` is called without a predecessor (in particular
    for loops that don't have a unique predecessor outside the loop) we
    never start climbing the predecessor chain, and thus don't mark the
    starting block as visited.
    
    Fixes https://github.com/llvm/llvm-project/issues/120615.

diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 8ab56025546e..b5668a14a4a2 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -15765,6 +15765,7 @@ void ScalarEvolution::LoopGuards::collectFromBlock(
   // original header.
   // TODO: share this logic with isLoopEntryGuardedByCond.
   unsigned NumCollectedConditions = 0;
+  VisitedBlocks.insert(Block);
   std::pair<const BasicBlock *, const BasicBlock *> Pair(Pred, Block);
   for (; Pair.first;
        Pair = SE.getPredecessorWithUniqueSuccessorForBB(Pair.first)) {


Regression tests:
file: llvm/test/Analysis/ScalarEvolution/backedge-taken-count-guard-info-with-multiple-predecessors.ll
commands: opt < %s -disable-output -passes=nary-reassociate --scalar-evolution-use-expensive-range-sharpening 2>&1
tests: test_name: pr120615
test_body: define void @pr120615() {
entry:
  br label %header

bb:                                               ; No predecessors!
  br label %header

header:                                           ; preds = %header, %bb, %entry
  %0 = phi i32 [ %1, %header ], [ 0, %bb ], [ 0, %entry ]
  %1 = add i32 %0, 1
  %icmp = icmp slt i32 %0, 0
  br i1 %icmp, label %header, label %exit

exit:                                             ; preds = %header
  ret void
}