commit f381cd069965dabfeb277f30a4e532d7fd498f6e
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Tue Sep 3 04:52:47 2024 -0700

    [SLP]Fix PR107036: Check if the type of the user is sizable before requesting its size.

    Only some instructions should be considered as potentially reducing the
    size of the operands types, not all instructions should be considered.

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

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 58137cd6f543..f58803fc56a2 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -16055,15 +16055,16 @@ void BoUpSLP::computeMinimumValueSizes() {
                     const TreeEntry *UserTE = E.UserTreeIndices.back().UserTE;
                     if (TE == UserTE || !TE)
                       return false;
+                    if (!isa<CastInst, BinaryOperator, FreezeInst, PHINode,
+                             SelectInst>(U) ||
+                        !isa<CastInst, BinaryOperator, FreezeInst, PHINode,
+                             SelectInst>(UserTE->getMainOp()))
+                      return true;
                     unsigned UserTESz = DL->getTypeSizeInBits(
                         UserTE->Scalars.front()->getType());
                     auto It = MinBWs.find(TE);
                     if (It != MinBWs.end() && It->second.first > UserTESz)
                       return true;
-                    // The size of icmp is always 1 and should not be
-                    // considered.
-                    if (TE->getOpcode() == Instruction::ICmp)
-                      return true;
                     return DL->getTypeSizeInBits(U->getType()) > UserTESz;
                   }));
         })) {

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

define void @test(ptr %i) {
bb:
  %i1 = getelementptr i8, ptr %i, i64 4
  br label %bb2

bb2:                                              ; preds = %bb2, %bb
  %i3 = phi i32 [ %i6, %bb2 ], [ 0, %bb ]
  %i4 = phi i32 [ %i8, %bb2 ], [ 0, %bb ]
  store i32 %i3, ptr %i, align 4
  store i32 %i4, ptr %i1, align 4
  %i5 = trunc i32 0 to i1
  %i6 = select i1 %i5, i32 0, i32 0
  %i7 = trunc i32 %i4 to i1
  %i8 = select i1 %i7, i32 0, i32 0
  br label %bb2
}

[SLP] Cannot getTypeInfo() on a type that is unsized!

I tried the following IR with SLP:

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

define void @foo(ptr %i) {
bb:
  %i1 = getelementptr i8, ptr %i, i64 4
  br label %bb2

bb2:                                              ; preds = %bb2, %bb
  %i3 = phi i32 [ %i6, %bb2 ], [ 0, %bb ]
  %i4 = phi i32 [ %i8, %bb2 ], [ 0, %bb ]
  store i32 %i3, ptr %i
  store i32 %i4, ptr %i1
  %i5 = trunc i32 0 to i1
  %i6 = select i1 %i5, i32 0, i32 0
  %i7 = trunc i32 %i4 to i1
  %i8 = select i1 %i7, i32 0, i32 0
  br label %bb2
}
```

It failed with an error output:`Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!"' failed`. It's getting the size returned by the `store i32 %i4, ptr %i1` instruction.

https://llvm.godbolt.org/z/fMx9qMcfK

cc f6e01b9ece1e73f6eda6e1dbff3aa72e917f4007 @alexey-bataev

https://github.com/llvm/llvm-project/blob/2cbd1bc830861bc08f78fb6cc11747b82f66c4c6/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp#L16067

`U` is `store i32 %i4, ptr %i1`.

Reverting f6e01b9ece1e73f6eda6e1dbff3aa72e917f4007 seems reasonable to me. What do you think? @alexey-bataev ^^

will fix it asap today


commit ac217ee389d63124432e5e6890851a678f7a676b
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Thu Feb 13 14:19:51 2025 -0800

    [SLP] Check for PHI nodes (potentially cycles!) when checking dependencies

    When checking for dependecies for gather nodes with users with the same
    last instruction, cannot rely on the index order, if there is (even
    potential!) cycle in the graph, which may cause order not work correctly
    and cause compiler crash.

    Fixes #127128

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index fb72a112b9ac..780cafe91d6b 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -13206,8 +13206,16 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry(
           continue;
         // If the user instruction is used for some reason in different
         // vectorized nodes - make it depend on index.
+        // If any vector node is PHI node, this dependency might not work
+        // because of cycle dependencies, so disable it.
         if (TEUseEI.UserTE != UseEI.UserTE &&
-            TEUseEI.UserTE->Idx < UseEI.UserTE->Idx)
+            (TEUseEI.UserTE->Idx < UseEI.UserTE->Idx ||
+             any_of(
+                 VectorizableTree,
+                 [](const std::unique_ptr<TreeEntry> &TE) {
+                   return TE->State == TreeEntry::Vectorize &&
+                          TE->getOpcode() == Instruction::PHI;
+                 })))
           continue;
       }

opt -passes=slp-vectorizer -mtriple=x86_64 -mattr=+avx2 -S < %s

define void @test() {
entry:
  %.pre.pre = load float, ptr poison, align 4
  br label %bb1

bb1:                                              ; preds = %bb2, %entry
  %.pre = phi float [ %.pre.pre, %entry ], [ %i2, %bb2 ]
  %foxtrot.0 = phi float [ undef, %entry ], [ %gulf.0, %bb2 ]
  br label %bb2

bb2:                                              ; preds = %bb2, %bb1
  %i = phi float [ %.pre, %bb1 ], [ %i2, %bb2 ]
  %gulf.0 = phi float [ %foxtrot.0, %bb1 ], [ %div, %bb2 ]
  %div = fdiv float %i, %gulf.0
  %i1 = load float, ptr poison, align 4
  %div1 = fdiv float %gulf.0, %i1
  %mul = fmul float %div, %div1
  tail call void @foo(float %mul)
  %i2 = load float, ptr poison, align 4
  %tobool = fcmp une float %i2, 0.000000e+00
  br i1 %tobool, label %bb1, label %bb2
}

declare void @foo(float)

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

SLPVectorizer miscompilation

```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:10:11:12:13"
target triple = "x86_64-unknown-linux-gnu"

define swiftcc { ptr addrspace(10), i8 } @julia__dir2ori_404(float %0) {
  %2 = fdiv float 0.000000e+00, 0.000000e+00
  %3 = fdiv float 0.000000e+00, 0.000000e+00
  %4 = fdiv float %0, 0.000000e+00
  br label %5

5:                                                ; preds = %1
  %6 = fmul float %4, 0.000000e+00
  %7 = fsub float 0.000000e+00, %6
  %8 = fmul float %3, 0.000000e+00
  %9 = fsub float 0.000000e+00, %8
  br label %11

10:                                               ; No predecessors!
  br label %11

11:                                               ; preds = %10, %5
  %12 = phi float [ %7, %5 ], [ 0.000000e+00, %10 ]
  %13 = phi float [ %9, %5 ], [ 0.000000e+00, %10 ]
  br label %14

14:                                               ; preds = %11
  %15 = fmul float %2, 0.000000e+00
  %16 = fsub float %12, %15
  %17 = fmul float %4, 0.000000e+00
  %18 = fsub float %13, %17
  %19 = fadd float %16, %18
  %20 = call float @llvm.fabs.f32(float %19)
  ret { ptr addrspace(10), i8 } zeroinitializer
}

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

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
```
produces
```
Instruction does not dominate all uses!
  %4 = insertelement <2 x float> <float poison, float 0.000000e+00>, float %0, i32 0
  %2 = shufflevector <2 x float> %4, <2 x float> <float 0.000000e+00, float poison>, <2 x i32> <i32 2, i32 0>
LLVM ERROR: Broken module found, compilation aborted!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes=slp-vectorizer -mcpu=haswell <source>
1.	Running pass "verify" on module "<source>"
 #0 0x00000000054edec8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x54edec8)
 #1 0x00000000054eb884 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #2 0x00007faaea842520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x00007faaea8969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x00007faaea842476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x00007faaea8287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x000000000082790d llvm::json::operator==(llvm::json::Value const&, llvm::json::Value const&) (.cold) JSON.cpp:0:0
 #7 0x000000000542b6e8 (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x542b6e8)
 #8 0x0000000005329278 (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5329278)
 #9 0x000000000095605e llvm::detail::PassModel<llvm::Module, llvm::VerifierPass, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x95605e)
#10 0x00000000052e7b50 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x52e7b50)
#11 0x000000000096174a llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x96174a)
#12 0x0000000000953c7c optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x953c7c)
#13 0x00007faaea829d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#14 0x00007faaea829e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#15 0x000000000094b555 _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x94b555)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```
on 19 and trunk.
Godbolt: https://godbolt.org/z/qxKP6198T

Bisected thanks to manyclangs to 66775f8ccdcc8264ef349518e1c59d96d4227823 (8e2b2c4181506efc5b9321c203dd107bbd63392b seemed to be good) @alexey-bataev


commit 5bcc82d43388bb0daa122d5fe7ecda5eca27fc16
Author: Nikita Popov <npopov@redhat.com>
Date:   Fri Sep 20 16:57:46 2024 +0200

    [LoopPeel] Fix LCSSA phi node invalidation

    In the test case, the BECount of the second loop uses %load,
    but we only have an LCSSA phi node for %add, so that is what
    gets invalidated. Use the forgetLcssaPhiWithNewPredecessor()
    API instead, which will invalidate the roots of the expression
    instead.

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

diff --git a/llvm/lib/Transforms/Utils/LoopPeel.cpp b/llvm/lib/Transforms/Utils/LoopPeel.cpp
index 5d7c0d947fac..760f1619e030 100644
--- a/llvm/lib/Transforms/Utils/LoopPeel.cpp
+++ b/llvm/lib/Transforms/Utils/LoopPeel.cpp
@@ -859,7 +859,7 @@ static void cloneLoopBlocks(
       if (LatchInst && L->contains(LatchInst))
         LatchVal = VMap[LatchVal];
       PHI.addIncoming(LatchVal, cast<BasicBlock>(VMap[Edge.first]));
-      SE.forgetValue(&PHI);
+      SE.forgetLcssaPhiWithNewPredecessor(L, &PHI);
     }

   // LastValueMap is updated with the values for the current loop

opt -S -passes="print<scalar-evolution>,loop-unroll" -unroll-runtime < %s 2>&1

define void @test(i1 %c, ptr %p) {
entry:
  br label %loop.1

loop.1:                                           ; preds = %loop.1, %entry
  %phi = phi ptr [ null, %entry ], [ %p, %loop.1 ]
  %load = load i64, ptr %p, align 8
  %add = add i64 %load, 1
  br i1 %c, label %if, label %loop.1

if:                                               ; preds = %loop.1
  %add.lcssa = phi i64 [ %add, %loop.1 ]
  %gep = getelementptr i64, ptr %p, i64 %add.lcssa
  br label %loop.2

loop.2:                                           ; preds = %loop.2, %if
  %iv = phi ptr [ %p, %if ], [ %iv.next, %loop.2 ]
  %iv.next = getelementptr i8, ptr %iv, i64 8
  %icmp = icmp eq ptr %iv, %gep
  br i1 %icmp, label %exit, label %loop.2

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

LTO error: Instruction does not dominate all uses

clang crashes while linking
```
clang: error: unable to execute command: Aborted (core dumped)
clang: error: linker command failed due to signal (use -v to see invocation)
```
I followed the instructions [here](https://llvm.org/docs/HowToSubmitABug.html) and narrowed it down to an LTO bug. File to reproduce is attached. [a.out.0.2.internalize-reduced.bc.tar.gz](https://github.com/user-attachments/files/17066318/a.out.0.2.internalize-reduced.bc.tar.gz)
```
$ opt "-passes=lto<O3>" a.out.0.2.internalize-reduced.bc
WARNING: You're attempting to print out a bitcode file.
This is inadvisable as it may cause display problems. If
you REALLY want to taste LLVM bitcode first-hand, you
can force output with the `-f' option.

Instruction does not dominate all uses!
  %.lcssa16 = phi i64 [ %12, %9 ]
  %27 = add i64 %.lcssa16, 2
LLVM ERROR: Broken module found, compilation aborted!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: opt -passes=lto<O3> reduced-redacted.bc                                                                                #0 0x00007e899efc4d90 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /usr/src/debug/llvm/llvm-18.1.8.src/lib/Support/Unix/Signals.inc:723:22
 #1 0x00007e899efc1d4d llvm::sys::RunSignalHandlers() /usr/src/debug/llvm/llvm-18.1.8.src/lib/Support/Signals.cpp:105:20
 #2 0x00007e899efc1d4d SignalHandler /usr/src/debug/llvm/llvm-18.1.8.src/lib/Support/Unix/Signals.inc:403:31
 #3 0x00007e899e24c1d0 (/usr/lib/libc.so.6+0x3d1d0)
 #4 0x00007e899e2a53f4 __pthread_kill_implementation /usr/src/debug/glibc/glibc/nptl/pthread_kill.c:44:76
 #5 0x00007e899e24c120 raise /usr/src/debug/glibc/glibc/signal/../sysdeps/posix/raise.c:27:6
 #6 0x00007e899e2334c3 abort /usr/src/debug/glibc/glibc/stdlib/abort.c:81:7
 #7 0x00007e899ecaba1b std::mutex::lock() /usr/include/c++/14.1.1/bits/std_mutex.h:117:22
 #8 0x00007e899ecaba1b std::lock_guard<std::mutex>::lock_guard(std::mutex&) /usr/include/c++/14.1.1/bits/std_mutex.h:250:23
 #9 0x00007e899ecaba1b llvm::install_bad_alloc_error_handler(void (*)(void*, char const*, bool), void*) /usr/src/debug/llvm/llvm-18.1.8.src/lib/Support/ErrorHandling.cpp:131:61
#10 0x00007e899eec070e (/usr/lib/libLLVM.so.18.1+0x6c070e)
#11 0x00007e899f21aa1b (/usr/lib/libLLVM.so.18.1+0xa1aa1b)
#12 0x000055a86e4acf57 llvm::detail::PassModel<llvm::Module, llvm::VerifierPass, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm:
:Module>&) /usr/src/debug/llvm/llvm-18.1.8.src/include/llvm/IR/PassManagerInternal.h:90:3
#13 0x00007e899f1d767e llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) /usr/src/debug/llvm/llvm-18.1.8.src/incl
ude/llvm/IR/PassManager.h:547:20
#14 0x000055a86e4b7052 llvm::SmallPtrSetImplBase::isSmall() const /usr/src/debug/llvm/llvm-18.1.8.src/include/llvm/ADT/SmallPtrSet.h:195:33
#15 0x000055a86e4b7052 llvm::SmallPtrSetImplBase::~SmallPtrSetImplBase() /usr/src/debug/llvm/llvm-18.1.8.src/include/llvm/ADT/SmallPtrSet.h:83:17
#16 0x000055a86e4b7052 llvm::SmallPtrSetImpl<llvm::AnalysisKey*>::~SmallPtrSetImpl() /usr/src/debug/llvm/llvm-18.1.8.src/include/llvm/ADT/SmallPtrSet.h:345:7
#17 0x000055a86e4b7052 llvm::SmallPtrSet<llvm::AnalysisKey*, 2u>::~SmallPtrSet() /usr/src/debug/llvm/llvm-18.1.8.src/include/llvm/ADT/SmallPtrSet.h:451:7
#18 0x000055a86e4b7052 llvm::PreservedAnalyses::~PreservedAnalyses() /usr/src/debug/llvm/llvm-18.1.8.src/include/llvm/IR/PassManager.h:172:7
#19 0x000055a86e4b7052 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutpu
tFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) /usr/src/debug/llvm/llvm-18.1.8
.src/tools/opt/NewPMDriver.cpp:527:10
#20 0x000055a86e4ab1ed std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>::~basic_string() /usr/include/c++/14.1.1/bits/basic_string.h:809:19
#21 0x000055a86e4ab1ed main /usr/src/debug/llvm/llvm-18.1.8.src/tools/opt/opt.cpp:747:3
#22 0x00007e899e234e08 __libc_start_call_main /usr/src/debug/glibc/glibc/csu/../sysdeps/nptl/libc_start_call_main.h:74:3
#23 0x00007e899e234ecc call_init /usr/src/debug/glibc/glibc/csu/../csu/libc-start.c:128:20
#24 0x00007e899e234ecc __libc_start_main /usr/src/debug/glibc/glibc/csu/../csu/libc-start.c:347:5
#25 0x000055a86e4abfd5 _start (/usr/bin/opt+0x1cfd5)
Aborted (core dumped)
```
This happened after adding `-fsplit-lto-unit` to some parts of my code base.

While bisecting using this reduced test case, I was able to reproduce this crash on several versions of LLVM between 15 and 18.1.8. I was also able to reproduce on the tip of `main` (e439fdf4ea0dbc6f001428f4d4956700bf26bb97). However, this crash did not reproduce on 15.0.7. The commit on 15.0.7 that "fixed" the issue is
```
commit f3c5289e78462fb96015f79c954d95a0d527ba55
Author: Martin Storsjö <martin@martin.st>
Date:   Wed Oct 5 14:44:21 2022 +0300

    Revert "Recommit "[SCEV] Look through single value PHIs." (take 3)"

    This reverts commit 20d798bd47ec5191de1b2a8a031da06a04e612e1.

    This commit caused crashes in some cases, see github issue #58152.
    This is fixed on main, but backporting it requires multiple
    nontrivial cherrypicks.

    Updating llvm/test/Transforms/LoopVectorize/create-induction-resume.ll
    with update_test_checks.py, so this isn't an exact automatic revert,
    as that test case was added after the reverted commit.

    This fixes #58152 for the release branch.

 llvm/lib/Analysis/ScalarEvolution.cpp              |  7 ++-
 llvm/test/Analysis/DependenceAnalysis/lcssa.ll     |  2 +-
 llvm/test/Analysis/ScalarEvolution/cycled_phis.ll  |  4 +-
 .../ScalarEvolution/incorrect-exit-count.ll        |  2 +-
 .../Analysis/ScalarEvolution/solve-quadratic-i1.ll |  4 +-
 .../ScalarEvolution/solve-quadratic-overflow.ll    |  6 +--
 llvm/test/Analysis/ScalarEvolution/trivial-phis.ll |  2 +-
 llvm/test/Transforms/LoopStrengthReduce/funclet.ll | 40 +++++++++-------
 .../LoopVectorize/create-induction-resume.ll       | 24 ++++------
 llvm/test/Transforms/LoopVectorize/pr45259.ll      | 55 +++++++++++-----------
 10 files changed, 75 insertions(+), 71 deletions(-)
```
specifically, this (almost) 1-line diff
```diff
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 4b2db80bc1ec..3b73f9511eca 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -6023,8 +6023,13 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) {
   if (const SCEV *S = createAddRecFromPHI(PN))
     return S;

+  // If the PHI has a single incoming value, follow that value, unless the
+  // PHI's incoming blocks are in a different loop, in which case doing so
+  // risks breaking LCSSA form. Instcombine would normally zap these, but
+  // it doesn't have DominatorTree information, so it may miss cases.
   if (Value *V = simplifyInstruction(PN, {getDataLayout(), &TLI, &DT, &AC}))
-    return getSCEV(V);
+    if (LI.replacementPreservesLCSSAForm(PN, V))
+      return getSCEV(V);

   if (const SCEV *S = createNodeFromSelectLikePHI(PN))
     return S;
```

Reduced:
```llvm
; RUN: opt -passes="print<scalar-evolution>,loop-unroll" -unroll-runtime
define void @test(i1 %c, ptr %p) {
entry:
  br label %loop

loop:
  %phi = phi ptr [ null, %entry ], [ %p, %loop ]
  %load = load i64, ptr %p, align 8
  %add = add i64 %load, 1
  br i1 %c, label %bb2, label %loop

bb2:
  %add.lcssa = phi i64 [ %add, %loop ]
  %gep = getelementptr i64, ptr %p, i64 %add.lcssa
  br label %loop2

loop2:
  %iv = phi ptr [ %p, %bb2 ], [ %iv.next, %loop2 ]
  %iv.next = getelementptr i8, ptr %iv, i64 8
  %icmp = icmp eq ptr %iv, %gep
  br i1 %icmp, label %exit, label %loop2

exit:
  ret void
}
```

From a cursory look, the problem here is that the BECount of `loop2` depends on `%load`, and after peeling it should instead depend on a phi node, but instead still depends on `%load`. As the BECount does not dominate the loop, SCEV is invalid.

This issue sounds very familiar, we've fixed variants of this in the past.


commit 2131115be5b9d8b39af80973d9b64c0adc41d38d
Author: Fangrui Song <i@maskray.me>
Date:   Sat Jan 25 13:35:11 2025 -0800

    [InstCombine] Drop Range attribute when simplifying 'fshl' based on demanded bits (#124429)

    When simplifying operands based on demanded bits, the return value range
    of llvm.fshl might change. Keeping the Range attribute might cause
    llvm.fshl to generate a poison and lead to miscompile. Drop the Range
    attribute similar to `dropPosonGeneratingFlags` elsewhere.

    Fix #124387

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 943598a30f04..2c8939b5a051 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -1039,11 +1039,14 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
         APInt DemandedMaskLHS(DemandedMask.lshr(ShiftAmt));
         APInt DemandedMaskRHS(DemandedMask.shl(BitWidth - ShiftAmt));
         if (I->getOperand(0) != I->getOperand(1)) {
-          if (SimplifyDemandedBits(I, 0, DemandedMaskLHS, LHSKnown,
-                                   Depth + 1, Q) ||
+          if (SimplifyDemandedBits(I, 0, DemandedMaskLHS, LHSKnown, Depth + 1,
+                                   Q) ||
               SimplifyDemandedBits(I, 1, DemandedMaskRHS, RHSKnown, Depth + 1,
-                                   Q))
+                                   Q)) {
+            // Range attribute may no longer hold.
+            I->dropPoisonGeneratingReturnAttributes();
             return I;
+          }
         } else { // fshl is a rotate
           // Avoid converting rotate into funnel shift.
           // Only simplify if one operand is constant.

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

define i8 @fshl_range_trunc(i1 %x) {
  %zext = zext i1 %x to i32
  %or = or disjoint i32 %zext, -2
  %fshl = call range(i32 -4, 2) i32 @llvm.fshl.i32(i32 %or, i32 %or, i32 1)
  %tr = trunc nsw i32 %fshl to i8
  ret i8 %tr
}

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

[clang] Miscompile with -O2/3/s

This code prints random value at `-O2/3/s` and -1 at `-O0/1`:

```c
int printf(const char *, ...);
int a, b;
void c(char d) { a = d; }
int e(int d) {
  if (d < 0)
    return 1;
  return 0;
}
int f() {
  if (b)
    return 0;
  return 1;
}
int g(int d) {
  int h = 0;
  if (3 + d)
    h = f() - 1 - 1;
  return e(h) + h + h;
}
int main() {
  int i = g(0);
  c(i);
  printf("%d\n", a);
}
```

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

It starts from x86_64 clang 19.1.0.

InstCombine miscompiles

```llvm
define i32 @src(i32 %x) local_unnamed_addr {
entry:
  %cmp = icmp eq i32 %x, 0
  %zext = zext i1 %cmp to i32
  %or = or disjoint i32 %zext, -2
  %fshl = call range(i32 -4, 2) i32 @llvm.fshl.i32(i32 %or, i32 %or, i32 1)
  %tr = trunc nsw i32 %fshl to i8
  %res = sext i8 %tr to i32
  ret i32 %res
}
```

edit: `g` has a Range return attribute, which is propagated to the call site in `main` after inlining.
InstCombine `InstCombinerImpl::SimplifyDemandedUseBits` simplifies the operand, but keeps the no-longer-valid Range return attribute.

Then, CorrelatedValuePropagationPass added nsw, and the value eventually becomes poison.

Slightly reduced: https://alive2.llvm.org/ce/z/3Kf7-2

I assume the problem is that we don't clear the return range attribute in SimplifyDemanded.


commit b5f4210e9f51f938ae517f219f04f9ab431a2684
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Mon May 13 14:27:59 2024 +0800

    [InstCombine] Drop nuw flag when CtlzOp is a sub nuw (#91776)

    See the following case:
    ```
    define i32 @src1(i32 %x) {
      %dec = sub nuw i32 -2, %x
      %ctlz = tail call i32 @llvm.ctlz.i32(i32 %dec, i1 false)
      %sub = sub nsw i32 32, %ctlz
      %shl = shl i32 1, %sub
      %ugt = icmp ult i32 %x, -2
      %sel = select i1 %ugt, i32 %shl, i32 1
      ret i32 %sel
    }

    define i32 @tgt1(i32 %x) {
      %dec = sub nuw i32 -2, %x
      %ctlz = tail call i32 @llvm.ctlz.i32(i32 %dec, i1 false)
      %sub = sub nsw i32 32, %ctlz
      %and = and i32 %sub, 31
      %shl = shl nuw i32 1, %and
      ret i32 %shl
    }
    ```
    `nuw` in `%dec` should be dropped after the select instruction is
    eliminated.

    Alive2: https://alive2.llvm.org/ce/z/7S9529

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

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index ee090e012508..a3ddb402bf66 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -3343,7 +3343,8 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) {
 // pattern.
 static bool isSafeToRemoveBitCeilSelect(ICmpInst::Predicate Pred, Value *Cond0,
                                         const APInt *Cond1, Value *CtlzOp,
-                                        unsigned BitWidth) {
+                                        unsigned BitWidth,
+                                        bool &ShouldDropNUW) {
   // The challenge in recognizing std::bit_ceil(X) is that the operand is used
   // for the CTLZ proper and select condition, each possibly with some
   // operation like add and sub.
@@ -3366,6 +3367,8 @@ static bool isSafeToRemoveBitCeilSelect(ICmpInst::Predicate Pred, Value *Cond0,
   ConstantRange CR = ConstantRange::makeExactICmpRegion(
       CmpInst::getInversePredicate(Pred), *Cond1);

+  ShouldDropNUW = false;
+
   // Match the operation that's used to compute CtlzOp from CommonAncestor.  If
   // CtlzOp == CommonAncestor, return true as no operation is needed.  If a
   // match is found, execute the operation on CR, update CR, and return true.
@@ -3379,6 +3382,7 @@ static bool isSafeToRemoveBitCeilSelect(ICmpInst::Predicate Pred, Value *Cond0,
       return true;
     }
     if (match(CtlzOp, m_Sub(m_APInt(C), m_Specific(CommonAncestor)))) {
+      ShouldDropNUW = true;
       CR = ConstantRange(*C).sub(CR);
       return true;
     }
@@ -3448,14 +3452,20 @@ static Instruction *foldBitCeil(SelectInst &SI, IRBuilderBase &Builder) {
     Pred = CmpInst::getInversePredicate(Pred);
   }

+  bool ShouldDropNUW;
+
   if (!match(FalseVal, m_One()) ||
       !match(TrueVal,
              m_OneUse(m_Shl(m_One(), m_OneUse(m_Sub(m_SpecificInt(BitWidth),
                                                     m_Value(Ctlz)))))) ||
       !match(Ctlz, m_Intrinsic<Intrinsic::ctlz>(m_Value(CtlzOp), m_Zero())) ||
-      !isSafeToRemoveBitCeilSelect(Pred, Cond0, Cond1, CtlzOp, BitWidth))
+      !isSafeToRemoveBitCeilSelect(Pred, Cond0, Cond1, CtlzOp, BitWidth,
+                                   ShouldDropNUW))
     return nullptr;

+  if (ShouldDropNUW)
+    cast<Instruction>(CtlzOp)->setHasNoUnsignedWrap(false);
+
   // Build 1 << (-CTLZ & (BitWidth-1)).  The negation likely corresponds to a
   // single hardware instruction as opposed to BitWidth - CTLZ, where BitWidth
   // is an integer constant.  Masking with BitWidth-1 comes free on some

define i32 @pr91691(i32 %0) {
  %2 = sub nuw i32 -2, %0
  %3 = tail call i32 @llvm.ctlz.i32(i32 %2, i1 false)
  %4 = sub i32 32, %3
  %5 = shl i32 1, %4
  %6 = icmp ult i32 %0, -2
  %7 = select i1 %6, i32 %5, i32 1
  ret i32 %7
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctlz.i32(i32, i1 immarg) #0

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

define <4 x i32> @bit_ceil_v4i32(<4 x i32> %x) {
  %dec = add <4 x i32> %x, splat (i32 -1)
  %ctlz = tail call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %dec, i1 false)
  %sub = sub <4 x i32> splat (i32 32), %ctlz
  %shl = shl <4 x i32> splat (i32 1), %sub
  %ugt = icmp ugt <4 x i32> %x, splat (i32 1)
  %sel = select <4 x i1> %ugt, <4 x i32> %shl, <4 x i32> splat (i32 1)
  ret <4 x i32> %sel
}

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

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

define i32 @pr91691_keep_nsw(i32 %0) {
  %2 = sub nsw i32 -2, %0
  %3 = tail call i32 @llvm.ctlz.i32(i32 %2, i1 false)
  %4 = sub i32 32, %3
  %5 = shl i32 1, %4
  %6 = icmp ult i32 %0, -2
  %7 = select i1 %6, i32 %5, i32 1
  ret i32 %7
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctlz.i32(i32, i1 immarg) #0

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

instcombine removes a select, making code more poisonous

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

this function:
```llvm
define i32 @f(i32 %0) {
  %2 = sub nuw i32 -2, %0
  %3 = tail call i32 @llvm.ctlz.i32(i32 %2, i1 false)
  %4 = sub i32 32, %3
  %5 = shl i32 1, %4
  %6 = icmp ult i32 %0, -2
  %7 = select i1 %6, i32 %5, i32 1
  ret i32 %7
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctlz.i32(i32, i1 immarg) #0

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

is getting rewritten to not have the select, but the select was blocking a poison value. the bad thing happens when -1 is passed as an argument, see the Alive link for a detailed execution trace

```llvm
define i32 @f(i32 %0) {
  %2 = sub nuw i32 -2, %0
  %3 = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 %2, i1 false)
  %4 = sub nsw i32 0, %3
  %5 = and i32 %4, 31
  %6 = shl nuw i32 1, %5
  ret i32 %6
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctlz.i32(i32, i1 immarg) #0

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

cc @nunoplopes


commit cc943a67d114e28c28f561c3b1a48ff2003264ce
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Thu Aug 29 15:05:09 2024 -0700

    [SLP]Fix PR106626: trye several attempts for lookup values, if not found.

    If the value is used in Scalar several times, the first attempt to find
    its position in the node (if ReuseShuffleIndices and ReorderIndices not
    empty) may fail. In this case need to find another copy of the same
    value and try again.
    Fixes https://github.com/llvm/llvm-project/issues/106626

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 775fa9ba75cf..edb2567fa057 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -3237,15 +3237,25 @@ private:
     /// When ReuseReorderShuffleIndices is empty it just returns position of \p
     /// V within vector of Scalars. Otherwise, try to remap on its reuse index.
     int findLaneForValue(Value *V) const {
-      unsigned FoundLane = std::distance(Scalars.begin(), find(Scalars, V));
-      assert(FoundLane < Scalars.size() && "Couldn't find extract lane");
-      if (!ReorderIndices.empty())
-        FoundLane = ReorderIndices[FoundLane];
-      assert(FoundLane < Scalars.size() && "Couldn't find extract lane");
-      if (!ReuseShuffleIndices.empty()) {
-        FoundLane = std::distance(ReuseShuffleIndices.begin(),
-                                  find(ReuseShuffleIndices, FoundLane));
+      unsigned FoundLane = getVectorFactor();
+      for (auto *It = find(Scalars, V), *End = Scalars.end(); It != End;
+           std::advance(It, 1)) {
+        if (*It != V)
+          continue;
+        FoundLane = std::distance(Scalars.begin(), It);
+        assert(FoundLane < Scalars.size() && "Couldn't find extract lane");
+        if (!ReorderIndices.empty())
+          FoundLane = ReorderIndices[FoundLane];
+        assert(FoundLane < Scalars.size() && "Couldn't find extract lane");
+        if (ReuseShuffleIndices.empty())
+          break;
+        if (auto *RIt = find(ReuseShuffleIndices, FoundLane);
+            RIt != ReuseShuffleIndices.end()) {
+          FoundLane = std::distance(ReuseShuffleIndices.begin(), RIt);
+          break;
+        }
       }
+      assert(FoundLane < getVectorFactor() && "Unable to find given value.");
       return FoundLane;
     }

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

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

bb61:                                             ; preds = %entry
  br label %bb64

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

bb63:                                             ; preds = %bb62
  br label %bb64

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

bb77:                                             ; preds = %bb64
  br label %bb78

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

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

bb184:                                            ; preds = %bb167
  br label %bb185

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

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

[SLP] Assertion "All elements in mask must be less than CommonVF." failed

[PR77529](https://github.com/llvm/llvm-project/pull/77529) trigger assertion on "All elements in mask must be less than CommonVF." failed.

@alexey-bataev

To reproduce, run with: opt -S -passes=slp-vectorizer t.ll -o o.ll
Using reduced t.ll below
```
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
target triple = "aarch64-unknown-linux-gnu"

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

bb61:
  br label %bb64

bb62:
  br i1 poison, label %bb63, label %bb64

bb63:
  br label %bb64

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

bb77:                                             ; preds = %bb64
  br label %bb78

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

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

bb184:                                            ; preds = %bb167
  br label %bb185

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

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


commit 01cbbc52dc95fe5d9e30ecbfb2ec8c7c1e0199c4
Author: Florian Hahn <flo@fhahn.com>
Date:   Wed Oct 9 13:18:53 2024 +0100

    [VPlan] Request lane 0 for pointer arg in PtrAdd.

    After 7f74651, the pointer operand may be replicated of a PtrAdd. Instead
    of requesting a single scalar, request lane 0, which correctly handles the
    case when there is a scalar-per-lane.

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

diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index 123eb0d8d71a..2468616be0bd 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -645,8 +645,8 @@ Value *VPInstruction::generate(VPTransformState &State) {
   case VPInstruction::PtrAdd: {
     assert(vputils::onlyFirstLaneUsed(this) &&
            "can only generate first lane for PtrAdd");
-    Value *Ptr = State.get(getOperand(0), /* IsScalar */ true);
-    Value *Addend = State.get(getOperand(1), /* IsScalar */ true);
+    Value *Ptr = State.get(getOperand(0), VPLane(0));
+    Value *Addend = State.get(getOperand(1), VPLane(0));
     return isInBounds() ? Builder.CreateInBoundsPtrAdd(Ptr, Addend, Name)
                         : Builder.CreatePtrAdd(Ptr, Addend, Name);
   }

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

target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define ptr @test_interleave_ptradd_with_replicated_op(ptr %m) #0 {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %ptr.iv = phi ptr [ %m, %entry ], [ %ptr.iv.next, %loop ]
  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop ]
  %ptr.iv.next = getelementptr i8, ptr %ptr.iv, i64 8
  %p.4 = getelementptr i8, ptr %ptr.iv, i64 4
  %l.1 = load i32, ptr %p.4, align 4
  %p.0 = getelementptr i8, ptr %ptr.iv, i64 0
  %l.2 = load i32, ptr %p.0, align 4
  %add = add i32 %l.1, %l.2
  store i32 %add, ptr %ptr.iv, align 4
  %iv.next = add i32 %iv, 1
  %tobool.not = icmp eq i32 %iv, 100
  br i1 %tobool.not, label %exit, label %loop

exit:                                             ; preds = %loop
  ret ptr %p.4
}

attributes #0 = { "target-cpu"="znver2" }

A/F: "Trying to access a single scalar per part but has multiple scalars " "per part."' failed after 7f74651

Recently one of our internal tests started hitting an assertion failure when compiling which I bisected back to commit 7f74651.

Here is a reduced repro from the crashing code:
```c
typedef float a;
typedef struct {
  a b, c;
} d;
typedef struct {
  d e;
  a f;
} g;
#define h()                                                                    \
  i = j->e.b;                                                                  \
  k = l->e.c;                                                                  \
  l->f = k;
a i, k;
int m;
g *l;
void n() {
  g *j = l + 1;
  for (; m; ++m, ++l, ++j) {
    h()
  }
}
```

When compiled with `-O2 -g -ffast-math -march=znver2` using a compiler built from 7f74651 you can see the crash:
```
$ ~/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang -c -O2 -g -ffast-math -march=znver2 repro.c
clang: /home/dyung/src/upstream/llvm_clean_git/llvm/lib/Transforms/Vectorize/VPlan.cpp:258: llvm::Value* llvm::VPTransformState::get(llvm::VPValue*, bool): Assertion `(VF.isScalar() || Def->isLiveIn() || hasVectorValue(Def) || !vputils::onlyFirstLaneUsed(Def) || (hasScalarValue(Def, VPLane(0)) && Data.VPV2Scalars[Def].size() == 1)) && "Trying to access a single scalar per part but has multiple scalars " "per part."' 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/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang -c -O2 -g -ffast-math -march=znver2 repro2.c
1.      <eof> parser at end of file
2.      Optimizer
3.      Running pass "function<eager-inv>(float2int,lower-constant-intrinsics,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<O2>,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 "repro2.c"
4.      Running pass "loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>" on function "n"
 #0 0x000055d0e9ad0e1f llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x235be1f)
 #1 0x000055d0e9ace96c llvm::sys::CleanupOnSignal(unsigned long) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x235996c)
 #2 0x000055d0e9a20cc8 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x00007f44c03e9420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #4 0x00007f44bfeb600b raise /build/glibc-LcI20x/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
 #5 0x00007f44bfe95859 abort /build/glibc-LcI20x/glibc-2.31/stdlib/abort.c:81:7
 #6 0x00007f44bfe95729 get_sysdep_segment_value /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:509:8
 #7 0x00007f44bfe95729 _nl_load_domain /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:970:34
 #8 0x00007f44bfea6fd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
 #9 0x000055d0eb66055a llvm::VPTransformState::get(llvm::VPValue*, bool) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x3eeb55a)
#10 0x000055d0eb6926a9 llvm::VPInstruction::generate(llvm::VPTransformState&) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x3f1d6a9)
#11 0x000055d0eb695d01 llvm::VPInstruction::execute(llvm::VPTransformState&) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x3f20d01)
#12 0x000055d0eb65fb77 llvm::VPBasicBlock::executeRecipes(llvm::VPTransformState*, llvm::BasicBlock*) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x3eeab77)
#13 0x000055d0eb66283e llvm::VPBasicBlock::execute(llvm::VPTransformState*) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x3eed83e)
#14 0x000055d0eb6645c8 llvm::VPRegionBlock::execute(llvm::VPTransformState*) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x3eef5c8)
#15 0x000055d0eb660b8e llvm::VPlan::execute(llvm::VPTransformState*) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x3eebb8e)
#16 0x000055d0eb5362cb 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*) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x3dc12cb)
#17 0x000055d0eb54baf4 llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x3dd6af4)
#18 0x000055d0eb54dac1 llvm::LoopVectorizePass::runImpl(llvm::Function&) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x3dd8ac1)
#19 0x000055d0eb54e133 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x3dd9133)
#20 0x000055d0eaf6f396 llvm::detail::PassModel<llvm::Function, llvm::LoopVectorizePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x37fa396)
#21 0x000055d0e9589031 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x1e14031)
#22 0x000055d0e86a7026 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/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0xf32026)
#23 0x000055d0e958799d llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x1e1299d)
#24 0x000055d0e86a79e6 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0xf329e6)
#25 0x000055d0e95873d1 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x1e123d1)
#26 0x000055d0e9d65d23 (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 0x000055d0e9d692f8 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/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x25f42f8)
#28 0x000055d0ea4492ac clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x2cd42ac)
#29 0x000055d0ec3dbb9c clang::ParseAST(clang::Sema&, bool, bool) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x4c66b9c)
#30 0x000055d0ea4496c8 clang::CodeGenAction::ExecuteAction() (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x2cd46c8)
#31 0x000055d0ea7119a9 clang::FrontendAction::Execute() (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x2f9c9a9)
#32 0x000055d0ea68d99e clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x2f1899e)
#33 0x000055d0ea7fe466 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x3089466)
#34 0x000055d0e862a295 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0xeb5295)
#35 0x000055d0e862201a ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#36 0x000055d0ea48f17d 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 0x000055d0e9a211d0 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x22ac1d0)
#38 0x000055d0ea48f79f 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 0x000055d0ea4538f4 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x2cde8f4)
#40 0x000055d0ea454a0d clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x2cdfa0d)
#41 0x000055d0ea45cb55 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0x2ce7b55)
#42 0x000055d0e862722b clang_main(int, char**, llvm::ToolContext const&) (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0xeb222b)
#43 0x000055d0e855712b main (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0xde212b)
#44 0x00007f44bfe97083 __libc_start_main /build/glibc-LcI20x/glibc-2.31/csu/../csu/libc-start.c:342:3
#45 0x000055d0e8621aae _start (/home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin/clang+0xeacaae)
clang: error: clang frontend command failed with exit code 134 (use -v to see invocation)
clang version 20.0.0 (https://github.com/llvm/llvm-project.git 7f74651837b8f95996ea4c774b2e604020446951)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/dyung/src/upstream/7f74651837b8f95996ea4c774b2e604020446951-linux/bin
Build config: +assertions
```

Here is a link to godbolt also showing the failure: https://godbolt.org/z/bnPM9qqYo


commit 18b02bbf441660683df7f3925946984203d49bab
Author: DianQK <dianqk@dianqk.net>
Date:   Wed Nov 20 19:52:51 2024 +0800

    [LICM] allow MemoryAccess creation failure (#116813)

    Fixes #116809.

    After running some passes (SimpleLoopUnswitch, LoopInstSimplify, etc.),
    MemorySSA might be outdated, and the instruction `I` may have become a
    non-memory touching instruction.

    LICM has already handled this, but it does not pass
    `CreationMustSucceed=false` to `createDefinedAccess`.

diff --git a/llvm/include/llvm/Analysis/MemorySSAUpdater.h b/llvm/include/llvm/Analysis/MemorySSAUpdater.h
index d4da3ef1146d..055feceefb05 100644
--- a/llvm/include/llvm/Analysis/MemorySSAUpdater.h
+++ b/llvm/include/llvm/Analysis/MemorySSAUpdater.h
@@ -190,7 +190,8 @@ public:
   /// inaccessible and it *must* have removeMemoryAccess called on it.
   MemoryAccess *createMemoryAccessInBB(Instruction *I, MemoryAccess *Definition,
                                        const BasicBlock *BB,
-                                       MemorySSA::InsertionPlace Point);
+                                       MemorySSA::InsertionPlace Point,
+                                       bool CreationMustSucceed = true);

   /// Create a MemoryAccess in MemorySSA before an existing MemoryAccess.
   ///
diff --git a/llvm/lib/Analysis/MemorySSAUpdater.cpp b/llvm/lib/Analysis/MemorySSAUpdater.cpp
index aa550f0b6a7b..f672bd0e1e13 100644
--- a/llvm/lib/Analysis/MemorySSAUpdater.cpp
+++ b/llvm/lib/Analysis/MemorySSAUpdater.cpp
@@ -1403,9 +1403,11 @@ void MemorySSAUpdater::changeToUnreachable(const Instruction *I) {

 MemoryAccess *MemorySSAUpdater::createMemoryAccessInBB(
     Instruction *I, MemoryAccess *Definition, const BasicBlock *BB,
-    MemorySSA::InsertionPlace Point) {
-  MemoryUseOrDef *NewAccess = MSSA->createDefinedAccess(I, Definition);
-  MSSA->insertIntoListsForBlock(NewAccess, BB, Point);
+    MemorySSA::InsertionPlace Point, bool CreationMustSucceed) {
+  MemoryUseOrDef *NewAccess = MSSA->createDefinedAccess(
+      I, Definition, /*Template=*/nullptr, CreationMustSucceed);
+  if (NewAccess)
+    MSSA->insertIntoListsForBlock(NewAccess, BB, Point);
   return NewAccess;
 }

diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index fa04ced7182d..94bfe44a847a 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -1465,8 +1465,11 @@ static Instruction *cloneInstructionInExitBlock(

   if (MSSAU.getMemorySSA()->getMemoryAccess(&I)) {
     // Create a new MemoryAccess and let MemorySSA set its defining access.
+    // After running some passes, MemorySSA might be outdated, and the
+    // instruction `I` may have become a non-memory touching instruction.
     MemoryAccess *NewMemAcc = MSSAU.createMemoryAccessInBB(
-        New, nullptr, New->getParent(), MemorySSA::Beginning);
+        New, nullptr, New->getParent(), MemorySSA::Beginning,
+        /*CreationMustSucceed=*/false);
     if (NewMemAcc) {
       if (auto *MemDef = dyn_cast<MemoryDef>(NewMemAcc))
         MSSAU.insertDef(MemDef, /*RenameUses=*/true);

opt -passes='loop-mssa(simple-loop-unswitch<nontrivial>,licm)' -verify-memoryssa -S < %s

; Check that running LICM after SimpleLoopUnswitch does not result in a crash.

define i32 @foo(i1 %arg, ptr %arg1) {
;
start:
  br label %loop

loop:                                              ; preds = %loop, %bb
  %i = select i1 %arg, ptr %arg1, ptr @bar
  %i3 = call i32 %i()
  br i1 %arg, label %loop, label %ret

ret:                                              ; preds = %loop
  ret i32 %i3
}

declare i32 @bar() nounwind willreturn memory(none)

[SimpleLoopUnswitch][LICM] Assertion `NewAccess != nullptr && "Tried to create a memory access for a " "non-memory touching instruction"'

The following IR triggers the assertion mentioned in the title:

```llvm
; opt -passes='loop-mssa(simple-loop-unswitch<nontrivial>,licm)'
define i32 @foo(i1 %arg, ptr %arg1) {
bb:
  br label %bb2

bb2:                                              ; preds = %bb2, %bb
  %i = select i1 %arg, ptr %arg1, ptr @bar
  %i3 = call i32 %i()
  br i1 %arg, label %bb2, label %bb4

bb4:                                              ; preds = %bb2
  ret i32 %i3
}

declare i32 @bar() nounwind willreturn memory(none)
```

https://llvm.godbolt.org/z/bj79jxo8x


commit 376dad72abb4960cd93e37e3e98de3950b5c3dfe
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Fri Dec 6 13:39:05 2024 -0800

    [SLP]Move resulting vector before inert point, if the late generated buildvector fully matched

    If the perfect diamond match was detected for the postponed buildvectors
    and the vector for the previous node comes after the current node, need
    to move the vector register before the current inserting point to
    prevent compiler crash.

    Fixes #119002

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 51841a842ce0..50590e51ae0e 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -16215,6 +16215,11 @@ BoUpSLP::vectorizeTree(const ExtraValueToDebugLocsMap &ExternallyUsedValues,
     }
     Builder.SetCurrentDebugLocation(UserI->getDebugLoc());
     Value *Vec = vectorizeTree(TE, /*PostponedPHIs=*/false);
+    if (auto *VecI = dyn_cast<Instruction>(Vec);
+        VecI && VecI->getParent() == Builder.GetInsertBlock() &&
+        Builder.GetInsertPoint()->comesBefore(VecI))
+      VecI->moveBeforePreserving(*Builder.GetInsertBlock(),
+                                 Builder.GetInsertPoint());
     if (Vec->getType() != PrevVec->getType()) {
       assert(Vec->getType()->isIntOrIntVectorTy() &&
              PrevVec->getType()->isIntOrIntVectorTy() &&

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

define void @test() {
bb:
  br label %bb1

bb1:                                              ; preds = %bb4, %bb
  %phi = phi i32 [ 0, %bb ], [ %add6, %bb4 ]
  %phi2 = phi i32 [ 0, %bb ], [ %add, %bb4 ]
  %or = or i32 %phi2, 0
  %or3 = or i32 %phi, 0
  br i1 false, label %bb7, label %bb4

bb4:                                              ; preds = %bb1
  %add = add i32 0, 0
  %add5 = add i32 0, 0
  %add6 = add i32 %phi, 0
  br i1 false, label %bb7, label %bb1

bb7:                                              ; preds = %bb4, %bb1
  %phi8 = phi i32 [ %or, %bb1 ], [ %add5, %bb4 ]
  %phi9 = phi i32 [ %or3, %bb1 ], [ %add6, %bb4 ]
  ret void
}

Instruction does not dominate all uses! LLVM ERROR: Broken module found, compilation aborted! (yet another)

To reproduce run the test below with -passes slp-vectorizer
```
; ModuleID = './reduced.ll'
source_filename = "./reduced.ll"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2"
target triple = "x86_64-unknown-linux-gnu"

define void @wombat() #0 gc "statepoint-example" {
bb:
  br label %bb1

bb1:                                              ; preds = %bb4, %bb
  %phi = phi i32 [ 0, %bb ], [ %add6, %bb4 ]
  %phi2 = phi i32 [ 0, %bb ], [ %add, %bb4 ]
  %or = or i32 %phi2, 0
  %or3 = or i32 %phi, 0
  br i1 false, label %bb7, label %bb4

bb4:                                              ; preds = %bb1
  %add = add i32 0, 0
  %add5 = add i32 0, 0
  %add6 = add i32 %phi, 0
  br i1 false, label %bb7, label %bb1

bb7:                                              ; preds = %bb4, %bb1
  %phi8 = phi i32 [ %or, %bb1 ], [ %add5, %bb4 ]
  %phi9 = phi i32 [ %or3, %bb1 ], [ %add6, %bb4 ]
  ret void
}

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

Stack dump:
```
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes slp-vectorizer <source>
1.	Running pass "verify" on module "<source>"
 #0 0x00000000051b4a48 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x51b4a48)
 #1 0x00000000051b243c SignalHandler(int) Signals.cpp:0:0
 #2 0x00007c6fb5442520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x00007c6fb54969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x00007c6fb5442476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x00007c6fb54287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x00000000007e2469 llvm::json::operator==(llvm::json::Value const&, llvm::json::Value const&) (.cold) JSON.cpp:0:0
 #7 0x00000000050f32d8 (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x50f32d8)
 #8 0x0000000004ff2498 (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4ff2498)
 #9 0x00000000009057ae llvm::detail::PassModel<llvm::Module, llvm::VerifierPass, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x9057ae)
#10 0x0000000004fb1d10 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4fb1d10)
#11 0x0000000000910d7a llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x910d7a)
#12 0x00000000009033f9 optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x9033f9)
#13 0x00007c6fb5429d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#14 0x00007c6fb5429e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#15 0x00000000008facde _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8facde)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```


commit e96c0c1d5e0a9916098b1a31acb006ea6c1108fb
Author: Quentin Dian <dianqk@dianqk.net>
Date:   Wed Mar 6 06:16:28 2024 +0800

     [InstCombine] Fix shift calculation in InstCombineCasts (#84027)

    Fixes #84025.

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index 33ed1d557537..45afa6363ae0 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -2167,14 +2167,14 @@ static bool collectInsertionElements(Value *V, unsigned Shift,
     Type *ElementIntTy = IntegerType::get(C->getContext(), ElementSize);

     for (unsigned i = 0; i != NumElts; ++i) {
-      unsigned ShiftI = Shift + i * ElementSize;
+      unsigned ShiftI = i * ElementSize;
       Constant *Piece = ConstantFoldBinaryInstruction(
           Instruction::LShr, C, ConstantInt::get(C->getType(), ShiftI));
       if (!Piece)
         return false;

       Piece = ConstantExpr::getTrunc(Piece, ElementIntTy);
-      if (!collectInsertionElements(Piece, ShiftI, Elements, VecEltTy,
+      if (!collectInsertionElements(Piece, ShiftI + Shift, Elements, VecEltTy,
                                     isBigEndian))
         return false;
     }

InstCombine calculated a wrong `insertelement` instruction

I tried this IR:

```llvm
define <4 x i32> @src(i32 %arg) {
  %i = zext i32 %arg to i64
  %i1 = shl i64 %i, 32
  %i2 = or i64 %i1, 65
  %i3 = zext i64 %i2 to i128
  %i4 = shl i128 %i3, 64
  %i5 = bitcast i128 %i4 to <4 x i32>
  ret <4 x i32> %i5
}

define <4 x i32> @tgt(i32 %arg) {
  %i5 = insertelement <4 x i32> <i32 0, i32 0, i32 0, i32 poison>, i32 %arg, i64 3
  ret <4 x i32> %i5
}
```

I expect `src` to be:

```llvm
define <4 x i32> @src(i32 %arg) {
  %i5 = insertelement <4 x i32> <i32 0, i32 0, i32 65, i32 poison>, i32 %arg, i64 3
  ret <4 x i32> %i5
}
```

But I'm getting the same instructions as `tgt`.

Godbolt: https://llvm.godbolt.org/z/KnMEY4rTq
Alive2: https://alive2.llvm.org/ce/z/7FIJNi
From: https://github.com/rust-lang/rust/issues/121996

Looks like this bug is almost 11 years old: https://github.com/llvm/llvm-project/commit/feb34713d531d1f48c37116e8cab84814202d057! Thanks for fixing

> Looks like this bug is almost 11 years old: [feb3471](https://github.com/llvm/llvm-project/commit/feb34713d531d1f48c37116e8cab84814202d057)! Thanks for fixing

Based on my experience, we likely have many more latent bugs. :)


commit fdaad738753cde2bba6480c2ee5d1e9fb45064b9
Author: XChy <xxs_chy@outlook.com>
Date:   Thu May 16 20:13:39 2024 +0800

    [Reg2Mem] Handle CallBr instructions (#90953)

    Fixes #90900

diff --git a/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp b/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp
index b2a88eadd3de..f03de2f25a41 100644
--- a/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp
+++ b/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp
@@ -50,6 +50,15 @@ AllocaInst *llvm::DemoteRegToStack(Instruction &I, bool VolatileLoads,
       assert(BB && "Unable to split critical edge.");
       (void)BB;
     }
+  } else if (CallBrInst *CBI = dyn_cast<CallBrInst>(&I)) {
+    for (int i = 0; i < CBI->getNumSuccessors(); i++) {
+      auto *Succ = CBI->getSuccessor(i);
+      if (!Succ->getSinglePredecessor()) {
+        assert(isCriticalEdge(II, i) && "Expected a critical edge!");
+        BasicBlock *BB = SplitCriticalEdge(II, i);
+        assert(BB && "Unable to split critical edge.");
+      }
+    }
   }

   // Change all of the users of the instruction to read from the stack slot.
@@ -102,9 +111,14 @@ AllocaInst *llvm::DemoteRegToStack(Instruction &I, bool VolatileLoads,
         new StoreInst(&I, Slot, Handler->getFirstInsertionPt());
       return Slot;
     }
+  } else if (InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
+    InsertPt = II->getNormalDest()->getFirstInsertionPt();
+  } else if (CallBrInst *CBI = dyn_cast<CallBrInst>(&I)) {
+    for (BasicBlock *Succ : successors(CBI))
+      new StoreInst(CBI, Slot, Succ->getFirstInsertionPt());
+    return Slot;
   } else {
-    InvokeInst &II = cast<InvokeInst>(I);
-    InsertPt = II.getNormalDest()->getFirstInsertionPt();
+    llvm_unreachable("Unsupported terminator for Reg2Mem");
   }

   new StoreInst(&I, Slot, InsertPt);

define void @crash() {
;
entry:
  %a = callbr i64 asm "", "=r,r,!i"(i64 0)
  to label %then [label %else]

then:
  %b = inttoptr i64 %a to ptr
  br label %else

else:
  ret void
}

Reg2Mem pass triggered assertion `isa<To>(V al) && "cast<Ty>() argument of incompatible type!"

https://godbolt.org/z/oxW8zbKr6
`opt --passes=reg2mem reduced.ll`
```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"
target triple = "x86_64-unknown-linux-gnu"

%struct.__large_struct = type { [100 x i64] }

define fastcc i64 @__se_sys_pselect6() {
  %1 = callbr i64 asm sideeffect "\0A1:\09movq $1,$0\0A .pushsection \22__ex_table\22,\22a\22\0A .balign 4\0A .long (1b) - .\0A .long (${2:l}) - .\0A .long 3 \0A .popsection\0A", "=r,*m,!i,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(%struct.__large_struct) null)
          to label %2 [label %common.ret]

2:                                                ; preds = %0
  %3 = inttoptr i64 %1 to ptr
  %4 = callbr i64 asm sideeffect "\0A1:\09movq $1,$0\0A .pushsection \22__ex_table\22,\22a\22\0A .balign 4\0A .long (1b) - .\0A .long (${2:l}) - .\0A .long 3 \0A .popsection\0A", "=r,*m,!i,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(%struct.__large_struct) null)
          to label %common.ret [label %common.ret]

common.ret:                                       ; preds = %2, %2, %0
  ret i64 0
}
```


commit 954ed05c1001489802ae43d4bea403181570a799
Author: Florian Hahn <flo@fhahn.com>
Date:   Mon Sep 2 21:25:30 2024 +0100

    [VPlan] Simplify MUL operands at recipe construction.

    This moves the logic to create simplified operands using SCEV to MUL
    recipe creation. This is needed to match the behavior of the legacy's cost
    model. TODOs are to extend to other opcodes and move to a transform.

    Note that this also restricts the number of SCEV simplifications we
    apply to more precisely match the cases handled by the legacy cost
    model.

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

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index a8722db654f5..a64848c1fdce 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -8393,6 +8393,20 @@ VPWidenRecipe *VPRecipeBuilder::tryToWiden(Instruction *I,
   case Instruction::Sub:
   case Instruction::Xor:
   case Instruction::Freeze:
+    if (I->getOpcode() == Instruction::Mul) {
+      // Simplify operands of multiplications using SCEV. This is needed at the
+      // moment to match the behavior of the legacy cost-model.
+      // TODO: Generalize to any opcode and move to VPlan transformation.
+      SmallVector<VPValue *> NewOps(Operands);
+      ScalarEvolution &SE = *PSE.getSE();
+      for (unsigned I = 0; I < Operands.size(); ++I) {
+        Value *V = NewOps[I]->getUnderlyingValue();
+        if (!isa<Constant>(V) && SE.isSCEVable(V->getType()))
+          if (auto *C = dyn_cast<SCEVConstant>(PSE.getSE()->getSCEV(V)))
+            NewOps[I] = Plan.getOrAddLiveIn(C->getValue());
+      }
+      return new VPWidenRecipe(*I, make_range(NewOps.begin(), NewOps.end()));
+    }
     return new VPWidenRecipe(*I, make_range(Operands.begin(), Operands.end()));
   };
 }
diff --git a/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h b/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h
index 0fbdeeddaf4a..25b8bf3e089e 100644
--- a/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h
+++ b/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h
@@ -174,11 +174,6 @@ public:
       if (auto *R = Ingredient2Recipe.lookup(I))
         return R->getVPSingleValue();
     }
-    ScalarEvolution &SE = *PSE.getSE();
-    if (!isa<Constant>(V) && SE.isSCEVable(V->getType()))
-      if (auto *C = dyn_cast<SCEVConstant>(PSE.getSE()->getSCEV(V)))
-        return Plan.getOrAddLiveIn(C->getValue());
-
     return Plan.getOrAddLiveIn(V);
   }
 };

target triple = "arm64-apple-macosx"

define i64 @mul_select_operand_known_1_via_scev() {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %red = phi i64 [ 12, %entry ], [ %red.next, %loop ]
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
  %0 = and i32 %iv, 1
  %cmp1.i = icmp eq i32 %0, 0
  %narrow.i = select i1 %cmp1.i, i32 1, i32 %iv
  %mul = zext nneg i32 %narrow.i to i64
  %red.next = mul nsw i64 %red, %mul
  %iv.next = add nuw nsw i32 %iv, 1
  %ec = icmp eq i32 %iv, 1
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  %res = phi i64 [ %red.next, %loop ]
  ret i64 %res
}

[clang] Crash with assertion failed in Vectorize

The compiler crashed with -O2 in this code:

```c
#include<stdint.h>
static uint8_t b[][1] = {127};
long a(int c, int e) {
  long d;
  for (; c <= e; c++)
    if (c % 2 == 0)
      ;
    else
      d *= c;
  return d;
}
int64_t f();
int16_t g() {
  int32_t h = 1653000360;
  f(a(h - 1653000360, b[0][0] - 126));
  uint8_t *i[] = {b, b};
}
```

The crash is:
```
clang: /root/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:7369: llvm::VectorizationFactor llvm::LoopVectorizationPlanner::computeBestVF(): Assertion `(BestFactor.Width == LegacyVF.Width || planContainsAdditionalSimplifications(getPlanFor(BestFactor.Width), CostCtx, OrigLoop)) && " VPlan cost model and legacy cost model disagreed"' 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.
```

The details can be found here: https://godbolt.org/z/eeWW6raPb


commit d51fcd4ed86ac6075c8a25b053c2b66051feaf62
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Tue Mar 5 21:08:15 2024 +0800

    [InstCombine] Handle scalable splat in `getFlippedStrictnessPredicateAndConstant` (#83980)

    This patch adds support for canonicalization of icmp with a scalable
    splat. Some optimizations assume that `icmp pred X, APInt C` is in
    canonical form.

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

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 55207a8343d0..1cebab8203ea 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6544,6 +6544,13 @@ InstCombiner::getFlippedStrictnessPredicateAndConstant(CmpInst::Predicate Pred,
       if (!SafeReplacementConstant)
         SafeReplacementConstant = CI;
     }
+  } else if (isa<VectorType>(C->getType())) {
+    // Handle scalable splat
+    Value *SplatC = C->getSplatValue();
+    auto *CI = dyn_cast_or_null<ConstantInt>(SplatC);
+    // Bail out if the constant can't be safely incremented/decremented.
+    if (!CI || !ConstantIsOk(CI))
+      return std::nullopt;
   } else {
     // ConstantExpr?
     return std::nullopt;

define <vscale x 2 x i1> @dont_crash(<vscale x 2 x i64> %x) {
entry:
  %div = sdiv <vscale x 2 x i64> %x, splat (i64 309383)
  %ret = icmp sge <vscale x 2 x i64> %div, zeroinitializer
  ret <vscale x 2 x i1> %ret
}

target datalayout = "e-p:64:64-p1:16:16-p2:32:32:32-p3:64:64:64"

define <vscale x 2 x i32> @scalable_sign_bits(<vscale x 2 x i8> %x) {
  %a = sext <vscale x 2 x i8> %x to <vscale x 2 x i32>
  %b = shl <vscale x 2 x i32> %a, splat (i32 16)
  ret <vscale x 2 x i32> %b
}

target datalayout = "e-p:64:64-p1:16:16-p2:32:32:32-p3:64:64:64"

define <vscale x 2 x i1> @scalable_non_zero(<vscale x 2 x i32> %x) {
  %a = or <vscale x 2 x i32> %x, splat (i32 1)
  %b = add <vscale x 2 x i32> %a, splat (i32 -1)
  %cmp = icmp ult <vscale x 2 x i32> %b, splat (i32 56)
  ret <vscale x 2 x i1> %cmp
}

define <vscale x 2 x i1> @sge(<vscale x 2 x i8> %x) {
  %cmp = icmp sge <vscale x 2 x i8> %x, zeroinitializer
  ret <vscale x 2 x i1> %cmp
}

[InstCombine][RISC-V] UNREACHABLE executed at InstCombineCompares.cpp:2788

Testcase:
```c
char a;
int b;
long *c[5][5];
int main() {
  for (int d = -2041027590; d; d++)
    a |= b <= c[3][d][8] / 309383;
}
```

Reduced LLVM IR:
```llvm ir
; ModuleID = 'reduced.ll'
source_filename = "red.c"
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

; Function Attrs: nofree norecurse nosync nounwind memory(readwrite, argmem: read, inaccessiblemem: none) uwtable vscale_range(2,1024)
define noundef signext i32 @main() #0 {
entry:
  %0 = getelementptr inbounds i8, <vscale x 2 x ptr> zeroinitializer, i64 64
  %wide.masked.gather = call <vscale x 2 x i64> @llvm.masked.gather.nxv2i64.nxv2p0(<vscale x 2 x ptr> %0, i32 8, <vscale x 2 x i1> shufflevector (<vscale x 2 x i1> insertelement (<vscale x 2 x i1> poison, i1 true, i64 0), <vscale x 2 x i1> poison, <vscale x 2 x i32> zeroinitializer), <vscale x 2 x i64> poison)
  %1 = sdiv <vscale x 2 x i64> %wide.masked.gather, shufflevector (<vscale x 2 x i64> insertelement (<vscale x 2 x i64> poison, i64 309383, i64 0), <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer)
  %2 = icmp sge <vscale x 2 x i64> %1, zeroinitializer
  %3 = zext <vscale x 2 x i1> %2 to <vscale x 2 x i8>
  %4 = call i8 @llvm.vector.reduce.or.nxv2i8(<vscale x 2 x i8> %3)
  store i8 %4, ptr null, align 1
  ret i32 0
}

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read)
declare <vscale x 2 x i64> @llvm.masked.gather.nxv2i64.nxv2p0(<vscale x 2 x ptr>, i32 immarg, <vscale x 2 x i1>, <vscale x 2 x i64>) #1

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i8 @llvm.vector.reduce.or.nxv2i8(<vscale x 2 x i8>) #2

; uselistorder directives
uselistorder <vscale x 2 x i64> poison, { 1, 2, 0 }

attributes #0 = { nofree norecurse nosync nounwind memory(readwrite, argmem: read, inaccessiblemem: none) uwtable vscale_range(2,1024) "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic-rv64" "target-features"="+64bit,+a,+c,+d,+f,+m,+relax,+v" }
attributes #1 = { nocallback nofree nosync nounwind willreturn memory(read) }
attributes #2 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
```

Backtrace:
```
> /scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt -passes="instcombine" reduced.ll --disable-output
Unhandled icmp predicate!
UNREACHABLE executed at /scratch/tc-testing/tc-feb-22-llvm/llvm/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp:2788!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: /scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt -passes=instcombine reduced.ll --disable-output
 #0 0x00005565be2171a0 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt+0x2ce31a0)
 #1 0x00005565be2145af llvm::sys::RunSignalHandlers() (/scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt+0x2ce05af)
 #2 0x00005565be214705 SignalHandler(int) Signals.cpp:0:0
 #3 0x00007f8b9f842520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x00007f8b9f8969fc __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x00007f8b9f8969fc __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #6 0x00007f8b9f8969fc pthread_kill ./nptl/pthread_kill.c:89:10
 #7 0x00007f8b9f842476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
 #8 0x00007f8b9f8287f3 abort ./stdlib/abort.c:81:7
 #9 0x00005565be14ca5e (/scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt+0x2c18a5e)
#10 0x00005565bd1c1139 llvm::InstCombinerImpl::foldICmpDivConstant(llvm::ICmpInst&, llvm::BinaryOperator*, llvm::APInt const&) (/scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt+0x1c8d139)
#11 0x00005565bd1d710e llvm::InstCombinerImpl::foldICmpBinOpWithConstant(llvm::ICmpInst&, llvm::BinaryOperator*, llvm::APInt const&) (/scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt+0x1ca310e)
#12 0x00005565bd1d7393 llvm::InstCombinerImpl::foldICmpInstWithConstant(llvm::ICmpInst&) (/scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt+0x1ca3393)
#13 0x00005565bd1e46eb llvm::InstCombinerImpl::visitICmpInst(llvm::ICmpInst&) (/scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt+0x1cb06eb)
#14 0x00005565bd1457a5 llvm::InstCombinerImpl::run() (/scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt+0x1c117a5)
#15 0x00005565bd146e85 combineInstructionsOverFunction(llvm::Function&, llvm::InstructionWorklist&, llvm::AAResults*, llvm::AssumptionCache&, llvm::TargetLibraryInfo&, llvm::TargetTransformInfo&, llvm::DominatorTree&, llvm::OptimizationRemarkEmitter&, llvm::BlockFrequencyInfo*, llvm::ProfileSummaryInfo*, llvm::LoopInfo*, llvm::InstCombineOptions const&) InstructionCombining.cpp:0:0
#16 0x00005565bd147ef5 llvm::InstCombinePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt+0x1c13ef5)
#17 0x00005565bc1e5c96 llvm::detail::PassModel<llvm::Function, llvm::InstCombinePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt+0xcb1c96)
#18 0x00005565be044751 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt+0x2b10751)
#19 0x00005565bc1dd5b6 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt+0xca95b6)
#20 0x00005565be04344b llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt+0x2b0f44b)
#21 0x00005565bc1e5746 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt+0xcb1746)
#22 0x00005565be0412c1 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt+0x2b0d2c1)
#23 0x00005565bba77e55 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) (/scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt+0x543e55)
#24 0x00005565bba6a296 optMain (/scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt+0x536296)
#25 0x00007f8b9f829d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#26 0x00007f8b9f829e40 call_init ./csu/../csu/libc-start.c:128:20
#27 0x00007f8b9f829e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#28 0x00005565bba5f5a5 _start (/scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt+0x52b5a5)
zsh: IOT instruction (core dumped)  /scratch/tc-testing/tc-feb-22-llvm/build/build-llvm-linux/bin/opt  reduced.ll
```

Godbolt: https://godbolt.org/z/9qdYfPTrE

Assert being tripped: https://github.com/llvm/llvm-project/blob/main/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp#L2788

Found via fuzzer.

Reduced test case: https://godbolt.org/z/5qocbWsW3
```
define <vscale x 2 x i1> @test(<vscale x 2 x i64> %p) {
entry:
  %1 = sdiv <vscale x 2 x i64> %p, splat (i64 309383)
  %2 = icmp sge <vscale x 2 x i64> %1, zeroinitializer
  ret <vscale x 2 x i1> %2
}

```


commit 68210c7c269b7b7325dedaea7cea9fe9d979fab5
Author: Florian Hahn <flo@fhahn.com>
Date:   Sat Oct 5 19:15:05 2024 +0100

    [VPlan] Only generate first lane for VPPredInstPHI if no others used.

    IF only the first lane of the result is used, only generate the first
    lane.

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

diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index 0d092b9c10ac..376b3d33be76 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -2185,6 +2185,9 @@ void VPPredInstPHIRecipe::execute(VPTransformState &State) {
     // predicated iteration inserts its generated value in the correct vector.
     State.reset(getOperand(0), VPhi);
   } else {
+    if (vputils::onlyFirstLaneUsed(this) && !State.Lane->isFirstLane())
+      return;
+
     Type *PredInstType = getOperand(0)->getUnderlyingValue()->getType();
     PHINode *Phi = State.Builder.CreatePHI(PredInstType, 2);
     Phi->addIncoming(PoisonValue::get(ScalarPredInst->getType()),

opt -p loop-vectorize -mtriple x86_64 -prefer-predicate-over-epilogue=predicate-dont-vectorize -mcpu=skylake-avx512 -S %s

define void @sdiv_feeding_gep_predicated(ptr %dst, i32 %x, i64 %M, i64 %conv6, i64 %N) {
entry:
  %conv61 = zext i32 %x to i64
  br label %loop

loop:                                             ; preds = %loop.latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %c = icmp ule i64 %iv, %M
  br i1 %c, label %then, label %loop.latch

then:                                             ; preds = %loop
  %div18 = sdiv i64 %M, %conv6
  %conv20 = trunc i64 %div18 to i32
  %mul30 = mul i64 %div18, %conv61
  %sub31 = sub i64 %iv, %mul30
  %conv34 = trunc i64 %sub31 to i32
  %mul35 = mul i32 %x, %conv20
  %add36 = add i32 %mul35, %conv34
  %idxprom = sext i32 %add36 to i64
  %gep = getelementptr double, ptr %dst, i64 %idxprom
  store double 0.000000e+00, ptr %gep, align 8
  br label %loop.latch

loop.latch:                                       ; preds = %then, %loop
  %iv.next = add i64 %iv, 1
  %ec = icmp eq i64 %iv.next, %N
  br i1 %ec, label %exit, label %loop

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

opt %s -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -S

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-pc-linux-gnu"

@c = external global [5 x i8]

define void @pr70590_recipe_without_underlying_instr(i64 %n, ptr noalias %dst) {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %inc, %loop.latch ]
  %cmp = icmp eq i64 %iv, %n
  br i1 %cmp, label %loop.latch, label %then

then:                                             ; preds = %loop.header
  %rem = srem i64 3, 0
  %add3 = add i64 %rem, -3
  %add5 = add i64 %iv, %add3
  %gep = getelementptr [5 x i8], ptr @c, i64 0, i64 %add5
  %l = load i8, ptr %gep, align 1
  br label %loop.latch

loop.latch:                                       ; preds = %then, %loop.header
  %sr = phi i8 [ 0, %loop.header ], [ %l, %then ]
  %gep.dst = getelementptr i8, ptr %dst, i64 %iv
  store i8 %sr, ptr %gep.dst, align 4
  %inc = add i64 %iv, 1
  %exitcond.not = icmp eq i64 %inc, 4
  br i1 %exitcond.not, label %exit, label %loop.header

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

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

target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define void @replicate_udiv_with_only_first_lane_used(i32 %x, ptr %dst, i64 %d) {
entry:
  %c = icmp eq i32 %x, 10
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  br i1 true, label %loop.latch, label %else

else:                                             ; preds = %loop.header
  %div.i = udiv i64 99, %d
  br label %loop.latch

loop.latch:                                       ; preds = %else, %loop.header
  %retval.0.i = phi i64 [ %div.i, %else ], [ 0, %loop.header ]
  %gep = getelementptr i16, ptr %dst, i64 %retval.0.i
  store i16 0, ptr %gep, align 2
  %iv.next = add i64 %iv, 1
  %cmp = icmp ult i64 %iv.next, 101
  br i1 %cmp, label %loop.header, label %exit

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

[clang] Assertion failed in VPlan.cpp:258

When I compiled the code with -O2 flag, it crashed:

```c
#include <stdint.h>
static uint8_t c[] = {1};
void a();
long b(int h) {
  long d = 0;
  if (h < 0)
    return -1;
  int e = 0;
  for (int f = 0; f <= h; f++) {
    e++;
    d += f;
  }
  long a = d / e;
  return a;
}
void g();
uint8_t i() {
  uint16_t k[4];
  int f;
  for (; g + f < 4; f++)
    k[b(c[0] - 1)] = 5;
  for (; f; a(k))
    ;
  uint8_t *l[3][3], j;
  l[0][j] = c;
}
```

The crash is:
```
clang: /root/llvm-project/llvm/lib/Transforms/Vectorize/VPlan.cpp:258: llvm::Value* llvm::VPTransformState::get(llvm::VPValue*, bool): Assertion `(VF.isScalar() || Def->isLiveIn() || hasVectorValue(Def) || !vputils::onlyFirstLaneUsed(Def) || (hasScalarValue(Def, VPLane(0)) && Data.VPV2Scalars[Def].size() == 1)) && "Trying to access a single scalar per part but has multiple scalars " "per part."' failed.
```

Details can be found here: https://godbolt.org/z/fTrKKha5E

Looks like a clang-19 regression: https://godbolt.org/z/6d3edKn86


commit 22da5a6e34ed6146752b24d9156a678b50fddaef
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Fri Apr 26 16:25:33 2024 +0800

    [IRCE] Skip icmp ptr in `InductiveRangeCheck::parseRangeCheckICmp` (#89967)

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

diff --git a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
index 9df28747570c..104e8ceb7967 100644
--- a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
@@ -279,6 +279,9 @@ bool InductiveRangeCheck::parseRangeCheckICmp(Loop *L, ICmpInst *ICI,
   Value *LHS = ICI->getOperand(0);
   Value *RHS = ICI->getOperand(1);

+  if (!LHS->getType()->isIntegerTy())
+    return false;
+
   // Canonicalize to the `Index Pred Invariant` comparison
   if (IsLoopInvariant(LHS)) {
     std::swap(LHS, RHS);

; Make sure we don't crash.
define void @pr89959() {
;
top:
  br label %L3

L3:
  %value_phi = phi ptr [ null, %top ], [ %0, %L13 ]
  %0 = getelementptr i8, ptr %value_phi, i64 8
  %.not = icmp ule ptr %value_phi, null
  br i1 %.not, label %L13, label %L15

L13:
  br label %L3

L15:
  ret void
}

Assertion in Scalar Evolution when running IRCE

The following IR crashes with
```llvm
define void @foo() {
top:
  br label %L3

L3:                                               ; preds = %L13, %top
  %value_phi = phi ptr [ null, %top ], [ %0, %L13 ]
  %0 = getelementptr i8, ptr %value_phi, i64 8
  %.not = icmp ule ptr %value_phi, null
  br i1 %.not, label %L13, label %L15

L13:                                              ; preds = %L3
  br label %L3

L15:                                              ; preds = %L3
  ret void
}
```

`opt --passes=irce`

https://godbolt.org/z/1sbvaT7r1