Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions llvm/lib/Analysis/InstructionSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reuse the result in the following call. See also

Constant *Elt = C->getAggregateElement(i);
if (!Elt)
return false;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, fixed.

OptResult = MinMaxOptResult::CannotOptimize;
break;
}
auto ElemResult = OptimizeConstMinMax(C->getAggregateElement(i),
IID, Call, &NewConst);
if (ElemResult == MinMaxOptResult::CannotOptimize ||
Expand Down
70 changes: 70 additions & 0 deletions llvm/test/Transforms/InstSimplify/fminmax-folds.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
}