diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 2a0a6a2d302b1..6f44713bd22cd 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -6985,8 +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) { - auto ElemResult = OptimizeConstMinMax(C->getAggregateElement(i), - IID, Call, &NewConst); + auto *Elt = C->getAggregateElement(i); + if (!Elt) { + OptResult = MinMaxOptResult::CannotOptimize; + break; + } + auto ElemResult = OptimizeConstMinMax(Elt, IID, Call, &NewConst); if (ElemResult == MinMaxOptResult::CannotOptimize || (ElemResult != OptResult && OptResult != MinMaxOptResult::UseEither && 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> 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> 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> 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> 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> 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> ) +; 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> 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> ) +; 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> to <4 x half>)) + ret <4 x half> %result +}