Skip to content

Commit 25c6a31

Browse files
igorban-intelgithub-actions[bot]
authored andcommitted
Automerge: [InstSimplify] Fix crash when optimizing minmax with bitcast constant vectors (#168055)
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>))
2 parents 42819bc + dd7a000 commit 25c6a31

File tree

2 files changed

+76
-2
lines changed

2 files changed

+76
-2
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6985,8 +6985,12 @@ Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType,
69856985
// VectorShuffle instruction, which is not allowed in simplifyBinOp.
69866986
OptResult = MinMaxOptResult::UseEither;
69876987
for (unsigned i = 0; i != ElemCount.getFixedValue(); ++i) {
6988-
auto ElemResult = OptimizeConstMinMax(C->getAggregateElement(i),
6989-
IID, Call, &NewConst);
6988+
auto *Elt = C->getAggregateElement(i);
6989+
if (!Elt) {
6990+
OptResult = MinMaxOptResult::CannotOptimize;
6991+
break;
6992+
}
6993+
auto ElemResult = OptimizeConstMinMax(Elt, IID, Call, &NewConst);
69906994
if (ElemResult == MinMaxOptResult::CannotOptimize ||
69916995
(ElemResult != OptResult &&
69926996
OptResult != MinMaxOptResult::UseEither &&

llvm/test/Transforms/InstSimplify/fminmax-folds.ll

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,3 +885,73 @@ define void @minmax_minmax_xy_maxmin_yx(double %x, double %y, ptr %minnum_res, p
885885
store double %final_maximumnum, ptr %maximumnum_res
886886
ret void
887887
}
888+
889+
;###############################################################
890+
;# Constant Expression Vector Tests #
891+
;###############################################################
892+
; Test that minmax intrinsics with constant expression vectors don't crash
893+
; when getAggregateElement returns null for certain constant expressions.
894+
; These tests cover various scenarios where getAggregateElement() fails:
895+
; - Bitcast from mismatched vector element counts
896+
; - Bitcast from integer to float vectors
897+
; - Bitcast from i64 with different element boundaries
898+
899+
; Test with bitcast from <1 x i32> to <2 x half> (element count mismatch)
900+
define <2 x half> @minmax_bitcast_v2f16_minnum(<2 x half> %x) {
901+
; CHECK-LABEL: @minmax_bitcast_v2f16_minnum(
902+
; 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>))
903+
; CHECK-NEXT: ret <2 x half> [[RESULT]]
904+
;
905+
%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>))
906+
ret <2 x half> %result
907+
}
908+
909+
; Test with bitcast from <2 x i32> to <4 x half> (different element boundaries)
910+
define <4 x half> @minmax_bitcast_v4f16_maxnum(<4 x half> %x) {
911+
; CHECK-LABEL: @minmax_bitcast_v4f16_maxnum(
912+
; 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>))
913+
; CHECK-NEXT: ret <4 x half> [[RESULT]]
914+
;
915+
%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>))
916+
ret <4 x half> %result
917+
}
918+
919+
; Test with bitcast from <1 x i64> to <2 x float> (scalar to vector bitcast)
920+
define <2 x float> @minmax_bitcast_v2f32_minimum(<2 x float> %x) {
921+
; CHECK-LABEL: @minmax_bitcast_v2f32_minimum(
922+
; 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>))
923+
; CHECK-NEXT: ret <2 x float> [[RESULT]]
924+
;
925+
%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>))
926+
ret <2 x float> %result
927+
}
928+
929+
; Test with bitcast from <1 x double> to <4 x half> (type size mismatch)
930+
define <4 x half> @minmax_bitcast_v4f16_maximum(<4 x half> %x) {
931+
; CHECK-LABEL: @minmax_bitcast_v4f16_maximum(
932+
; 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>))
933+
; CHECK-NEXT: ret <4 x half> [[RESULT]]
934+
;
935+
%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>))
936+
ret <4 x half> %result
937+
}
938+
939+
; Test with bitcast from <2 x i16> to <2 x half> (integer to float)
940+
define <2 x half> @minmax_bitcast_v2f16_minimumnum(<2 x half> %x) {
941+
; CHECK-LABEL: @minmax_bitcast_v2f16_minimumnum(
942+
; CHECK-NEXT: [[RESULT:%.*]] = call <2 x half> @llvm.minimumnum.v2f16(<2 x half> [[X:%.*]], <2 x half> <half 0xH3F80, half 0xH3F00>)
943+
; CHECK-NEXT: ret <2 x half> [[RESULT]]
944+
;
945+
%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>))
946+
ret <2 x half> %result
947+
}
948+
949+
; Test with bitcast from <4 x i16> to <4 x half> (matching element count but getAggregateElement may fail)
950+
define <4 x half> @minmax_bitcast_v4f16_maximumnum(<4 x half> %x) {
951+
; CHECK-LABEL: @minmax_bitcast_v4f16_maximumnum(
952+
; 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>)
953+
; CHECK-NEXT: ret <4 x half> [[RESULT]]
954+
;
955+
%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>))
956+
ret <4 x half> %result
957+
}

0 commit comments

Comments
 (0)