[llvm] [InstSimplify] Fix crash when optimizing minmax with bitcast constant vectors (PR #168055)

Igor Gorban via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 14 09:45:57 PST 2025


https://github.com/igorban-intel updated https://github.com/llvm/llvm-project/pull/168055

>From eb47c52fbd6788c9d39fe90fa4b39837c4e72ab9 Mon Sep 17 00:00:00 2001
From: "Gorban, Igor" <igor.gorban at intel.com>
Date: Fri, 14 Nov 2025 13:00:22 +0100
Subject: [PATCH 1/2] [InstSimplify] Fix crash when optimizing minmax with
 bitcast constant vectors

When simplifying min/max intrinsics with fixed-size vector constants,
InstructionSimplify attempts to optimize element-wise. However,
getAggregateElement() can return null for certain constant expressions
like bitcasts, leading to a null pointer dereference.

This patch adds a check to bail out of the optimization when
getAggregateElement() returns null, preventing the crash while
maintaining correct behavior for normal constant vectors.

Fixes crash with patterns like:
  call <2 x half> @llvm.minnum.v2f16(<2 x half> %x,
                                     <2 x half> bitcast (<1 x i32> <i32 N> to <2 x half>))
---
 llvm/lib/Analysis/InstructionSimplify.cpp     |  4 ++
 .../Transforms/InstSimplify/fminmax-folds.ll  | 70 +++++++++++++++++++
 2 files changed, 74 insertions(+)

diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 2a0a6a2d302b1..e5d2842a0ae7b 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -6985,6 +6985,10 @@ Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType,
           // VectorShuffle instruction, which is not allowed in simplifyBinOp.
           OptResult = MinMaxOptResult::UseEither;
           for (unsigned i = 0; i != ElemCount.getFixedValue(); ++i) {
+            if (!C->getAggregateElement(i)) {
+              OptResult = MinMaxOptResult::CannotOptimize;
+              break;
+            }
             auto ElemResult = OptimizeConstMinMax(C->getAggregateElement(i),
                                                   IID, Call, &NewConst);
             if (ElemResult == MinMaxOptResult::CannotOptimize ||
diff --git a/llvm/test/Transforms/InstSimplify/fminmax-folds.ll b/llvm/test/Transforms/InstSimplify/fminmax-folds.ll
index 3a03f8627ab68..091e85920c0df 100644
--- a/llvm/test/Transforms/InstSimplify/fminmax-folds.ll
+++ b/llvm/test/Transforms/InstSimplify/fminmax-folds.ll
@@ -885,3 +885,73 @@ define void @minmax_minmax_xy_maxmin_yx(double %x, double %y, ptr %minnum_res, p
   store double %final_maximumnum, ptr %maximumnum_res
   ret void
 }
+
+;###############################################################
+;#            Constant Expression Vector Tests                 #
+;###############################################################
+; Test that minmax intrinsics with constant expression vectors don't crash
+; when getAggregateElement returns null for certain constant expressions.
+; These tests cover various scenarios where getAggregateElement() fails:
+; - Bitcast from mismatched vector element counts
+; - Bitcast from integer to float vectors
+; - Bitcast from i64 with different element boundaries
+
+; Test with bitcast from <1 x i32> to <2 x half> (element count mismatch)
+define <2 x half> @minmax_bitcast_v2f16_minnum(<2 x half> %x) {
+; CHECK-LABEL: @minmax_bitcast_v2f16_minnum(
+; CHECK-NEXT:    [[RESULT:%.*]] = call <2 x half> @llvm.minnum.v2f16(<2 x half> [[X:%.*]], <2 x half> bitcast (<1 x i32> splat (i32 1078530011) to <2 x half>))
+; CHECK-NEXT:    ret <2 x half> [[RESULT]]
+;
+  %result = call <2 x half> @llvm.minnum.v2f16(<2 x half> %x, <2 x half> bitcast (<1 x i32> <i32 1078530011> to <2 x half>))
+  ret <2 x half> %result
+}
+
+; Test with bitcast from <2 x i32> to <4 x half> (different element boundaries)
+define <4 x half> @minmax_bitcast_v4f16_maxnum(<4 x half> %x) {
+; CHECK-LABEL: @minmax_bitcast_v4f16_maxnum(
+; CHECK-NEXT:    [[RESULT:%.*]] = call <4 x half> @llvm.maxnum.v4f16(<4 x half> [[X:%.*]], <4 x half> bitcast (<2 x i32> <i32 1078530011, i32 1073741824> to <4 x half>))
+; CHECK-NEXT:    ret <4 x half> [[RESULT]]
+;
+  %result = call <4 x half> @llvm.maxnum.v4f16(<4 x half> %x, <4 x half> bitcast (<2 x i32> <i32 1078530011, i32 1073741824> to <4 x half>))
+  ret <4 x half> %result
+}
+
+; Test with bitcast from <1 x i64> to <2 x float> (scalar to vector bitcast)
+define <2 x float> @minmax_bitcast_v2f32_minimum(<2 x float> %x) {
+; CHECK-LABEL: @minmax_bitcast_v2f32_minimum(
+; CHECK-NEXT:    [[RESULT:%.*]] = call <2 x float> @llvm.minimum.v2f32(<2 x float> [[X:%.*]], <2 x float> bitcast (<1 x i64> splat (i64 4638564619268087808) to <2 x float>))
+; CHECK-NEXT:    ret <2 x float> [[RESULT]]
+;
+  %result = call <2 x float> @llvm.minimum.v2f32(<2 x float> %x, <2 x float> bitcast (<1 x i64> <i64 4638564619268087808> to <2 x float>))
+  ret <2 x float> %result
+}
+
+; Test with bitcast from <1 x double> to <4 x half> (type size mismatch)
+define <4 x half> @minmax_bitcast_v4f16_maximum(<4 x half> %x) {
+; CHECK-LABEL: @minmax_bitcast_v4f16_maximum(
+; CHECK-NEXT:    [[RESULT:%.*]] = call <4 x half> @llvm.maximum.v4f16(<4 x half> [[X:%.*]], <4 x half> bitcast (<1 x double> splat (double 0x400921FB54442D18) to <4 x half>))
+; CHECK-NEXT:    ret <4 x half> [[RESULT]]
+;
+  %result = call <4 x half> @llvm.maximum.v4f16(<4 x half> %x, <4 x half> bitcast (<1 x double> <double 0x400921FB54442D18> to <4 x half>))
+  ret <4 x half> %result
+}
+
+; Test with bitcast from <2 x i16> to <2 x half> (integer to float)
+define <2 x half> @minmax_bitcast_v2f16_minimumnum(<2 x half> %x) {
+; CHECK-LABEL: @minmax_bitcast_v2f16_minimumnum(
+; CHECK-NEXT:    [[RESULT:%.*]] = call <2 x half> @llvm.minimumnum.v2f16(<2 x half> [[X:%.*]], <2 x half> <half 0xH3F80, half 0xH3F00>)
+; CHECK-NEXT:    ret <2 x half> [[RESULT]]
+;
+  %result = call <2 x half> @llvm.minimumnum.v2f16(<2 x half> %x, <2 x half> bitcast (<2 x i16> <i16 16256, i16 16128> to <2 x half>))
+  ret <2 x half> %result
+}
+
+; Test with bitcast from <4 x i16> to <4 x half> (matching element count but getAggregateElement may fail)
+define <4 x half> @minmax_bitcast_v4f16_maximumnum(<4 x half> %x) {
+; CHECK-LABEL: @minmax_bitcast_v4f16_maximumnum(
+; CHECK-NEXT:    [[RESULT:%.*]] = call <4 x half> @llvm.maximumnum.v4f16(<4 x half> [[X:%.*]], <4 x half> <half 0xH3C00, half 0xH3F00, half 0xH3F80, half 0xH4000>)
+; CHECK-NEXT:    ret <4 x half> [[RESULT]]
+;
+  %result = call <4 x half> @llvm.maximumnum.v4f16(<4 x half> %x, <4 x half> bitcast (<4 x i16> <i16 15360, i16 16128, i16 16256, i16 16384> to <4 x half>))
+  ret <4 x half> %result
+}

>From 8c9b67764c80e8ac23ffec9ea72a3a29bc5978e6 Mon Sep 17 00:00:00 2001
From: "Gorban, Igor" <igor.gorban at intel.com>
Date: Fri, 14 Nov 2025 18:44:45 +0100
Subject: [PATCH 2/2] Apply suggestion from @dtcxzyw

---
 llvm/lib/Analysis/InstructionSimplify.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index e5d2842a0ae7b..6f44713bd22cd 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -6985,12 +6985,12 @@ Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType,
           // VectorShuffle instruction, which is not allowed in simplifyBinOp.
           OptResult = MinMaxOptResult::UseEither;
           for (unsigned i = 0; i != ElemCount.getFixedValue(); ++i) {
-            if (!C->getAggregateElement(i)) {
+            auto *Elt = C->getAggregateElement(i);
+            if (!Elt) {
               OptResult = MinMaxOptResult::CannotOptimize;
               break;
             }
-            auto ElemResult = OptimizeConstMinMax(C->getAggregateElement(i),
-                                                  IID, Call, &NewConst);
+            auto ElemResult = OptimizeConstMinMax(Elt, IID, Call, &NewConst);
             if (ElemResult == MinMaxOptResult::CannotOptimize ||
                 (ElemResult != OptResult &&
                  OptResult != MinMaxOptResult::UseEither &&



More information about the llvm-commits mailing list