https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/175381
Test some more refined cases, such as ordering with 0s and within known positive and known negative cases. >From 972718e06a4b3fd0d731b93d83ed3be8422d0373 Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Thu, 8 Jan 2026 14:39:22 +0100 Subject: [PATCH] InstCombine: Add more tests for min/max SimplifyDemandedFPClass Test some more refined cases, such as ordering with 0s and within known positive and known negative cases. --- .../simplify-demanded-fpclass-maximum.ll | 394 ++++++++++++++++++ .../simplify-demanded-fpclass-maximumnum.ll | 392 +++++++++++++++++ .../simplify-demanded-fpclass-minimum.ll | 393 +++++++++++++++++ .../simplify-demanded-fpclass-minimumnum.ll | 392 +++++++++++++++++ 4 files changed, 1571 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll index 31c73a5d9abf9..4ebbc064c16f3 100644 --- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll +++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll @@ -30,6 +30,21 @@ declare nofpclass(pinf norm sub zero) float @returns_ninf_or_nan() declare nofpclass(norm sub zero nan) float @returns_inf() declare nofpclass(norm sub zero) float @returns_inf_or_nan() +declare nofpclass(inf pnorm sub zero nan) float @returns_nnorm() +declare nofpclass(inf nnorm sub zero nan) float @returns_pnorm() + +declare nofpclass(inf pnorm sub zero) float @returns_nnorm_or_nan() +declare nofpclass(inf nnorm sub zero) float @returns_pnorm_or_nan() + +declare nofpclass(inf norm psub zero nan) float @returns_nsub() +declare nofpclass(inf norm nsub zero nan) float @returns_psub() + +declare nofpclass(pinf pnorm psub zero nan) float @returns_negative_nonzero() +declare nofpclass(ninf nnorm nsub zero nan) float @returns_positive_nonzero() +declare nofpclass(pinf pnorm psub zero) float @returns_negative_nonzero_or_nan() +declare nofpclass(ninf nnorm nsub zero) float @returns_positive_nonzero_or_nan() + + ; -> qnan define nofpclass(inf norm sub zero) float @ret_only_nan(float %x, float %y) { ; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_only_nan( @@ -370,6 +385,32 @@ define nofpclass(snan) float @cannot_fold_negative_or_zero__positive_or_zero_1() ret float %result } +define nofpclass(snan) float @nsz_fold_negative_or_zero__positive_or_zero_0() { +; CHECK-LABEL: define nofpclass(snan) float @nsz_fold_negative_or_zero__positive_or_zero_0() { +; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() +; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan nsz float @llvm.maximum.f32(float [[MUST_BE_NEGATIVE_OR_ZERO]], float [[MUST_BE_POSITIVE_OR_ZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %must.be.negative.or.zero = call float @returns_positive_or_zero() + %must.be.positive.or.zero = call float @returns_negative_or_zero() + %result = call nsz float @llvm.maximum.f32(float %must.be.negative.or.zero, float %must.be.positive.or.zero) + ret float %result +} + +define nofpclass(snan) float @nsz_fold_negative_or_zero__positive_or_zero_1() { +; CHECK-LABEL: define nofpclass(snan) float @nsz_fold_negative_or_zero__positive_or_zero_1() { +; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() +; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan nsz float @llvm.maximum.f32(float [[MUST_BE_POSITIVE_OR_ZERO]], float [[MUST_BE_NEGATIVE_OR_ZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %must.be.negative.or.zero = call float @returns_positive_or_zero() + %must.be.positive.or.zero = call float @returns_negative_or_zero() + %result = call nsz float @llvm.maximum.f32(float %must.be.positive.or.zero, float %must.be.negative.or.zero) + ret float %result +} + define nofpclass(nsub) float @lhs_must_be_pinf_or_nan(float %unknown, float nofpclass(ninf norm zero sub) %must.be.pinf.or.nan) { ; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_pinf_or_nan( ; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(ninf zero sub norm) [[MUST_BE_PINF_OR_NAN:%.*]]) { @@ -1692,6 +1733,359 @@ define nofpclass(snan) float @not_nan__maximum_noundef_md__not_nan(float nofpcla ret float %result } + +define nofpclass(snan) float @select_is_positive_or_0__maximum__nnorm_0(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__maximum__nnorm_0( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[NNORM:%.*]] = call float @returns_nnorm() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[SELECT]], float [[NNORM]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %nnorm = call float @returns_nnorm() + %result = call float @llvm.maximum.f32(float %select, float %nnorm) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__maximum__nnorm_1(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__maximum__nnorm_1( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[NNORM:%.*]] = call float @returns_nnorm() +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[NNORM]], float [[SELECT]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %nnorm = call float @returns_nnorm() + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %result = call float @llvm.maximum.f32(float %nnorm, float %select) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__maximum__nnorm_or_nan_0(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__maximum__nnorm_or_nan_0( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[NNORM_OR_NAN:%.*]] = call float @returns_nnorm_or_nan() +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[SELECT]], float [[NNORM_OR_NAN]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %nnorm.or.nan = call float @returns_nnorm_or_nan() + %result = call float @llvm.maximum.f32(float %select, float %nnorm.or.nan) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__maximum__nnorm_or_nan_1(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__maximum__nnorm_or_nan_1( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[NNORM_OR_NAN:%.*]] = call float @returns_nnorm_or_nan() +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NNORM_OR_NAN]], float [[SELECT]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %nnorm.or.nan = call float @returns_nnorm_or_nan() + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %result = call float @llvm.maximum.f32(float %nnorm.or.nan, float %select) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__maximum__negative(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__maximum__negative( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[SELECT]], float [[NEGATIVE]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %negative = call float @returns_negative() + %result = call float @llvm.maximum.f32(float %select, float %negative) + ret float %result +} + +define nofpclass(snan) float @negative__maximum__select_is_positive_or_0(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @negative__maximum__select_is_positive_or_0( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[NEGATIVE]], float [[SELECT]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %negative = call float @returns_negative() + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %result = call float @llvm.maximum.f32(float %negative, float %select) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__maximum__negative_or_zero(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__maximum__negative_or_zero( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[NEGATIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[SELECT]], float [[NEGATIVE_OR_ZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %negative.or.zero = call float @returns_negative_or_zero() + %result = call float @llvm.maximum.f32(float %select, float %negative.or.zero) + ret float %result +} + +define nofpclass(snan) float @negative_or_zero__maximum__select_is_positive_or_0(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @negative_or_zero__maximum__select_is_positive_or_0( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[NEGATIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[NEGATIVE_OR_ZERO]], float [[SELECT]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %negative.or.zero = call float @returns_negative_or_zero() + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %result = call float @llvm.maximum.f32(float %negative.or.zero, float %select) + ret float %result +} + +define nofpclass(snan) float @negative_or_zero__maximum__positive() { +; CHECK-LABEL: define nofpclass(snan) float @negative_or_zero__maximum__positive() { +; CHECK-NEXT: [[NEG_NONZERO:%.*]] = call float @returns_negative_nonzero() +; CHECK-NEXT: [[POSITIVE:%.*]] = call float @returns_positive() +; CHECK-NEXT: ret float [[POSITIVE]] +; + %neg.nonzero = call float @returns_negative_nonzero() + %positive = call float @returns_positive() + %result = call float @llvm.maximum.f32(float %neg.nonzero, float %positive) + ret float %result +} + +define nofpclass(snan) float @positive__maximum__negative_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @positive__maximum__negative_or_zero() { +; CHECK-NEXT: [[POSITIVE:%.*]] = call float @returns_positive() +; CHECK-NEXT: [[NEG_NONZERO:%.*]] = call float @returns_negative_nonzero() +; CHECK-NEXT: ret float [[POSITIVE]] +; + %positive = call float @returns_positive() + %neg.nonzero = call float @returns_negative_nonzero() + %result = call float @llvm.maximum.f32(float %positive, float %neg.nonzero) + ret float %result +} + +define nofpclass(snan) float @negative_or_zero__maximum__positive_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @negative_or_zero__maximum__positive_or_zero() { +; CHECK-NEXT: [[NEG_NONZERO:%.*]] = call float @returns_negative_nonzero() +; CHECK-NEXT: [[POSITIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[NEG_NONZERO]], float [[POSITIVE_OR_ZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %neg.nonzero = call float @returns_negative_nonzero() + %positive.or.zero = call float @returns_positive_or_zero() + %result = call float @llvm.maximum.f32(float %neg.nonzero, float %positive.or.zero) + ret float %result +} + +define nofpclass(snan) float @positive_or_zero__maximum__negative_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @positive_or_zero__maximum__negative_or_zero() { +; CHECK-NEXT: [[POSITIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() +; CHECK-NEXT: [[NEG_NONZERO:%.*]] = call float @returns_negative_nonzero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[POSITIVE_OR_ZERO]], float [[NEG_NONZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %positive.or.zero = call float @returns_positive_or_zero() + %neg.nonzero = call float @returns_negative_nonzero() + %result = call float @llvm.maximum.f32(float %positive.or.zero, float %neg.nonzero) + ret float %result +} + +define nofpclass(snan) float @positive_or_zero__maximum__negative() { +; CHECK-LABEL: define nofpclass(snan) float @positive_or_zero__maximum__negative() { +; CHECK-NEXT: [[POS_NONZERO:%.*]] = call float @returns_positive_nonzero() +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: ret float [[POS_NONZERO]] +; + %pos.nonzero = call float @returns_positive_nonzero() + %negative = call float @returns_negative() + %result = call float @llvm.maximum.f32(float %pos.nonzero, float %negative) + ret float %result +} + +define nofpclass(snan) float @negative__maximum__positive_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @negative__maximum__positive_or_zero() { +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: [[POS_NONZERO:%.*]] = call float @returns_positive_nonzero() +; CHECK-NEXT: ret float [[POS_NONZERO]] +; + %negative = call float @returns_negative() + %pos.nonzero = call float @returns_positive_nonzero() + %result = call float @llvm.maximum.f32(float %negative, float %pos.nonzero) + ret float %result +} + +define nofpclass(snan) float @positive_or_zero__maximum__negative_or_nan() { +; CHECK-LABEL: define nofpclass(snan) float @positive_or_zero__maximum__negative_or_nan() { +; CHECK-NEXT: [[POS_NONZERO:%.*]] = call float @returns_positive_nonzero() +; CHECK-NEXT: [[NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan() +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[POS_NONZERO]], float [[NEGATIVE_OR_NAN]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %pos.nonzero = call float @returns_positive_nonzero() + %negative.or.nan = call float @returns_negative_or_nan() + %result = call float @llvm.maximum.f32(float %pos.nonzero, float %negative.or.nan) + ret float %result +} + +define nofpclass(snan) float @negative_or_nan__maximum__positive_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @negative_or_nan__maximum__positive_or_zero() { +; CHECK-NEXT: [[NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan() +; CHECK-NEXT: [[POS_NONZERO:%.*]] = call float @returns_positive_nonzero() +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NEGATIVE_OR_NAN]], float [[POS_NONZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %negative.or.nan = call float @returns_negative_or_nan() + %pos.nonzero = call float @returns_positive_nonzero() + %result = call float @llvm.maximum.f32(float %negative.or.nan, float %pos.nonzero) + ret float %result +} + +define nofpclass(snan) float @positive_or_zero_or_nan__maximum__negative() { +; CHECK-LABEL: define nofpclass(snan) float @positive_or_zero_or_nan__maximum__negative() { +; CHECK-NEXT: [[POS_NONZERO_OR_NAN:%.*]] = call float @returns_positive_nonzero_or_nan() +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: ret float [[POS_NONZERO_OR_NAN]] +; + %pos.nonzero.or.nan = call float @returns_positive_nonzero_or_nan() + %negative = call float @returns_negative() + %result = call float @llvm.maximum.f32(float %pos.nonzero.or.nan, float %negative) + ret float %result +} + +define nofpclass(snan) float @negative__maximum__positive_or_zero_or_nan() { +; CHECK-LABEL: define nofpclass(snan) float @negative__maximum__positive_or_zero_or_nan() { +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: [[POS_NONZERO_OR_NAN:%.*]] = call float @returns_positive_nonzero_or_nan() +; CHECK-NEXT: ret float [[POS_NONZERO_OR_NAN]] +; + %negative = call float @returns_negative() + %pos.nonzero.or.nan = call float @returns_positive_nonzero_or_nan() + %result = call float @llvm.maximum.f32(float %negative, float %pos.nonzero.or.nan) + ret float %result +} + +define nofpclass(snan) float @known_pnorm__maximum__known_psub() { +; CHECK-LABEL: define nofpclass(snan) float @known_pnorm__maximum__known_psub() { +; CHECK-NEXT: [[PNORM:%.*]] = call float @returns_pnorm() +; CHECK-NEXT: [[PSUB:%.*]] = call float @returns_psub() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[PNORM]], float [[PSUB]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %pnorm = call float @returns_pnorm() + %psub = call float @returns_psub() + %result = call float @llvm.maximum.f32(float %pnorm, float %psub) + ret float %result +} + +define nofpclass(snan) float @known_psub__maximum__known_pnorm() { +; CHECK-LABEL: define nofpclass(snan) float @known_psub__maximum__known_pnorm() { +; CHECK-NEXT: [[PSUB:%.*]] = call float @returns_psub() +; CHECK-NEXT: [[PNORM:%.*]] = call float @returns_pnorm() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[PSUB]], float [[PNORM]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %psub = call float @returns_psub() + %pnorm = call float @returns_pnorm() + %result = call float @llvm.maximum.f32(float %psub, float %pnorm) + ret float %result +} + +define nofpclass(snan) float @known_pinf__maximum__known_psub() { +; CHECK-LABEL: define nofpclass(snan) float @known_pinf__maximum__known_psub() { +; CHECK-NEXT: [[PINF:%.*]] = call float @returns_pinf() +; CHECK-NEXT: [[PSUB:%.*]] = call float @returns_psub() +; CHECK-NEXT: ret float 0x7FF0000000000000 +; + %pinf = call float @returns_pinf() + %psub = call float @returns_psub() + %result = call float @llvm.maximum.f32(float %pinf, float %psub) + ret float %result +} + +define nofpclass(snan) float @known_psub__maximum__known_pinf() { +; CHECK-LABEL: define nofpclass(snan) float @known_psub__maximum__known_pinf() { +; CHECK-NEXT: [[PSUB:%.*]] = call float @returns_psub() +; CHECK-NEXT: [[PINF:%.*]] = call float @returns_pinf() +; CHECK-NEXT: ret float 0x7FF0000000000000 +; + %psub = call float @returns_psub() + %pinf = call float @returns_pinf() + %result = call float @llvm.maximum.f32(float %psub, float %pinf) + ret float %result +} + +define nofpclass(snan) float @known_nnorm__maximum__known_nsub() { +; CHECK-LABEL: define nofpclass(snan) float @known_nnorm__maximum__known_nsub() { +; CHECK-NEXT: [[NNORM:%.*]] = call float @returns_nnorm() +; CHECK-NEXT: [[NSUB:%.*]] = call float @returns_nsub() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[NNORM]], float [[NSUB]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %nnorm = call float @returns_nnorm() + %nsub = call float @returns_nsub() + %result = call float @llvm.maximum.f32(float %nnorm, float %nsub) + ret float %result +} + +define nofpclass(snan) float @known_nsub__maximum__known_nnorm() { +; CHECK-LABEL: define nofpclass(snan) float @known_nsub__maximum__known_nnorm() { +; CHECK-NEXT: [[NSUB:%.*]] = call float @returns_nsub() +; CHECK-NEXT: [[NNORM:%.*]] = call float @returns_nnorm() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[NSUB]], float [[NNORM]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %nsub = call float @returns_nsub() + %nnorm = call float @returns_nnorm() + %result = call float @llvm.maximum.f32(float %nsub, float %nnorm) + ret float %result +} + +define nofpclass(snan) float @known_ninf__maximum__known_nsub() { +; CHECK-LABEL: define nofpclass(snan) float @known_ninf__maximum__known_nsub() { +; CHECK-NEXT: [[NINF:%.*]] = call float @returns_ninf() +; CHECK-NEXT: [[NSUB:%.*]] = call float @returns_nsub() +; CHECK-NEXT: ret float [[NSUB]] +; + %ninf = call float @returns_ninf() + %nsub = call float @returns_nsub() + %result = call float @llvm.maximum.f32(float %ninf, float %nsub) + ret float %result +} + +define nofpclass(snan) float @known_nsub__maximum__known_ninf() { +; CHECK-LABEL: define nofpclass(snan) float @known_nsub__maximum__known_ninf() { +; CHECK-NEXT: [[NSUB:%.*]] = call float @returns_nsub() +; CHECK-NEXT: [[NINF:%.*]] = call float @returns_ninf() +; CHECK-NEXT: ret float [[NSUB]] +; + %nsub = call float @returns_nsub() + %ninf = call float @returns_ninf() + %result = call float @llvm.maximum.f32(float %nsub, float %ninf) + ret float %result +} + !0 = !{} attributes #0 = { "denormal-fp-math"="preserve-sign,preserve-sign" } diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximumnum.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximumnum.ll index a073e58eef8a9..c8f48c8ef3171 100644 --- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximumnum.ll +++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximumnum.ll @@ -30,6 +30,20 @@ declare nofpclass(pinf norm sub zero) float @returns_ninf_or_nan() declare nofpclass(norm sub zero nan) float @returns_inf() declare nofpclass(norm sub zero) float @returns_inf_or_nan() +declare nofpclass(inf pnorm sub zero nan) float @returns_nnorm() +declare nofpclass(inf nnorm sub zero nan) float @returns_pnorm() + +declare nofpclass(inf pnorm sub zero) float @returns_nnorm_or_nan() +declare nofpclass(inf nnorm sub zero) float @returns_pnorm_or_nan() + +declare nofpclass(inf norm psub zero nan) float @returns_nsub() +declare nofpclass(inf norm nsub zero nan) float @returns_psub() + +declare nofpclass(pinf pnorm psub zero nan) float @returns_negative_nonzero() +declare nofpclass(ninf nnorm nsub zero nan) float @returns_positive_nonzero() +declare nofpclass(pinf pnorm psub zero) float @returns_negative_nonzero_or_nan() +declare nofpclass(ninf nnorm nsub zero) float @returns_positive_nonzero_or_nan() + ; -> qnan define nofpclass(inf norm sub zero) float @ret_only_nan(float %x, float %y) { ; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_only_nan( @@ -372,6 +386,32 @@ define nofpclass(snan) float @cannot_fold_negative_or_zero__positive_or_zero_1() ret float %result } +define nofpclass(snan) float @nsz_fold_negative_or_zero__positive_or_zero_0() { +; CHECK-LABEL: define nofpclass(snan) float @nsz_fold_negative_or_zero__positive_or_zero_0() { +; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() +; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan nsz float @llvm.maximumnum.f32(float [[MUST_BE_NEGATIVE_OR_ZERO]], float [[MUST_BE_POSITIVE_OR_ZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %must.be.negative.or.zero = call float @returns_positive_or_zero() + %must.be.positive.or.zero = call float @returns_negative_or_zero() + %result = call nsz float @llvm.maximumnum.f32(float %must.be.negative.or.zero, float %must.be.positive.or.zero) + ret float %result +} + +define nofpclass(snan) float @nsz_fold_negative_or_zero__positive_or_zero_1() { +; CHECK-LABEL: define nofpclass(snan) float @nsz_fold_negative_or_zero__positive_or_zero_1() { +; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() +; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan nsz float @llvm.maximumnum.f32(float [[MUST_BE_POSITIVE_OR_ZERO]], float [[MUST_BE_NEGATIVE_OR_ZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %must.be.negative.or.zero = call float @returns_positive_or_zero() + %must.be.positive.or.zero = call float @returns_negative_or_zero() + %result = call nsz float @llvm.maximumnum.f32(float %must.be.positive.or.zero, float %must.be.negative.or.zero) + ret float %result +} + define nofpclass(nsub) float @lhs_must_be_pinf_or_nan(float %unknown, float nofpclass(ninf norm zero sub) %must.be.pinf.or.nan) { ; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_pinf_or_nan( ; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(ninf zero sub norm) [[MUST_BE_PINF_OR_NAN:%.*]]) { @@ -1700,6 +1740,358 @@ define nofpclass(snan) float @not_nan__maximumnum_noundef_md__not_nan(float nofp ret float %result } +define nofpclass(snan) float @select_is_positive_or_0__maximumnum__nnorm_0(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__maximumnum__nnorm_0( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[NNORM:%.*]] = call float @returns_nnorm() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximumnum.f32(float [[SELECT]], float [[NNORM]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %nnorm = call float @returns_nnorm() + %result = call float @llvm.maximumnum.f32(float %select, float %nnorm) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__maximumnum__nnorm_1(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__maximumnum__nnorm_1( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[NNORM:%.*]] = call float @returns_nnorm() +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximumnum.f32(float [[NNORM]], float [[SELECT]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %nnorm = call float @returns_nnorm() + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %result = call float @llvm.maximumnum.f32(float %nnorm, float %select) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__maximumnum__nnorm_or_nan_0(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__maximumnum__nnorm_or_nan_0( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[NNORM_OR_NAN:%.*]] = call float @returns_nnorm_or_nan() +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[SELECT]], float [[NNORM_OR_NAN]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %nnorm.or.nan = call float @returns_nnorm_or_nan() + %result = call float @llvm.maximumnum.f32(float %select, float %nnorm.or.nan) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__maximumnum__nnorm_or_nan_1(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__maximumnum__nnorm_or_nan_1( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[NNORM_OR_NAN:%.*]] = call float @returns_nnorm_or_nan() +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NNORM_OR_NAN]], float [[SELECT]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %nnorm.or.nan = call float @returns_nnorm_or_nan() + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %result = call float @llvm.maximumnum.f32(float %nnorm.or.nan, float %select) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__maximumnum__negative(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__maximumnum__negative( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximumnum.f32(float [[SELECT]], float [[NEGATIVE]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %negative = call float @returns_negative() + %result = call float @llvm.maximumnum.f32(float %select, float %negative) + ret float %result +} + +define nofpclass(snan) float @negative__maximumnum__select_is_positive_or_0(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @negative__maximumnum__select_is_positive_or_0( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximumnum.f32(float [[NEGATIVE]], float [[SELECT]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %negative = call float @returns_negative() + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %result = call float @llvm.maximumnum.f32(float %negative, float %select) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__maximumnum__negative_or_zero(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__maximumnum__negative_or_zero( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[NEGATIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximumnum.f32(float [[SELECT]], float [[NEGATIVE_OR_ZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %negative.or.zero = call float @returns_negative_or_zero() + %result = call float @llvm.maximumnum.f32(float %select, float %negative.or.zero) + ret float %result +} + +define nofpclass(snan) float @negative_or_zero__maximumnum__select_is_positive_or_0(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @negative_or_zero__maximumnum__select_is_positive_or_0( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[NEGATIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximumnum.f32(float [[NEGATIVE_OR_ZERO]], float [[SELECT]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %negative.or.zero = call float @returns_negative_or_zero() + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %result = call float @llvm.maximumnum.f32(float %negative.or.zero, float %select) + ret float %result +} + +define nofpclass(snan) float @negative_or_zero__maximumnum__positive() { +; CHECK-LABEL: define nofpclass(snan) float @negative_or_zero__maximumnum__positive() { +; CHECK-NEXT: [[NEG_NONZERO:%.*]] = call float @returns_negative_nonzero() +; CHECK-NEXT: [[POSITIVE:%.*]] = call float @returns_positive() +; CHECK-NEXT: ret float [[POSITIVE]] +; + %neg.nonzero = call float @returns_negative_nonzero() + %positive = call float @returns_positive() + %result = call float @llvm.maximumnum.f32(float %neg.nonzero, float %positive) + ret float %result +} + +define nofpclass(snan) float @positive__maximumnum__negative_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @positive__maximumnum__negative_or_zero() { +; CHECK-NEXT: [[POSITIVE:%.*]] = call float @returns_positive() +; CHECK-NEXT: [[NEG_NONZERO:%.*]] = call float @returns_negative_nonzero() +; CHECK-NEXT: ret float [[POSITIVE]] +; + %positive = call float @returns_positive() + %neg.nonzero = call float @returns_negative_nonzero() + %result = call float @llvm.maximumnum.f32(float %positive, float %neg.nonzero) + ret float %result +} + +define nofpclass(snan) float @negative_or_zero__maximumnum__positive_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @negative_or_zero__maximumnum__positive_or_zero() { +; CHECK-NEXT: [[NEG_NONZERO:%.*]] = call float @returns_negative_nonzero() +; CHECK-NEXT: [[POSITIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximumnum.f32(float [[NEG_NONZERO]], float [[POSITIVE_OR_ZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %neg.nonzero = call float @returns_negative_nonzero() + %positive.or.zero = call float @returns_positive_or_zero() + %result = call float @llvm.maximumnum.f32(float %neg.nonzero, float %positive.or.zero) + ret float %result +} + +define nofpclass(snan) float @positive_or_zero__maximumnum__negative_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @positive_or_zero__maximumnum__negative_or_zero() { +; CHECK-NEXT: [[POSITIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() +; CHECK-NEXT: [[NEG_NONZERO:%.*]] = call float @returns_negative_nonzero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximumnum.f32(float [[POSITIVE_OR_ZERO]], float [[NEG_NONZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %positive.or.zero = call float @returns_positive_or_zero() + %neg.nonzero = call float @returns_negative_nonzero() + %result = call float @llvm.maximumnum.f32(float %positive.or.zero, float %neg.nonzero) + ret float %result +} + +define nofpclass(snan) float @positive_or_zero__maximumnum__negative() { +; CHECK-LABEL: define nofpclass(snan) float @positive_or_zero__maximumnum__negative() { +; CHECK-NEXT: [[POS_NONZERO:%.*]] = call float @returns_positive_nonzero() +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: ret float [[POS_NONZERO]] +; + %pos.nonzero = call float @returns_positive_nonzero() + %negative = call float @returns_negative() + %result = call float @llvm.maximumnum.f32(float %pos.nonzero, float %negative) + ret float %result +} + +define nofpclass(snan) float @negative__maximumnum__positive_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @negative__maximumnum__positive_or_zero() { +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: [[POS_NONZERO:%.*]] = call float @returns_positive_nonzero() +; CHECK-NEXT: ret float [[POS_NONZERO]] +; + %negative = call float @returns_negative() + %pos.nonzero = call float @returns_positive_nonzero() + %result = call float @llvm.maximumnum.f32(float %negative, float %pos.nonzero) + ret float %result +} + +define nofpclass(snan) float @positive_or_zero__maximumnum__negative_or_nan() { +; CHECK-LABEL: define nofpclass(snan) float @positive_or_zero__maximumnum__negative_or_nan() { +; CHECK-NEXT: [[POS_NONZERO:%.*]] = call float @returns_positive_nonzero() +; CHECK-NEXT: [[NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan() +; CHECK-NEXT: ret float [[POS_NONZERO]] +; + %pos.nonzero = call float @returns_positive_nonzero() + %negative.or.nan = call float @returns_negative_or_nan() + %result = call float @llvm.maximumnum.f32(float %pos.nonzero, float %negative.or.nan) + ret float %result +} + +define nofpclass(snan) float @negative_or_nan__maximumnum__positive_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @negative_or_nan__maximumnum__positive_or_zero() { +; CHECK-NEXT: [[NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan() +; CHECK-NEXT: [[POS_NONZERO:%.*]] = call float @returns_positive_nonzero() +; CHECK-NEXT: ret float [[POS_NONZERO]] +; + %negative.or.nan = call float @returns_negative_or_nan() + %pos.nonzero = call float @returns_positive_nonzero() + %result = call float @llvm.maximumnum.f32(float %negative.or.nan, float %pos.nonzero) + ret float %result +} + +define nofpclass(snan) float @positive_or_zero_or_nan__maximumnum__negative() { +; CHECK-LABEL: define nofpclass(snan) float @positive_or_zero_or_nan__maximumnum__negative() { +; CHECK-NEXT: [[POS_NONZERO_OR_NAN:%.*]] = call float @returns_positive_nonzero_or_nan() +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[POS_NONZERO_OR_NAN]], float [[NEGATIVE]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %pos.nonzero.or.nan = call float @returns_positive_nonzero_or_nan() + %negative = call float @returns_negative() + %result = call float @llvm.maximumnum.f32(float %pos.nonzero.or.nan, float %negative) + ret float %result +} + +define nofpclass(snan) float @negative__maximumnum__positive_or_zero_or_nan() { +; CHECK-LABEL: define nofpclass(snan) float @negative__maximumnum__positive_or_zero_or_nan() { +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: [[POS_NONZERO_OR_NAN:%.*]] = call float @returns_positive_nonzero_or_nan() +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NEGATIVE]], float [[POS_NONZERO_OR_NAN]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %negative = call float @returns_negative() + %pos.nonzero.or.nan = call float @returns_positive_nonzero_or_nan() + %result = call float @llvm.maximumnum.f32(float %negative, float %pos.nonzero.or.nan) + ret float %result +} + +define nofpclass(snan) float @known_pnorm__maximumnum__known_psub() { +; CHECK-LABEL: define nofpclass(snan) float @known_pnorm__maximumnum__known_psub() { +; CHECK-NEXT: [[PNORM:%.*]] = call float @returns_pnorm() +; CHECK-NEXT: [[PSUB:%.*]] = call float @returns_psub() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximumnum.f32(float [[PNORM]], float [[PSUB]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %pnorm = call float @returns_pnorm() + %psub = call float @returns_psub() + %result = call float @llvm.maximumnum.f32(float %pnorm, float %psub) + ret float %result +} + +define nofpclass(snan) float @known_psub__maximumnum__known_pnorm() { +; CHECK-LABEL: define nofpclass(snan) float @known_psub__maximumnum__known_pnorm() { +; CHECK-NEXT: [[PSUB:%.*]] = call float @returns_psub() +; CHECK-NEXT: [[PNORM:%.*]] = call float @returns_pnorm() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximumnum.f32(float [[PSUB]], float [[PNORM]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %psub = call float @returns_psub() + %pnorm = call float @returns_pnorm() + %result = call float @llvm.maximumnum.f32(float %psub, float %pnorm) + ret float %result +} + +define nofpclass(snan) float @known_pinf__maximumnum__known_psub() { +; CHECK-LABEL: define nofpclass(snan) float @known_pinf__maximumnum__known_psub() { +; CHECK-NEXT: [[PINF:%.*]] = call float @returns_pinf() +; CHECK-NEXT: [[PSUB:%.*]] = call float @returns_psub() +; CHECK-NEXT: ret float 0x7FF0000000000000 +; + %pinf = call float @returns_pinf() + %psub = call float @returns_psub() + %result = call float @llvm.maximumnum.f32(float %pinf, float %psub) + ret float %result +} + +define nofpclass(snan) float @known_psub__maximumnum__known_pinf() { +; CHECK-LABEL: define nofpclass(snan) float @known_psub__maximumnum__known_pinf() { +; CHECK-NEXT: [[PSUB:%.*]] = call float @returns_psub() +; CHECK-NEXT: [[PINF:%.*]] = call float @returns_pinf() +; CHECK-NEXT: ret float 0x7FF0000000000000 +; + %psub = call float @returns_psub() + %pinf = call float @returns_pinf() + %result = call float @llvm.maximumnum.f32(float %psub, float %pinf) + ret float %result +} + +define nofpclass(snan) float @known_nnorm__maximumnum__known_nsub() { +; CHECK-LABEL: define nofpclass(snan) float @known_nnorm__maximumnum__known_nsub() { +; CHECK-NEXT: [[NNORM:%.*]] = call float @returns_nnorm() +; CHECK-NEXT: [[NSUB:%.*]] = call float @returns_nsub() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximumnum.f32(float [[NNORM]], float [[NSUB]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %nnorm = call float @returns_nnorm() + %nsub = call float @returns_nsub() + %result = call float @llvm.maximumnum.f32(float %nnorm, float %nsub) + ret float %result +} + +define nofpclass(snan) float @known_nsub__maximumnum__known_nnorm() { +; CHECK-LABEL: define nofpclass(snan) float @known_nsub__maximumnum__known_nnorm() { +; CHECK-NEXT: [[NSUB:%.*]] = call float @returns_nsub() +; CHECK-NEXT: [[NNORM:%.*]] = call float @returns_nnorm() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximumnum.f32(float [[NSUB]], float [[NNORM]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %nsub = call float @returns_nsub() + %nnorm = call float @returns_nnorm() + %result = call float @llvm.maximumnum.f32(float %nsub, float %nnorm) + ret float %result +} + +define nofpclass(snan) float @known_ninf__maximumnum__known_nsub() { +; CHECK-LABEL: define nofpclass(snan) float @known_ninf__maximumnum__known_nsub() { +; CHECK-NEXT: [[NINF:%.*]] = call float @returns_ninf() +; CHECK-NEXT: [[NSUB:%.*]] = call float @returns_nsub() +; CHECK-NEXT: ret float [[NSUB]] +; + %ninf = call float @returns_ninf() + %nsub = call float @returns_nsub() + %result = call float @llvm.maximumnum.f32(float %ninf, float %nsub) + ret float %result +} + +define nofpclass(snan) float @known_nsub__maximumnum__known_ninf() { +; CHECK-LABEL: define nofpclass(snan) float @known_nsub__maximumnum__known_ninf() { +; CHECK-NEXT: [[NSUB:%.*]] = call float @returns_nsub() +; CHECK-NEXT: [[NINF:%.*]] = call float @returns_ninf() +; CHECK-NEXT: ret float [[NSUB]] +; + %nsub = call float @returns_nsub() + %ninf = call float @returns_ninf() + %result = call float @llvm.maximumnum.f32(float %nsub, float %ninf) + ret float %result +} + !0 = !{} attributes #0 = { "denormal-fp-math"="preserve-sign,preserve-sign" } diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-minimum.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-minimum.ll index 927d5b0f0705f..f840c211baf55 100644 --- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-minimum.ll +++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-minimum.ll @@ -30,6 +30,20 @@ declare nofpclass(pinf norm sub zero) float @returns_ninf_or_nan() declare nofpclass(norm sub zero nan) float @returns_inf() declare nofpclass(norm sub zero) float @returns_inf_or_nan() +declare nofpclass(inf pnorm sub zero nan) float @returns_nnorm() +declare nofpclass(inf nnorm sub zero nan) float @returns_pnorm() + +declare nofpclass(inf pnorm sub zero) float @returns_nnorm_or_nan() +declare nofpclass(inf nnorm sub zero) float @returns_pnorm_or_nan() + +declare nofpclass(inf norm psub zero nan) float @returns_nsub() +declare nofpclass(inf norm nsub zero nan) float @returns_psub() + +declare nofpclass(pinf pnorm psub zero nan) float @returns_negative_nonzero() +declare nofpclass(ninf nnorm nsub zero nan) float @returns_positive_nonzero() +declare nofpclass(pinf pnorm psub zero) float @returns_negative_nonzero_or_nan() +declare nofpclass(ninf nnorm nsub zero) float @returns_positive_nonzero_or_nan() + ; -> qnan define nofpclass(inf norm sub zero) float @ret_only_nan(float %x, float %y) { ; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_only_nan( @@ -372,6 +386,32 @@ define nofpclass(snan) float @cannot_fold_negative_or_zero__positive_or_zero_1() ret float %result } +define nofpclass(snan) float @nsz_fold_negative_or_zero__positive_or_zero_0() { +; CHECK-LABEL: define nofpclass(snan) float @nsz_fold_negative_or_zero__positive_or_zero_0() { +; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() +; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan nsz float @llvm.minimum.f32(float [[MUST_BE_NEGATIVE_OR_ZERO]], float [[MUST_BE_POSITIVE_OR_ZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %must.be.negative.or.zero = call float @returns_positive_or_zero() + %must.be.positive.or.zero = call float @returns_negative_or_zero() + %result = call nsz float @llvm.minimum.f32(float %must.be.negative.or.zero, float %must.be.positive.or.zero) + ret float %result +} + +define nofpclass(snan) float @nsz_fold_negative_or_zero__positive_or_zero_1() { +; CHECK-LABEL: define nofpclass(snan) float @nsz_fold_negative_or_zero__positive_or_zero_1() { +; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() +; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan nsz float @llvm.minimum.f32(float [[MUST_BE_POSITIVE_OR_ZERO]], float [[MUST_BE_NEGATIVE_OR_ZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %must.be.negative.or.zero = call float @returns_positive_or_zero() + %must.be.positive.or.zero = call float @returns_negative_or_zero() + %result = call nsz float @llvm.minimum.f32(float %must.be.positive.or.zero, float %must.be.negative.or.zero) + ret float %result +} + define nofpclass(nsub) float @lhs_must_be_pinf_or_nan(float %unknown, float nofpclass(ninf norm zero sub) %must.be.pinf.or.nan) { ; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_pinf_or_nan( ; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(ninf zero sub norm) [[MUST_BE_PINF_OR_NAN:%.*]]) { @@ -1694,6 +1734,359 @@ define nofpclass(snan) float @not_nan__minimum_noundef_md__not_nan(float nofpcla ret float %result } + +define nofpclass(snan) float @select_is_positive_or_0__minimum__nnorm_0(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__minimum__nnorm_0( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[NNORM:%.*]] = call float @returns_nnorm() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[SELECT]], float [[NNORM]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %nnorm = call float @returns_nnorm() + %result = call float @llvm.minimum.f32(float %select, float %nnorm) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__minimum__nnorm_1(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__minimum__nnorm_1( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[NNORM:%.*]] = call float @returns_nnorm() +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[NNORM]], float [[SELECT]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %nnorm = call float @returns_nnorm() + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %result = call float @llvm.minimum.f32(float %nnorm, float %select) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__minimum__nnorm_or_nan_0(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__minimum__nnorm_or_nan_0( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[NNORM_OR_NAN:%.*]] = call float @returns_nnorm_or_nan() +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[SELECT]], float [[NNORM_OR_NAN]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %nnorm.or.nan = call float @returns_nnorm_or_nan() + %result = call float @llvm.minimum.f32(float %select, float %nnorm.or.nan) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__minimum__nnorm_or_nan_1(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__minimum__nnorm_or_nan_1( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[NNORM_OR_NAN:%.*]] = call float @returns_nnorm_or_nan() +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[NNORM_OR_NAN]], float [[SELECT]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %nnorm.or.nan = call float @returns_nnorm_or_nan() + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %result = call float @llvm.minimum.f32(float %nnorm.or.nan, float %select) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__minimum__negative(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__minimum__negative( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[SELECT]], float [[NEGATIVE]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %negative = call float @returns_negative() + %result = call float @llvm.minimum.f32(float %select, float %negative) + ret float %result +} + +define nofpclass(snan) float @negative__minimum__select_is_positive_or_0(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @negative__minimum__select_is_positive_or_0( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[NEGATIVE]], float [[SELECT]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %negative = call float @returns_negative() + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %result = call float @llvm.minimum.f32(float %negative, float %select) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__minimum__negative_or_zero(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__minimum__negative_or_zero( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[NEGATIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[SELECT]], float [[NEGATIVE_OR_ZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %negative.or.zero = call float @returns_negative_or_zero() + %result = call float @llvm.minimum.f32(float %select, float %negative.or.zero) + ret float %result +} + +define nofpclass(snan) float @negative_or_zero__minimum__select_is_positive_or_0(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @negative_or_zero__minimum__select_is_positive_or_0( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[NEGATIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[NEGATIVE_OR_ZERO]], float [[SELECT]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %negative.or.zero = call float @returns_negative_or_zero() + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %result = call float @llvm.minimum.f32(float %negative.or.zero, float %select) + ret float %result +} + +define nofpclass(snan) float @negative_or_zero__minimum__positive() { +; CHECK-LABEL: define nofpclass(snan) float @negative_or_zero__minimum__positive() { +; CHECK-NEXT: [[NEG_NONZERO:%.*]] = call float @returns_negative_nonzero() +; CHECK-NEXT: [[POSITIVE:%.*]] = call float @returns_positive() +; CHECK-NEXT: ret float [[NEG_NONZERO]] +; + %neg.nonzero = call float @returns_negative_nonzero() + %positive = call float @returns_positive() + %result = call float @llvm.minimum.f32(float %neg.nonzero, float %positive) + ret float %result +} + +define nofpclass(snan) float @positive__minimum__negative_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @positive__minimum__negative_or_zero() { +; CHECK-NEXT: [[POSITIVE:%.*]] = call float @returns_positive() +; CHECK-NEXT: [[NEG_NONZERO:%.*]] = call float @returns_negative_nonzero() +; CHECK-NEXT: ret float [[NEG_NONZERO]] +; + %positive = call float @returns_positive() + %neg.nonzero = call float @returns_negative_nonzero() + %result = call float @llvm.minimum.f32(float %positive, float %neg.nonzero) + ret float %result +} + +define nofpclass(snan) float @negative_or_zero__minimum__positive_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @negative_or_zero__minimum__positive_or_zero() { +; CHECK-NEXT: [[NEG_NONZERO:%.*]] = call float @returns_negative_nonzero() +; CHECK-NEXT: [[POSITIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[NEG_NONZERO]], float [[POSITIVE_OR_ZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %neg.nonzero = call float @returns_negative_nonzero() + %positive.or.zero = call float @returns_positive_or_zero() + %result = call float @llvm.minimum.f32(float %neg.nonzero, float %positive.or.zero) + ret float %result +} + +define nofpclass(snan) float @positive_or_zero__minimum__negative_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @positive_or_zero__minimum__negative_or_zero() { +; CHECK-NEXT: [[POSITIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() +; CHECK-NEXT: [[NEG_NONZERO:%.*]] = call float @returns_negative_nonzero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[POSITIVE_OR_ZERO]], float [[NEG_NONZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %positive.or.zero = call float @returns_positive_or_zero() + %neg.nonzero = call float @returns_negative_nonzero() + %result = call float @llvm.minimum.f32(float %positive.or.zero, float %neg.nonzero) + ret float %result +} + +define nofpclass(snan) float @positive_or_zero__minimum__negative() { +; CHECK-LABEL: define nofpclass(snan) float @positive_or_zero__minimum__negative() { +; CHECK-NEXT: [[POS_NONZERO:%.*]] = call float @returns_positive_nonzero() +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: ret float [[NEGATIVE]] +; + %pos.nonzero = call float @returns_positive_nonzero() + %negative = call float @returns_negative() + %result = call float @llvm.minimum.f32(float %pos.nonzero, float %negative) + ret float %result +} + +define nofpclass(snan) float @negative__minimum__positive_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @negative__minimum__positive_or_zero() { +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: [[POS_NONZERO:%.*]] = call float @returns_positive_nonzero() +; CHECK-NEXT: ret float [[NEGATIVE]] +; + %negative = call float @returns_negative() + %pos.nonzero = call float @returns_positive_nonzero() + %result = call float @llvm.minimum.f32(float %negative, float %pos.nonzero) + ret float %result +} + +define nofpclass(snan) float @positive_or_zero__minimum__negative_or_nan() { +; CHECK-LABEL: define nofpclass(snan) float @positive_or_zero__minimum__negative_or_nan() { +; CHECK-NEXT: [[POS_NONZERO:%.*]] = call float @returns_positive_nonzero() +; CHECK-NEXT: [[NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan() +; CHECK-NEXT: ret float [[NEGATIVE_OR_NAN]] +; + %pos.nonzero = call float @returns_positive_nonzero() + %negative.or.nan = call float @returns_negative_or_nan() + %result = call float @llvm.minimum.f32(float %pos.nonzero, float %negative.or.nan) + ret float %result +} + +define nofpclass(snan) float @negative_or_nan__minimum__positive_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @negative_or_nan__minimum__positive_or_zero() { +; CHECK-NEXT: [[NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan() +; CHECK-NEXT: [[POS_NONZERO:%.*]] = call float @returns_positive_nonzero() +; CHECK-NEXT: ret float [[NEGATIVE_OR_NAN]] +; + %negative.or.nan = call float @returns_negative_or_nan() + %pos.nonzero = call float @returns_positive_nonzero() + %result = call float @llvm.minimum.f32(float %negative.or.nan, float %pos.nonzero) + ret float %result +} + +define nofpclass(snan) float @positive_or_zero_or_nan__minimum__negative() { +; CHECK-LABEL: define nofpclass(snan) float @positive_or_zero_or_nan__minimum__negative() { +; CHECK-NEXT: [[POS_NONZERO_OR_NAN:%.*]] = call float @returns_positive_nonzero_or_nan() +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[POS_NONZERO_OR_NAN]], float [[NEGATIVE]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %pos.nonzero.or.nan = call float @returns_positive_nonzero_or_nan() + %negative = call float @returns_negative() + %result = call float @llvm.minimum.f32(float %pos.nonzero.or.nan, float %negative) + ret float %result +} + +define nofpclass(snan) float @negative__minimum__positive_or_zero_or_nan() { +; CHECK-LABEL: define nofpclass(snan) float @negative__minimum__positive_or_zero_or_nan() { +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: [[POS_NONZERO_OR_NAN:%.*]] = call float @returns_positive_nonzero_or_nan() +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[NEGATIVE]], float [[POS_NONZERO_OR_NAN]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %negative = call float @returns_negative() + %pos.nonzero.or.nan = call float @returns_positive_nonzero_or_nan() + %result = call float @llvm.minimum.f32(float %negative, float %pos.nonzero.or.nan) + ret float %result +} + +define nofpclass(snan) float @known_pnorm__minimum__known_psub() { +; CHECK-LABEL: define nofpclass(snan) float @known_pnorm__minimum__known_psub() { +; CHECK-NEXT: [[PNORM:%.*]] = call float @returns_pnorm() +; CHECK-NEXT: [[PSUB:%.*]] = call float @returns_psub() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[PNORM]], float [[PSUB]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %pnorm = call float @returns_pnorm() + %psub = call float @returns_psub() + %result = call float @llvm.minimum.f32(float %pnorm, float %psub) + ret float %result +} + +define nofpclass(snan) float @known_psub__minimum__known_pnorm() { +; CHECK-LABEL: define nofpclass(snan) float @known_psub__minimum__known_pnorm() { +; CHECK-NEXT: [[PSUB:%.*]] = call float @returns_psub() +; CHECK-NEXT: [[PNORM:%.*]] = call float @returns_pnorm() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[PSUB]], float [[PNORM]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %psub = call float @returns_psub() + %pnorm = call float @returns_pnorm() + %result = call float @llvm.minimum.f32(float %psub, float %pnorm) + ret float %result +} + +define nofpclass(snan) float @known_pinf__minimum__known_psub() { +; CHECK-LABEL: define nofpclass(snan) float @known_pinf__minimum__known_psub() { +; CHECK-NEXT: [[PINF:%.*]] = call float @returns_pinf() +; CHECK-NEXT: [[PSUB:%.*]] = call float @returns_psub() +; CHECK-NEXT: ret float [[PSUB]] +; + %pinf = call float @returns_pinf() + %psub = call float @returns_psub() + %result = call float @llvm.minimum.f32(float %pinf, float %psub) + ret float %result +} + +define nofpclass(snan) float @known_psub__minimum__known_pinf() { +; CHECK-LABEL: define nofpclass(snan) float @known_psub__minimum__known_pinf() { +; CHECK-NEXT: [[PSUB:%.*]] = call float @returns_psub() +; CHECK-NEXT: [[PINF:%.*]] = call float @returns_pinf() +; CHECK-NEXT: ret float [[PSUB]] +; + %psub = call float @returns_psub() + %pinf = call float @returns_pinf() + %result = call float @llvm.minimum.f32(float %psub, float %pinf) + ret float %result +} + +define nofpclass(snan) float @known_nnorm__minimum__known_nsub() { +; CHECK-LABEL: define nofpclass(snan) float @known_nnorm__minimum__known_nsub() { +; CHECK-NEXT: [[NNORM:%.*]] = call float @returns_nnorm() +; CHECK-NEXT: [[NSUB:%.*]] = call float @returns_nsub() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[NNORM]], float [[NSUB]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %nnorm = call float @returns_nnorm() + %nsub = call float @returns_nsub() + %result = call float @llvm.minimum.f32(float %nnorm, float %nsub) + ret float %result +} + +define nofpclass(snan) float @known_nsub__minimum__known_nnorm() { +; CHECK-LABEL: define nofpclass(snan) float @known_nsub__minimum__known_nnorm() { +; CHECK-NEXT: [[NSUB:%.*]] = call float @returns_nsub() +; CHECK-NEXT: [[NNORM:%.*]] = call float @returns_nnorm() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[NSUB]], float [[NNORM]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %nsub = call float @returns_nsub() + %nnorm = call float @returns_nnorm() + %result = call float @llvm.minimum.f32(float %nsub, float %nnorm) + ret float %result +} + +define nofpclass(snan) float @known_ninf__minimum__known_nsub() { +; CHECK-LABEL: define nofpclass(snan) float @known_ninf__minimum__known_nsub() { +; CHECK-NEXT: [[NINF:%.*]] = call float @returns_ninf() +; CHECK-NEXT: [[NSUB:%.*]] = call float @returns_nsub() +; CHECK-NEXT: ret float 0xFFF0000000000000 +; + %ninf = call float @returns_ninf() + %nsub = call float @returns_nsub() + %result = call float @llvm.minimum.f32(float %ninf, float %nsub) + ret float %result +} + +define nofpclass(snan) float @known_nsub__minimum__known_ninf() { +; CHECK-LABEL: define nofpclass(snan) float @known_nsub__minimum__known_ninf() { +; CHECK-NEXT: [[NSUB:%.*]] = call float @returns_nsub() +; CHECK-NEXT: [[NINF:%.*]] = call float @returns_ninf() +; CHECK-NEXT: ret float 0xFFF0000000000000 +; + %nsub = call float @returns_nsub() + %ninf = call float @returns_ninf() + %result = call float @llvm.minimum.f32(float %nsub, float %ninf) + ret float %result +} + !0 = !{} attributes #0 = { "denormal-fp-math"="preserve-sign,preserve-sign" } diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-minimumnum.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-minimumnum.ll index 9ff1d7f403bf7..6c78b4515f76d 100644 --- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-minimumnum.ll +++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-minimumnum.ll @@ -30,6 +30,20 @@ declare nofpclass(pinf norm sub zero) float @returns_ninf_or_nan() declare nofpclass(norm sub zero nan) float @returns_inf() declare nofpclass(norm sub zero) float @returns_inf_or_nan() +declare nofpclass(inf pnorm sub zero nan) float @returns_nnorm() +declare nofpclass(inf nnorm sub zero nan) float @returns_pnorm() + +declare nofpclass(inf pnorm sub zero) float @returns_nnorm_or_nan() +declare nofpclass(inf nnorm sub zero) float @returns_pnorm_or_nan() + +declare nofpclass(inf norm psub zero nan) float @returns_nsub() +declare nofpclass(inf norm nsub zero nan) float @returns_psub() + +declare nofpclass(pinf pnorm psub zero nan) float @returns_negative_nonzero() +declare nofpclass(ninf nnorm nsub zero nan) float @returns_positive_nonzero() +declare nofpclass(pinf pnorm psub zero) float @returns_negative_nonzero_or_nan() +declare nofpclass(ninf nnorm nsub zero) float @returns_positive_nonzero_or_nan() + ; -> qnan define nofpclass(inf norm sub zero) float @ret_only_nan(float %x, float %y) { ; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_only_nan( @@ -370,6 +384,32 @@ define nofpclass(snan) float @cannot_fold_negative_or_zero__positive_or_zero_1() ret float %result } +define nofpclass(snan) float @nsz_fold_negative_or_zero__positive_or_zero_0() { +; CHECK-LABEL: define nofpclass(snan) float @nsz_fold_negative_or_zero__positive_or_zero_0() { +; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() +; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan nsz float @llvm.minimumnum.f32(float [[MUST_BE_NEGATIVE_OR_ZERO]], float [[MUST_BE_POSITIVE_OR_ZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %must.be.negative.or.zero = call float @returns_positive_or_zero() + %must.be.positive.or.zero = call float @returns_negative_or_zero() + %result = call nsz float @llvm.minimumnum.f32(float %must.be.negative.or.zero, float %must.be.positive.or.zero) + ret float %result +} + +define nofpclass(snan) float @nsz_fold_negative_or_zero__positive_or_zero_1() { +; CHECK-LABEL: define nofpclass(snan) float @nsz_fold_negative_or_zero__positive_or_zero_1() { +; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() +; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan nsz float @llvm.minimumnum.f32(float [[MUST_BE_POSITIVE_OR_ZERO]], float [[MUST_BE_NEGATIVE_OR_ZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %must.be.negative.or.zero = call float @returns_positive_or_zero() + %must.be.positive.or.zero = call float @returns_negative_or_zero() + %result = call nsz float @llvm.minimumnum.f32(float %must.be.positive.or.zero, float %must.be.negative.or.zero) + ret float %result +} + define nofpclass(nsub) float @lhs_must_be_pinf_or_nan(float %unknown, float nofpclass(ninf norm zero sub) %must.be.pinf.or.nan) { ; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_pinf_or_nan( ; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(ninf zero sub norm) [[MUST_BE_PINF_OR_NAN:%.*]]) { @@ -1698,6 +1738,358 @@ define nofpclass(snan) float @not_nan__minimumnum_noundef_md__not_nan(float nofp ret float %result } +define nofpclass(snan) float @select_is_positive_or_0__minimumnum__nnorm_0(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__minimumnum__nnorm_0( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[NNORM:%.*]] = call float @returns_nnorm() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimumnum.f32(float [[SELECT]], float [[NNORM]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %nnorm = call float @returns_nnorm() + %result = call float @llvm.minimumnum.f32(float %select, float %nnorm) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__minimumnum__nnorm_1(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__minimumnum__nnorm_1( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[NNORM:%.*]] = call float @returns_nnorm() +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimumnum.f32(float [[NNORM]], float [[SELECT]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %nnorm = call float @returns_nnorm() + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %result = call float @llvm.minimumnum.f32(float %nnorm, float %select) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__minimumnum__nnorm_or_nan_0(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__minimumnum__nnorm_or_nan_0( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[NNORM_OR_NAN:%.*]] = call float @returns_nnorm_or_nan() +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[SELECT]], float [[NNORM_OR_NAN]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %nnorm.or.nan = call float @returns_nnorm_or_nan() + %result = call float @llvm.minimumnum.f32(float %select, float %nnorm.or.nan) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__minimumnum__nnorm_or_nan_1(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__minimumnum__nnorm_or_nan_1( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[NNORM_OR_NAN:%.*]] = call float @returns_nnorm_or_nan() +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NNORM_OR_NAN]], float [[SELECT]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %nnorm.or.nan = call float @returns_nnorm_or_nan() + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %result = call float @llvm.minimumnum.f32(float %nnorm.or.nan, float %select) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__minimumnum__negative(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__minimumnum__negative( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimumnum.f32(float [[SELECT]], float [[NEGATIVE]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %negative = call float @returns_negative() + %result = call float @llvm.minimumnum.f32(float %select, float %negative) + ret float %result +} + +define nofpclass(snan) float @negative__minimumnum__select_is_positive_or_0(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @negative__minimumnum__select_is_positive_or_0( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimumnum.f32(float [[NEGATIVE]], float [[SELECT]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %negative = call float @returns_negative() + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %result = call float @llvm.minimumnum.f32(float %negative, float %select) + ret float %result +} + +define nofpclass(snan) float @select_is_positive_or_0__minimumnum__negative_or_zero(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @select_is_positive_or_0__minimumnum__negative_or_zero( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[NEGATIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimumnum.f32(float [[SELECT]], float [[NEGATIVE_OR_ZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %negative.or.zero = call float @returns_negative_or_zero() + %result = call float @llvm.minimumnum.f32(float %select, float %negative.or.zero) + ret float %result +} + +define nofpclass(snan) float @negative_or_zero__minimumnum__select_is_positive_or_0(float noundef %arg) { +; CHECK-LABEL: define nofpclass(snan) float @negative_or_zero__minimumnum__select_is_positive_or_0( +; CHECK-SAME: float noundef [[ARG:%.*]]) { +; CHECK-NEXT: [[NEGATIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() +; CHECK-NEXT: [[IS_POS_OR_ZERO:%.*]] = fcmp oge float [[ARG]], 0.000000e+00 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_POS_OR_ZERO]], float [[ARG]], float 0.000000e+00 +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimumnum.f32(float [[NEGATIVE_OR_ZERO]], float [[SELECT]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %negative.or.zero = call float @returns_negative_or_zero() + %is.pos.or.zero = fcmp oge float %arg, 0.0 + %select = select i1 %is.pos.or.zero, float %arg, float 0.0 + %result = call float @llvm.minimumnum.f32(float %negative.or.zero, float %select) + ret float %result +} + +define nofpclass(snan) float @negative_or_zero__minimumnum__positive() { +; CHECK-LABEL: define nofpclass(snan) float @negative_or_zero__minimumnum__positive() { +; CHECK-NEXT: [[NEG_NONZERO:%.*]] = call float @returns_negative_nonzero() +; CHECK-NEXT: [[POSITIVE:%.*]] = call float @returns_positive() +; CHECK-NEXT: ret float [[NEG_NONZERO]] +; + %neg.nonzero = call float @returns_negative_nonzero() + %positive = call float @returns_positive() + %result = call float @llvm.minimumnum.f32(float %neg.nonzero, float %positive) + ret float %result +} + +define nofpclass(snan) float @positive__minimumnum__negative_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @positive__minimumnum__negative_or_zero() { +; CHECK-NEXT: [[POSITIVE:%.*]] = call float @returns_positive() +; CHECK-NEXT: [[NEG_NONZERO:%.*]] = call float @returns_negative_nonzero() +; CHECK-NEXT: ret float [[NEG_NONZERO]] +; + %positive = call float @returns_positive() + %neg.nonzero = call float @returns_negative_nonzero() + %result = call float @llvm.minimumnum.f32(float %positive, float %neg.nonzero) + ret float %result +} + +define nofpclass(snan) float @negative_or_zero__minimumnum__positive_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @negative_or_zero__minimumnum__positive_or_zero() { +; CHECK-NEXT: [[NEG_NONZERO:%.*]] = call float @returns_negative_nonzero() +; CHECK-NEXT: [[POSITIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimumnum.f32(float [[NEG_NONZERO]], float [[POSITIVE_OR_ZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %neg.nonzero = call float @returns_negative_nonzero() + %positive.or.zero = call float @returns_positive_or_zero() + %result = call float @llvm.minimumnum.f32(float %neg.nonzero, float %positive.or.zero) + ret float %result +} + +define nofpclass(snan) float @positive_or_zero__minimumnum__negative_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @positive_or_zero__minimumnum__negative_or_zero() { +; CHECK-NEXT: [[POSITIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() +; CHECK-NEXT: [[NEG_NONZERO:%.*]] = call float @returns_negative_nonzero() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimumnum.f32(float [[POSITIVE_OR_ZERO]], float [[NEG_NONZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %positive.or.zero = call float @returns_positive_or_zero() + %neg.nonzero = call float @returns_negative_nonzero() + %result = call float @llvm.minimumnum.f32(float %positive.or.zero, float %neg.nonzero) + ret float %result +} + +define nofpclass(snan) float @positive_or_zero__minimumnum__negative() { +; CHECK-LABEL: define nofpclass(snan) float @positive_or_zero__minimumnum__negative() { +; CHECK-NEXT: [[POS_NONZERO:%.*]] = call float @returns_positive_nonzero() +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: ret float [[NEGATIVE]] +; + %pos.nonzero = call float @returns_positive_nonzero() + %negative = call float @returns_negative() + %result = call float @llvm.minimumnum.f32(float %pos.nonzero, float %negative) + ret float %result +} + +define nofpclass(snan) float @negative__minimumnum__positive_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @negative__minimumnum__positive_or_zero() { +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: [[POS_NONZERO:%.*]] = call float @returns_positive_nonzero() +; CHECK-NEXT: ret float [[NEGATIVE]] +; + %negative = call float @returns_negative() + %pos.nonzero = call float @returns_positive_nonzero() + %result = call float @llvm.minimumnum.f32(float %negative, float %pos.nonzero) + ret float %result +} + +define nofpclass(snan) float @positive_or_zero__minimumnum__negative_or_nan() { +; CHECK-LABEL: define nofpclass(snan) float @positive_or_zero__minimumnum__negative_or_nan() { +; CHECK-NEXT: [[POS_NONZERO:%.*]] = call float @returns_positive_nonzero() +; CHECK-NEXT: [[NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan() +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[POS_NONZERO]], float [[NEGATIVE_OR_NAN]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %pos.nonzero = call float @returns_positive_nonzero() + %negative.or.nan = call float @returns_negative_or_nan() + %result = call float @llvm.minimumnum.f32(float %pos.nonzero, float %negative.or.nan) + ret float %result +} + +define nofpclass(snan) float @negative_or_nan__minimumnum__positive_or_zero() { +; CHECK-LABEL: define nofpclass(snan) float @negative_or_nan__minimumnum__positive_or_zero() { +; CHECK-NEXT: [[NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan() +; CHECK-NEXT: [[POS_NONZERO:%.*]] = call float @returns_positive_nonzero() +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NEGATIVE_OR_NAN]], float [[POS_NONZERO]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %negative.or.nan = call float @returns_negative_or_nan() + %pos.nonzero = call float @returns_positive_nonzero() + %result = call float @llvm.minimumnum.f32(float %negative.or.nan, float %pos.nonzero) + ret float %result +} + +define nofpclass(snan) float @positive_or_zero_or_nan__minimumnum__negative() { +; CHECK-LABEL: define nofpclass(snan) float @positive_or_zero_or_nan__minimumnum__negative() { +; CHECK-NEXT: [[POS_NONZERO_OR_NAN:%.*]] = call float @returns_positive_nonzero_or_nan() +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: ret float [[NEGATIVE]] +; + %pos.nonzero.or.nan = call float @returns_positive_nonzero_or_nan() + %negative = call float @returns_negative() + %result = call float @llvm.minimumnum.f32(float %pos.nonzero.or.nan, float %negative) + ret float %result +} + +define nofpclass(snan) float @negative__minimumnum__positive_or_zero_or_nan() { +; CHECK-LABEL: define nofpclass(snan) float @negative__minimumnum__positive_or_zero_or_nan() { +; CHECK-NEXT: [[NEGATIVE:%.*]] = call float @returns_negative() +; CHECK-NEXT: [[POS_NONZERO_OR_NAN:%.*]] = call float @returns_positive_nonzero_or_nan() +; CHECK-NEXT: ret float [[NEGATIVE]] +; + %negative = call float @returns_negative() + %pos.nonzero.or.nan = call float @returns_positive_nonzero_or_nan() + %result = call float @llvm.minimumnum.f32(float %negative, float %pos.nonzero.or.nan) + ret float %result +} + +define nofpclass(snan) float @known_pnorm__minimumnum__known_psub() { +; CHECK-LABEL: define nofpclass(snan) float @known_pnorm__minimumnum__known_psub() { +; CHECK-NEXT: [[PNORM:%.*]] = call float @returns_pnorm() +; CHECK-NEXT: [[PSUB:%.*]] = call float @returns_psub() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimumnum.f32(float [[PNORM]], float [[PSUB]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %pnorm = call float @returns_pnorm() + %psub = call float @returns_psub() + %result = call float @llvm.minimumnum.f32(float %pnorm, float %psub) + ret float %result +} + +define nofpclass(snan) float @known_psub__minimumnum__known_pnorm() { +; CHECK-LABEL: define nofpclass(snan) float @known_psub__minimumnum__known_pnorm() { +; CHECK-NEXT: [[PSUB:%.*]] = call float @returns_psub() +; CHECK-NEXT: [[PNORM:%.*]] = call float @returns_pnorm() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimumnum.f32(float [[PSUB]], float [[PNORM]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %psub = call float @returns_psub() + %pnorm = call float @returns_pnorm() + %result = call float @llvm.minimumnum.f32(float %psub, float %pnorm) + ret float %result +} + +define nofpclass(snan) float @known_pinf__minimumnum__known_psub() { +; CHECK-LABEL: define nofpclass(snan) float @known_pinf__minimumnum__known_psub() { +; CHECK-NEXT: [[PINF:%.*]] = call float @returns_pinf() +; CHECK-NEXT: [[PSUB:%.*]] = call float @returns_psub() +; CHECK-NEXT: ret float [[PSUB]] +; + %pinf = call float @returns_pinf() + %psub = call float @returns_psub() + %result = call float @llvm.minimumnum.f32(float %pinf, float %psub) + ret float %result +} + +define nofpclass(snan) float @known_psub__minimumnum__known_pinf() { +; CHECK-LABEL: define nofpclass(snan) float @known_psub__minimumnum__known_pinf() { +; CHECK-NEXT: [[PSUB:%.*]] = call float @returns_psub() +; CHECK-NEXT: [[PINF:%.*]] = call float @returns_pinf() +; CHECK-NEXT: ret float [[PSUB]] +; + %psub = call float @returns_psub() + %pinf = call float @returns_pinf() + %result = call float @llvm.minimumnum.f32(float %psub, float %pinf) + ret float %result +} + +define nofpclass(snan) float @known_nnorm__minimumnum__known_nsub() { +; CHECK-LABEL: define nofpclass(snan) float @known_nnorm__minimumnum__known_nsub() { +; CHECK-NEXT: [[NNORM:%.*]] = call float @returns_nnorm() +; CHECK-NEXT: [[NSUB:%.*]] = call float @returns_nsub() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimumnum.f32(float [[NNORM]], float [[NSUB]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %nnorm = call float @returns_nnorm() + %nsub = call float @returns_nsub() + %result = call float @llvm.minimumnum.f32(float %nnorm, float %nsub) + ret float %result +} + +define nofpclass(snan) float @known_nsub__minimumnum__known_nnorm() { +; CHECK-LABEL: define nofpclass(snan) float @known_nsub__minimumnum__known_nnorm() { +; CHECK-NEXT: [[NSUB:%.*]] = call float @returns_nsub() +; CHECK-NEXT: [[NNORM:%.*]] = call float @returns_nnorm() +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimumnum.f32(float [[NSUB]], float [[NNORM]]) +; CHECK-NEXT: ret float [[RESULT]] +; + %nsub = call float @returns_nsub() + %nnorm = call float @returns_nnorm() + %result = call float @llvm.minimumnum.f32(float %nsub, float %nnorm) + ret float %result +} + +define nofpclass(snan) float @known_ninf__minimumnum__known_nsub() { +; CHECK-LABEL: define nofpclass(snan) float @known_ninf__minimumnum__known_nsub() { +; CHECK-NEXT: [[NINF:%.*]] = call float @returns_ninf() +; CHECK-NEXT: [[NSUB:%.*]] = call float @returns_nsub() +; CHECK-NEXT: ret float 0xFFF0000000000000 +; + %ninf = call float @returns_ninf() + %nsub = call float @returns_nsub() + %result = call float @llvm.minimumnum.f32(float %ninf, float %nsub) + ret float %result +} + +define nofpclass(snan) float @known_nsub__minimumnum__known_ninf() { +; CHECK-LABEL: define nofpclass(snan) float @known_nsub__minimumnum__known_ninf() { +; CHECK-NEXT: [[NSUB:%.*]] = call float @returns_nsub() +; CHECK-NEXT: [[NINF:%.*]] = call float @returns_ninf() +; CHECK-NEXT: ret float 0xFFF0000000000000 +; + %nsub = call float @returns_nsub() + %ninf = call float @returns_ninf() + %result = call float @llvm.minimumnum.f32(float %nsub, float %ninf) + ret float %result +} + !0 = !{} attributes #0 = { "denormal-fp-math"="preserve-sign,preserve-sign" } _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
