Bug type: crash
Component: VectorCombine
Bug location: llvm/lib/Transforms/Vectorize/VectorCombine.cpp: canScalarizeAccess
Issue title: [VectorCombine] Crash occured while fold load-insertelement-store
Labels: vectorizers
crash
Reported by: ParkHanbum

This is an IR sample that crashes.

```
define void @src_1_idx(ptr %q, i8 zeroext %s, i1 %idx) {
entry:
  %0 = load <16 x i8>, ptr %q
  %v1 = insertelement <16 x i8> %0, i8 %s, i1 %idx
  store <16 x i8> %v1, ptr %q
  ret void
}

define void @src_2_idx(ptr %q, i8 zeroext %s, i8 %idx) {
entry:
  %0 = load <256 x i8>, ptr %q
  %v1 = insertelement <256 x i8> %0, i8 %s, i8 %idx
  store <256 x i8> %v1, ptr %q
  ret void
}
```

and this is debugging message with crash dump
```
VECTORCOMBINE on src_2_idx
VC: Visiting:   %0 = load <16 x i8>, ptr %q, align 16
VC: Visiting:   %v1 = insertelement <16 x i8> %0, i8 %s, i1 %idx
VC: Visiting:   store <16 x i8> %v1, ptr %q, align 16
Assertion failed: (llvm::isUIntN(BitWidth, val) && "Value is not an N-bit unsigned value"), function APInt, file APInt.h, line 128.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: bin/opt -passes=vector-combine t1.ll -S -debug
1.	Running pass "function(vector-combine)" on module "t1.ll"
2.	Running pass "vector-combine" on function "src_2_idx"
 #0 0x00000001026ca6ac llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/Users/b2sy/work/test3/bin/opt+0x1019566ac)
 #1 0x00000001026c8770 llvm::sys::RunSignalHandlers() (/Users/b2sy/work/test3/bin/opt+0x101954770)
 #2 0x00000001026cae7c SignalHandler(int, __siginfo*, void*) (/Users/b2sy/work/test3/bin/opt+0x101956e7c)
 #3 0x000000019733ede4 (/usr/lib/system/libsystem_platform.dylib+0x180482de4)
 #4 0x0000000197307f70 (/usr/lib/system/libsystem_pthread.dylib+0x18044bf70)
 #5 0x0000000197214908 (/usr/lib/system/libsystem_c.dylib+0x180358908)
 #6 0x0000000197213c1c (/usr/lib/system/libsystem_c.dylib+0x180357c1c)
 #7 0x00000001032ad794 isUpperSubvectorUndef(llvm::SDValue, llvm::SDLoc const&, llvm::SelectionDAG&) (.cold.2) (/Users/b2sy/work/test3/bin/opt+0x102539794)
 #8 0x00000001029c4990 canScalarizeAccess(llvm::VectorType*, llvm::Value*, llvm::Instruction*, llvm::AssumptionCache&, llvm::DominatorTree const&) (/Users/b2sy/work/test3/bin/opt+0x101c50990)
```

problem occured here 
```
// VectorCombine.cpp:1447
  unsigned IntWidth = Idx->getType()->getScalarSizeInBits();
  APInt Zero(IntWidth, 0);  
  APInt MaxElts(IntWidth, NumElements);  <<< crash
  ConstantRange ValidIndices(Zero, MaxElts);
  ConstantRange IdxRange(IntWidth, true);
```

I think this code is necessary because it checks to see if the index specified by insertelement is in an accessible range on the vector, so I think we need to add exception handling to fix the problem.

What do you think?

Note that this is not a real-world issue, but a bug that I discovered while writing the patch and creating the verification code.



Comments: author: ParkHanbum
body: No. I am trying to verify i8 type for that IR because I was trying to support multiple inserts but alive didn't make it. So i reduce type size then occured this issue.
author: RKSimon
body: I'm not sure whether this should be addressed or not - oddly the langref doesn't say that the index type must be able to dereference all elements, just that its treated as unsigned (so I guess we assume implicit zext?)
author: RKSimon
body: @dtcxzyw Do you know whether smaller index types are handled anywhere else in the codebase please?
author: dtcxzyw
body: > [@dtcxzyw](https://github.com/dtcxzyw) Do you know whether smaller index types are handled anywhere else in the codebase please?

I don't know. But this crash can be fixed by passing `implicitTrunc=true` into the APInt constructor, as we did in https://github.com/llvm/llvm-project/pull/80309.


Fix patch:
commit f572a5951a664d57e909928d5595285212ad6884
Author: Simon Pilgrim <llvm-dev@redking.me.uk>
Date:   Thu Apr 24 14:17:46 2025 +0100

    [VectorCombine] Ensure canScalarizeAccess handles cases where the index type can't represent all inbounds values
    
    Fixes #132563

diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index bd225bcc0635..04c084ffdda9 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -1438,6 +1438,7 @@ static ScalarizationResult canScalarizeAccess(VectorType *VecTy, Value *Idx,
   // This is the number of elements of fixed vector types,
   // or the minimum number of elements of scalable vector types.
   uint64_t NumElements = VecTy->getElementCount().getKnownMinValue();
+  unsigned IntWidth = Idx->getType()->getScalarSizeInBits();
 
   if (auto *C = dyn_cast<ConstantInt>(Idx)) {
     if (C->getValue().ult(NumElements))
@@ -1445,7 +1446,10 @@ static ScalarizationResult canScalarizeAccess(VectorType *VecTy, Value *Idx,
     return ScalarizationResult::unsafe();
   }
 
-  unsigned IntWidth = Idx->getType()->getScalarSizeInBits();
+  // Always unsafe if the index type can't handle all inbound values.
+  if (!llvm::isUIntN(IntWidth, NumElements))
+    return ScalarizationResult::unsafe();
+
   APInt Zero(IntWidth, 0);
   APInt MaxElts(IntWidth, NumElements);
   ConstantRange ValidIndices(Zero, MaxElts);


Regression tests:
file: llvm/test/Transforms/VectorCombine/pr132563.ll
commands: opt -passes=vector-combine -S %s
tests: test_name: <module>
test_body: 
; Ensure canScalarizeAccess handles cases where the index type can't represent all inbounds values

define void @src_1_idx(ptr %q, i8 zeroext %s, i1 %idx) {
;
  %ld = load <16 x i8>, ptr %q
  %v1 = insertelement <16 x i8> %ld, i8 %s, i1 %idx
  store <16 x i8> %v1, ptr %q
  ret void
}

define void @src_2_idx(ptr %q, i8 zeroext %s, i8 %idx) {
;
  %ld = load <256 x i8>, ptr %q
  %v1 = insertelement <256 x i8> %ld, i8 %s, i8 %idx
  store <256 x i8> %v1, ptr %q
  ret void
}