[llvm-branch-commits] [llvm] InstCombine: Add more tests for min/max SimplifyDemandedFPClass (PR #175381)
Matt Arsenault via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sun Jan 11 09:36:24 PST 2026
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/175381
>From 64f4a16b3cd5b838c659a1d8a24b42b641f9fa1a Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
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" }
More information about the llvm-branch-commits
mailing list