[llvm] Fix InstCombine variable folding crash (PR #205148)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 5 12:09:49 PDT 2026


https://github.com/rdevshp updated https://github.com/llvm/llvm-project/pull/205148

>From 3e7a9f17fee3c30b0a4c616ed5f437d5b6dfacc7 Mon Sep 17 00:00:00 2001
From: rdevshp <rdevshp at gmail.com>
Date: Mon, 22 Jun 2026 17:12:41 +0000
Subject: [PATCH 1/3] Fix InstCombine variable folding crash

---
 .../InstCombine/InstCombineShifts.cpp         | 11 +++++----
 ...e-length-signext-after-high-bit-extract.ll | 23 +++++++++++++++++++
 2 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 605d80f2be7de..9de75409af00b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -1760,10 +1760,13 @@ InstCombinerImpl::foldVariableSignZeroExtensionOfVariableHighBitExtract(
 
   // Check that constant C is a splat of the element-wise bitwidth of V.
   auto BitWidthSplat = [](Constant *C, Value *V) {
-    return match(
-        C, m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_EQ,
-                              APInt(C->getType()->getScalarSizeInBits(),
-                                    V->getType()->getScalarSizeInBits())));
+    auto CBitWidth = C->getType()->getScalarSizeInBits();
+    auto VBitWidth = V->getType()->getScalarSizeInBits();
+    if (!llvm::isUIntN(CBitWidth, VBitWidth))
+      return false;
+
+    return match(C, m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_EQ,
+                                       APInt(CBitWidth, VBitWidth)));
   };
 
   // It should look like variable-length sign-extension on the outside:
diff --git a/llvm/test/Transforms/InstCombine/conditional-variable-length-signext-after-high-bit-extract.ll b/llvm/test/Transforms/InstCombine/conditional-variable-length-signext-after-high-bit-extract.ll
index ccccafdf5f3c7..faa8a7df81c1e 100644
--- a/llvm/test/Transforms/InstCombine/conditional-variable-length-signext-after-high-bit-extract.ll
+++ b/llvm/test/Transforms/InstCombine/conditional-variable-length-signext-after-high-bit-extract.ll
@@ -1150,3 +1150,26 @@ define i32 @bitwidth_does_not_fit(i3 %arg) {
   %inc = add i32 %shr, 1
   ret i32 %inc
 }
+
+define i16 @shift_count_bitwidth_does_not_fit(i16 %x, i4 %n) {
+; CHECK-LABEL: @shift_count_bitwidth_does_not_fit(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[HIGHBITS:%.*]] = lshr i16 [[X:%.*]], 1
+; CHECK-NEXT:    [[SUB1:%.*]] = sub i4 0, [[N:%.*]]
+; CHECK-NEXT:    [[Z1:%.*]] = zext i4 [[SUB1]] to i16
+; CHECK-NEXT:    [[SHL:%.*]] = shl i16 [[HIGHBITS]], [[Z1]]
+; CHECK-NEXT:    [[SUB2:%.*]] = sub i4 0, [[N]]
+; CHECK-NEXT:    [[Z2:%.*]] = zext i4 [[SUB2]] to i16
+; CHECK-NEXT:    [[ASHR:%.*]] = ashr i16 [[SHL]], [[Z2]]
+; CHECK-NEXT:    ret i16 [[ASHR]]
+;
+entry:
+  %highbits = lshr i16 %x, 1
+  %sub1 = sub i4 0, %n
+  %z1 = zext i4 %sub1 to i16
+  %shl = shl i16 %highbits, %z1
+  %sub2 = sub i4 0, %n
+  %z2 = zext i4 %sub2 to i16
+  %ashr = ashr i16 %shl, %z2
+  ret i16 %ashr
+}

>From 90f409ac731073e4d85519689fce7ed5d1a738f8 Mon Sep 17 00:00:00 2001
From: rdevshp <rdevshp at gmail.com>
Date: Tue, 23 Jun 2026 19:36:27 +0000
Subject: [PATCH 2/3] Remove entry label from the test case
 shift_count_bitwidth_does_not_fit

---
 ...onditional-variable-length-signext-after-high-bit-extract.ll | 2 --
 1 file changed, 2 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/conditional-variable-length-signext-after-high-bit-extract.ll b/llvm/test/Transforms/InstCombine/conditional-variable-length-signext-after-high-bit-extract.ll
index faa8a7df81c1e..6b33a4dcc3768 100644
--- a/llvm/test/Transforms/InstCombine/conditional-variable-length-signext-after-high-bit-extract.ll
+++ b/llvm/test/Transforms/InstCombine/conditional-variable-length-signext-after-high-bit-extract.ll
@@ -1153,7 +1153,6 @@ define i32 @bitwidth_does_not_fit(i3 %arg) {
 
 define i16 @shift_count_bitwidth_does_not_fit(i16 %x, i4 %n) {
 ; CHECK-LABEL: @shift_count_bitwidth_does_not_fit(
-; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[HIGHBITS:%.*]] = lshr i16 [[X:%.*]], 1
 ; CHECK-NEXT:    [[SUB1:%.*]] = sub i4 0, [[N:%.*]]
 ; CHECK-NEXT:    [[Z1:%.*]] = zext i4 [[SUB1]] to i16
@@ -1163,7 +1162,6 @@ define i16 @shift_count_bitwidth_does_not_fit(i16 %x, i4 %n) {
 ; CHECK-NEXT:    [[ASHR:%.*]] = ashr i16 [[SHL]], [[Z2]]
 ; CHECK-NEXT:    ret i16 [[ASHR]]
 ;
-entry:
   %highbits = lshr i16 %x, 1
   %sub1 = sub i4 0, %n
   %z1 = zext i4 %sub1 to i16

>From 810e244e6b2550b276882c7b676279cfa1328092 Mon Sep 17 00:00:00 2001
From: rdevshp <rdevshp at gmail.com>
Date: Sun, 5 Jul 2026 19:07:51 +0000
Subject: [PATCH 3/3] use m_SpecificIntAllowPoison(uint64_t V) instead

---
 llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 9de75409af00b..241bc3bba51c2 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -1760,13 +1760,8 @@ InstCombinerImpl::foldVariableSignZeroExtensionOfVariableHighBitExtract(
 
   // Check that constant C is a splat of the element-wise bitwidth of V.
   auto BitWidthSplat = [](Constant *C, Value *V) {
-    auto CBitWidth = C->getType()->getScalarSizeInBits();
-    auto VBitWidth = V->getType()->getScalarSizeInBits();
-    if (!llvm::isUIntN(CBitWidth, VBitWidth))
-      return false;
-
-    return match(C, m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_EQ,
-                                       APInt(CBitWidth, VBitWidth)));
+    return match(C,
+                 m_SpecificIntAllowPoison(V->getType()->getScalarSizeInBits()));
   };
 
   // It should look like variable-length sign-extension on the outside:



More information about the llvm-commits mailing list