[llvm-branch-commits] [llvm] InstCombine: Add baseline minimumnum/maximumnum SimplifyDemandedFPClass tests (PR #173976)

Matt Arsenault via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Dec 30 13:46:11 PST 2025


https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/173976

>From 731dc7d93a562b28e1bd4710aedac98ef611df23 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 30 Dec 2025 09:29:58 +0100
Subject: [PATCH] InstCombine: Add baseline minimumnum/maximumnum
 SimplifyDemandedFPClass tests

---
 .../simplify-demanded-fpclass-maximumnum.ll   | 1625 +++++++++++++++++
 .../simplify-demanded-fpclass-minimumnum.ll   | 1625 +++++++++++++++++
 2 files changed, 3250 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximumnum.ll
 create mode 100644 llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-minimumnum.ll

diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximumnum.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximumnum.ll
new file mode 100644
index 0000000000000..fcbe2df985ea5
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximumnum.ll
@@ -0,0 +1,1625 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+declare nofpclass(ninf nnorm nsub nzero nan) float @returns_positive()
+declare nofpclass(ninf nnorm nsub nzero) float @returns_positive_or_nan()
+
+declare nofpclass(pinf pnorm psub pzero nan) float @returns_negative()
+declare nofpclass(pinf pnorm psub pzero) float @returns_negative_or_nan()
+
+declare nofpclass(ninf nnorm nsub nan) float @returns_positive_or_zero()
+declare nofpclass(pinf pnorm psub nan) float @returns_negative_or_zero()
+
+declare nofpclass(ninf nnorm nsub) float @returns_positive_or_zero_or_nan()
+declare nofpclass(pinf pnorm psub) float @returns_negative_or_zero_or_nan()
+
+declare nofpclass(inf sub norm nan) float @returns_zero()
+declare nofpclass(inf sub norm) float @returns_zero_or_nan()
+declare nofpclass(inf sub norm nan pzero) float @returns_nzero()
+declare nofpclass(inf sub norm pzero) float @returns_nzero_or_nan()
+declare nofpclass(inf sub norm nan nzero) float @returns_pzero()
+declare nofpclass(inf sub norm nzero) float @returns_pzero_or_nan()
+declare nofpclass(inf norm sub zero) float @returns_nan()
+
+declare nofpclass(ninf norm sub zero nan) float @returns_pinf()
+declare nofpclass(ninf norm sub zero) float @returns_pinf_or_nan()
+
+declare nofpclass(pinf norm sub zero nan) float @returns_ninf()
+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()
+
+; -> 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(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(inf norm sub zero qnan) float @ret_only_snan(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(qnan inf zero sub norm) float @ret_only_snan(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(inf norm sub zero snan) float @ret_only_qnan(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(snan inf zero sub norm) float @ret_only_qnan(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(nan norm sub zero) float @ret_only_inf(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(nan zero sub norm) float @ret_only_inf(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(nan pinf norm sub zero) float @ret_only_ninf(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(nan pinf zero sub norm) float @ret_only_ninf(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    ret float 0xFFF0000000000000
+;
+  %result = call float @llvm.maximumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(nan ninf norm sub zero) float @ret_only_pinf(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(nan ninf zero sub norm) float @ret_only_pinf(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    ret float 0x7FF0000000000000
+;
+  %result = call float @llvm.maximumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(inf nan norm sub) float @ret_only_zero(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) float @ret_only_zero(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(inf nan norm sub nzero) float @ret_only_pzero(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(nan inf nzero sub norm) float @ret_only_pzero(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    ret float 0.000000e+00
+;
+  %result = call float @llvm.maximumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(inf nan norm sub pzero) float @ret_only_nzero(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(nan inf pzero sub norm) float @ret_only_nzero(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    ret float -0.000000e+00
+;
+  %result = call float @llvm.maximumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(inf) float @ret_no_infs(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(inf) float @ret_no_infs(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(nan inf) float @ret_no_nans_no_infs(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(nan inf) float @ret_no_nans_no_infs(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+; -> qnan
+define nofpclass(ninf nnorm nsub nzero) float @ret_known_positive_or_nan__maximumnum__negative_or_nan___negative_or_nan() {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_known_positive_or_nan__maximumnum__negative_or_nan___negative_or_nan() {
+; CHECK-NEXT:    [[MUST_BE_NEGATIVE_OR_NAN0:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[MUST_BE_NEGATIVE_OR_NAN1:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[MUST_BE_NEGATIVE_OR_NAN0]], float [[MUST_BE_NEGATIVE_OR_NAN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %must.be.negative.or.nan0 = call float @returns_negative_or_nan()
+  %must.be.negative.or.nan1 = call float @returns_negative_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %must.be.negative.or.nan0, float %must.be.negative.or.nan1)
+  ret float %result
+}
+
+; -> qnan
+define nofpclass(pinf pnorm psub pzero) float @ret_known_negative_or_nan__maximumnum__positive_or_nan___positive_or_nan() {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_known_negative_or_nan__maximumnum__positive_or_nan___positive_or_nan() {
+; CHECK-NEXT:    [[MUST_BE_POSITIVE_OR_NAN0:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[MUST_BE_POSITIVE_OR_NAN1:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[MUST_BE_POSITIVE_OR_NAN0]], float [[MUST_BE_POSITIVE_OR_NAN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %must.be.positive.or.nan0 = call float @returns_positive_or_nan()
+  %must.be.positive.or.nan1 = call float @returns_positive_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %must.be.positive.or.nan0, float %must.be.positive.or.nan1)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_positive_or_nan__maximumnum__known_negative_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_positive_or_nan__maximumnum__known_negative_or_nan() {
+; CHECK-NEXT:    [[MUST_BE_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[MUST_BE_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[MUST_BE_POSITIVE_OR_NAN]], float [[MUST_BE_NEGATIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %must.be.positive.or.nan = call float @returns_positive_or_nan()
+  %must.be.negative.or.nan = call float @returns_negative_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %must.be.positive.or.nan, float %must.be.negative.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_negative_or_nan__maximumnum__known_positive_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_negative_or_nan__maximumnum__known_positive_or_nan() {
+; CHECK-NEXT:    [[MUST_BE_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[MUST_BE_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[MUST_BE_NEGATIVE_OR_NAN]], float [[MUST_BE_POSITIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %must.be.negative.or.nan = call float @returns_negative_or_nan()
+  %must.be.positive.or.nan = call float @returns_positive_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %must.be.negative.or.nan, float %must.be.positive.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_positive_or_nan__maximumnum__known_negative() {
+; CHECK-LABEL: define nofpclass(snan) float @known_positive_or_nan__maximumnum__known_negative() {
+; CHECK-NEXT:    [[MUST_BE_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[MUST_BE_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[MUST_BE_POSITIVE_OR_NAN]], float [[MUST_BE_NEGATIVE]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %must.be.positive.or.nan = call float @returns_positive_or_nan()
+  %must.be.negative = call float @returns_negative()
+  %result = call float @llvm.maximumnum.f32(float %must.be.positive.or.nan, float %must.be.negative)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_negative__maximumnum__known_positive_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_negative__maximumnum__known_positive_or_nan() {
+; CHECK-NEXT:    [[MUST_BE_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[MUST_BE_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[MUST_BE_NEGATIVE]], float [[MUST_BE_POSITIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %must.be.negative = call float @returns_negative()
+  %must.be.positive.or.nan = call float @returns_positive_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %must.be.negative, float %must.be.positive.or.nan)
+  ret float %result
+}
+
+define nofpclass(ninf nnorm nsub nzero) float @ret_always_positive_or_nan__select_always_negative_or_unknown__maximumnum__unknown(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_always_positive_or_nan__select_always_negative_or_unknown__maximumnum__unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[SELECT_LHS]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative = call float @returns_negative()
+  %select.lhs = select i1 %cond, float %always.negative, float %unknown0
+  %result = call float @llvm.maximumnum.f32(float %select.lhs, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(ninf nnorm nsub nzero) float @ret_always_positive_or_nan__unknown__maximumnum__select_always_negative_or_unknown(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_always_positive_or_nan__unknown__maximumnum__select_always_negative_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative = call float @returns_negative()
+  %select.rhs = select i1 %cond, float %always.negative, float %unknown0
+  %result = call float @llvm.maximumnum.f32(float %unknown1, float %select.rhs)
+  ret float %result
+}
+
+define nofpclass(ninf nnorm nsub nzero nan) float @ret_always_positive__select_always_negative_or_unknown__maximumnum__unknown(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_always_positive__select_always_negative_or_unknown__maximumnum__unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[SELECT_LHS]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative = call float @returns_negative()
+  %select.lhs = select i1 %cond, float %always.negative, float %unknown0
+  %result = call float @llvm.maximumnum.f32(float %select.lhs, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(ninf nnorm nsub nzero nan) float @ret_always_positive__unknown__maximumnum__select_always_negative_or_unknown(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_always_positive__unknown__maximumnum__select_always_negative_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative = call float @returns_negative()
+  %select.rhs = select i1 %cond, float %always.negative, float %unknown0
+  %result = call float @llvm.maximumnum.f32(float %unknown1, float %select.rhs)
+  ret float %result
+}
+
+define nofpclass(ninf nnorm nsub nzero) float @ret_always_negative_or_nan__simplify_unneeded_lhs_rhs(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_always_negative_or_nan__simplify_unneeded_lhs_rhs(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE0:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE1:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE0]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[UNKNOWN1]], float [[ALWAYS_NEGATIVE1]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[SELECT_LHS]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative0 = call float @returns_negative()
+  %always.negative1 = call float @returns_negative()
+  %select.lhs = select i1 %cond, float %always.negative0, float %unknown0
+  %select.rhs = select i1 %cond, float %unknown1, float %always.negative1
+  %result = call float @llvm.maximumnum.f32(float %select.lhs, float %select.rhs)
+  ret float %result
+}
+
+define nofpclass(ninf nnorm nsub nzero nan) float @ret_always_negative__simplify_unneeded_lhs_rhs(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_always_negative__simplify_unneeded_lhs_rhs(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE0:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE1:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE0]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[UNKNOWN1]], float [[ALWAYS_NEGATIVE1]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[SELECT_LHS]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative0 = call float @returns_negative()
+  %always.negative1 = call float @returns_negative()
+  %select.lhs = select i1 %cond, float %always.negative0, float %unknown0
+  %select.rhs = select i1 %cond, float %unknown1, float %always.negative1
+  %result = call float @llvm.maximumnum.f32(float %select.lhs, float %select.rhs)
+  ret float %result
+}
+
+define nofpclass(nan) float @no_fold_select_always_negative_0(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(nan) float @no_fold_select_always_negative_0(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[SELECT_LHS]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative = call float @returns_negative()
+  %select.lhs = select i1 %cond, float %always.negative, float %unknown0
+  %result = call float @llvm.maximumnum.f32(float %select.lhs, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(nan) float @no_fold_select_always_negative_1(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(nan) float @no_fold_select_always_negative_1(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative = call float @returns_negative()
+  %select.rhs = select i1 %cond, float %always.negative, float %unknown0
+  %result = call float @llvm.maximumnum.f32(float %unknown1, float %select.rhs)
+  ret float %result
+}
+
+; Cannot fold out due to possible -0
+define nofpclass(snan) float @cannot_fold_negative_or_zero__positive_or_zero_0() {
+; CHECK-LABEL: define nofpclass(snan) float @cannot_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 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 float @llvm.maximumnum.f32(float %must.be.negative.or.zero, float %must.be.positive.or.zero)
+  ret float %result
+}
+
+; Cannot fold out due to possible -0
+define nofpclass(snan) float @cannot_fold_negative_or_zero__positive_or_zero_1() {
+; CHECK-LABEL: define nofpclass(snan) float @cannot_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 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 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:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[MUST_BE_PINF_OR_NAN]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %must.be.pinf.or.nan, float %unknown)
+  ret float %result
+}
+
+define nofpclass(nsub) float @rhs_must_be_pinf_or_nan(float nofpclass(ninf norm zero sub) %must.be.pinf.or.nan, float %unknown) {
+; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_pinf_or_nan(
+; CHECK-SAME: float nofpclass(ninf zero sub norm) [[MUST_BE_PINF_OR_NAN:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN]], float [[MUST_BE_PINF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %unknown, float %must.be.pinf.or.nan)
+  ret float %result
+}
+
+define nofpclass(nsub) float @lhs_must_be_pinf(float %unknown, float nofpclass(nan ninf norm zero sub) %must.be.pinf) {
+; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_pinf(
+; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[MUST_BE_PINF]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %must.be.pinf, float %unknown)
+  ret float %result
+}
+
+define nofpclass(nsub) float @rhs_must_be_pinf(float nofpclass(nan ninf norm zero sub) %must.be.pinf, float %unknown) {
+; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_pinf(
+; CHECK-SAME: float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN]], float [[MUST_BE_PINF]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %unknown, float %must.be.pinf)
+  ret float %result
+}
+
+; -> inf
+define nofpclass(nsub) float @lhs_must_be_pinf_rhs_non_nan(float nofpclass(nan) %not.nan, float nofpclass(nan ninf norm zero sub) %must.be.pinf) {
+; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_pinf_rhs_non_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]], float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[MUST_BE_PINF]], float [[NOT_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %must.be.pinf, float %not.nan)
+  ret float %result
+}
+
+; -> inf
+define nofpclass(nsub) float @rhs_must_be_pinf_lhs_non_nan(float nofpclass(nan ninf norm zero sub) %must.be.pinf, float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_pinf_lhs_non_nan(
+; CHECK-SAME: float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]], float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_NAN]], float [[MUST_BE_PINF]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.nan, float %must.be.pinf)
+  ret float %result
+}
+
+define nofpclass(nsub) float @lhs_must_be_ninf_or_nan(float %unknown, float nofpclass(pinf norm zero sub) %must.be.ninf.or.nan) {
+; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_ninf_or_nan(
+; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(pinf zero sub norm) [[MUST_BE_NINF_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[MUST_BE_NINF_OR_NAN]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %must.be.ninf.or.nan, float %unknown)
+  ret float %result
+}
+
+define nofpclass(nsub) float @rhs_must_be_ninf_or_nan(float nofpclass(pinf norm zero sub) %must.be.ninf.or.nan, float %unknown) {
+; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_ninf_or_nan(
+; CHECK-SAME: float nofpclass(pinf zero sub norm) [[MUST_BE_NINF_OR_NAN:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN]], float [[MUST_BE_NINF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %unknown, float %must.be.ninf.or.nan)
+  ret float %result
+}
+
+define nofpclass(nsub) float @lhs_must_be_ninf(float %unknown, float nofpclass(nan pinf norm zero sub) %must.be.ninf) {
+; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_ninf(
+; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(nan pinf zero sub norm) [[MUST_BE_NINF:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[MUST_BE_NINF]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %must.be.ninf, float %unknown)
+  ret float %result
+}
+
+define nofpclass(nsub) float @rhs_must_be_ninf(float nofpclass(nan pinf norm zero sub) %must.be.ninf, float %unknown) {
+; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_ninf(
+; CHECK-SAME: float nofpclass(nan pinf zero sub norm) [[MUST_BE_NINF:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN]], float [[MUST_BE_NINF]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %unknown, float %must.be.ninf)
+  ret float %result
+}
+
+
+; -> not.nan
+define nofpclass(nsub) float @lhs_must_be_ninf_rhs_non_nan(float nofpclass(nan) %not.nan, float nofpclass(nan pinf norm zero sub) %must.be.ninf) {
+; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_ninf_rhs_non_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]], float nofpclass(nan pinf zero sub norm) [[MUST_BE_NINF:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[MUST_BE_NINF]], float [[NOT_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %must.be.ninf, float %not.nan)
+  ret float %result
+}
+
+; -> not.nan
+define nofpclass(nsub) float @rhs_must_be_ninf_lhs_non_nan(float nofpclass(nan pinf norm zero sub) %must.be.ninf, float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_ninf_lhs_non_nan(
+; CHECK-SAME: float nofpclass(nan pinf zero sub norm) [[MUST_BE_NINF:%.*]], float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_NAN]], float [[MUST_BE_NINF]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.nan, float %must.be.ninf)
+  ret float %result
+}
+
+define nofpclass(nzero) float @result_not_nzero(float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(nzero) float @result_not_nzero(
+; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %unknown0, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(pzero) float @result_not_pzero(float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(pzero) float @result_not_pzero(
+; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %unknown0, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(zero) float @result_not_zero(float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(zero) float @result_not_zero(
+; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %unknown0, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(zero) float @result_not_zero__daz(float %unknown0, float %unknown1) #0 {
+; CHECK-LABEL: define nofpclass(zero) float @result_not_zero__daz(
+; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %unknown0, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(zero) float @result_not_zero__dynamic(float %unknown0, float %unknown1) #1 {
+; CHECK-LABEL: define nofpclass(zero) float @result_not_zero__dynamic(
+; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) #[[ATTR1:[0-9]+]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %unknown0, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(zero) float @result_not_zero_or_sub(float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(zero) float @result_not_zero_or_sub(
+; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %unknown0, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(zero sub) float @result_not_zero_or_sub__daz(float %unknown0, float %unknown1) #0 {
+; CHECK-LABEL: define nofpclass(zero sub) float @result_not_zero_or_sub__daz(
+; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %unknown0, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(zero sub) float @result_not_zero_or_sub__dynamic(float %unknown0, float %unknown1) #1 {
+; CHECK-LABEL: define nofpclass(zero sub) float @result_not_zero_or_sub__dynamic(
+; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %unknown0, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(snan) float @lhs_not_zero(float nofpclass(zero) %not.zero, float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @lhs_not_zero(
+; CHECK-SAME: float nofpclass(zero) [[NOT_ZERO:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_ZERO]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.zero, float %unknown)
+  ret float %result
+}
+
+define nofpclass(snan) float @rhs_not_zero(float %unknown, float nofpclass(zero) %not.zero) {
+; CHECK-LABEL: define nofpclass(snan) float @rhs_not_zero(
+; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(zero) [[NOT_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN]], float [[NOT_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %unknown, float %not.zero)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_zero(float nofpclass(zero) %not.zero0, float nofpclass(zero) %not.zero1) {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero(
+; CHECK-SAME: float nofpclass(zero) [[NOT_ZERO0:%.*]], float nofpclass(zero) [[NOT_ZERO1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_ZERO0]], float [[NOT_ZERO1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.zero0, float %not.zero1)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_zero__daz(float nofpclass(zero) %not.zero0, float nofpclass(zero) %not.zero1) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero__daz(
+; CHECK-SAME: float nofpclass(zero) [[NOT_ZERO0:%.*]], float nofpclass(zero) [[NOT_ZERO1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_ZERO0]], float [[NOT_ZERO1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.zero0, float %not.zero1)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_zero__dynamic(float nofpclass(zero) %not.zero0, float nofpclass(zero) %not.zero1) #2 {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero__dynamic(
+; CHECK-SAME: float nofpclass(zero) [[NOT_ZERO0:%.*]], float nofpclass(zero) [[NOT_ZERO1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_ZERO0]], float [[NOT_ZERO1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.zero0, float %not.zero1)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_zero_or_sub(float nofpclass(zero sub) %not.zero.sub.0, float nofpclass(zero sub) %not.zero.sub.1) {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero_or_sub(
+; CHECK-SAME: float nofpclass(zero sub) [[NOT_ZERO_SUB_0:%.*]], float nofpclass(zero sub) [[NOT_ZERO_SUB_1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.zero.sub.0, float %not.zero.sub.1)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_zero_or_sub__daz(float nofpclass(zero sub) %not.zero.sub.0, float nofpclass(zero sub) %not.zero.sub.1) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero_or_sub__daz(
+; CHECK-SAME: float nofpclass(zero sub) [[NOT_ZERO_SUB_0:%.*]], float nofpclass(zero sub) [[NOT_ZERO_SUB_1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.zero.sub.0, float %not.zero.sub.1)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_zero_or_sub__dynamic(float nofpclass(zero sub) %not.zero.sub.0, float nofpclass(zero sub) %not.zero.sub.1) #2 {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero_or_sub__dynamic(
+; CHECK-SAME: float nofpclass(zero sub) [[NOT_ZERO_SUB_0:%.*]], float nofpclass(zero sub) [[NOT_ZERO_SUB_1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.zero.sub.0, float %not.zero.sub.1)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_nzero(float nofpclass(nzero) %not.nzero0, float nofpclass(nzero) %not.nzero1) {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_nzero(
+; CHECK-SAME: float nofpclass(nzero) [[NOT_NZERO0:%.*]], float nofpclass(nzero) [[NOT_NZERO1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_NZERO0]], float [[NOT_NZERO1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.nzero0, float %not.nzero1)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_pzero(float nofpclass(pzero) %not.pzero0, float nofpclass(pzero) %not.pzero1) {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_pzero(
+; CHECK-SAME: float nofpclass(pzero) [[NOT_PZERO0:%.*]], float nofpclass(pzero) [[NOT_PZERO1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_PZERO0]], float [[NOT_PZERO1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.pzero0, float %not.pzero1)
+  ret float %result
+}
+
+define nofpclass(snan) float @lhs_not_nzero_rhs_not_pzero(float nofpclass(nzero) %not.nzero, float nofpclass(pzero) %not.pzero) {
+; CHECK-LABEL: define nofpclass(snan) float @lhs_not_nzero_rhs_not_pzero(
+; CHECK-SAME: float nofpclass(nzero) [[NOT_NZERO:%.*]], float nofpclass(pzero) [[NOT_PZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_NZERO]], float [[NOT_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.nzero, float %not.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @rhs_not_nzero_lhs_not_pzero(float nofpclass(pzero) %not.nzero, float nofpclass(nzero) %not.pzero) {
+; CHECK-LABEL: define nofpclass(snan) float @rhs_not_nzero_lhs_not_pzero(
+; CHECK-SAME: float nofpclass(pzero) [[NOT_NZERO:%.*]], float nofpclass(nzero) [[NOT_PZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_NZERO]], float [[NOT_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.nzero, float %not.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_nzero__dynamic(float nofpclass(nzero) %not.nzero0, float nofpclass(nzero) %not.nzero1) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_nzero__dynamic(
+; CHECK-SAME: float nofpclass(nzero) [[NOT_NZERO0:%.*]], float nofpclass(nzero) [[NOT_NZERO1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_NZERO0]], float [[NOT_NZERO1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.nzero0, float %not.nzero1)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_pzero__dynamic(float nofpclass(pzero) %not.pzero0, float nofpclass(pzero) %not.pzero1) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_pzero__dynamic(
+; CHECK-SAME: float nofpclass(pzero) [[NOT_PZERO0:%.*]], float nofpclass(pzero) [[NOT_PZERO1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_PZERO0]], float [[NOT_PZERO1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.pzero0, float %not.pzero1)
+  ret float %result
+}
+
+define nofpclass(snan) float @lhs_not_nzero_rhs_not_pzero__dynamic(float nofpclass(nzero) %not.nzero, float nofpclass(pzero) %not.pzero) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @lhs_not_nzero_rhs_not_pzero__dynamic(
+; CHECK-SAME: float nofpclass(nzero) [[NOT_NZERO:%.*]], float nofpclass(pzero) [[NOT_PZERO:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_NZERO]], float [[NOT_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.nzero, float %not.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @rhs_not_nzero_lhs_not_pzero__dynamic(float nofpclass(pzero) %not.nzero, float nofpclass(nzero) %not.pzero) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @rhs_not_nzero_lhs_not_pzero__dynamic(
+; CHECK-SAME: float nofpclass(pzero) [[NOT_NZERO:%.*]], float nofpclass(nzero) [[NOT_PZERO:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_NZERO]], float [[NOT_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.nzero, float %not.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_nzero_nsub__dynamic(float nofpclass(nzero nsub) %not.nzero0, float nofpclass(nzero nsub) %not.nzero1) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_nzero_nsub__dynamic(
+; CHECK-SAME: float nofpclass(nzero nsub) [[NOT_NZERO0:%.*]], float nofpclass(nzero nsub) [[NOT_NZERO1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_NZERO0]], float [[NOT_NZERO1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.nzero0, float %not.nzero1)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_pzero_psub__dynamic(float nofpclass(pzero psub) %not.pzero0, float nofpclass(pzero psub) %not.pzero1) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_pzero_psub__dynamic(
+; CHECK-SAME: float nofpclass(pzero psub) [[NOT_PZERO0:%.*]], float nofpclass(pzero psub) [[NOT_PZERO1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_PZERO0]], float [[NOT_PZERO1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.pzero0, float %not.pzero1)
+  ret float %result
+}
+
+define nofpclass(snan) float @lhs_not_nzero_nsub_rhs_not_pzero__dynamic(float nofpclass(nzero nsub) %not.nzero, float nofpclass(pzero psub) %not.pzero) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @lhs_not_nzero_nsub_rhs_not_pzero__dynamic(
+; CHECK-SAME: float nofpclass(nzero nsub) [[NOT_NZERO:%.*]], float nofpclass(pzero psub) [[NOT_PZERO:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_NZERO]], float [[NOT_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.nzero, float %not.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @rhs_not_nzero_nsub_lhs_not_pzero_psub__dynamic(float nofpclass(pzero psub) %not.nzero, float nofpclass(nzero nsub) %not.pzero) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @rhs_not_nzero_nsub_lhs_not_pzero_psub__dynamic(
+; CHECK-SAME: float nofpclass(pzero psub) [[NOT_NZERO:%.*]], float nofpclass(nzero nsub) [[NOT_PZERO:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_NZERO]], float [[NOT_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %not.nzero, float %not.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @not_nan__maximumnum__unknown(float nofpclass(nan) %x, float %y) {
+; CHECK-LABEL: define nofpclass(snan) float @not_nan__maximumnum__unknown(
+; CHECK-SAME: float nofpclass(nan) [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(snan) float @unknown__maximumnum__not_nan(float %x, float nofpclass(nan) %y) {
+; CHECK-LABEL: define nofpclass(snan) float @unknown__maximumnum__not_nan(
+; CHECK-SAME: float [[X:%.*]], float nofpclass(nan) [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(snan) float @not_nan__maximumnum__not_nan(float nofpclass(nan) %x, float nofpclass(nan) %y) {
+; CHECK-LABEL: define nofpclass(snan) float @not_nan__maximumnum__not_nan(
+; CHECK-SAME: float nofpclass(nan) [[X:%.*]], float nofpclass(nan) [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(snan) float @not_snan__maximumnum__not_snan(float nofpclass(snan) %x, float nofpclass(snan) %y) {
+; CHECK-LABEL: define nofpclass(snan) float @not_snan__maximumnum__not_snan(
+; CHECK-SAME: float nofpclass(snan) [[X:%.*]], float nofpclass(snan) [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(inf) float @ret_noinf__not_qnan__maximumnum__not_qnan(float nofpclass(qnan) %x, float nofpclass(qnan) %y) {
+; CHECK-LABEL: define nofpclass(inf) float @ret_noinf__not_qnan__maximumnum__not_qnan(
+; CHECK-SAME: float nofpclass(qnan) [[X:%.*]], float nofpclass(qnan) [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_positive__maximumnum__only_zero() {
+; CHECK-LABEL: define nofpclass(snan) float @known_positive__maximumnum__only_zero() {
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[KNOWN_ZERO:%.*]] = call float @returns_zero()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_POSITIVE]], float [[KNOWN_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.positive = call float @returns_positive()
+  %known.zero = call float @returns_zero()
+  %result = call float @llvm.maximumnum.f32(float %known.positive, float %known.zero)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_zero__maximumnum__known_positive() {
+; CHECK-LABEL: define nofpclass(snan) float @only_zero__maximumnum__known_positive() {
+; CHECK-NEXT:    [[KNOWN_ZERO:%.*]] = call float @returns_zero()
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_ZERO]], float [[KNOWN_POSITIVE]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.zero = call float @returns_zero()
+  %known.positive = call float @returns_positive()
+  %result = call float @llvm.maximumnum.f32(float %known.zero, float %known.positive)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_positive__maximumnum__only_zero_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_positive__maximumnum__only_zero_or_nan() {
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[KNOWN_ZERO_OR_NAN:%.*]] = call float @returns_zero_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_POSITIVE]], float [[KNOWN_ZERO_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.positive = call float @returns_positive()
+  %known.zero.or.nan = call float @returns_zero_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %known.positive, float %known.zero.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_zero_or_nan__maximumnum__known_positive() {
+; CHECK-LABEL: define nofpclass(snan) float @only_zero_or_nan__maximumnum__known_positive() {
+; CHECK-NEXT:    [[KNOWN_ZERO_OR_NAN:%.*]] = call float @returns_zero_or_nan()
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_ZERO_OR_NAN]], float [[KNOWN_POSITIVE]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.zero.or.nan = call float @returns_zero_or_nan()
+  %known.positive = call float @returns_positive()
+  %result = call float @llvm.maximumnum.f32(float %known.zero.or.nan, float %known.positive)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_positive_or_nan__maximumnum__only_zero() {
+; CHECK-LABEL: define nofpclass(snan) float @known_positive_or_nan__maximumnum__only_zero() {
+; CHECK-NEXT:    [[KNOWN_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[KNOWN_ZERO:%.*]] = call float @returns_zero()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_POSITIVE_OR_NAN]], float [[KNOWN_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.positive.or.nan = call float @returns_positive_or_nan()
+  %known.zero = call float @returns_zero()
+  %result = call float @llvm.maximumnum.f32(float %known.positive.or.nan, float %known.zero)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_zero__maximumnum__known_positive_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @only_zero__maximumnum__known_positive_or_nan() {
+; CHECK-NEXT:    [[KNOWN_ZERO:%.*]] = call float @returns_zero()
+; CHECK-NEXT:    [[KNOWN_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_ZERO]], float [[KNOWN_POSITIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.zero = call float @returns_zero()
+  %known.positive.or.nan = call float @returns_positive_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %known.zero, float %known.positive.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_positive__maximumnum__only_nzero() {
+; CHECK-LABEL: define nofpclass(snan) float @known_positive__maximumnum__only_nzero() {
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[KNOWN_NZERO:%.*]] = call float @returns_nzero()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_POSITIVE]], float [[KNOWN_NZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.positive = call float @returns_positive()
+  %known.nzero = call float @returns_nzero()
+  %result = call float @llvm.maximumnum.f32(float %known.positive, float %known.nzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_nzero__maximumnum__known_positive() {
+; CHECK-LABEL: define nofpclass(snan) float @only_nzero__maximumnum__known_positive() {
+; CHECK-NEXT:    [[KNOWN_NZERO:%.*]] = call float @returns_nzero()
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_NZERO]], float [[KNOWN_POSITIVE]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.nzero = call float @returns_nzero()
+  %known.positive = call float @returns_positive()
+  %result = call float @llvm.maximumnum.f32(float %known.nzero, float %known.positive)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_positive__maximumnum__only_pzero() {
+; CHECK-LABEL: define nofpclass(snan) float @known_positive__maximumnum__only_pzero() {
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[KNOWN_PZERO:%.*]] = call float @returns_pzero()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_POSITIVE]], float [[KNOWN_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.positive = call float @returns_positive()
+  %known.pzero = call float @returns_pzero()
+  %result = call float @llvm.maximumnum.f32(float %known.positive, float %known.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_pzero__maximumnum__known_positive() {
+; CHECK-LABEL: define nofpclass(snan) float @only_pzero__maximumnum__known_positive() {
+; CHECK-NEXT:    [[KNOWN_PZERO:%.*]] = call float @returns_pzero()
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_PZERO]], float [[KNOWN_POSITIVE]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.pzero = call float @returns_pzero()
+  %known.positive = call float @returns_positive()
+  %result = call float @llvm.maximumnum.f32(float %known.pzero, float %known.positive)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_negative__maximumnum__only_zero_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_negative__maximumnum__only_zero_or_nan() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[KNOWN_ZERO_OR_NAN:%.*]] = call float @returns_zero_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_NEGATIVE]], float [[KNOWN_ZERO_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative = call float @returns_negative()
+  %known.zero.or.nan = call float @returns_zero_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %known.negative, float %known.zero.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_zero_or_nan__maximumnum__known_negative() {
+; CHECK-LABEL: define nofpclass(snan) float @only_zero_or_nan__maximumnum__known_negative() {
+; CHECK-NEXT:    [[KNOWN_ZERO_OR_NAN:%.*]] = call float @returns_zero_or_nan()
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_ZERO_OR_NAN]], float [[KNOWN_NEGATIVE]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.zero.or.nan = call float @returns_zero_or_nan()
+  %known.negative = call float @returns_negative()
+  %result = call float @llvm.maximumnum.f32(float %known.zero.or.nan, float %known.negative)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_negative_or_nan__maximumnum__only_zero() {
+; CHECK-LABEL: define nofpclass(snan) float @known_negative_or_nan__maximumnum__only_zero() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[KNOWN_ZERO:%.*]] = call float @returns_zero()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_NEGATIVE_OR_NAN]], float [[KNOWN_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative.or.nan = call float @returns_negative_or_nan()
+  %known.zero = call float @returns_zero()
+  %result = call float @llvm.maximumnum.f32(float %known.negative.or.nan, float %known.zero)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_zero__maximumnum__known_negative_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @only_zero__maximumnum__known_negative_or_nan() {
+; CHECK-NEXT:    [[KNOWN_ZERO:%.*]] = call float @returns_zero()
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_ZERO]], float [[KNOWN_NEGATIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.zero = call float @returns_zero()
+  %known.negative.or.nan = call float @returns_negative_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %known.zero, float %known.negative.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_negative__maximumnum__only_nzero() {
+; CHECK-LABEL: define nofpclass(snan) float @known_negative__maximumnum__only_nzero() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[KNOWN_NZERO:%.*]] = call float @returns_nzero()
+; CHECK-NEXT:    ret float -0.000000e+00
+;
+  %known.negative = call float @returns_negative()
+  %known.nzero = call float @returns_nzero()
+  %result = call float @llvm.maximumnum.f32(float %known.negative, float %known.nzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_nzero__maximumnum__known_negative() {
+; CHECK-LABEL: define nofpclass(snan) float @only_nzero__maximumnum__known_negative() {
+; CHECK-NEXT:    [[KNOWN_NZERO:%.*]] = call float @returns_nzero()
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    ret float -0.000000e+00
+;
+  %known.nzero = call float @returns_nzero()
+  %known.negative = call float @returns_negative()
+  %result = call float @llvm.maximumnum.f32(float %known.nzero, float %known.negative)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_negative__maximumnum__only_nzero_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_negative__maximumnum__only_nzero_or_nan() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[KNOWN_NZERO_OR_NAN:%.*]] = call float @returns_nzero_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_NEGATIVE]], float [[KNOWN_NZERO_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative = call float @returns_negative()
+  %known.nzero.or.nan = call float @returns_nzero_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %known.negative, float %known.nzero.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_nzero_or_nan__maximumnum__known_negative() {
+; CHECK-LABEL: define nofpclass(snan) float @only_nzero_or_nan__maximumnum__known_negative() {
+; CHECK-NEXT:    [[KNOWN_NZERO_OR_NAN:%.*]] = call float @returns_nzero_or_nan()
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_NZERO_OR_NAN]], float [[KNOWN_NEGATIVE]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.nzero.or.nan = call float @returns_nzero_or_nan()
+  %known.negative = call float @returns_negative()
+  %result = call float @llvm.maximumnum.f32(float %known.nzero.or.nan, float %known.negative)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_negative__maximumnum__only_pzero() {
+; CHECK-LABEL: define nofpclass(snan) float @known_negative__maximumnum__only_pzero() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[KNOWN_PZERO:%.*]] = call float @returns_pzero()
+; CHECK-NEXT:    ret float 0.000000e+00
+;
+  %known.negative = call float @returns_negative()
+  %known.pzero = call float @returns_pzero()
+  %result = call float @llvm.maximumnum.f32(float %known.negative, float %known.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_pzero__maximumnum__known_negative() {
+; CHECK-LABEL: define nofpclass(snan) float @only_pzero__maximumnum__known_negative() {
+; CHECK-NEXT:    [[KNOWN_PZERO:%.*]] = call float @returns_pzero()
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    ret float 0.000000e+00
+;
+  %known.pzero = call float @returns_pzero()
+  %known.negative = call float @returns_negative()
+  %result = call float @llvm.maximumnum.f32(float %known.pzero, float %known.negative)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_negative__maximumnum__only_pzero_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_negative__maximumnum__only_pzero_or_nan() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[KNOWN_PZERO_OR_NAN:%.*]] = call float @returns_pzero_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_NEGATIVE]], float [[KNOWN_PZERO_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative = call float @returns_negative()
+  %known.pzero.or.nan = call float @returns_pzero_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %known.negative, float %known.pzero.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_pzero_or_nan__maximumnum__known_negative() {
+; CHECK-LABEL: define nofpclass(snan) float @only_pzero_or_nan__maximumnum__known_negative() {
+; CHECK-NEXT:    [[KNOWN_PZERO_OR_NAN:%.*]] = call float @returns_pzero_or_nan()
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_PZERO_OR_NAN]], float [[KNOWN_NEGATIVE]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.pzero.or.nan = call float @returns_pzero_or_nan()
+  %known.negative = call float @returns_negative()
+  %result = call float @llvm.maximumnum.f32(float %known.pzero.or.nan, float %known.negative)
+  ret float %result
+}
+
+define nofpclass(pinf pnorm psub pzero) float @ret_always_negative_or_nan__unknown__maximumnum__select_always_negative_or_unknown(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_always_negative_or_nan__unknown__maximumnum__select_always_negative_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative = call float @returns_negative()
+  %select.rhs = select i1 %cond, float %always.negative, float %unknown0
+  %result = call float @llvm.maximumnum.f32(float %unknown1, float %select.rhs)
+  ret float %result
+}
+
+define nofpclass(pinf pnorm psub pzero) float @ret_always_negative_or_nan__unknown__maximumnum__select_always_positive_or_unknown(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_always_negative_or_nan__unknown__maximumnum__select_always_positive_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[ALWAYS_POSITIVE]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.positive = call float @returns_positive()
+  %select.rhs = select i1 %cond, float %always.positive, float %unknown0
+  %result = call float @llvm.maximumnum.f32(float %unknown1, float %select.rhs)
+  ret float %result
+}
+
+define nofpclass(pinf pnorm psub) float @ret_always_positive_nonzero__maximumnum__not_zero_select_positive_or_unknown(i1 %cond, float %unknown, float nofpclass(zero) %not.zero) {
+; CHECK-LABEL: define nofpclass(pinf psub pnorm) float @ret_always_positive_nonzero__maximumnum__not_zero_select_positive_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(zero) [[NOT_ZERO:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[ALWAYS_POSITIVE]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_ZERO]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.positive = call float @returns_positive()
+  %select.rhs = select i1 %cond, float %always.positive, float %unknown
+  %result = call float @llvm.maximumnum.f32(float %not.zero, float %select.rhs)
+  ret float %result
+}
+
+define nofpclass(pinf pnorm psub) float @ret_always_positive_nonzero__maximumnum__not_zero_select_negative_or_unknown(i1 %cond, float %unknown, float nofpclass(zero) %not.zero) {
+; CHECK-LABEL: define nofpclass(pinf psub pnorm) float @ret_always_positive_nonzero__maximumnum__not_zero_select_negative_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(zero) [[NOT_ZERO:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_ZERO]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative = call float @returns_negative()
+  %select.rhs = select i1 %cond, float %always.negative, float %unknown
+  %result = call float @llvm.maximumnum.f32(float %not.zero, float %select.rhs)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_positive__maximumnum__only_pzero_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_positive__maximumnum__only_pzero_or_nan() {
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[KNOWN_PZERO_OR_NAN:%.*]] = call float @returns_pzero_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_POSITIVE]], float [[KNOWN_PZERO_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.positive = call float @returns_positive()
+  %known.pzero.or.nan = call float @returns_pzero_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %known.positive, float %known.pzero.or.nan)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_nonan__known_negative_or_nan__maximumnum__known_positive_or_nan() {
+; CHECK-LABEL: define nofpclass(nan) float @ret_nonan__known_negative_or_nan__maximumnum__known_positive_or_nan() {
+; CHECK-NEXT:    [[MUST_BE_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[MUST_BE_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[MUST_BE_NEGATIVE_OR_NAN]], float [[MUST_BE_POSITIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %must.be.negative.or.nan = call float @returns_negative_or_nan()
+  %must.be.positive.or.nan = call float @returns_positive_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %must.be.negative.or.nan, float %must.be.positive.or.nan)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_nonan__known_positive_or_nan__maximumnum__known_negative_or_nan() {
+; CHECK-LABEL: define nofpclass(nan) float @ret_nonan__known_positive_or_nan__maximumnum__known_negative_or_nan() {
+; CHECK-NEXT:    [[MUST_BE_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[MUST_BE_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[MUST_BE_POSITIVE_OR_NAN]], float [[MUST_BE_NEGATIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %must.be.positive.or.nan = call float @returns_positive_or_nan()
+  %must.be.negative.or.nan = call float @returns_negative_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %must.be.positive.or.nan, float %must.be.negative.or.nan)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_nonan__select_nan_or_unknown__maximumnum__unknown(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_nonan__select_nan_or_unknown__maximumnum__unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NAN:%.*]] = call float @returns_nan()
+; CHECK-NEXT:    [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NAN]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[SELECT_LHS]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.nan = call float @returns_nan()
+  %select.lhs = select i1 %cond, float %always.nan, float %unknown0
+  %result = call float @llvm.maximumnum.f32(float %select.lhs, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_nonan__unknown__maximumnum__select_nan_or_unknown(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_nonan__unknown__maximumnum__select_nan_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NAN:%.*]] = call float @returns_nan()
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[UNKNOWN0]], float [[ALWAYS_NAN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.nan = call float @returns_nan()
+  %select.rhs = select i1 %cond, float %unknown0, float %always.nan
+  %result = call float @llvm.maximumnum.f32(float %unknown1, float %select.rhs)
+  ret float %result
+}
+
+define nofpclass(ninf nnorm nsub nzero) float @result_known_positive_or_nan__known_positive__maximumnum__not_nan(float nofpclass(ninf nnorm nsub nzero) %lhs, float nofpclass(nan) %rhs) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @result_known_positive_or_nan__known_positive__maximumnum__not_nan(
+; CHECK-SAME: float nofpclass(ninf nzero nsub nnorm) [[LHS:%.*]], float nofpclass(nan) [[RHS:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[LHS]], float [[RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %lhs, float %rhs)
+  ret float %result
+}
+
+define nofpclass(ninf nnorm nsub nzero) float @result_known_positive_or_nan__not_nan__maximumnum__known_positive(float nofpclass(nan) %lhs, float nofpclass(ninf nnorm nsub nzero) %rhs) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @result_known_positive_or_nan__not_nan__maximumnum__known_positive(
+; CHECK-SAME: float nofpclass(nan) [[LHS:%.*]], float nofpclass(ninf nzero nsub nnorm) [[RHS:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[LHS]], float [[RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.maximumnum.f32(float %lhs, float %rhs)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_always_positive__maximumnum__known_always_negative_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_always_positive__maximumnum__known_always_negative_or_nan() {
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_POSITIVE]], float [[KNOWN_NEGATIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.positive = call float @returns_positive()
+  %known.negative.or.nan = call float @returns_negative_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %known.positive, float %known.negative.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_always_negative_or_nan__maximumnum__known_always_positive() {
+; CHECK-LABEL: define nofpclass(snan) float @known_always_negative_or_nan__maximumnum__known_always_positive() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_NEGATIVE_OR_NAN]], float [[KNOWN_POSITIVE]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative.or.nan = call float @returns_negative_or_nan()
+  %known.positive = call float @returns_positive()
+  %result = call float @llvm.maximumnum.f32(float %known.negative.or.nan, float %known.positive)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_always_positive_or_nan__maximumnum__known_always_negative_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_always_positive_or_nan__maximumnum__known_always_negative_or_nan() {
+; CHECK-NEXT:    [[KNOWN_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_POSITIVE_OR_NAN]], float [[KNOWN_NEGATIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.positive.or.nan = call float @returns_positive_or_nan()
+  %known.negative.or.nan = call float @returns_negative_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %known.positive.or.nan, float %known.negative.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_always_negative_or_nan__maximumnum__known_always_positive_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_always_negative_or_nan__maximumnum__known_always_positive_or_nan() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[KNOWN_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_NEGATIVE_OR_NAN]], float [[KNOWN_POSITIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative.or.nan = call float @returns_negative_or_nan()
+  %known.positive.or.nan = call float @returns_positive_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %known.negative.or.nan, float %known.positive.or.nan)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nan__known_always_positive_or_nan__maximumnum__known_always_negative_or_nan() {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__known_always_positive_or_nan__maximumnum__known_always_negative_or_nan() {
+; CHECK-NEXT:    [[KNOWN_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_POSITIVE_OR_NAN]], float [[KNOWN_NEGATIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.positive.or.nan = call float @returns_positive_or_nan()
+  %known.negative.or.nan = call float @returns_negative_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %known.positive.or.nan, float %known.negative.or.nan)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nan__known_always_negative_or_nan__maximumnum__known_always_positive_or_nan() {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__known_always_negative_or_nan__maximumnum__known_always_positive_or_nan() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[KNOWN_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[KNOWN_NEGATIVE_OR_NAN]], float [[KNOWN_POSITIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative.or.nan = call float @returns_negative_or_nan()
+  %known.positive.or.nan = call float @returns_positive_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %known.negative.or.nan, float %known.positive.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @pinf__maximumnum__unknown(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @pinf__maximumnum__unknown(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[PINF:%.*]] = call float @returns_pinf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[PINF]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %pinf = call float @returns_pinf()
+  %result = call float @llvm.maximumnum.f32(float %pinf, float %unknown)
+  ret float %result
+}
+
+define nofpclass(snan) float @unknown__maximumnum__pinf(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @unknown__maximumnum__pinf(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[PINF:%.*]] = call float @returns_pinf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN]], float [[PINF]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %pinf = call float @returns_pinf()
+  %result = call float @llvm.maximumnum.f32(float %unknown, float %pinf)
+  ret float %result
+}
+
+define nofpclass(snan) float @pinf_or_nan__maximumnum__unknown(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @pinf_or_nan__maximumnum__unknown(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[PINF_OR_NAN:%.*]] = call float @returns_pinf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[PINF_OR_NAN]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %pinf.or.nan = call float @returns_pinf_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %pinf.or.nan, float %unknown)
+  ret float %result
+}
+
+define nofpclass(snan) float @unknown__maximumnum__pinf_or_nan(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @unknown__maximumnum__pinf_or_nan(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[PINF_OR_NAN:%.*]] = call float @returns_pinf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN]], float [[PINF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %pinf.or.nan = call float @returns_pinf_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %unknown, float %pinf.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @ninf__maximumnum__unknown(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @ninf__maximumnum__unknown(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NINF:%.*]] = call float @returns_ninf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NINF]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %ninf = call float @returns_ninf()
+  %result = call float @llvm.maximumnum.f32(float %ninf, float %unknown)
+  ret float %result
+}
+
+define nofpclass(snan) float @unknown__maximumnum__ninf(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @unknown__maximumnum__ninf(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NINF:%.*]] = call float @returns_ninf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN]], float [[NINF]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %ninf = call float @returns_ninf()
+  %result = call float @llvm.maximumnum.f32(float %unknown, float %ninf)
+  ret float %result
+}
+
+define nofpclass(snan) float @ninf_or_nan__maximumnum__unknown(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @ninf_or_nan__maximumnum__unknown(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NINF_OR_NAN:%.*]] = call float @returns_ninf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NINF_OR_NAN]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %ninf.or.nan = call float @returns_ninf_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %ninf.or.nan, float %unknown)
+  ret float %result
+}
+
+define nofpclass(snan) float @unknown__maximumnum__ninf_or_nan(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @unknown__maximumnum__ninf_or_nan(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NINF_OR_NAN:%.*]] = call float @returns_ninf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN]], float [[NINF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %ninf.or.nan = call float @returns_ninf_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %unknown, float %ninf.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @inf__maximumnum__unknown(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @inf__maximumnum__unknown(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[INF:%.*]] = call float @returns_inf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[INF]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %inf = call float @returns_inf()
+  %result = call float @llvm.maximumnum.f32(float %inf, float %unknown)
+  ret float %result
+}
+
+define nofpclass(snan) float @unknown__maximumnum__inf(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @unknown__maximumnum__inf(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[INF:%.*]] = call float @returns_inf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN]], float [[INF]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %inf = call float @returns_inf()
+  %result = call float @llvm.maximumnum.f32(float %unknown, float %inf)
+  ret float %result
+}
+
+define nofpclass(snan) float @inf_or_nan__maximumnum__unknown(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @inf_or_nan__maximumnum__unknown(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[INF_OR_NAN:%.*]] = call float @returns_inf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[INF_OR_NAN]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %inf.or.nan = call float @returns_inf_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %inf.or.nan, float %unknown)
+  ret float %result
+}
+
+define nofpclass(snan) float @unknown__maximumnum__inf_or_nan(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @unknown__maximumnum__inf_or_nan(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[INF_OR_NAN:%.*]] = call float @returns_inf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[UNKNOWN]], float [[INF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %inf.or.nan = call float @returns_inf_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %unknown, float %inf.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @ninf_or_nan__maximumnum__not_nan(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @ninf_or_nan__maximumnum__not_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[NINF_OR_NAN:%.*]] = call float @returns_ninf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NINF_OR_NAN]], float [[NOT_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %ninf.or.nan = call float @returns_ninf_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %ninf.or.nan, float %not.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @not_nan__maximumnum__ninf_or_nan(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @not_nan__maximumnum__ninf_or_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[NINF_OR_NAN:%.*]] = call float @returns_ninf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_NAN]], float [[NINF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %ninf.or.nan = call float @returns_ninf_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %not.nan, float %ninf.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @pinf_or_nan__maximumnum__not_nan(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @pinf_or_nan__maximumnum__not_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[PINF_OR_NAN:%.*]] = call float @returns_pinf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[PINF_OR_NAN]], float [[NOT_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %pinf.or.nan = call float @returns_pinf_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %pinf.or.nan, float %not.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @not_nan__maximumnum__pinf_or_nan(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @not_nan__maximumnum__pinf_or_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[PINF_OR_NAN:%.*]] = call float @returns_pinf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_NAN]], float [[PINF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %pinf.or.nan = call float @returns_pinf_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %not.nan, float %pinf.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @inf_or_nan__maximumnum__not_nan(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @inf_or_nan__maximumnum__not_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[INF_OR_NAN:%.*]] = call float @returns_inf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[INF_OR_NAN]], float [[NOT_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %inf.or.nan = call float @returns_inf_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %inf.or.nan, float %not.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @not_nan__maximumnum__inf_or_nan(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @not_nan__maximumnum__inf_or_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[INF_OR_NAN:%.*]] = call float @returns_inf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_NAN]], float [[INF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %inf.or.nan = call float @returns_inf_or_nan()
+  %result = call float @llvm.maximumnum.f32(float %not.nan, float %inf.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @ninf__maximumnum__not_nan(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @ninf__maximumnum__not_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[NINF_OR_NAN:%.*]] = call float @returns_ninf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NINF_OR_NAN]], float [[NOT_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %ninf.or.nan = call float @returns_ninf()
+  %result = call float @llvm.maximumnum.f32(float %ninf.or.nan, float %not.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @not_nan__maximumnum__ninf(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @not_nan__maximumnum__ninf(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[NINF_OR_NAN:%.*]] = call float @returns_ninf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_NAN]], float [[NINF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %ninf.or.nan = call float @returns_ninf()
+  %result = call float @llvm.maximumnum.f32(float %not.nan, float %ninf.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @pinf__maximumnum__not_nan(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @pinf__maximumnum__not_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[PINF_OR_NAN:%.*]] = call float @returns_pinf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[PINF_OR_NAN]], float [[NOT_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %pinf.or.nan = call float @returns_pinf()
+  %result = call float @llvm.maximumnum.f32(float %pinf.or.nan, float %not.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @not_nan__maximumnum__pinf(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @not_nan__maximumnum__pinf(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[PINF_OR_NAN:%.*]] = call float @returns_pinf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_NAN]], float [[PINF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %pinf.or.nan = call float @returns_pinf()
+  %result = call float @llvm.maximumnum.f32(float %not.nan, float %pinf.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @inf__maximumnum__not_nan(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @inf__maximumnum__not_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[INF_OR_NAN:%.*]] = call float @returns_inf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[INF_OR_NAN]], float [[NOT_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %inf.or.nan = call float @returns_inf()
+  %result = call float @llvm.maximumnum.f32(float %inf.or.nan, float %not.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @not_nan__maximumnum__inf(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @not_nan__maximumnum__inf(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[INF_OR_NAN:%.*]] = call float @returns_inf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.maximumnum.f32(float [[NOT_NAN]], float [[INF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %inf.or.nan = call float @returns_inf()
+  %result = call float @llvm.maximumnum.f32(float %not.nan, float %inf.or.nan)
+  ret float %result
+}
+
+attributes #0 = { "denormal-fp-math"="preserve-sign,preserve-sign" }
+attributes #1 = { "denormal-fp-math"="dynamic,dynamic" }
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-minimumnum.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-minimumnum.ll
new file mode 100644
index 0000000000000..8d1d2d3f3f91a
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-minimumnum.ll
@@ -0,0 +1,1625 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+declare nofpclass(ninf nnorm nsub nzero nan) float @returns_positive()
+declare nofpclass(ninf nnorm nsub nzero) float @returns_positive_or_nan()
+
+declare nofpclass(pinf pnorm psub pzero nan) float @returns_negative()
+declare nofpclass(pinf pnorm psub pzero) float @returns_negative_or_nan()
+
+declare nofpclass(ninf nnorm nsub nan) float @returns_positive_or_zero()
+declare nofpclass(pinf pnorm psub nan) float @returns_negative_or_zero()
+
+declare nofpclass(ninf nnorm nsub) float @returns_positive_or_zero_or_nan()
+declare nofpclass(pinf pnorm psub) float @returns_negative_or_zero_or_nan()
+
+declare nofpclass(inf sub norm nan) float @returns_zero()
+declare nofpclass(inf sub norm) float @returns_zero_or_nan()
+declare nofpclass(inf sub norm nan pzero) float @returns_nzero()
+declare nofpclass(inf sub norm pzero) float @returns_nzero_or_nan()
+declare nofpclass(inf sub norm nan nzero) float @returns_pzero()
+declare nofpclass(inf sub norm nzero) float @returns_pzero_or_nan()
+declare nofpclass(inf norm sub zero) float @returns_nan()
+
+declare nofpclass(ninf norm sub zero nan) float @returns_pinf()
+declare nofpclass(ninf norm sub zero) float @returns_pinf_or_nan()
+
+declare nofpclass(pinf norm sub zero nan) float @returns_ninf()
+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()
+
+; -> 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(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(inf norm sub zero qnan) float @ret_only_snan(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(qnan inf zero sub norm) float @ret_only_snan(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(inf norm sub zero snan) float @ret_only_qnan(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(snan inf zero sub norm) float @ret_only_qnan(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(nan norm sub zero) float @ret_only_inf(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(nan zero sub norm) float @ret_only_inf(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(nan pinf norm sub zero) float @ret_only_ninf(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(nan pinf zero sub norm) float @ret_only_ninf(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    ret float 0xFFF0000000000000
+;
+  %result = call float @llvm.minimumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(nan ninf norm sub zero) float @ret_only_pinf(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(nan ninf zero sub norm) float @ret_only_pinf(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    ret float 0x7FF0000000000000
+;
+  %result = call float @llvm.minimumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(inf nan norm sub) float @ret_only_zero(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) float @ret_only_zero(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(inf nan norm sub nzero) float @ret_only_pzero(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(nan inf nzero sub norm) float @ret_only_pzero(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    ret float 0.000000e+00
+;
+  %result = call float @llvm.minimumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(inf nan norm sub pzero) float @ret_only_nzero(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(nan inf pzero sub norm) float @ret_only_nzero(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    ret float -0.000000e+00
+;
+  %result = call float @llvm.minimumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(inf) float @ret_no_infs(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(inf) float @ret_no_infs(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(nan inf) float @ret_no_nans_no_infs(float %x, float %y) {
+; CHECK-LABEL: define nofpclass(nan inf) float @ret_no_nans_no_infs(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+; -> qnan
+define nofpclass(ninf nnorm nsub nzero) float @ret_known_positive_or_nan__minimumnum__negative_or_nan___negative_or_nan() {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_known_positive_or_nan__minimumnum__negative_or_nan___negative_or_nan() {
+; CHECK-NEXT:    [[MUST_BE_NEGATIVE_OR_NAN0:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[MUST_BE_NEGATIVE_OR_NAN1:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[MUST_BE_NEGATIVE_OR_NAN0]], float [[MUST_BE_NEGATIVE_OR_NAN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %must.be.negative.or.nan0 = call float @returns_negative_or_nan()
+  %must.be.negative.or.nan1 = call float @returns_negative_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %must.be.negative.or.nan0, float %must.be.negative.or.nan1)
+  ret float %result
+}
+
+; -> qnan
+define nofpclass(pinf pnorm psub pzero) float @ret_known_negative_or_nan__minimumnum__positive_or_nan___positive_or_nan() {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_known_negative_or_nan__minimumnum__positive_or_nan___positive_or_nan() {
+; CHECK-NEXT:    [[MUST_BE_POSITIVE_OR_NAN0:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[MUST_BE_POSITIVE_OR_NAN1:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[MUST_BE_POSITIVE_OR_NAN0]], float [[MUST_BE_POSITIVE_OR_NAN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %must.be.positive.or.nan0 = call float @returns_positive_or_nan()
+  %must.be.positive.or.nan1 = call float @returns_positive_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %must.be.positive.or.nan0, float %must.be.positive.or.nan1)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_positive_or_nan__minimumnum__known_negative_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_positive_or_nan__minimumnum__known_negative_or_nan() {
+; CHECK-NEXT:    [[MUST_BE_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[MUST_BE_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[MUST_BE_POSITIVE_OR_NAN]], float [[MUST_BE_NEGATIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %must.be.positive.or.nan = call float @returns_positive_or_nan()
+  %must.be.negative.or.nan = call float @returns_negative_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %must.be.positive.or.nan, float %must.be.negative.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_negative_or_nan__minimumnum__known_positive_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_negative_or_nan__minimumnum__known_positive_or_nan() {
+; CHECK-NEXT:    [[MUST_BE_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[MUST_BE_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[MUST_BE_NEGATIVE_OR_NAN]], float [[MUST_BE_POSITIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %must.be.negative.or.nan = call float @returns_negative_or_nan()
+  %must.be.positive.or.nan = call float @returns_positive_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %must.be.negative.or.nan, float %must.be.positive.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_positive_or_nan__minimumnum__known_negative() {
+; CHECK-LABEL: define nofpclass(snan) float @known_positive_or_nan__minimumnum__known_negative() {
+; CHECK-NEXT:    [[MUST_BE_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[MUST_BE_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[MUST_BE_POSITIVE_OR_NAN]], float [[MUST_BE_NEGATIVE]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %must.be.positive.or.nan = call float @returns_positive_or_nan()
+  %must.be.negative = call float @returns_negative()
+  %result = call float @llvm.minimumnum.f32(float %must.be.positive.or.nan, float %must.be.negative)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_negative__minimumnum__known_positive_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_negative__minimumnum__known_positive_or_nan() {
+; CHECK-NEXT:    [[MUST_BE_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[MUST_BE_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[MUST_BE_NEGATIVE]], float [[MUST_BE_POSITIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %must.be.negative = call float @returns_negative()
+  %must.be.positive.or.nan = call float @returns_positive_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %must.be.negative, float %must.be.positive.or.nan)
+  ret float %result
+}
+
+define nofpclass(ninf nnorm nsub nzero) float @ret_always_positive_or_nan__select_always_negative_or_unknown__minimumnum__unknown(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_always_positive_or_nan__select_always_negative_or_unknown__minimumnum__unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[SELECT_LHS]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative = call float @returns_negative()
+  %select.lhs = select i1 %cond, float %always.negative, float %unknown0
+  %result = call float @llvm.minimumnum.f32(float %select.lhs, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(ninf nnorm nsub nzero) float @ret_always_positive_or_nan__unknown__minimumnum__select_always_negative_or_unknown(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_always_positive_or_nan__unknown__minimumnum__select_always_negative_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative = call float @returns_negative()
+  %select.rhs = select i1 %cond, float %always.negative, float %unknown0
+  %result = call float @llvm.minimumnum.f32(float %unknown1, float %select.rhs)
+  ret float %result
+}
+
+define nofpclass(ninf nnorm nsub nzero nan) float @ret_always_positive__select_always_negative_or_unknown__minimumnum__unknown(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_always_positive__select_always_negative_or_unknown__minimumnum__unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[SELECT_LHS]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative = call float @returns_negative()
+  %select.lhs = select i1 %cond, float %always.negative, float %unknown0
+  %result = call float @llvm.minimumnum.f32(float %select.lhs, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(ninf nnorm nsub nzero nan) float @ret_always_positive__unknown__minimumnum__select_always_negative_or_unknown(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_always_positive__unknown__minimumnum__select_always_negative_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative = call float @returns_negative()
+  %select.rhs = select i1 %cond, float %always.negative, float %unknown0
+  %result = call float @llvm.minimumnum.f32(float %unknown1, float %select.rhs)
+  ret float %result
+}
+
+define nofpclass(ninf nnorm nsub nzero) float @ret_always_negative_or_nan__simplify_unneeded_lhs_rhs(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_always_negative_or_nan__simplify_unneeded_lhs_rhs(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE0:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE1:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE0]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[UNKNOWN1]], float [[ALWAYS_NEGATIVE1]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[SELECT_LHS]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative0 = call float @returns_negative()
+  %always.negative1 = call float @returns_negative()
+  %select.lhs = select i1 %cond, float %always.negative0, float %unknown0
+  %select.rhs = select i1 %cond, float %unknown1, float %always.negative1
+  %result = call float @llvm.minimumnum.f32(float %select.lhs, float %select.rhs)
+  ret float %result
+}
+
+define nofpclass(ninf nnorm nsub nzero nan) float @ret_always_negative__simplify_unneeded_lhs_rhs(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_always_negative__simplify_unneeded_lhs_rhs(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE0:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE1:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE0]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[UNKNOWN1]], float [[ALWAYS_NEGATIVE1]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[SELECT_LHS]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative0 = call float @returns_negative()
+  %always.negative1 = call float @returns_negative()
+  %select.lhs = select i1 %cond, float %always.negative0, float %unknown0
+  %select.rhs = select i1 %cond, float %unknown1, float %always.negative1
+  %result = call float @llvm.minimumnum.f32(float %select.lhs, float %select.rhs)
+  ret float %result
+}
+
+define nofpclass(nan) float @no_fold_select_always_negative_0(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(nan) float @no_fold_select_always_negative_0(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[SELECT_LHS]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative = call float @returns_negative()
+  %select.lhs = select i1 %cond, float %always.negative, float %unknown0
+  %result = call float @llvm.minimumnum.f32(float %select.lhs, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(nan) float @no_fold_select_always_negative_1(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(nan) float @no_fold_select_always_negative_1(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative = call float @returns_negative()
+  %select.rhs = select i1 %cond, float %always.negative, float %unknown0
+  %result = call float @llvm.minimumnum.f32(float %unknown1, float %select.rhs)
+  ret float %result
+}
+
+; Cannot fold out due to possible -0
+define nofpclass(snan) float @cannot_fold_negative_or_zero__positive_or_zero_0() {
+; CHECK-LABEL: define nofpclass(snan) float @cannot_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 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 float @llvm.minimumnum.f32(float %must.be.negative.or.zero, float %must.be.positive.or.zero)
+  ret float %result
+}
+
+; Cannot fold out due to possible -0
+define nofpclass(snan) float @cannot_fold_negative_or_zero__positive_or_zero_1() {
+; CHECK-LABEL: define nofpclass(snan) float @cannot_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 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 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:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[MUST_BE_PINF_OR_NAN]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %must.be.pinf.or.nan, float %unknown)
+  ret float %result
+}
+
+define nofpclass(nsub) float @rhs_must_be_pinf_or_nan(float nofpclass(ninf norm zero sub) %must.be.pinf.or.nan, float %unknown) {
+; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_pinf_or_nan(
+; CHECK-SAME: float nofpclass(ninf zero sub norm) [[MUST_BE_PINF_OR_NAN:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN]], float [[MUST_BE_PINF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %unknown, float %must.be.pinf.or.nan)
+  ret float %result
+}
+
+define nofpclass(nsub) float @lhs_must_be_pinf(float %unknown, float nofpclass(nan ninf norm zero sub) %must.be.pinf) {
+; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_pinf(
+; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[MUST_BE_PINF]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %must.be.pinf, float %unknown)
+  ret float %result
+}
+
+define nofpclass(nsub) float @rhs_must_be_pinf(float nofpclass(nan ninf norm zero sub) %must.be.pinf, float %unknown) {
+; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_pinf(
+; CHECK-SAME: float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN]], float [[MUST_BE_PINF]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %unknown, float %must.be.pinf)
+  ret float %result
+}
+
+; -> inf
+define nofpclass(nsub) float @lhs_must_be_pinf_rhs_non_nan(float nofpclass(nan) %not.nan, float nofpclass(nan ninf norm zero sub) %must.be.pinf) {
+; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_pinf_rhs_non_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]], float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[MUST_BE_PINF]], float [[NOT_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %must.be.pinf, float %not.nan)
+  ret float %result
+}
+
+; -> inf
+define nofpclass(nsub) float @rhs_must_be_pinf_lhs_non_nan(float nofpclass(nan ninf norm zero sub) %must.be.pinf, float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_pinf_lhs_non_nan(
+; CHECK-SAME: float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]], float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_NAN]], float [[MUST_BE_PINF]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.nan, float %must.be.pinf)
+  ret float %result
+}
+
+define nofpclass(nsub) float @lhs_must_be_ninf_or_nan(float %unknown, float nofpclass(pinf norm zero sub) %must.be.ninf.or.nan) {
+; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_ninf_or_nan(
+; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(pinf zero sub norm) [[MUST_BE_NINF_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[MUST_BE_NINF_OR_NAN]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %must.be.ninf.or.nan, float %unknown)
+  ret float %result
+}
+
+define nofpclass(nsub) float @rhs_must_be_ninf_or_nan(float nofpclass(pinf norm zero sub) %must.be.ninf.or.nan, float %unknown) {
+; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_ninf_or_nan(
+; CHECK-SAME: float nofpclass(pinf zero sub norm) [[MUST_BE_NINF_OR_NAN:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN]], float [[MUST_BE_NINF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %unknown, float %must.be.ninf.or.nan)
+  ret float %result
+}
+
+define nofpclass(nsub) float @lhs_must_be_ninf(float %unknown, float nofpclass(nan pinf norm zero sub) %must.be.ninf) {
+; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_ninf(
+; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(nan pinf zero sub norm) [[MUST_BE_NINF:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[MUST_BE_NINF]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %must.be.ninf, float %unknown)
+  ret float %result
+}
+
+define nofpclass(nsub) float @rhs_must_be_ninf(float nofpclass(nan pinf norm zero sub) %must.be.ninf, float %unknown) {
+; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_ninf(
+; CHECK-SAME: float nofpclass(nan pinf zero sub norm) [[MUST_BE_NINF:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN]], float [[MUST_BE_NINF]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %unknown, float %must.be.ninf)
+  ret float %result
+}
+
+
+; -> not.nan
+define nofpclass(nsub) float @lhs_must_be_ninf_rhs_non_nan(float nofpclass(nan) %not.nan, float nofpclass(nan pinf norm zero sub) %must.be.ninf) {
+; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_ninf_rhs_non_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]], float nofpclass(nan pinf zero sub norm) [[MUST_BE_NINF:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[MUST_BE_NINF]], float [[NOT_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %must.be.ninf, float %not.nan)
+  ret float %result
+}
+
+; -> not.nan
+define nofpclass(nsub) float @rhs_must_be_ninf_lhs_non_nan(float nofpclass(nan pinf norm zero sub) %must.be.ninf, float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_ninf_lhs_non_nan(
+; CHECK-SAME: float nofpclass(nan pinf zero sub norm) [[MUST_BE_NINF:%.*]], float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_NAN]], float [[MUST_BE_NINF]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.nan, float %must.be.ninf)
+  ret float %result
+}
+
+define nofpclass(nzero) float @result_not_nzero(float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(nzero) float @result_not_nzero(
+; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %unknown0, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(pzero) float @result_not_pzero(float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(pzero) float @result_not_pzero(
+; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %unknown0, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(zero) float @result_not_zero(float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(zero) float @result_not_zero(
+; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %unknown0, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(zero) float @result_not_zero__daz(float %unknown0, float %unknown1) #0 {
+; CHECK-LABEL: define nofpclass(zero) float @result_not_zero__daz(
+; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %unknown0, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(zero) float @result_not_zero__dynamic(float %unknown0, float %unknown1) #1 {
+; CHECK-LABEL: define nofpclass(zero) float @result_not_zero__dynamic(
+; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) #[[ATTR1:[0-9]+]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %unknown0, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(zero) float @result_not_zero_or_sub(float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(zero) float @result_not_zero_or_sub(
+; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %unknown0, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(zero sub) float @result_not_zero_or_sub__daz(float %unknown0, float %unknown1) #0 {
+; CHECK-LABEL: define nofpclass(zero sub) float @result_not_zero_or_sub__daz(
+; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %unknown0, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(zero sub) float @result_not_zero_or_sub__dynamic(float %unknown0, float %unknown1) #1 {
+; CHECK-LABEL: define nofpclass(zero sub) float @result_not_zero_or_sub__dynamic(
+; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %unknown0, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(snan) float @lhs_not_zero(float nofpclass(zero) %not.zero, float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @lhs_not_zero(
+; CHECK-SAME: float nofpclass(zero) [[NOT_ZERO:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_ZERO]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.zero, float %unknown)
+  ret float %result
+}
+
+define nofpclass(snan) float @rhs_not_zero(float %unknown, float nofpclass(zero) %not.zero) {
+; CHECK-LABEL: define nofpclass(snan) float @rhs_not_zero(
+; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(zero) [[NOT_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN]], float [[NOT_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %unknown, float %not.zero)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_zero(float nofpclass(zero) %not.zero0, float nofpclass(zero) %not.zero1) {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero(
+; CHECK-SAME: float nofpclass(zero) [[NOT_ZERO0:%.*]], float nofpclass(zero) [[NOT_ZERO1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_ZERO0]], float [[NOT_ZERO1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.zero0, float %not.zero1)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_zero__daz(float nofpclass(zero) %not.zero0, float nofpclass(zero) %not.zero1) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero__daz(
+; CHECK-SAME: float nofpclass(zero) [[NOT_ZERO0:%.*]], float nofpclass(zero) [[NOT_ZERO1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_ZERO0]], float [[NOT_ZERO1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.zero0, float %not.zero1)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_zero__dynamic(float nofpclass(zero) %not.zero0, float nofpclass(zero) %not.zero1) #2 {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero__dynamic(
+; CHECK-SAME: float nofpclass(zero) [[NOT_ZERO0:%.*]], float nofpclass(zero) [[NOT_ZERO1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_ZERO0]], float [[NOT_ZERO1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.zero0, float %not.zero1)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_zero_or_sub(float nofpclass(zero sub) %not.zero.sub.0, float nofpclass(zero sub) %not.zero.sub.1) {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero_or_sub(
+; CHECK-SAME: float nofpclass(zero sub) [[NOT_ZERO_SUB_0:%.*]], float nofpclass(zero sub) [[NOT_ZERO_SUB_1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.zero.sub.0, float %not.zero.sub.1)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_zero_or_sub__daz(float nofpclass(zero sub) %not.zero.sub.0, float nofpclass(zero sub) %not.zero.sub.1) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero_or_sub__daz(
+; CHECK-SAME: float nofpclass(zero sub) [[NOT_ZERO_SUB_0:%.*]], float nofpclass(zero sub) [[NOT_ZERO_SUB_1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.zero.sub.0, float %not.zero.sub.1)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_zero_or_sub__dynamic(float nofpclass(zero sub) %not.zero.sub.0, float nofpclass(zero sub) %not.zero.sub.1) #2 {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero_or_sub__dynamic(
+; CHECK-SAME: float nofpclass(zero sub) [[NOT_ZERO_SUB_0:%.*]], float nofpclass(zero sub) [[NOT_ZERO_SUB_1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.zero.sub.0, float %not.zero.sub.1)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_nzero(float nofpclass(nzero) %not.nzero0, float nofpclass(nzero) %not.nzero1) {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_nzero(
+; CHECK-SAME: float nofpclass(nzero) [[NOT_NZERO0:%.*]], float nofpclass(nzero) [[NOT_NZERO1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_NZERO0]], float [[NOT_NZERO1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.nzero0, float %not.nzero1)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_pzero(float nofpclass(pzero) %not.pzero0, float nofpclass(pzero) %not.pzero1) {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_pzero(
+; CHECK-SAME: float nofpclass(pzero) [[NOT_PZERO0:%.*]], float nofpclass(pzero) [[NOT_PZERO1:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_PZERO0]], float [[NOT_PZERO1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.pzero0, float %not.pzero1)
+  ret float %result
+}
+
+define nofpclass(snan) float @lhs_not_nzero_rhs_not_pzero(float nofpclass(nzero) %not.nzero, float nofpclass(pzero) %not.pzero) {
+; CHECK-LABEL: define nofpclass(snan) float @lhs_not_nzero_rhs_not_pzero(
+; CHECK-SAME: float nofpclass(nzero) [[NOT_NZERO:%.*]], float nofpclass(pzero) [[NOT_PZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_NZERO]], float [[NOT_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.nzero, float %not.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @rhs_not_nzero_lhs_not_pzero(float nofpclass(pzero) %not.nzero, float nofpclass(nzero) %not.pzero) {
+; CHECK-LABEL: define nofpclass(snan) float @rhs_not_nzero_lhs_not_pzero(
+; CHECK-SAME: float nofpclass(pzero) [[NOT_NZERO:%.*]], float nofpclass(nzero) [[NOT_PZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_NZERO]], float [[NOT_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.nzero, float %not.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_nzero__dynamic(float nofpclass(nzero) %not.nzero0, float nofpclass(nzero) %not.nzero1) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_nzero__dynamic(
+; CHECK-SAME: float nofpclass(nzero) [[NOT_NZERO0:%.*]], float nofpclass(nzero) [[NOT_NZERO1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_NZERO0]], float [[NOT_NZERO1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.nzero0, float %not.nzero1)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_pzero__dynamic(float nofpclass(pzero) %not.pzero0, float nofpclass(pzero) %not.pzero1) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_pzero__dynamic(
+; CHECK-SAME: float nofpclass(pzero) [[NOT_PZERO0:%.*]], float nofpclass(pzero) [[NOT_PZERO1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_PZERO0]], float [[NOT_PZERO1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.pzero0, float %not.pzero1)
+  ret float %result
+}
+
+define nofpclass(snan) float @lhs_not_nzero_rhs_not_pzero__dynamic(float nofpclass(nzero) %not.nzero, float nofpclass(pzero) %not.pzero) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @lhs_not_nzero_rhs_not_pzero__dynamic(
+; CHECK-SAME: float nofpclass(nzero) [[NOT_NZERO:%.*]], float nofpclass(pzero) [[NOT_PZERO:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_NZERO]], float [[NOT_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.nzero, float %not.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @rhs_not_nzero_lhs_not_pzero__dynamic(float nofpclass(pzero) %not.nzero, float nofpclass(nzero) %not.pzero) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @rhs_not_nzero_lhs_not_pzero__dynamic(
+; CHECK-SAME: float nofpclass(pzero) [[NOT_NZERO:%.*]], float nofpclass(nzero) [[NOT_PZERO:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_NZERO]], float [[NOT_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.nzero, float %not.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_nzero_nsub__dynamic(float nofpclass(nzero nsub) %not.nzero0, float nofpclass(nzero nsub) %not.nzero1) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_nzero_nsub__dynamic(
+; CHECK-SAME: float nofpclass(nzero nsub) [[NOT_NZERO0:%.*]], float nofpclass(nzero nsub) [[NOT_NZERO1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_NZERO0]], float [[NOT_NZERO1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.nzero0, float %not.nzero1)
+  ret float %result
+}
+
+define nofpclass(snan) float @sources_not_pzero_psub__dynamic(float nofpclass(pzero psub) %not.pzero0, float nofpclass(pzero psub) %not.pzero1) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @sources_not_pzero_psub__dynamic(
+; CHECK-SAME: float nofpclass(pzero psub) [[NOT_PZERO0:%.*]], float nofpclass(pzero psub) [[NOT_PZERO1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_PZERO0]], float [[NOT_PZERO1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.pzero0, float %not.pzero1)
+  ret float %result
+}
+
+define nofpclass(snan) float @lhs_not_nzero_nsub_rhs_not_pzero__dynamic(float nofpclass(nzero nsub) %not.nzero, float nofpclass(pzero psub) %not.pzero) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @lhs_not_nzero_nsub_rhs_not_pzero__dynamic(
+; CHECK-SAME: float nofpclass(nzero nsub) [[NOT_NZERO:%.*]], float nofpclass(pzero psub) [[NOT_PZERO:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_NZERO]], float [[NOT_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.nzero, float %not.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @rhs_not_nzero_nsub_lhs_not_pzero_psub__dynamic(float nofpclass(pzero psub) %not.nzero, float nofpclass(nzero nsub) %not.pzero) #1 {
+; CHECK-LABEL: define nofpclass(snan) float @rhs_not_nzero_nsub_lhs_not_pzero_psub__dynamic(
+; CHECK-SAME: float nofpclass(pzero psub) [[NOT_NZERO:%.*]], float nofpclass(nzero nsub) [[NOT_PZERO:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_NZERO]], float [[NOT_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %not.nzero, float %not.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @not_nan__minimumnum__unknown(float nofpclass(nan) %x, float %y) {
+; CHECK-LABEL: define nofpclass(snan) float @not_nan__minimumnum__unknown(
+; CHECK-SAME: float nofpclass(nan) [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(snan) float @unknown__minimumnum__not_nan(float %x, float nofpclass(nan) %y) {
+; CHECK-LABEL: define nofpclass(snan) float @unknown__minimumnum__not_nan(
+; CHECK-SAME: float [[X:%.*]], float nofpclass(nan) [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(snan) float @not_nan__minimumnum__not_nan(float nofpclass(nan) %x, float nofpclass(nan) %y) {
+; CHECK-LABEL: define nofpclass(snan) float @not_nan__minimumnum__not_nan(
+; CHECK-SAME: float nofpclass(nan) [[X:%.*]], float nofpclass(nan) [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(snan) float @not_snan__minimumnum__not_snan(float nofpclass(snan) %x, float nofpclass(snan) %y) {
+; CHECK-LABEL: define nofpclass(snan) float @not_snan__minimumnum__not_snan(
+; CHECK-SAME: float nofpclass(snan) [[X:%.*]], float nofpclass(snan) [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(inf) float @ret_noinf__not_qnan__minimumnum__not_qnan(float nofpclass(qnan) %x, float nofpclass(qnan) %y) {
+; CHECK-LABEL: define nofpclass(inf) float @ret_noinf__not_qnan__minimumnum__not_qnan(
+; CHECK-SAME: float nofpclass(qnan) [[X:%.*]], float nofpclass(qnan) [[Y:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %x, float %y)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_positive__minimumnum__only_zero() {
+; CHECK-LABEL: define nofpclass(snan) float @known_positive__minimumnum__only_zero() {
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[KNOWN_ZERO:%.*]] = call float @returns_zero()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_POSITIVE]], float [[KNOWN_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.positive = call float @returns_positive()
+  %known.zero = call float @returns_zero()
+  %result = call float @llvm.minimumnum.f32(float %known.positive, float %known.zero)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_zero__minimumnum__known_positive() {
+; CHECK-LABEL: define nofpclass(snan) float @only_zero__minimumnum__known_positive() {
+; CHECK-NEXT:    [[KNOWN_ZERO:%.*]] = call float @returns_zero()
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_ZERO]], float [[KNOWN_POSITIVE]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.zero = call float @returns_zero()
+  %known.positive = call float @returns_positive()
+  %result = call float @llvm.minimumnum.f32(float %known.zero, float %known.positive)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_positive__minimumnum__only_zero_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_positive__minimumnum__only_zero_or_nan() {
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[KNOWN_ZERO_OR_NAN:%.*]] = call float @returns_zero_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_POSITIVE]], float [[KNOWN_ZERO_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.positive = call float @returns_positive()
+  %known.zero.or.nan = call float @returns_zero_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %known.positive, float %known.zero.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_zero_or_nan__minimumnum__known_positive() {
+; CHECK-LABEL: define nofpclass(snan) float @only_zero_or_nan__minimumnum__known_positive() {
+; CHECK-NEXT:    [[KNOWN_ZERO_OR_NAN:%.*]] = call float @returns_zero_or_nan()
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_ZERO_OR_NAN]], float [[KNOWN_POSITIVE]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.zero.or.nan = call float @returns_zero_or_nan()
+  %known.positive = call float @returns_positive()
+  %result = call float @llvm.minimumnum.f32(float %known.zero.or.nan, float %known.positive)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_positive_or_nan__minimumnum__only_zero() {
+; CHECK-LABEL: define nofpclass(snan) float @known_positive_or_nan__minimumnum__only_zero() {
+; CHECK-NEXT:    [[KNOWN_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[KNOWN_ZERO:%.*]] = call float @returns_zero()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_POSITIVE_OR_NAN]], float [[KNOWN_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.positive.or.nan = call float @returns_positive_or_nan()
+  %known.zero = call float @returns_zero()
+  %result = call float @llvm.minimumnum.f32(float %known.positive.or.nan, float %known.zero)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_zero__minimumnum__known_positive_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @only_zero__minimumnum__known_positive_or_nan() {
+; CHECK-NEXT:    [[KNOWN_ZERO:%.*]] = call float @returns_zero()
+; CHECK-NEXT:    [[KNOWN_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_ZERO]], float [[KNOWN_POSITIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.zero = call float @returns_zero()
+  %known.positive.or.nan = call float @returns_positive_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %known.zero, float %known.positive.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_positive__minimumnum__only_nzero() {
+; CHECK-LABEL: define nofpclass(snan) float @known_positive__minimumnum__only_nzero() {
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[KNOWN_NZERO:%.*]] = call float @returns_nzero()
+; CHECK-NEXT:    ret float -0.000000e+00
+;
+  %known.positive = call float @returns_positive()
+  %known.nzero = call float @returns_nzero()
+  %result = call float @llvm.minimumnum.f32(float %known.positive, float %known.nzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_nzero__minimumnum__known_positive() {
+; CHECK-LABEL: define nofpclass(snan) float @only_nzero__minimumnum__known_positive() {
+; CHECK-NEXT:    [[KNOWN_NZERO:%.*]] = call float @returns_nzero()
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    ret float -0.000000e+00
+;
+  %known.nzero = call float @returns_nzero()
+  %known.positive = call float @returns_positive()
+  %result = call float @llvm.minimumnum.f32(float %known.nzero, float %known.positive)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_positive__minimumnum__only_pzero() {
+; CHECK-LABEL: define nofpclass(snan) float @known_positive__minimumnum__only_pzero() {
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[KNOWN_PZERO:%.*]] = call float @returns_pzero()
+; CHECK-NEXT:    ret float 0.000000e+00
+;
+  %known.positive = call float @returns_positive()
+  %known.pzero = call float @returns_pzero()
+  %result = call float @llvm.minimumnum.f32(float %known.positive, float %known.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_pzero__minimumnum__known_positive() {
+; CHECK-LABEL: define nofpclass(snan) float @only_pzero__minimumnum__known_positive() {
+; CHECK-NEXT:    [[KNOWN_PZERO:%.*]] = call float @returns_pzero()
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    ret float 0.000000e+00
+;
+  %known.pzero = call float @returns_pzero()
+  %known.positive = call float @returns_positive()
+  %result = call float @llvm.minimumnum.f32(float %known.pzero, float %known.positive)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_negative__minimumnum__only_zero_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_negative__minimumnum__only_zero_or_nan() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[KNOWN_ZERO_OR_NAN:%.*]] = call float @returns_zero_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_NEGATIVE]], float [[KNOWN_ZERO_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative = call float @returns_negative()
+  %known.zero.or.nan = call float @returns_zero_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %known.negative, float %known.zero.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_zero_or_nan__minimumnum__known_negative() {
+; CHECK-LABEL: define nofpclass(snan) float @only_zero_or_nan__minimumnum__known_negative() {
+; CHECK-NEXT:    [[KNOWN_ZERO_OR_NAN:%.*]] = call float @returns_zero_or_nan()
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_ZERO_OR_NAN]], float [[KNOWN_NEGATIVE]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.zero.or.nan = call float @returns_zero_or_nan()
+  %known.negative = call float @returns_negative()
+  %result = call float @llvm.minimumnum.f32(float %known.zero.or.nan, float %known.negative)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_negative_or_nan__minimumnum__only_zero() {
+; CHECK-LABEL: define nofpclass(snan) float @known_negative_or_nan__minimumnum__only_zero() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[KNOWN_ZERO:%.*]] = call float @returns_zero()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_NEGATIVE_OR_NAN]], float [[KNOWN_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative.or.nan = call float @returns_negative_or_nan()
+  %known.zero = call float @returns_zero()
+  %result = call float @llvm.minimumnum.f32(float %known.negative.or.nan, float %known.zero)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_zero__minimumnum__known_negative_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @only_zero__minimumnum__known_negative_or_nan() {
+; CHECK-NEXT:    [[KNOWN_ZERO:%.*]] = call float @returns_zero()
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_ZERO]], float [[KNOWN_NEGATIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.zero = call float @returns_zero()
+  %known.negative.or.nan = call float @returns_negative_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %known.zero, float %known.negative.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_negative__minimumnum__only_nzero() {
+; CHECK-LABEL: define nofpclass(snan) float @known_negative__minimumnum__only_nzero() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[KNOWN_NZERO:%.*]] = call float @returns_nzero()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_NEGATIVE]], float [[KNOWN_NZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative = call float @returns_negative()
+  %known.nzero = call float @returns_nzero()
+  %result = call float @llvm.minimumnum.f32(float %known.negative, float %known.nzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_nzero__minimumnum__known_negative() {
+; CHECK-LABEL: define nofpclass(snan) float @only_nzero__minimumnum__known_negative() {
+; CHECK-NEXT:    [[KNOWN_NZERO:%.*]] = call float @returns_nzero()
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_NZERO]], float [[KNOWN_NEGATIVE]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.nzero = call float @returns_nzero()
+  %known.negative = call float @returns_negative()
+  %result = call float @llvm.minimumnum.f32(float %known.nzero, float %known.negative)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_negative__minimumnum__only_nzero_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_negative__minimumnum__only_nzero_or_nan() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[KNOWN_NZERO_OR_NAN:%.*]] = call float @returns_nzero_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_NEGATIVE]], float [[KNOWN_NZERO_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative = call float @returns_negative()
+  %known.nzero.or.nan = call float @returns_nzero_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %known.negative, float %known.nzero.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_nzero_or_nan__minimumnum__known_negative() {
+; CHECK-LABEL: define nofpclass(snan) float @only_nzero_or_nan__minimumnum__known_negative() {
+; CHECK-NEXT:    [[KNOWN_NZERO_OR_NAN:%.*]] = call float @returns_nzero_or_nan()
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_NZERO_OR_NAN]], float [[KNOWN_NEGATIVE]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.nzero.or.nan = call float @returns_nzero_or_nan()
+  %known.negative = call float @returns_negative()
+  %result = call float @llvm.minimumnum.f32(float %known.nzero.or.nan, float %known.negative)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_negative__minimumnum__only_pzero() {
+; CHECK-LABEL: define nofpclass(snan) float @known_negative__minimumnum__only_pzero() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[KNOWN_PZERO:%.*]] = call float @returns_pzero()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_NEGATIVE]], float [[KNOWN_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative = call float @returns_negative()
+  %known.pzero = call float @returns_pzero()
+  %result = call float @llvm.minimumnum.f32(float %known.negative, float %known.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_pzero__minimumnum__known_negative() {
+; CHECK-LABEL: define nofpclass(snan) float @only_pzero__minimumnum__known_negative() {
+; CHECK-NEXT:    [[KNOWN_PZERO:%.*]] = call float @returns_pzero()
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_PZERO]], float [[KNOWN_NEGATIVE]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.pzero = call float @returns_pzero()
+  %known.negative = call float @returns_negative()
+  %result = call float @llvm.minimumnum.f32(float %known.pzero, float %known.negative)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_negative__minimumnum__only_pzero_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_negative__minimumnum__only_pzero_or_nan() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[KNOWN_PZERO_OR_NAN:%.*]] = call float @returns_pzero_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_NEGATIVE]], float [[KNOWN_PZERO_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative = call float @returns_negative()
+  %known.pzero.or.nan = call float @returns_pzero_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %known.negative, float %known.pzero.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @only_pzero_or_nan__minimumnum__known_negative() {
+; CHECK-LABEL: define nofpclass(snan) float @only_pzero_or_nan__minimumnum__known_negative() {
+; CHECK-NEXT:    [[KNOWN_PZERO_OR_NAN:%.*]] = call float @returns_pzero_or_nan()
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_PZERO_OR_NAN]], float [[KNOWN_NEGATIVE]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.pzero.or.nan = call float @returns_pzero_or_nan()
+  %known.negative = call float @returns_negative()
+  %result = call float @llvm.minimumnum.f32(float %known.pzero.or.nan, float %known.negative)
+  ret float %result
+}
+
+define nofpclass(pinf pnorm psub pzero) float @ret_always_negative_or_nan__unknown__minimumnum__select_always_negative_or_unknown(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_always_negative_or_nan__unknown__minimumnum__select_always_negative_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative = call float @returns_negative()
+  %select.rhs = select i1 %cond, float %always.negative, float %unknown0
+  %result = call float @llvm.minimumnum.f32(float %unknown1, float %select.rhs)
+  ret float %result
+}
+
+define nofpclass(pinf pnorm psub pzero) float @ret_always_negative_or_nan__unknown__minimumnum__select_always_positive_or_unknown(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_always_negative_or_nan__unknown__minimumnum__select_always_positive_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[ALWAYS_POSITIVE]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.positive = call float @returns_positive()
+  %select.rhs = select i1 %cond, float %always.positive, float %unknown0
+  %result = call float @llvm.minimumnum.f32(float %unknown1, float %select.rhs)
+  ret float %result
+}
+
+define nofpclass(pinf pnorm psub) float @ret_always_positive_nonzero__minimumnum__not_zero_select_positive_or_unknown(i1 %cond, float %unknown, float nofpclass(zero) %not.zero) {
+; CHECK-LABEL: define nofpclass(pinf psub pnorm) float @ret_always_positive_nonzero__minimumnum__not_zero_select_positive_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(zero) [[NOT_ZERO:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[ALWAYS_POSITIVE]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_ZERO]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.positive = call float @returns_positive()
+  %select.rhs = select i1 %cond, float %always.positive, float %unknown
+  %result = call float @llvm.minimumnum.f32(float %not.zero, float %select.rhs)
+  ret float %result
+}
+
+define nofpclass(pinf pnorm psub) float @ret_always_positive_nonzero__minimumnum__not_zero_select_negative_or_unknown(i1 %cond, float %unknown, float nofpclass(zero) %not.zero) {
+; CHECK-LABEL: define nofpclass(pinf psub pnorm) float @ret_always_positive_nonzero__minimumnum__not_zero_select_negative_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(zero) [[NOT_ZERO:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_ZERO]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.negative = call float @returns_negative()
+  %select.rhs = select i1 %cond, float %always.negative, float %unknown
+  %result = call float @llvm.minimumnum.f32(float %not.zero, float %select.rhs)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_positive__minimumnum__only_pzero_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_positive__minimumnum__only_pzero_or_nan() {
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[KNOWN_PZERO_OR_NAN:%.*]] = call float @returns_pzero_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_POSITIVE]], float [[KNOWN_PZERO_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.positive = call float @returns_positive()
+  %known.pzero.or.nan = call float @returns_pzero_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %known.positive, float %known.pzero.or.nan)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_nonan__known_negative_or_nan__minimumnum__known_positive_or_nan() {
+; CHECK-LABEL: define nofpclass(nan) float @ret_nonan__known_negative_or_nan__minimumnum__known_positive_or_nan() {
+; CHECK-NEXT:    [[MUST_BE_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[MUST_BE_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[MUST_BE_NEGATIVE_OR_NAN]], float [[MUST_BE_POSITIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %must.be.negative.or.nan = call float @returns_negative_or_nan()
+  %must.be.positive.or.nan = call float @returns_positive_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %must.be.negative.or.nan, float %must.be.positive.or.nan)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_nonan__known_positive_or_nan__minimumnum__known_negative_or_nan() {
+; CHECK-LABEL: define nofpclass(nan) float @ret_nonan__known_positive_or_nan__minimumnum__known_negative_or_nan() {
+; CHECK-NEXT:    [[MUST_BE_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[MUST_BE_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[MUST_BE_POSITIVE_OR_NAN]], float [[MUST_BE_NEGATIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %must.be.positive.or.nan = call float @returns_positive_or_nan()
+  %must.be.negative.or.nan = call float @returns_negative_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %must.be.positive.or.nan, float %must.be.negative.or.nan)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_nonan__select_nan_or_unknown__minimumnum__unknown(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_nonan__select_nan_or_unknown__minimumnum__unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NAN:%.*]] = call float @returns_nan()
+; CHECK-NEXT:    [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NAN]], float [[UNKNOWN0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[SELECT_LHS]], float [[UNKNOWN1]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.nan = call float @returns_nan()
+  %select.lhs = select i1 %cond, float %always.nan, float %unknown0
+  %result = call float @llvm.minimumnum.f32(float %select.lhs, float %unknown1)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_nonan__unknown__minimumnum__select_nan_or_unknown(i1 %cond, float %unknown0, float %unknown1) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_nonan__unknown__minimumnum__select_nan_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_NAN:%.*]] = call float @returns_nan()
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[UNKNOWN0]], float [[ALWAYS_NAN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.nan = call float @returns_nan()
+  %select.rhs = select i1 %cond, float %unknown0, float %always.nan
+  %result = call float @llvm.minimumnum.f32(float %unknown1, float %select.rhs)
+  ret float %result
+}
+
+define nofpclass(ninf nnorm nsub nzero) float @result_known_positive_or_nan__known_positive__minimumnum__not_nan(float nofpclass(ninf nnorm nsub nzero) %lhs, float nofpclass(nan) %rhs) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @result_known_positive_or_nan__known_positive__minimumnum__not_nan(
+; CHECK-SAME: float nofpclass(ninf nzero nsub nnorm) [[LHS:%.*]], float nofpclass(nan) [[RHS:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[LHS]], float [[RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %lhs, float %rhs)
+  ret float %result
+}
+
+define nofpclass(ninf nnorm nsub nzero) float @result_known_positive_or_nan__not_nan__minimumnum__known_positive(float nofpclass(nan) %lhs, float nofpclass(ninf nnorm nsub nzero) %rhs) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @result_known_positive_or_nan__not_nan__minimumnum__known_positive(
+; CHECK-SAME: float nofpclass(nan) [[LHS:%.*]], float nofpclass(ninf nzero nsub nnorm) [[RHS:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[LHS]], float [[RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.minimumnum.f32(float %lhs, float %rhs)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_always_positive__minimumnum__known_always_negative_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_always_positive__minimumnum__known_always_negative_or_nan() {
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_POSITIVE]], float [[KNOWN_NEGATIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.positive = call float @returns_positive()
+  %known.negative.or.nan = call float @returns_negative_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %known.positive, float %known.negative.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_always_negative_or_nan__minimumnum__known_always_positive() {
+; CHECK-LABEL: define nofpclass(snan) float @known_always_negative_or_nan__minimumnum__known_always_positive() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_NEGATIVE_OR_NAN]], float [[KNOWN_POSITIVE]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative.or.nan = call float @returns_negative_or_nan()
+  %known.positive = call float @returns_positive()
+  %result = call float @llvm.minimumnum.f32(float %known.negative.or.nan, float %known.positive)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_always_positive_or_nan__minimumnum__known_always_negative_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_always_positive_or_nan__minimumnum__known_always_negative_or_nan() {
+; CHECK-NEXT:    [[KNOWN_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_POSITIVE_OR_NAN]], float [[KNOWN_NEGATIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.positive.or.nan = call float @returns_positive_or_nan()
+  %known.negative.or.nan = call float @returns_negative_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %known.positive.or.nan, float %known.negative.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @known_always_negative_or_nan__minimumnum__known_always_positive_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) float @known_always_negative_or_nan__minimumnum__known_always_positive_or_nan() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[KNOWN_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_NEGATIVE_OR_NAN]], float [[KNOWN_POSITIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative.or.nan = call float @returns_negative_or_nan()
+  %known.positive.or.nan = call float @returns_positive_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %known.negative.or.nan, float %known.positive.or.nan)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nan__known_always_positive_or_nan__minimumnum__known_always_negative_or_nan() {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__known_always_positive_or_nan__minimumnum__known_always_negative_or_nan() {
+; CHECK-NEXT:    [[KNOWN_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_POSITIVE_OR_NAN]], float [[KNOWN_NEGATIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.positive.or.nan = call float @returns_positive_or_nan()
+  %known.negative.or.nan = call float @returns_negative_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %known.positive.or.nan, float %known.negative.or.nan)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nan__known_always_negative_or_nan__minimumnum__known_always_positive_or_nan() {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__known_always_negative_or_nan__minimumnum__known_always_positive_or_nan() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan()
+; CHECK-NEXT:    [[KNOWN_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[KNOWN_NEGATIVE_OR_NAN]], float [[KNOWN_POSITIVE_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative.or.nan = call float @returns_negative_or_nan()
+  %known.positive.or.nan = call float @returns_positive_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %known.negative.or.nan, float %known.positive.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @pinf__minimumnum__unknown(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @pinf__minimumnum__unknown(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[PINF:%.*]] = call float @returns_pinf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[PINF]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %pinf = call float @returns_pinf()
+  %result = call float @llvm.minimumnum.f32(float %pinf, float %unknown)
+  ret float %result
+}
+
+define nofpclass(snan) float @unknown__minimumnum__pinf(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @unknown__minimumnum__pinf(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[PINF:%.*]] = call float @returns_pinf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN]], float [[PINF]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %pinf = call float @returns_pinf()
+  %result = call float @llvm.minimumnum.f32(float %unknown, float %pinf)
+  ret float %result
+}
+
+define nofpclass(snan) float @pinf_or_nan__minimumnum__unknown(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @pinf_or_nan__minimumnum__unknown(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[PINF_OR_NAN:%.*]] = call float @returns_pinf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[PINF_OR_NAN]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %pinf.or.nan = call float @returns_pinf_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %pinf.or.nan, float %unknown)
+  ret float %result
+}
+
+define nofpclass(snan) float @unknown__minimumnum__pinf_or_nan(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @unknown__minimumnum__pinf_or_nan(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[PINF_OR_NAN:%.*]] = call float @returns_pinf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN]], float [[PINF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %pinf.or.nan = call float @returns_pinf_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %unknown, float %pinf.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @ninf__minimumnum__unknown(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @ninf__minimumnum__unknown(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NINF:%.*]] = call float @returns_ninf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NINF]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %ninf = call float @returns_ninf()
+  %result = call float @llvm.minimumnum.f32(float %ninf, float %unknown)
+  ret float %result
+}
+
+define nofpclass(snan) float @unknown__minimumnum__ninf(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @unknown__minimumnum__ninf(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NINF:%.*]] = call float @returns_ninf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN]], float [[NINF]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %ninf = call float @returns_ninf()
+  %result = call float @llvm.minimumnum.f32(float %unknown, float %ninf)
+  ret float %result
+}
+
+define nofpclass(snan) float @ninf_or_nan__minimumnum__unknown(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @ninf_or_nan__minimumnum__unknown(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NINF_OR_NAN:%.*]] = call float @returns_ninf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NINF_OR_NAN]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %ninf.or.nan = call float @returns_ninf_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %ninf.or.nan, float %unknown)
+  ret float %result
+}
+
+define nofpclass(snan) float @unknown__minimumnum__ninf_or_nan(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @unknown__minimumnum__ninf_or_nan(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NINF_OR_NAN:%.*]] = call float @returns_ninf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN]], float [[NINF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %ninf.or.nan = call float @returns_ninf_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %unknown, float %ninf.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @inf__minimumnum__unknown(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @inf__minimumnum__unknown(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[INF:%.*]] = call float @returns_inf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[INF]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %inf = call float @returns_inf()
+  %result = call float @llvm.minimumnum.f32(float %inf, float %unknown)
+  ret float %result
+}
+
+define nofpclass(snan) float @unknown__minimumnum__inf(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @unknown__minimumnum__inf(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[INF:%.*]] = call float @returns_inf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN]], float [[INF]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %inf = call float @returns_inf()
+  %result = call float @llvm.minimumnum.f32(float %unknown, float %inf)
+  ret float %result
+}
+
+define nofpclass(snan) float @inf_or_nan__minimumnum__unknown(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @inf_or_nan__minimumnum__unknown(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[INF_OR_NAN:%.*]] = call float @returns_inf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[INF_OR_NAN]], float [[UNKNOWN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %inf.or.nan = call float @returns_inf_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %inf.or.nan, float %unknown)
+  ret float %result
+}
+
+define nofpclass(snan) float @unknown__minimumnum__inf_or_nan(float %unknown) {
+; CHECK-LABEL: define nofpclass(snan) float @unknown__minimumnum__inf_or_nan(
+; CHECK-SAME: float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[INF_OR_NAN:%.*]] = call float @returns_inf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[UNKNOWN]], float [[INF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %inf.or.nan = call float @returns_inf_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %unknown, float %inf.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @ninf_or_nan__minimumnum__not_nan(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @ninf_or_nan__minimumnum__not_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[NINF_OR_NAN:%.*]] = call float @returns_ninf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NINF_OR_NAN]], float [[NOT_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %ninf.or.nan = call float @returns_ninf_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %ninf.or.nan, float %not.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @not_nan__minimumnum__ninf_or_nan(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @not_nan__minimumnum__ninf_or_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[NINF_OR_NAN:%.*]] = call float @returns_ninf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_NAN]], float [[NINF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %ninf.or.nan = call float @returns_ninf_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %not.nan, float %ninf.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @pinf_or_nan__minimumnum__not_nan(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @pinf_or_nan__minimumnum__not_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[PINF_OR_NAN:%.*]] = call float @returns_pinf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[PINF_OR_NAN]], float [[NOT_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %pinf.or.nan = call float @returns_pinf_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %pinf.or.nan, float %not.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @not_nan__minimumnum__pinf_or_nan(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @not_nan__minimumnum__pinf_or_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[PINF_OR_NAN:%.*]] = call float @returns_pinf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_NAN]], float [[PINF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %pinf.or.nan = call float @returns_pinf_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %not.nan, float %pinf.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @inf_or_nan__minimumnum__not_nan(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @inf_or_nan__minimumnum__not_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[INF_OR_NAN:%.*]] = call float @returns_inf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[INF_OR_NAN]], float [[NOT_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %inf.or.nan = call float @returns_inf_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %inf.or.nan, float %not.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @not_nan__minimumnum__inf_or_nan(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @not_nan__minimumnum__inf_or_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[INF_OR_NAN:%.*]] = call float @returns_inf_or_nan()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_NAN]], float [[INF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %inf.or.nan = call float @returns_inf_or_nan()
+  %result = call float @llvm.minimumnum.f32(float %not.nan, float %inf.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @ninf__minimumnum__not_nan(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @ninf__minimumnum__not_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[NINF_OR_NAN:%.*]] = call float @returns_ninf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NINF_OR_NAN]], float [[NOT_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %ninf.or.nan = call float @returns_ninf()
+  %result = call float @llvm.minimumnum.f32(float %ninf.or.nan, float %not.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @not_nan__minimumnum__ninf(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @not_nan__minimumnum__ninf(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[NINF_OR_NAN:%.*]] = call float @returns_ninf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_NAN]], float [[NINF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %ninf.or.nan = call float @returns_ninf()
+  %result = call float @llvm.minimumnum.f32(float %not.nan, float %ninf.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @pinf__minimumnum__not_nan(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @pinf__minimumnum__not_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[PINF_OR_NAN:%.*]] = call float @returns_pinf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[PINF_OR_NAN]], float [[NOT_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %pinf.or.nan = call float @returns_pinf()
+  %result = call float @llvm.minimumnum.f32(float %pinf.or.nan, float %not.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @not_nan__minimumnum__pinf(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @not_nan__minimumnum__pinf(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[PINF_OR_NAN:%.*]] = call float @returns_pinf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_NAN]], float [[PINF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %pinf.or.nan = call float @returns_pinf()
+  %result = call float @llvm.minimumnum.f32(float %not.nan, float %pinf.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @inf__minimumnum__not_nan(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @inf__minimumnum__not_nan(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[INF_OR_NAN:%.*]] = call float @returns_inf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[INF_OR_NAN]], float [[NOT_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %inf.or.nan = call float @returns_inf()
+  %result = call float @llvm.minimumnum.f32(float %inf.or.nan, float %not.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @not_nan__minimumnum__inf(float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @not_nan__minimumnum__inf(
+; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[INF_OR_NAN:%.*]] = call float @returns_inf()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.minimumnum.f32(float [[NOT_NAN]], float [[INF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %inf.or.nan = call float @returns_inf()
+  %result = call float @llvm.minimumnum.f32(float %not.nan, float %inf.or.nan)
+  ret float %result
+}
+
+attributes #0 = { "denormal-fp-math"="preserve-sign,preserve-sign" }
+attributes #1 = { "denormal-fp-math"="dynamic,dynamic" }



More information about the llvm-branch-commits mailing list