[llvm] d1b402b - [InstCombine] Avoid overflow in `foldVecExtTruncToExtElt` (#180414)

via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 9 05:09:53 PST 2026


Author: Yingwei Zheng
Date: 2026-02-09T21:09:48+08:00
New Revision: d1b402b61298d7f28578650e452874e51ea818c4

URL: https://github.com/llvm/llvm-project/commit/d1b402b61298d7f28578650e452874e51ea818c4
DIFF: https://github.com/llvm/llvm-project/commit/d1b402b61298d7f28578650e452874e51ea818c4.diff

LOG: [InstCombine] Avoid overflow in `foldVecExtTruncToExtElt` (#180414)

This weird pattern was introduced by LoopVectorize. But it was placed in
an unreachable path, so we cannot assert that the indices are always
valid in InstCombine.
Closes https://github.com/llvm/llvm-project/issues/180233.

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
    llvm/test/Transforms/InstCombine/trunc-extractelement.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index 0cd2c09726a2d..a75c24bb91219 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -698,6 +698,10 @@ static Instruction *foldVecExtTruncToExtElt(TruncInst &Trunc,
   auto VecElts = VecOpTy->getElementCount();
 
   uint64_t BitCastNumElts = VecElts.getKnownMinValue() * TruncRatio;
+  // Make sure we don't overflow in the calculation of the new index.
+  // (VecOpIdx + 1) * TruncRatio should not overflow.
+  if (Cst->uge(std::numeric_limits<uint64_t>::max() / TruncRatio))
+    return nullptr;
   uint64_t VecOpIdx = Cst->getZExtValue();
   uint64_t NewIdx = IC.getDataLayout().isBigEndian()
                         ? (VecOpIdx + 1) * TruncRatio - 1
@@ -711,17 +715,21 @@ static Instruction *foldVecExtTruncToExtElt(TruncInst &Trunc,
       return nullptr;
 
     uint64_t IdxOfs = ShiftAmount->udiv(DstBits).getZExtValue();
+    // IdxOfs is guaranteed to be less than TruncRatio, so we won't overflow in
+    // the adjustment.
+    assert(IdxOfs < TruncRatio &&
+           "IdxOfs is expected to be less than TruncRatio.");
     NewIdx = IC.getDataLayout().isBigEndian() ? (NewIdx - IdxOfs)
                                               : (NewIdx + IdxOfs);
   }
 
   assert(BitCastNumElts <= std::numeric_limits<uint32_t>::max() &&
-         NewIdx <= std::numeric_limits<uint32_t>::max() && "overflow 32-bits");
+         "overflow 32-bits");
 
   auto *BitCastTo =
       VectorType::get(DstType, BitCastNumElts, VecElts.isScalable());
   Value *BitCast = IC.Builder.CreateBitCast(VecOp, BitCastTo);
-  return ExtractElementInst::Create(BitCast, IC.Builder.getInt32(NewIdx));
+  return ExtractElementInst::Create(BitCast, IC.Builder.getInt64(NewIdx));
 }
 
 /// Funnel/Rotate left/right may occur in a wider type than necessary because of

diff  --git a/llvm/test/Transforms/InstCombine/trunc-extractelement.ll b/llvm/test/Transforms/InstCombine/trunc-extractelement.ll
index ba2d07009d9c7..074b5b35d7f2d 100644
--- a/llvm/test/Transforms/InstCombine/trunc-extractelement.ll
+++ b/llvm/test/Transforms/InstCombine/trunc-extractelement.ll
@@ -296,3 +296,37 @@ define <4 x i64> @PR45314(<4 x i64> %x) {
   %b = bitcast <8 x i32> %s to <4 x i64>
   ret <4 x i64> %b
 }
+
+; Make sure we don't overflow when computing the new index.
+define i16 @test_overflow_idx1(<vscale x 16 x i32> %vec) {
+; ANY-LABEL: @test_overflow_idx1(
+; ANY-NEXT:  entry:
+; ANY-NEXT:    [[EXT:%.*]] = extractelement <vscale x 16 x i32> [[VEC:%.*]], i64 -1
+; ANY-NEXT:    [[TRUNC:%.*]] = trunc i32 [[EXT]] to i16
+; ANY-NEXT:    ret i16 [[TRUNC]]
+;
+entry:
+  %ext = extractelement <vscale x 16 x i32> %vec, i64 -1
+  %trunc = trunc i32 %ext to i16
+  ret i16 %trunc
+}
+
+; Make sure we don't overflow when computing the new index.
+define i16 @test_overflow_idx2(<vscale x 16 x i32> %vec) {
+; LE-LABEL: @test_overflow_idx2(
+; LE-NEXT:  entry:
+; LE-NEXT:    [[TMP0:%.*]] = bitcast <vscale x 16 x i32> [[VEC:%.*]] to <vscale x 32 x i16>
+; LE-NEXT:    [[TRUNC:%.*]] = extractelement <vscale x 32 x i16> [[TMP0]], i64 4294967296
+; LE-NEXT:    ret i16 [[TRUNC]]
+;
+; BE-LABEL: @test_overflow_idx2(
+; BE-NEXT:  entry:
+; BE-NEXT:    [[TMP0:%.*]] = bitcast <vscale x 16 x i32> [[VEC:%.*]] to <vscale x 32 x i16>
+; BE-NEXT:    [[TRUNC:%.*]] = extractelement <vscale x 32 x i16> [[TMP0]], i64 4294967297
+; BE-NEXT:    ret i16 [[TRUNC]]
+;
+entry:
+  %ext = extractelement <vscale x 16 x i32> %vec, i32 2147483648
+  %trunc = trunc i32 %ext to i16
+  ret i16 %trunc
+}


        


More information about the llvm-commits mailing list