[llvm-branch-commits] [llvm] InstCombine: Add SimplifyDemandedFPClass tests for round (PR #174841)

Matt Arsenault via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sun Jan 11 03:08:34 PST 2026


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

>From 5551b487c7bd55e0c2905521339c9dd4bc9c1d4a Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Mon, 29 Dec 2025 19:22:12 +0100
Subject: [PATCH 1/2] InstCombine: Add SimplifyDemandedFPClass tests for round

Add tests for the family of rounding intrinsics
---
 ...fy-demanded-fpclass-rounding-intrinsics.ll | 1073 +++++++++++++++++
 1 file changed, 1073 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-rounding-intrinsics.ll

diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-rounding-intrinsics.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-rounding-intrinsics.ll
new file mode 100644
index 0000000000000..29c97b3ec76ed
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-rounding-intrinsics.ll
@@ -0,0 +1,1073 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+define nofpclass(snan) float @ret_no_snan__floor_no_snan(float nofpclass(nan) %x) {
+; CHECK-LABEL: define nofpclass(snan) float @ret_no_snan__floor_no_snan(
+; CHECK-SAME: float nofpclass(nan) [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[X]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %x)
+  ret float %result
+}
+
+define nofpclass(inf norm sub zero) float @ret_only_nan__floor(float %x) {
+; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_only_nan__floor(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[X]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %x)
+  ret float %result
+}
+
+define nofpclass(inf norm sub zero) <2 x float> @ret_only_nan__floor_vec(<2 x float> %x) {
+; CHECK-LABEL: define nofpclass(inf zero sub norm) <2 x float> @ret_only_nan__floor_vec(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call <2 x float> @llvm.floor.v2f32(<2 x float> [[X]])
+; CHECK-NEXT:    ret <2 x float> [[RESULT]]
+;
+  %result = call <2 x float> @llvm.floor.v2f32(<2 x float> %x)
+  ret <2 x float> %result
+}
+
+define nofpclass(inf norm sub zero qnan) float @ret_only_snan__floor(float %x) {
+; CHECK-LABEL: define nofpclass(qnan inf zero sub norm) float @ret_only_snan__floor(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[X]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %x)
+  ret float %result
+}
+
+define nofpclass(inf norm sub zero snan) float @ret_only_qnan__floor(float %x) {
+; CHECK-LABEL: define nofpclass(snan inf zero sub norm) float @ret_only_qnan__floor(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[X]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %x)
+  ret float %result
+}
+
+define nofpclass(nan norm sub zero) float @ret_only_inf__floor(float %x) {
+; CHECK-LABEL: define nofpclass(nan zero sub norm) float @ret_only_inf__floor(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[X]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %x)
+  ret float %result
+}
+
+define nofpclass(nan pinf norm sub zero) float @ret_only_ninf__floor(float %x) {
+; CHECK-LABEL: define nofpclass(nan pinf zero sub norm) float @ret_only_ninf__floor(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    ret float 0xFFF0000000000000
+;
+  %result = call float @llvm.floor.f32(float %x)
+  ret float %result
+}
+
+define nofpclass(nan ninf norm sub zero) float @ret_only_pinf__floor(float %x) {
+; CHECK-LABEL: define nofpclass(nan ninf zero sub norm) float @ret_only_pinf__floor(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    ret float 0x7FF0000000000000
+;
+  %result = call float @llvm.floor.f32(float %x)
+  ret float %result
+}
+
+define nofpclass(inf nan norm sub) float @ret_only_zero__floor(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) float @ret_only_zero__floor(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[X]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %x)
+  ret float %result
+}
+
+define nofpclass(inf nan norm sub nzero) float @ret_only_pzero__floor(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf nzero sub norm) float @ret_only_pzero__floor(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    ret float 0.000000e+00
+;
+  %result = call float @llvm.floor.f32(float %x)
+  ret float %result
+}
+
+define nofpclass(inf nan norm sub pzero) float @ret_only_nzero__floor(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf pzero sub norm) float @ret_only_nzero__floor(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    ret float -0.000000e+00
+;
+  %result = call float @llvm.floor.f32(float %x)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans__floor(float %x) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans__floor(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[X]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %x)
+  ret float %result
+}
+
+define nofpclass(inf) float @ret_no_infs__floor(float %x) {
+; CHECK-LABEL: define nofpclass(inf) float @ret_no_infs__floor(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[X]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %x)
+  ret float %result
+}
+
+define nofpclass(nan inf) float @ret_no_nans_no_infs__floor(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf) float @ret_no_nans_no_infs__floor(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[X]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %x)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans__simplify_select_nan__floor(i1 %cond, float nofpclass(inf norm sub zero) %is.nan, float %unknown) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans__simplify_select_nan__floor(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(inf zero sub norm) [[IS_NAN:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[IS_NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %is.nan, float %unknown
+  %result = call float @llvm.floor.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(inf) float @ret_no_infs__simplify_select_inf__floor(i1 %cond, float nofpclass(nan norm sub zero) %is.inf, float %unknown) {
+; CHECK-LABEL: define nofpclass(inf) float @ret_no_infs__simplify_select_inf__floor(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan zero sub norm) [[IS_INF:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[IS_INF]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %is.inf, float %unknown
+  %result = call float @llvm.floor.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan inf) float @ret_no_inf_no_nan__simplify_select_inf_or_nan__floor(i1 %cond, float nofpclass(norm sub zero) %is.inf.or.nan, float %unknown) {
+; CHECK-LABEL: define nofpclass(nan inf) float @ret_no_inf_no_nan__simplify_select_inf_or_nan__floor(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(zero sub norm) [[IS_INF_OR_NAN:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[IS_INF_OR_NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %is.inf.or.nan, float %unknown
+  %result = call float @llvm.floor.f32(float %select)
+  ret float %result
+}
+
+define float @ret_nozero_select_zero__floor(i1 %cond, float nofpclass(inf norm sub nan) %is.zero, float %unknown) {
+; CHECK-LABEL: define float @ret_nozero_select_zero__floor(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan inf sub norm) [[IS_ZERO:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[IS_ZERO]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %is.zero, float %unknown
+  %result = call float @llvm.floor.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_sub_or_zero__floor(float nofpclass(nan inf norm) %sub.or.zero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_sub_or_zero__floor(
+; CHECK-SAME: float nofpclass(nan inf norm) [[SUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[SUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %sub.or.zero)
+  ret float %result
+}
+
+define nofpclass(snan) <2 x float> @source_known_sub_or_zero__floor_vec(<2 x float> nofpclass(nan inf norm) %sub.or.zero) {
+; CHECK-LABEL: define nofpclass(snan) <2 x float> @source_known_sub_or_zero__floor_vec(
+; CHECK-SAME: <2 x float> nofpclass(nan inf norm) [[SUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call <2 x float> @llvm.floor.v2f32(<2 x float> [[SUB_OR_ZERO]])
+; CHECK-NEXT:    ret <2 x float> [[RESULT]]
+;
+  %result = call <2 x float> @llvm.floor.v2f32(<2 x float> %sub.or.zero)
+  ret <2 x float> %result
+}
+
+define nofpclass(snan) float @source_known_sub_or_zero_or_nan__floor(float nofpclass(inf norm) %sub.or.zero.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_sub_or_zero_or_nan__floor(
+; CHECK-SAME: float nofpclass(inf norm) [[SUB_OR_ZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[SUB_OR_ZERO_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %sub.or.zero.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) <2 x float> @source_known_sub_or_zero_or_nan__floor_vec(<2 x float> nofpclass(inf norm) %sub.or.zero.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) <2 x float> @source_known_sub_or_zero_or_nan__floor_vec(
+; CHECK-SAME: <2 x float> nofpclass(inf norm) [[SUB_OR_ZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call <2 x float> @llvm.floor.v2f32(<2 x float> [[SUB_OR_ZERO_OR_NAN]])
+; CHECK-NEXT:    ret <2 x float> [[RESULT]]
+;
+  %result = call <2 x float> @llvm.floor.v2f32(<2 x float> %sub.or.zero.or.nan)
+  ret <2 x float> %result
+}
+
+define nofpclass(snan) float @source_known_psub_or_pzero__floor(float nofpclass(nan inf norm nsub nzero) %psub.or.pzero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_psub_or_pzero__floor(
+; CHECK-SAME: float nofpclass(nan inf nzero nsub norm) [[PSUB_OR_PZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[PSUB_OR_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %psub.or.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_psub_or_pzero_or_nan__floor(float nofpclass(inf norm nsub nzero) %psub.or.pzero.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_psub_or_pzero_or_nan__floor(
+; CHECK-SAME: float nofpclass(inf nzero nsub norm) [[PSUB_OR_PZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[PSUB_OR_PZERO_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %psub.or.pzero.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_nsub_or_nzero__floor(float nofpclass(nan inf norm psub pzero) %nsub.or.nzero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_nsub_or_nzero__floor(
+; CHECK-SAME: float nofpclass(nan inf pzero psub norm) [[NSUB_OR_NZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[NSUB_OR_NZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %nsub.or.nzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_nsub_or_nzero_or_nan__floor(float nofpclass(inf norm psub pzero) %nsub.or.nzero.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_nsub_or_nzero_or_nan__floor(
+; CHECK-SAME: float nofpclass(inf pzero psub norm) [[NSUB_OR_NZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[NSUB_OR_NZERO_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %nsub.or.nzero.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_inf__floor(float nofpclass(nan norm sub zero) %inf) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_inf__floor(
+; CHECK-SAME: float nofpclass(nan zero sub norm) [[INF:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[INF]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %inf)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_inf_or_nan__floor(float nofpclass(norm sub zero) %inf.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_inf_or_nan__floor(
+; CHECK-SAME: float nofpclass(zero sub norm) [[INF_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[INF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %inf.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_inf_or_nan_or_zero__floor(float nofpclass(norm sub) %inf.or.nan.or.zero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_inf_or_nan_or_zero__floor(
+; CHECK-SAME: float nofpclass(sub norm) [[INF_OR_NAN_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[INF_OR_NAN_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %inf.or.nan.or.zero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_inf_or_nan_or_zero_or_sub__floor(float nofpclass(norm) %inf.or.nan.or.zero.or.sub) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_inf_or_nan_or_zero_or_sub__floor(
+; CHECK-SAME: float nofpclass(norm) [[INF_OR_NAN_OR_ZERO_OR_SUB:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[INF_OR_NAN_OR_ZERO_OR_SUB]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %inf.or.nan.or.zero.or.sub)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_inf_or_zero__floor(float nofpclass(nan norm sub) %inf.or.zero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_inf_or_zero__floor(
+; CHECK-SAME: float nofpclass(nan sub norm) [[INF_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[INF_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %inf.or.zero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_sub__floor(float nofpclass(inf nan norm zero) %sub) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_sub__floor(
+; CHECK-SAME: float nofpclass(nan inf zero norm) [[SUB:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[SUB]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %sub)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_psub__floor(float nofpclass(inf nan norm nsub zero) %psub) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_psub__floor(
+; CHECK-SAME: float nofpclass(nan inf zero nsub norm) [[PSUB:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[PSUB]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %psub)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_nsub__floor(float nofpclass(inf nan norm psub zero) %nsub) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_nsub__floor(
+; CHECK-SAME: float nofpclass(nan inf zero psub norm) [[NSUB:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[NSUB]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %nsub)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_pinf__floor(float nofpclass(nan ninf norm sub zero) %pinf) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_pinf__floor(
+; CHECK-SAME: float nofpclass(nan ninf zero sub norm) [[PINF:%.*]]) {
+; CHECK-NEXT:    ret float 0x7FF0000000000000
+;
+  %result = call float @llvm.floor.f32(float %pinf)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_pinf_or_nan__floor(float nofpclass(ninf norm sub zero) %pinf.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_pinf_or_nan__floor(
+; CHECK-SAME: float nofpclass(ninf zero sub norm) [[PINF_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[PINF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %pinf.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_ninf__floor(float nofpclass(nan pinf norm sub zero) %ninf) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_ninf__floor(
+; CHECK-SAME: float nofpclass(nan pinf zero sub norm) [[NINF:%.*]]) {
+; CHECK-NEXT:    ret float 0xFFF0000000000000
+;
+  %result = call float @llvm.floor.f32(float %ninf)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_ninf_or_nan__floor(float nofpclass(pinf norm sub zero) %ninf.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_ninf_or_nan__floor(
+; CHECK-SAME: float nofpclass(pinf zero sub norm) [[NINF_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[NINF_OR_NAN]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %ninf.or.nan)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_not_pinf__floor(float nofpclass(pinf) %not.pinf) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_not_pinf__floor(
+; CHECK-SAME: float nofpclass(pinf) [[NOT_PINF:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[NOT_PINF]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %not.pinf)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_not_ninf__floor(float nofpclass(ninf) %not.ninf) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_not_ninf__floor(
+; CHECK-SAME: float nofpclass(ninf) [[NOT_NINF:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[NOT_NINF]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %not.ninf)
+  ret float %result
+}
+
+define nofpclass(snan) ppc_fp128 @source_known_not_pinf__floor__ppcf128(ppc_fp128 nofpclass(pinf) %not.pinf) {
+; CHECK-LABEL: define nofpclass(snan) ppc_fp128 @source_known_not_pinf__floor__ppcf128(
+; CHECK-SAME: ppc_fp128 nofpclass(pinf) [[NOT_PINF:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call ppc_fp128 @llvm.floor.ppcf128(ppc_fp128 [[NOT_PINF]])
+; CHECK-NEXT:    ret ppc_fp128 [[RESULT]]
+;
+  %result = call ppc_fp128 @llvm.floor.ppcf128(ppc_fp128 %not.pinf)
+  ret ppc_fp128 %result
+}
+
+define nofpclass(snan) <2 x ppc_fp128> @source_known_not_pinf__floor__v2ppcf128(<2 x ppc_fp128> nofpclass(pinf) %not.pinf) {
+; CHECK-LABEL: define nofpclass(snan) <2 x ppc_fp128> @source_known_not_pinf__floor__v2ppcf128(
+; CHECK-SAME: <2 x ppc_fp128> nofpclass(pinf) [[NOT_PINF:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call <2 x ppc_fp128> @llvm.floor.v2ppcf128(<2 x ppc_fp128> [[NOT_PINF]])
+; CHECK-NEXT:    ret <2 x ppc_fp128> [[RESULT]]
+;
+  %result = call <2 x ppc_fp128> @llvm.floor.v2ppcf128(<2 x ppc_fp128> %not.pinf)
+  ret <2 x ppc_fp128> %result
+}
+
+define nofpclass(snan) ppc_fp128 @source_known_not_ninf__floor_ppcf128(ppc_fp128 nofpclass(ninf) %not.ninf) {
+; CHECK-LABEL: define nofpclass(snan) ppc_fp128 @source_known_not_ninf__floor_ppcf128(
+; CHECK-SAME: ppc_fp128 nofpclass(ninf) [[NOT_NINF:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call ppc_fp128 @llvm.floor.ppcf128(ppc_fp128 [[NOT_NINF]])
+; CHECK-NEXT:    ret ppc_fp128 [[RESULT]]
+;
+  %result = call ppc_fp128 @llvm.floor.ppcf128(ppc_fp128 %not.ninf)
+  ret ppc_fp128 %result
+}
+
+define nofpclass(nan) float @ret_no_nans__simplify_select_nan__trunc(i1 %cond, float nofpclass(inf norm sub zero) %is.nan, float %unknown) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans__simplify_select_nan__trunc(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(inf zero sub norm) [[IS_NAN:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[IS_NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %is.nan, float %unknown
+  %result = call float @llvm.trunc.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans__simplify_select_nan__ceil(i1 %cond, float nofpclass(inf norm sub zero) %is.nan, float %unknown) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans__simplify_select_nan__ceil(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(inf zero sub norm) [[IS_NAN:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[IS_NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.ceil.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %is.nan, float %unknown
+  %result = call float @llvm.ceil.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans__simplify_select_nan__rint(i1 %cond, float nofpclass(inf norm sub zero) %is.nan, float %unknown) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans__simplify_select_nan__rint(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(inf zero sub norm) [[IS_NAN:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[IS_NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.rint.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %is.nan, float %unknown
+  %result = call float @llvm.rint.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans__simplify_select_nan__nearbyint(i1 %cond, float nofpclass(inf norm sub zero) %is.nan, float %unknown) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans__simplify_select_nan__nearbyint(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(inf zero sub norm) [[IS_NAN:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[IS_NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.nearbyint.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %is.nan, float %unknown
+  %result = call float @llvm.nearbyint.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans__simplify_select_nan__round(i1 %cond, float nofpclass(inf norm sub zero) %is.nan, float %unknown) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans__simplify_select_nan__round(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(inf zero sub norm) [[IS_NAN:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[IS_NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.round.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %is.nan, float %unknown
+  %result = call float @llvm.round.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans__simplify_select_nan__roundeven(i1 %cond, float nofpclass(inf norm sub zero) %is.nan, float %unknown) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans__simplify_select_nan__roundeven(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(inf zero sub norm) [[IS_NAN:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[IS_NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.roundeven.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %is.nan, float %unknown
+  %result = call float @llvm.roundeven.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_sub_or_zero__trunc(float nofpclass(nan inf norm) %sub.or.zero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_sub_or_zero__trunc(
+; CHECK-SAME: float nofpclass(nan inf norm) [[SUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[SUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.trunc.f32(float %sub.or.zero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_psub_or_pzero__trunc(float nofpclass(nan inf norm nsub nzero) %psub.or.pzero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_psub_or_pzero__trunc(
+; CHECK-SAME: float nofpclass(nan inf nzero nsub norm) [[PSUB_OR_PZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[PSUB_OR_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.trunc.f32(float %psub.or.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_nsub_or_nzero__trunc(float nofpclass(nan inf norm psub pzero) %nsub.or.nzero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_nsub_or_nzero__trunc(
+; CHECK-SAME: float nofpclass(nan inf pzero psub norm) [[NSUB_OR_NZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[NSUB_OR_NZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.trunc.f32(float %nsub.or.nzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_inf_or_nan_or_zero__trunc(float nofpclass(norm sub) %inf.or.nan.or.zero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_inf_or_nan_or_zero__trunc(
+; CHECK-SAME: float nofpclass(sub norm) [[INF_OR_NAN_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[INF_OR_NAN_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.trunc.f32(float %inf.or.nan.or.zero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_inf_or_nan_or_zero_or_sub__trunc(float nofpclass(norm) %inf.or.nan.or.zero.or.sub) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_inf_or_nan_or_zero_or_sub__trunc(
+; CHECK-SAME: float nofpclass(norm) [[INF_OR_NAN_OR_ZERO_OR_SUB:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[INF_OR_NAN_OR_ZERO_OR_SUB]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.trunc.f32(float %inf.or.nan.or.zero.or.sub)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_inf_or_zero__trunc(float nofpclass(nan norm sub) %inf.or.zero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_inf_or_zero__trunc(
+; CHECK-SAME: float nofpclass(nan sub norm) [[INF_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[INF_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.trunc.f32(float %inf.or.zero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_sub__trunc(float nofpclass(inf nan norm zero) %sub) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_sub__trunc(
+; CHECK-SAME: float nofpclass(nan inf zero norm) [[SUB:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[SUB]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.trunc.f32(float %sub)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_psub__trunc(float nofpclass(inf nan norm nsub zero) %psub) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_psub__trunc(
+; CHECK-SAME: float nofpclass(nan inf zero nsub norm) [[PSUB:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[PSUB]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.trunc.f32(float %psub)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_nsub__trunc(float nofpclass(inf nan norm psub zero) %nsub) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_nsub__trunc(
+; CHECK-SAME: float nofpclass(nan inf zero psub norm) [[NSUB:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[NSUB]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.trunc.f32(float %nsub)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_sub_or_zero__ceil(float nofpclass(nan inf norm) %sub.or.zero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_sub_or_zero__ceil(
+; CHECK-SAME: float nofpclass(nan inf norm) [[SUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.ceil.f32(float [[SUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.ceil.f32(float %sub.or.zero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_psub_or_pzero__ceil(float nofpclass(nan inf norm nsub nzero) %psub.or.pzero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_psub_or_pzero__ceil(
+; CHECK-SAME: float nofpclass(nan inf nzero nsub norm) [[PSUB_OR_PZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.ceil.f32(float [[PSUB_OR_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.ceil.f32(float %psub.or.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_nsub_or_nzero__ceil(float nofpclass(nan inf norm psub pzero) %nsub.or.nzero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_nsub_or_nzero__ceil(
+; CHECK-SAME: float nofpclass(nan inf pzero psub norm) [[NSUB_OR_NZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.ceil.f32(float [[NSUB_OR_NZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.ceil.f32(float %nsub.or.nzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_sub_or_zero__rint(float nofpclass(nan inf norm) %sub.or.zero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_sub_or_zero__rint(
+; CHECK-SAME: float nofpclass(nan inf norm) [[SUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.rint.f32(float [[SUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.rint.f32(float %sub.or.zero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_psub_or_pzero__rint(float nofpclass(nan inf norm nsub nzero) %psub.or.pzero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_psub_or_pzero__rint(
+; CHECK-SAME: float nofpclass(nan inf nzero nsub norm) [[PSUB_OR_PZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.rint.f32(float [[PSUB_OR_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.rint.f32(float %psub.or.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_nsub_or_nzero__rint(float nofpclass(nan inf norm psub pzero) %nsub.or.nzero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_nsub_or_nzero__rint(
+; CHECK-SAME: float nofpclass(nan inf pzero psub norm) [[NSUB_OR_NZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.rint.f32(float [[NSUB_OR_NZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.rint.f32(float %nsub.or.nzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_sub_or_zero__nearbyint(float nofpclass(nan inf norm) %sub.or.zero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_sub_or_zero__nearbyint(
+; CHECK-SAME: float nofpclass(nan inf norm) [[SUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.nearbyint.f32(float [[SUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.nearbyint.f32(float %sub.or.zero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_psub_or_pzero__nearbyint(float nofpclass(nan inf norm nsub nzero) %psub.or.pzero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_psub_or_pzero__nearbyint(
+; CHECK-SAME: float nofpclass(nan inf nzero nsub norm) [[PSUB_OR_PZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.nearbyint.f32(float [[PSUB_OR_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.nearbyint.f32(float %psub.or.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_nsub_or_nzero__nearbyint(float nofpclass(nan inf norm psub pzero) %nsub.or.nzero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_nsub_or_nzero__nearbyint(
+; CHECK-SAME: float nofpclass(nan inf pzero psub norm) [[NSUB_OR_NZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.nearbyint.f32(float [[NSUB_OR_NZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.nearbyint.f32(float %nsub.or.nzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_sub_or_zero__round(float nofpclass(nan inf norm) %sub.or.zero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_sub_or_zero__round(
+; CHECK-SAME: float nofpclass(nan inf norm) [[SUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.round.f32(float [[SUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.round.f32(float %sub.or.zero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_psub_or_pzero__round(float nofpclass(nan inf norm nsub nzero) %psub.or.pzero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_psub_or_pzero__round(
+; CHECK-SAME: float nofpclass(nan inf nzero nsub norm) [[PSUB_OR_PZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.round.f32(float [[PSUB_OR_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.round.f32(float %psub.or.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_nsub_or_nzero__round(float nofpclass(nan inf norm psub pzero) %nsub.or.nzero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_nsub_or_nzero__round(
+; CHECK-SAME: float nofpclass(nan inf pzero psub norm) [[NSUB_OR_NZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.round.f32(float [[NSUB_OR_NZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.round.f32(float %nsub.or.nzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_sub_or_zero__roundeven(float nofpclass(nan inf norm) %sub.or.zero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_sub_or_zero__roundeven(
+; CHECK-SAME: float nofpclass(nan inf norm) [[SUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.roundeven.f32(float [[SUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.roundeven.f32(float %sub.or.zero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_psub_or_pzero__roundeven(float nofpclass(nan inf norm nsub nzero) %psub.or.pzero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_psub_or_pzero__roundeven(
+; CHECK-SAME: float nofpclass(nan inf nzero nsub norm) [[PSUB_OR_PZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.roundeven.f32(float [[PSUB_OR_PZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.roundeven.f32(float %psub.or.pzero)
+  ret float %result
+}
+
+define nofpclass(snan) float @source_known_nsub_or_nzero__roundeven(float nofpclass(nan inf norm psub pzero) %nsub.or.nzero) {
+; CHECK-LABEL: define nofpclass(snan) float @source_known_nsub_or_nzero__roundeven(
+; CHECK-SAME: float nofpclass(nan inf pzero psub norm) [[NSUB_OR_NZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.roundeven.f32(float [[NSUB_OR_NZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.roundeven.f32(float %nsub.or.nzero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__floor(float nofpclass(inf norm) %sub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__floor(
+; CHECK-SAME: float nofpclass(inf norm) [[SUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[SUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %sub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__floor(float nofpclass(inf norm nsub) %psub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__floor(
+; CHECK-SAME: float nofpclass(inf nsub norm) [[PSUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[PSUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %psub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__floor(float nofpclass(inf norm psub) %nsub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__floor(
+; CHECK-SAME: float nofpclass(inf psub norm) [[NSUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[NSUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.floor.f32(float %nsub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__trunc(float nofpclass(inf norm) %sub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__trunc(
+; CHECK-SAME: float nofpclass(inf norm) [[SUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[SUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.trunc.f32(float %sub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__trunc(float nofpclass(inf norm nsub) %psub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__trunc(
+; CHECK-SAME: float nofpclass(inf nsub norm) [[PSUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[PSUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.trunc.f32(float %psub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__trunc(float nofpclass(inf norm psub) %nsub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__trunc(
+; CHECK-SAME: float nofpclass(inf psub norm) [[NSUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[NSUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.trunc.f32(float %nsub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__ceil(float nofpclass(inf norm) %sub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__ceil(
+; CHECK-SAME: float nofpclass(inf norm) [[SUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.ceil.f32(float [[SUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.ceil.f32(float %sub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__ceil(float nofpclass(inf norm nsub) %psub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__ceil(
+; CHECK-SAME: float nofpclass(inf nsub norm) [[PSUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.ceil.f32(float [[PSUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.ceil.f32(float %psub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__ceil(float nofpclass(inf norm psub) %nsub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__ceil(
+; CHECK-SAME: float nofpclass(inf psub norm) [[NSUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.ceil.f32(float [[NSUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.ceil.f32(float %nsub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__rint(float nofpclass(inf norm) %sub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__rint(
+; CHECK-SAME: float nofpclass(inf norm) [[SUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.rint.f32(float [[SUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.rint.f32(float %sub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__rint(float nofpclass(inf norm nsub) %psub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__rint(
+; CHECK-SAME: float nofpclass(inf nsub norm) [[PSUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.rint.f32(float [[PSUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.rint.f32(float %psub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__rint(float nofpclass(inf norm psub) %nsub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__rint(
+; CHECK-SAME: float nofpclass(inf psub norm) [[NSUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.rint.f32(float [[NSUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.rint.f32(float %nsub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__nearbyint(float nofpclass(inf norm) %sub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__nearbyint(
+; CHECK-SAME: float nofpclass(inf norm) [[SUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.nearbyint.f32(float [[SUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.nearbyint.f32(float %sub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__nearbyint(float nofpclass(inf norm nsub) %psub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__nearbyint(
+; CHECK-SAME: float nofpclass(inf nsub norm) [[PSUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.nearbyint.f32(float [[PSUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.nearbyint.f32(float %psub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__nearbyint(float nofpclass(inf norm psub) %nsub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__nearbyint(
+; CHECK-SAME: float nofpclass(inf psub norm) [[NSUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.nearbyint.f32(float [[NSUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.nearbyint.f32(float %nsub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__round(float nofpclass(inf norm) %sub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__round(
+; CHECK-SAME: float nofpclass(inf norm) [[SUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.round.f32(float [[SUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.round.f32(float %sub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__round(float nofpclass(inf norm nsub) %psub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__round(
+; CHECK-SAME: float nofpclass(inf nsub norm) [[PSUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.round.f32(float [[PSUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.round.f32(float %psub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__round(float nofpclass(inf norm psub) %nsub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__round(
+; CHECK-SAME: float nofpclass(inf psub norm) [[NSUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.round.f32(float [[NSUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.round.f32(float %nsub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__roundeven(float nofpclass(inf norm) %sub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__roundeven(
+; CHECK-SAME: float nofpclass(inf norm) [[SUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.roundeven.f32(float [[SUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.roundeven.f32(float %sub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__roundeven(float nofpclass(inf norm nsub) %psub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__roundeven(
+; CHECK-SAME: float nofpclass(inf nsub norm) [[PSUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.roundeven.f32(float [[PSUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.roundeven.f32(float %psub.or.zero)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__roundeven(float nofpclass(inf norm psub) %nsub.or.zero) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__roundeven(
+; CHECK-SAME: float nofpclass(inf psub norm) [[NSUB_OR_ZERO:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.roundeven.f32(float [[NSUB_OR_ZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.roundeven.f32(float %nsub.or.zero)
+  ret float %result
+}
+
+; select cannot be dropped, possible zero result implies possible subnormal source
+define nofpclass(nsub) float @ret_no_nsub__roundeven__select_source_only_nsub_or_unknown(i1 %cond, float nofpclass(nan inf norm zero psub) %only.nsub, float %unknown) {
+; CHECK-LABEL: define nofpclass(nsub) float @ret_no_nsub__roundeven__select_source_only_nsub_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan inf zero psub norm) [[ONLY_NSUB:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[ONLY_NSUB]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.roundeven.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %only.nsub, float %unknown
+  %result = call float @llvm.roundeven.f32(float %select)
+  ret float %result
+}
+
+; select cannot be dropped, possible zero result implies possible subnormal source
+define nofpclass(psub) float @ret_no_psub__roundeven__select_source_only_nsub_or_unknown(i1 %cond, float nofpclass(nan inf norm zero nsub) %only.psub, float %unknown) {
+; CHECK-LABEL: define nofpclass(psub) float @ret_no_psub__roundeven__select_source_only_nsub_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan inf zero nsub norm) [[ONLY_PSUB:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[ONLY_PSUB]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.roundeven.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %only.psub, float %unknown
+  %result = call float @llvm.roundeven.f32(float %select)
+  ret float %result
+}
+
+; select cannot be dropped, possible zero result implies possible subnormal source
+define nofpclass(sub) float @ret_no_sub__roundeven__select_source_only_sub_or_unknown(i1 %cond, float nofpclass(nan inf norm zero) %only.sub, float %unknown) {
+; CHECK-LABEL: define nofpclass(sub) float @ret_no_sub__roundeven__select_source_only_sub_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan inf zero norm) [[ONLY_SUB:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[ONLY_SUB]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.roundeven.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %only.sub, float %unknown
+  %result = call float @llvm.roundeven.f32(float %select)
+  ret float %result
+}
+
+; select cannot be dropped, possible zero result implies possible subnormal source
+define nofpclass(nsub) float @ret_no_nsub__trunc__select_source_only_nsub_or_unknown(i1 %cond, float nofpclass(nan inf norm zero psub) %only.nsub, float %unknown) {
+; CHECK-LABEL: define nofpclass(nsub) float @ret_no_nsub__trunc__select_source_only_nsub_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan inf zero psub norm) [[ONLY_NSUB:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[ONLY_NSUB]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %only.nsub, float %unknown
+  %result = call float @llvm.trunc.f32(float %select)
+  ret float %result
+}
+
+; select cannot be dropped, possible zero result implies possible subnormal source
+define nofpclass(psub) float @ret_no_psub__trunc__select_source_only_nsub_or_unknown(i1 %cond, float nofpclass(nan inf norm zero nsub) %only.psub, float %unknown) {
+; CHECK-LABEL: define nofpclass(psub) float @ret_no_psub__trunc__select_source_only_nsub_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan inf zero nsub norm) [[ONLY_PSUB:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[ONLY_PSUB]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %only.psub, float %unknown
+  %result = call float @llvm.trunc.f32(float %select)
+  ret float %result
+}
+
+; select cannot be dropped, possible zero result implies possible subnormal source
+define nofpclass(sub) float @ret_no_sub__trunc__select_source_only_sub_or_unknown(i1 %cond, float nofpclass(nan inf norm zero) %only.sub, float %unknown) {
+; CHECK-LABEL: define nofpclass(sub) float @ret_no_sub__trunc__select_source_only_sub_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan inf zero norm) [[ONLY_SUB:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[ONLY_SUB]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %only.sub, float %unknown
+  %result = call float @llvm.trunc.f32(float %select)
+  ret float %result
+}
+
+; select cannot be dropped, possible zero result implies possible subnormal source
+define nofpclass(nsub) float @ret_no_nsub__floor__select_source_only_nsub_or_unknown(i1 %cond, float nofpclass(nan inf norm zero psub) %only.nsub, float %unknown) {
+; CHECK-LABEL: define nofpclass(nsub) float @ret_no_nsub__floor__select_source_only_nsub_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan inf zero psub norm) [[ONLY_NSUB:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[ONLY_NSUB]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %only.nsub, float %unknown
+  %result = call float @llvm.floor.f32(float %select)
+  ret float %result
+}
+
+; select cannot be dropped, possible zero result implies possible subnormal source
+define nofpclass(psub) float @ret_no_psub__floor__select_source_only_nsub_or_unknown(i1 %cond, float nofpclass(nan inf norm zero nsub) %only.psub, float %unknown) {
+; CHECK-LABEL: define nofpclass(psub) float @ret_no_psub__floor__select_source_only_nsub_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan inf zero nsub norm) [[ONLY_PSUB:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[ONLY_PSUB]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %only.psub, float %unknown
+  %result = call float @llvm.floor.f32(float %select)
+  ret float %result
+}
+
+; select cannot be dropped, possible zero result implies possible subnormal source
+define nofpclass(sub) float @ret_no_sub__floor__select_source_only_sub_or_unknown(i1 %cond, float nofpclass(nan inf norm zero) %only.sub, float %unknown) {
+; CHECK-LABEL: define nofpclass(sub) float @ret_no_sub__floor__select_source_only_sub_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan inf zero norm) [[ONLY_SUB:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[ONLY_SUB]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %only.sub, float %unknown
+  %result = call float @llvm.floor.f32(float %select)
+  ret float %result
+}

>From 59163d8e7b151855c53beeed6f3e87b9e1cad429 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Sun, 11 Jan 2026 09:47:54 +0100
Subject: [PATCH 2/2] Tests for 0 result implying normal input

---
 ...fy-demanded-fpclass-rounding-intrinsics.ll | 144 ++++++++++++++++++
 1 file changed, 144 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-rounding-intrinsics.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-rounding-intrinsics.ll
index 29c97b3ec76ed..59e1a2215d838 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-rounding-intrinsics.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-rounding-intrinsics.ll
@@ -1071,3 +1071,147 @@ define nofpclass(sub) float @ret_no_sub__floor__select_source_only_sub_or_unknow
   %result = call float @llvm.floor.f32(float %select)
   ret float %result
 }
+
+define nofpclass(nan norm sub) float @zero_demands_norm_input__floor(i1 %cond, float %unknown, float nofpclass(nan inf sub zero) %only.norm) {
+; CHECK-LABEL: define nofpclass(nan sub norm) float @zero_demands_norm_input__floor(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(nan inf zero sub) [[ONLY_NORM:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[UNKNOWN]], float [[ONLY_NORM]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %unknown, float %only.norm
+  %result = call float @llvm.floor.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan norm sub nzero) float @pzero_demands_pnorm_input__floor(i1 %cond, float %unknown, float nofpclass(nan inf nnorm sub zero) %only.pnorm) {
+; CHECK-LABEL: define nofpclass(nan nzero sub norm) float @pzero_demands_pnorm_input__floor(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(nan inf zero sub nnorm) [[ONLY_PNORM:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[UNKNOWN]], float [[ONLY_PNORM]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %unknown, float %only.pnorm
+  %result = call float @llvm.floor.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan norm sub pzero) float @nzero_demands_pnorm_input__floor(i1 %cond, float %unknown, float nofpclass(nan inf pnorm sub zero) %only.nnorm) {
+; CHECK-LABEL: define nofpclass(nan pzero sub norm) float @nzero_demands_pnorm_input__floor(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(nan inf zero sub pnorm) [[ONLY_NNORM:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[UNKNOWN]], float [[ONLY_NNORM]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.floor.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %unknown, float %only.nnorm
+  %result = call float @llvm.floor.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan norm sub) float @zero_demands_norm_input__ceil(i1 %cond, float %unknown, float nofpclass(nan inf sub zero) %only.norm) {
+; CHECK-LABEL: define nofpclass(nan sub norm) float @zero_demands_norm_input__ceil(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(nan inf zero sub) [[ONLY_NORM:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[UNKNOWN]], float [[ONLY_NORM]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.ceil.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %unknown, float %only.norm
+  %result = call float @llvm.ceil.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan norm sub nzero) float @pzero_demands_pnorm_input__ceil(i1 %cond, float %unknown, float nofpclass(nan inf nnorm sub zero) %only.pnorm) {
+; CHECK-LABEL: define nofpclass(nan nzero sub norm) float @pzero_demands_pnorm_input__ceil(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(nan inf zero sub nnorm) [[ONLY_PNORM:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[UNKNOWN]], float [[ONLY_PNORM]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.ceil.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %unknown, float %only.pnorm
+  %result = call float @llvm.ceil.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan norm sub pzero) float @nzero_demands_pnorm_input__ceil(i1 %cond, float %unknown, float nofpclass(nan inf pnorm sub zero) %only.nnorm) {
+; CHECK-LABEL: define nofpclass(nan pzero sub norm) float @nzero_demands_pnorm_input__ceil(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(nan inf zero sub pnorm) [[ONLY_NNORM:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[UNKNOWN]], float [[ONLY_NNORM]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.ceil.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %unknown, float %only.nnorm
+  %result = call float @llvm.ceil.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan norm sub) float @zero_demands_norm_input__trunc(i1 %cond, float %unknown, float nofpclass(nan inf sub zero) %only.norm) {
+; CHECK-LABEL: define nofpclass(nan sub norm) float @zero_demands_norm_input__trunc(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(nan inf zero sub) [[ONLY_NORM:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[UNKNOWN]], float [[ONLY_NORM]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %unknown, float %only.norm
+  %result = call float @llvm.trunc.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan norm sub nzero) float @pzero_demands_pnorm_input__trunc(i1 %cond, float %unknown, float nofpclass(nan inf nnorm sub zero) %only.pnorm) {
+; CHECK-LABEL: define nofpclass(nan nzero sub norm) float @pzero_demands_pnorm_input__trunc(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(nan inf zero sub nnorm) [[ONLY_PNORM:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[UNKNOWN]], float [[ONLY_PNORM]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %unknown, float %only.pnorm
+  %result = call float @llvm.trunc.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan norm sub pzero) float @nzero_demands_pnorm_input__trunc(i1 %cond, float %unknown, float nofpclass(nan inf pnorm sub zero) %only.nnorm) {
+; CHECK-LABEL: define nofpclass(nan pzero sub norm) float @nzero_demands_pnorm_input__trunc(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(nan inf zero sub pnorm) [[ONLY_NNORM:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[UNKNOWN]], float [[ONLY_NNORM]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %unknown, float %only.nnorm
+  %result = call float @llvm.trunc.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan norm sub) float @zero_demands_norm_input__round(i1 %cond, float %unknown, float nofpclass(nan inf sub zero) %only.norm) {
+; CHECK-LABEL: define nofpclass(nan sub norm) float @zero_demands_norm_input__round(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(nan inf zero sub) [[ONLY_NORM:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[UNKNOWN]], float [[ONLY_NORM]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.round.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %unknown, float %only.norm
+  %result = call float @llvm.round.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan norm sub nzero) float @pzero_demands_pnorm_input__round(i1 %cond, float %unknown, float nofpclass(nan inf nnorm sub zero) %only.pnorm) {
+; CHECK-LABEL: define nofpclass(nan nzero sub norm) float @pzero_demands_pnorm_input__round(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(nan inf zero sub nnorm) [[ONLY_PNORM:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[UNKNOWN]], float [[ONLY_PNORM]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.round.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %unknown, float %only.pnorm
+  %result = call float @llvm.round.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan norm sub pzero) float @nzero_demands_pnorm_input__round(i1 %cond, float %unknown, float nofpclass(nan inf pnorm sub zero) %only.nnorm) {
+; CHECK-LABEL: define nofpclass(nan pzero sub norm) float @nzero_demands_pnorm_input__round(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(nan inf zero sub pnorm) [[ONLY_NNORM:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[UNKNOWN]], float [[ONLY_NNORM]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.round.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %unknown, float %only.nnorm
+  %result = call float @llvm.round.f32(float %select)
+  ret float %result
+}



More information about the llvm-branch-commits mailing list