Bug type: crash
Component: InstCombine
Bug location: llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp: InstCombiner::getFlippedStrictnessPredicateAndConstant
Issue title: [InstCombine][RISC-V] UNREACHABLE executed at InstCombineCompares.cpp:2788
Labels: crash
llvm:instcombine
Reported by: patrick-rivos

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.

Comments: author: dtcxzyw
body: 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
}

```

Fix patch:
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;


Regression tests:
file: llvm/test/Transforms/InstCombine/pr83931.ll
commands: opt -S -passes=instcombine < %s
tests: test_name: dont_crash
test_body: 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
}

file: llvm/test/Transforms/InstCombine/select.ll
commands: opt < %s -passes=instcombine -S
tests: test_name: scalable_sign_bits
test_body: 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
}

test_name: scalable_non_zero
test_body: 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
}

file: llvm/test/Transforms/InstCombine/vscale_cmp.ll
commands: opt < %s -passes=instcombine -S
tests: test_name: sge
test_body: 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
}