Bug type: crash
Component: SimplifyIndVar
Bug location: llvm/lib/Transforms/Utils/SimplifyIndVar.cpp: WidenIV::widenIVUse
Issue title: [clang] Crash with O2 optimization flag
Labels: regression
release:backport
confirmed
crash
llvm:transforms
Reported by: cardigan1008

I compiled this code with -O2 flag and it crashed. The code is:

```c
#include <stdint.h>
long a, c;
unsigned d;
int32_t g;
uint8_t h[];
long b(long p1, long k) {
  long e = k;
  int b = 0;
  while (e) {
    e /= 10;
    b++;
  }
  for (int f = 0; f < b; f++)
    p1 *= 10;
  a = p1 + k;
  return a;
}
long i(int p1, int, int l) {
  int j = l / p1;
  for (int f = 0; f < p1; f++) {
    if (d > l)
      break;
    c = d += j;
  }
}
uint32_t m() {
  for (g = 8; b(35, 46) - 3546 + g >= 0; g--)
    ;
  h[i(g + 1, 0, -4294967221)];
}
```

The crash is: clang: /root/llvm-project/llvm/include/llvm/Support/Casting.h:662: decltype(auto) llvm::dyn_cast(From*) [with To = llvm::BinaryOperator; From = llvm::Instruction]: Assertion `detail::isPresent(Val) && "dyn_cast on a non-existent value"' failed.


The details can be found here: https://godbolt.org/z/37WsGxMcv

Comments: author: shafik
body: Looks like a regression, does not crash in clang-18: https://godbolt.org/z/1zYqs3sbz
author: dtcxzyw
body: Reproducer: https://godbolt.org/z/bbdhPxx5E

```
; bin/opt -passes=indvars reduced.ll -S
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"

define i32 @m() {
entry:
  %div.i4 = sdiv i32 1, 0
  br label %for.body.i6

for.body.i6:                                      ; preds = %if.end.i, %entry
  %add57.i = phi i32 [ %add.i7, %if.end.i ], [ 0, %entry ]
  br i1 true, label %i.exit, label %if.end.i

if.end.i:                                         ; preds = %for.body.i6
  %add.i7 = add i32 %add57.i, %div.i4
  %conv.i = zext i32 %add57.i to i64
  store i64 %conv.i, ptr null, align 8
  br label %for.body.i6

i.exit:                                           ; preds = %for.body.i6
  ret i32 0
}
```
cc @nikic
author: DimitryAndric
body: This regressed with `llvmorg-19-init-02822-g`4db93e5d564 ("[IndVars] Recompute flags if needed in widenIVUse of IV increment. (#82352)") by @fhahn.

Fix patch:
commit c9a5e1b665dbba898e9981fd7d48881947e6560e
Author: Nikita Popov <npopov@redhat.com>
Date:   Wed Aug 28 12:54:14 2024 +0200

    [IndVars] Check if WideInc available before trying to use it
    
    WideInc/WideIncExpr can be null. Previously this worked out
    because the comparison with WideIncExpr would fail. Now we have
    accesses to WideInc prior to that. Avoid the issue with an
    explicit check.
    
    Fixes https://github.com/llvm/llvm-project/issues/106239.

diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
index 8e3a14bb4f6d..a950a4f57ef4 100644
--- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -1928,18 +1928,24 @@ Instruction *WidenIV::widenIVUse(WidenIV::NarrowIVDefUse DU,
     if (!WideAddRec.first)
       return nullptr;
 
-    // Reuse the IV increment that SCEVExpander created. Recompute flags, unless
-    // the flags for both increments agree and it is safe to use the ones from
-    // the original inc. In that case, the new use of the wide increment won't
-    // be more poisonous.
-    bool NeedToRecomputeFlags =
-        !SCEVExpander::canReuseFlagsFromOriginalIVInc(OrigPhi, WidePhi,
-                                                      DU.NarrowUse, WideInc) ||
-        DU.NarrowUse->hasNoUnsignedWrap() != WideInc->hasNoUnsignedWrap() ||
-        DU.NarrowUse->hasNoSignedWrap() != WideInc->hasNoSignedWrap();
+    auto CanUseWideInc = [&]() {
+      if (!WideInc)
+        return false;
+      // Reuse the IV increment that SCEVExpander created. Recompute flags,
+      // unless the flags for both increments agree and it is safe to use the
+      // ones from the original inc. In that case, the new use of the wide
+      // increment won't be more poisonous.
+      bool NeedToRecomputeFlags =
+          !SCEVExpander::canReuseFlagsFromOriginalIVInc(
+              OrigPhi, WidePhi, DU.NarrowUse, WideInc) ||
+          DU.NarrowUse->hasNoUnsignedWrap() != WideInc->hasNoUnsignedWrap() ||
+          DU.NarrowUse->hasNoSignedWrap() != WideInc->hasNoSignedWrap();
+      return WideAddRec.first == WideIncExpr &&
+             Rewriter.hoistIVInc(WideInc, DU.NarrowUse, NeedToRecomputeFlags);
+    };
+
     Instruction *WideUse = nullptr;
-    if (WideAddRec.first == WideIncExpr &&
-        Rewriter.hoistIVInc(WideInc, DU.NarrowUse, NeedToRecomputeFlags))
+    if (CanUseWideInc())
       WideUse = WideInc;
     else {
       WideUse = cloneIVUser(DU, WideAddRec.first);


Regression tests:
file: llvm/test/Transforms/IndVarSimplify/pr106239.ll
commands: opt -S -passes=indvars < %s
tests: test_name: m
test_body: target datalayout = "n8:16:32:64"

define i32 @m() {
entry:
  %div.i4 = sdiv i32 1, 0
  br label %for.body.i6

for.body.i6:                                      ; preds = %if.end.i, %entry
  %add57.i = phi i32 [ %add.i7, %if.end.i ], [ 0, %entry ]
  br i1 true, label %i.exit, label %if.end.i

if.end.i:                                         ; preds = %for.body.i6
  %add.i7 = add i32 %add57.i, %div.i4
  %conv.i = zext i32 %add57.i to i64
  store i64 %conv.i, ptr null, align 8
  br label %for.body.i6

i.exit:                                           ; preds = %for.body.i6
  ret i32 0
}