Bug type: crash
Component: LoopVectorize
Bug location: llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp: VPlanTransforms::truncateToMinimalBitwidths
Issue title: llvm crash on loop-vectorize: Assertion `OldResSizeInBits > NewResSizeInBits && "Nothing to shrink?"' failed.
Labels: vectorizers
crash
Reported by: shao-hua-li

llvm crashes on the following IR.

Bisected to 822c749aec69ace75bd3923a4c850e2fd2e34fb1, which was committed by @fhahn 

Compiler explorer: https://godbolt.org/z/rWj9dhvPo

```llvm
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define void @i(i64 %0) {
entry:
  %conv = sext i16 1 to i32
  br label %for.body

for.body:                                         ; preds = %for.body, %entry
  %1 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
  %tobool.not.i = icmp eq i64 %0, 0
  %..i = select i1 %tobool.not.i, i32 0, i32 0
  %cmp = icmp eq i32 %..i, 0
  %conv1 = zext i1 %tobool.not.i to i32
  %or = or i32 %conv1, %conv
  %cmp2 = icmp slt i32 %or, 7
  %conv4 = zext i1 %cmp2 to i64
  store i64 %conv4, ptr null, align 8
  %inc = add i32 %1, 1
  %tobool.not = icmp eq i32 %inc, 0
  br i1 %tobool.not, label %for.cond.for.end_crit_edge, label %for.body

for.cond.for.end_crit_edge:                       ; preds = %for.body
  ret void
}
```

```console
% opt -passes=loop-vectorize reduced.ll
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /zdata/shaoli/compilers/ccbuilder-compilers/clang-822c749aec69ace75bd3923a4c850e2fd2e34fb1/bin/opt -disable-output -passes=loop-vectorize reduced.ll
 #0 0x00007f5302fedeff llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-822c749aec69ace75bd3923a4c850e2fd2e34fb1/bin/../lib/libLLVM-18git.so+0x902eff)
 #1 0x00007f5302feb654 SignalHandler(int) Signals.cpp:0:0
 #2 0x00007f5302300090 (/lib/x86_64-linux-gnu/libc.so.6+0x43090)
 #3 0x00007f5304a458f0 llvm::InnerLoopVectorizer::truncateToMinimalBitwidths(llvm::VPTransformState&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-822c749aec69ace75bd3923a4c850e2fd2e34fb1/bin/../lib/libLLVM-18git.so+0x235a8f0)
 #4 0x00007f5304a49d95 llvm::InnerLoopVectorizer::fixVectorizedLoop(llvm::VPTransformState&, llvm::VPlan&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-822c749aec69ace75bd3923a4c850e2fd2e34fb1/bin/../lib/libLLVM-18git.so+0x235ed95)
 #5 0x00007f5304a4abb1 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*>>*) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-822c749aec69ace75bd3923a4c850e2fd2e34fb1/bin/../lib/libLLVM-18git.so+0x235fbb1)
 #6 0x00007f5304a4d564 llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-822c749aec69ace75bd3923a4c850e2fd2e34fb1/bin/../lib/libLLVM-18git.so+0x2362564)
 #7 0x00007f5304a4fbdd llvm::LoopVectorizePass::runImpl(llvm::Function&, llvm::ScalarEvolution&, llvm::LoopInfo&, llvm::TargetTransformInfo&, llvm::DominatorTree&, llvm::BlockFrequencyInfo*, llvm::TargetLibraryInfo*, llvm::DemandedBits&, llvm::AssumptionCache&, llvm::LoopAccessInfoManager&, llvm::OptimizationRemarkEmitter&, llvm::ProfileSummaryInfo*) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-822c749aec69ace75bd3923a4c850e2fd2e34fb1/bin/../lib/libLLVM-18git.so+0x2364bdd)
 #8 0x00007f5304a50e20 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-822c749aec69ace75bd3923a4c850e2fd2e34fb1/bin/../lib/libLLVM-18git.so+0x2365e20)
 #9 0x00007f5305e0d916 llvm::detail::PassModel<llvm::Function, llvm::LoopVectorizePass, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-822c749aec69ace75bd3923a4c850e2fd2e34fb1/bin/../lib/libLLVM-18git.so+0x3722916)
#10 0x00007f53031fd3fd llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-822c749aec69ace75bd3923a4c850e2fd2e34fb1/bin/../lib/libLLVM-18git.so+0xb123fd)
#11 0x00007f5305e069f6 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-822c749aec69ace75bd3923a4c850e2fd2e34fb1/bin/../lib/libLLVM-18git.so+0x371b9f6)
#12 0x00007f53031fbc8d llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-822c749aec69ace75bd3923a4c850e2fd2e34fb1/bin/../lib/libLLVM-18git.so+0xb10c8d)
#13 0x00007f5305e0d696 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-822c749aec69ace75bd3923a4c850e2fd2e34fb1/bin/../lib/libLLVM-18git.so+0x3722696)
#14 0x00007f53031f9c0d llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-822c749aec69ace75bd3923a4c850e2fd2e34fb1/bin/../lib/libLLVM-18git.so+0xb0ec0d)
#15 0x0000555c5281fcb5 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) (/zdata/shaoli/compilers/ccbuilder-compilers/clang-822c749aec69ace75bd3923a4c850e2fd2e34fb1/bin/opt+0x25cb5)
#16 0x0000555c52813876 main (/zdata/shaoli/compilers/ccbuilder-compilers/clang-822c749aec69ace75bd3923a4c850e2fd2e34fb1/bin/opt+0x19876)
#17 0x00007f53022e1083 __libc_start_main /build/glibc-wuryBv/glibc-2.31/csu/../csu/libc-start.c:342:3
#18 0x0000555c5281451e _start (/zdata/shaoli/compilers/ccbuilder-compilers/clang-822c749aec69ace75bd3923a4c850e2fd2e34fb1/bin/opt+0x1a51e)
[1]    1975861 segmentation fault   -disable-output -passes=loop-vectorize reduced.ll
```


This IR is reduced from 
```C
long a, b;
int c, d, f;
static long *e = &b;
static short g = 5;
int h() {
  if (a)
    return 0;
  return 5;
}
void i() {
  int j;
  long **k = &e;
  for (; d; d++) {
    j = h();
    *e = 6 >= (g | (j + c == 0));
  }
  j =  &k || 1;
  short *l[6];
  l[f] = &g;
}
int main() {}
```


Fix patch:
commit 17fb3e82f6c950267bb01cc2fd2a84b0d9e9d0d8
Author: Florian Hahn <flo@fhahn.com>
Date:   Tue Apr 23 11:50:25 2024 +0100

    [VPlan] Skip extending ICmp results in trunateToMinimalBitwidth.
    
    Results of icmp don't need extending after truncating their operands, as
    the result will always be i1. Skip them during extending.
    
    Fixes https://github.com/llvm/llvm-project/issues/79742
    Fixes https://github.com/llvm/llvm-project/issues/85185

diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index 007dc3f89b3f..9580dc4a27f6 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -1031,7 +1031,9 @@ void VPlanTransforms::truncateToMinimalBitwidths(
       if (auto *VPW = dyn_cast<VPRecipeWithIRFlags>(&R))
         VPW->dropPoisonGeneratingFlags();
 
-      if (OldResSizeInBits != NewResSizeInBits) {
+      using namespace llvm::VPlanPatternMatch;
+      if (OldResSizeInBits != NewResSizeInBits &&
+          !match(&R, m_Binary<Instruction::ICmp>(m_VPValue(), m_VPValue()))) {
         // Extend result to original width.
         auto *Ext =
             new VPWidenCastRecipe(Instruction::ZExt, ResultVPV, OldResTy);
@@ -1040,8 +1042,9 @@ void VPlanTransforms::truncateToMinimalBitwidths(
         Ext->setOperand(0, ResultVPV);
         assert(OldResSizeInBits > NewResSizeInBits && "Nothing to shrink?");
       } else
-        assert(cast<VPWidenRecipe>(&R)->getOpcode() == Instruction::ICmp &&
-               "Only ICmps should not need extending the result.");
+        assert(
+            match(&R, m_Binary<Instruction::ICmp>(m_VPValue(), m_VPValue())) &&
+            "Only ICmps should not need extending the result.");
 
       assert(!isa<VPWidenStoreRecipe>(&R) && "stores cannot be narrowed");
       if (isa<VPWidenLoadRecipe>(&R))


Regression tests:
file: llvm/test/Transforms/LoopVectorize/trunc-extended-icmps.ll
commands: opt -p loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -S %s
tests: test_name: test_icmp_and_op_zext
test_body: target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"

define i32 @test_icmp_and_op_zext(ptr %dst, i64 %a) {
entry:
  %and = and i64 %a, 7304878031173690989
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i16 [ 1, %entry ], [ %iv.next, %loop ]
  %c = icmp ne i64 %and, 0
  %c.ext = zext i1 %c to i64
  %or = or i64 %and, %c.ext
  %or.trunc = trunc i64 %or to i8
  %gep = getelementptr i8, ptr %dst, i16 %iv
  store i8 %or.trunc, ptr %gep, align 1
  %iv.next = add i16 %iv, 1
  %ec = icmp eq i16 %iv.next, 1000
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret i32 0
}

test_name: ext_cmp
test_body: target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"

define void @ext_cmp(ptr %src.1, ptr %src.2, ptr noalias %dst) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %gep.src.1 = getelementptr inbounds i16, ptr %src.1, i64 %iv
  %i2 = load i16, ptr %gep.src.1, align 2
  %i3 = sext i16 %i2 to i32
  %c.1 = icmp sgt i32 0, %i3
  %gep.src.2 = getelementptr inbounds i8, ptr %src.2, i64 %iv
  %i4 = load i8, ptr %gep.src.2, align 2
  %i5 = zext i8 %i4 to i32
  %i6 = select i1 %c.1, i32 0, i32 %i5
  %i7 = and i32 %i6, 0
  %i8 = trunc nuw nsw i32 %i7 to i16
  %gep.dst = getelementptr inbounds i16, ptr %dst, i64 %iv
  store i16 %i8, ptr %gep.dst, align 2
  %iv.next = add nsw i64 %iv, 1
  %ec = icmp eq i64 %iv.next, 1000
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

test_name: test_icmp_constant_op_zext
test_body: target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"

define i32 @test_icmp_constant_op_zext(ptr %dst) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i16 [ 1, %entry ], [ %iv.next, %loop ]
  %c = icmp ne i64 7304878031173690989, 0
  %c.ext = zext i1 %c to i64
  %or = or i64 7304878031173690989, %c.ext
  %or.trunc = trunc i64 %or to i8
  %gep = getelementptr i8, ptr %dst, i16 %iv
  store i8 %or.trunc, ptr %gep, align 1
  %iv.next = add i16 %iv, 1
  %ec = icmp eq i16 %iv.next, 1000
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret i32 0
}