[llvm-branch-commits] [llvm] InstCombine: Add fptrunc SimplifyDemandedFPClass baseline tests (PR #175420)

Matt Arsenault via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sun Jan 11 01:22:56 PST 2026


https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/175420

Also llvm.fptrunc.round, which should be the same.

>From 9cb79e5ac8219bfd6137e7a1ac2b8c8115b8fe0f Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 30 Dec 2025 17:17:02 +0100
Subject: [PATCH] InstCombine: Add fptrunc SimplifyDemandedFPClass baseline
 tests

Also llvm.fptrunc.round, which should be the same.
---
 ...simplify-demanded-fpclass-fptrunc-round.ll | 533 ++++++++++++++++++
 .../simplify-demanded-fpclass-fptrunc.ll      | 533 ++++++++++++++++++
 2 files changed, 1066 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fptrunc-round.ll
 create mode 100644 llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fptrunc.ll

diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fptrunc-round.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fptrunc-round.ll
new file mode 100644
index 0000000000000..1997da17e18e0
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fptrunc-round.ll
@@ -0,0 +1,533 @@
+; 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(inf norm sub zero) float @returns_nan_f32()
+declare nofpclass(nan ninf norm sub zero) float @returns_pinf_f32()
+declare nofpclass(nan pinf norm sub zero) float @returns_ninf_f32()
+declare nofpclass(nan norm sub zero) float @returns_inf_f32()
+declare nofpclass(norm sub zero) float @returns_inf_or_nan_f32()
+
+declare nofpclass(inf nan norm psub zero) float @returns_nsub_f32()
+declare nofpclass(inf nan norm nsub zero) float @returns_psub_f32()
+declare nofpclass(inf nan norm zero) float @returns_sub_f32()
+
+declare nofpclass(nan pinf pnorm psub pzero) float @returns_negative_f32()
+declare nofpclass(pinf pnorm psub pzero) float @returns_negative_or_nan_f32()
+
+declare nofpclass(nan ninf nnorm nsub nzero) float @returns_positive_f32()
+declare nofpclass(ninf nnorm nsub nzero) float @returns_positive_or_nan_f32()
+
+declare nofpclass(nan inf norm sub) float @returns_zero_f32()
+declare nofpclass(nan inf norm sub nzero) float @returns_pzero_f32()
+declare nofpclass(nan inf norm sub pzero) float @returns_nzero_f32()
+declare nofpclass(inf norm sub) float @returns_zero_or_nan_f32()
+
+declare nofpclass(nan inf sub zero) float @returns_norm_f32()
+declare nofpclass(nan inf nnorm sub zero) float @returns_pnorm_f32()
+declare nofpclass(nan inf pnorm sub zero) float @returns_nnorm_f32()
+
+
+define nofpclass(inf norm sub zero qnan) half @ret_only_snan__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(qnan inf zero sub norm) half @ret_only_snan__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[X]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = call half @llvm.fptrunc.round.f16.f32(float %x, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(inf norm sub zero snan) half @ret_only_qnan__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(snan inf zero sub norm) half @ret_only_qnan__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[X]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = call half @llvm.fptrunc.round.f16.f32(float %x, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(inf norm sub zero) half @ret_only_nan__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(inf zero sub norm) half @ret_only_nan__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[X]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = call half @llvm.fptrunc.round.f16.f32(float %x, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(nan norm sub zero) half @ret_only_inf__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan zero sub norm) half @ret_only_inf__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[X]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = call half @llvm.fptrunc.round.f16.f32(float %x, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(nan pinf norm sub zero) half @ret_only_ninf__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan pinf zero sub norm) half @ret_only_ninf__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    ret half 0xHFC00
+;
+  %result = call half @llvm.fptrunc.round.f16.f32(float %x, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(nan ninf norm sub zero) half @ret_only_pinf__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan ninf zero sub norm) half @ret_only_pinf__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    ret half 0xH7C00
+;
+  %result = call half @llvm.fptrunc.round.f16.f32(float %x, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(inf nan norm sub) half @ret_only_zero__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) half @ret_only_zero__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[X]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = call half @llvm.fptrunc.round.f16.f32(float %x, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(inf nan norm sub nzero) half @ret_only_pzero__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf nzero sub norm) half @ret_only_pzero__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    ret half 0xH0000
+;
+  %result = call half @llvm.fptrunc.round.f16.f32(float %x, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(inf nan norm sub pzero) half @ret_only_nzero__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf pzero sub norm) half @ret_only_nzero__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    ret half 0xH8000
+;
+  %result = call half @llvm.fptrunc.round.f16.f32(float %x, metadata !"round.downward")
+  ret half %result
+}
+
+; Fold out select
+define nofpclass(nan) half @ret_no_nan__fptrunc__select_nan_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_no_nan__fptrunc__select_nan_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NAN:%.*]] = call float @returns_nan_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %nan = call float @returns_nan_f32()
+  %select = select i1 %cond, float %nan, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
+
+; Fold out select
+define nofpclass(pinf) half @ret_no_pinf__fptrunc__select_pinf_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(pinf) half @ret_no_pinf__fptrunc__select_pinf_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[PINF:%.*]] = call float @returns_pinf_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[PINF]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %pinf = call float @returns_pinf_f32()
+  %select = select i1 %cond, float %pinf, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
+
+; Fold out select
+define nofpclass(ninf) half @ret_no_ninf__fptrunc__select_ninf_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(ninf) half @ret_no_ninf__fptrunc__select_ninf_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NINF:%.*]] = call float @returns_ninf_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NINF]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %ninf = call float @returns_ninf_f32()
+  %select = select i1 %cond, float %ninf, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
+
+; Fold out select
+define nofpclass(inf) half @ret_no_inf__fptrunc__select_inf_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_no_inf__fptrunc__select_inf_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[INF:%.*]] = call float @returns_inf_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[INF]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %inf = call float @returns_inf_f32()
+  %select = select i1 %cond, float %inf, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
+
+; Fold out select
+define nofpclass(nan inf) half @ret_no_inf_no_nan__fptrunc__select_inf_or_nan_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(nan inf) half @ret_no_inf_no_nan__fptrunc__select_inf_or_nan_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[INF_OR_NAN:%.*]] = call float @returns_inf_or_nan_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[INF_OR_NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %inf.or.nan = call float @returns_inf_or_nan_f32()
+  %select = select i1 %cond, float %inf.or.nan, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(nsub) half @ret_no_nsub__fptrunc__select_nsub_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(nsub) half @ret_no_nsub__fptrunc__select_nsub_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NSUB:%.*]] = call float @returns_nsub_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NSUB]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %nsub = call float @returns_nsub_f32()
+  %select = select i1 %cond, float %nsub, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(psub) half @ret_no_psub__fptrunc__select_psub_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(psub) half @ret_no_psub__fptrunc__select_psub_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[PSUB:%.*]] = call float @returns_psub_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[PSUB]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %psub = call float @returns_psub_f32()
+  %select = select i1 %cond, float %psub, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(sub) half @ret_no_sub__fptrunc__select_sub_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(sub) half @ret_no_sub__fptrunc__select_sub_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SUB:%.*]] = call float @returns_sub_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[SUB]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %sub = call float @returns_sub_f32()
+  %select = select i1 %cond, float %sub, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
+
+; Remove select
+define nofpclass(pinf pnorm psub pzero) half @ret_no_positive__fptrunc__select_positive_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) half @ret_no_positive__fptrunc__select_positive_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[POSITIVE:%.*]] = call float @returns_positive_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[POSITIVE]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %positive = call float @returns_positive_f32()
+  %select = select i1 %cond, float %positive, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
+
+; No remove select
+define nofpclass(pinf pnorm psub pzero) half @ret_no_positive__fptrunc__select_positive_nan_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) half @ret_no_positive__fptrunc__select_positive_nan_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[POSITIVE_OR_NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %positive.or.nan = call float @returns_positive_or_nan_f32()
+  %select = select i1 %cond, float %positive.or.nan, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
+
+; Remove select
+define nofpclass(nan pinf pnorm psub pzero) half @ret_no_positive_no_nan__fptrunc__select_positive_nan_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) half @ret_no_positive_no_nan__fptrunc__select_positive_nan_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[POSITIVE_OR_NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %positive.or.nan = call float @returns_positive_or_nan_f32()
+  %select = select i1 %cond, float %positive.or.nan, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
+
+; Remove select
+define nofpclass(ninf nnorm nsub nzero) half @ret_no_negative__fptrunc__select_negative_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) half @ret_no_negative__fptrunc__select_negative_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NEGATIVE:%.*]] = call float @returns_negative_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NEGATIVE]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %negative = call float @returns_negative_f32()
+  %select = select i1 %cond, float %negative, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
+
+; No remove select
+define nofpclass(ninf nnorm nsub nzero) half @ret_no_negative__fptrunc__select_negative_nan_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) half @ret_no_negative__fptrunc__select_negative_nan_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NEGATIVE_OR_NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %negative.or.nan = call float @returns_negative_or_nan_f32()
+  %select = select i1 %cond, float %negative.or.nan, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
+
+; Remove select
+define nofpclass(nan ninf nnorm nsub nzero) half @ret_no_negative_no_nan__fptrunc__select_negative_nan_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) half @ret_no_negative_no_nan__fptrunc__select_negative_nan_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NEGATIVE_OR_NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %negative.or.nan = call float @returns_negative_or_nan_f32()
+  %select = select i1 %cond, float %negative.or.nan, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(snan) half @ret_no_snan__fptrunc__always_zero() {
+; CHECK-LABEL: define nofpclass(snan) half @ret_no_snan__fptrunc__always_zero() {
+; CHECK-NEXT:    [[ZERO:%.*]] = call float @returns_zero_f32()
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[ZERO]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %zero = call float @returns_zero_f32()
+  %result = call half @llvm.fptrunc.round.f16.f32(float %zero, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(snan) half @ret_no_snan__fptrunc__always_zero_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) half @ret_no_snan__fptrunc__always_zero_or_nan() {
+; CHECK-NEXT:    [[ZERO_OR_NAN:%.*]] = call float @returns_zero_or_nan_f32()
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[ZERO_OR_NAN]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %zero.or.nan = call float @returns_zero_or_nan_f32()
+  %result = call half @llvm.fptrunc.round.f16.f32(float %zero.or.nan, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(snan) half @ret_no_snan__fptrunc__always_inf() {
+; CHECK-LABEL: define nofpclass(snan) half @ret_no_snan__fptrunc__always_inf() {
+; CHECK-NEXT:    [[INF:%.*]] = call float @returns_inf_f32()
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[INF]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %inf = call float @returns_inf_f32()
+  %result = call half @llvm.fptrunc.round.f16.f32(float %inf, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(snan) half @ret_no_snan__fptrunc__always_inf_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) half @ret_no_snan__fptrunc__always_inf_or_nan() {
+; CHECK-NEXT:    [[INF_OR_NAN:%.*]] = call float @returns_inf_or_nan_f32()
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[INF_OR_NAN]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %inf.or.nan = call float @returns_inf_or_nan_f32()
+  %result = call half @llvm.fptrunc.round.f16.f32(float %inf.or.nan, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(inf nan norm zero) half @ret_only_sub__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf zero norm) half @ret_only_sub__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[X]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = call half @llvm.fptrunc.round.f16.f32(float %x, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(inf nan norm zero nsub) half @ret_only_psub__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf zero nsub norm) half @ret_only_psub__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[X]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = call half @llvm.fptrunc.round.f16.f32(float %x, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(inf nan norm zero psub) half @ret_only_nsub__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf zero psub norm) half @ret_only_nsub__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[X]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = call half @llvm.fptrunc.round.f16.f32(float %x, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(inf nan norm) half @ret_only_sub_zero__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf norm) half @ret_only_sub_zero__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[X]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = call half @llvm.fptrunc.round.f16.f32(float %x, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(inf nan norm nzero nsub) half @ret_only_psub_pzero__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf nzero nsub norm) half @ret_only_psub_pzero__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[X]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = call half @llvm.fptrunc.round.f16.f32(float %x, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(inf nan norm pzero psub) half @ret_only_nsub_nzero__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf pzero psub norm) half @ret_only_nsub_nzero__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[X]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = call half @llvm.fptrunc.round.f16.f32(float %x, metadata !"round.downward")
+  ret half %result
+}
+
+; -> +inf
+define nofpclass(ninf) half @ret_no_ninf__fptrunc__inf() {
+; CHECK-LABEL: define nofpclass(ninf) half @ret_no_ninf__fptrunc__inf() {
+; CHECK-NEXT:    [[INF:%.*]] = call float @returns_inf_f32()
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[INF]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %inf = call float @returns_inf_f32()
+  %result = call half @llvm.fptrunc.round.f16.f32(float %inf, metadata !"round.downward")
+  ret half %result
+}
+
+; -> -inf
+define nofpclass(pinf) half @ret_no_pinf__fptrunc__inf() {
+; CHECK-LABEL: define nofpclass(pinf) half @ret_no_pinf__fptrunc__inf() {
+; CHECK-NEXT:    [[INF:%.*]] = call float @returns_inf_f32()
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[INF]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %inf = call float @returns_inf_f32()
+  %result = call half @llvm.fptrunc.round.f16.f32(float %inf, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(nzero) half @ret_no_nzero__fptrunc__select_nzero_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(nzero) half @ret_no_nzero__fptrunc__select_nzero_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NZERO:%.*]] = call float @returns_nzero_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NZERO]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %nzero = call float @returns_nzero_f32()
+  %select = select i1 %cond, float %nzero, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(pzero) half @ret_no_pzero__fptrunc__select_pzero_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(pzero) half @ret_no_pzero__fptrunc__select_pzero_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[PZERO:%.*]] = call float @returns_pzero_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[PZERO]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %pzero = call float @returns_pzero_f32()
+  %select = select i1 %cond, float %pzero, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(zero) half @ret_no_zero__fptrunc__select_zero_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(zero) half @ret_no_zero__fptrunc__select_zero_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[ZERO:%.*]] = call float @returns_zero_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[ZERO]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %zero = call float @returns_zero_f32()
+  %select = select i1 %cond, float %zero, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(nnorm) half @ret_no_nnorm__fptrunc__select_nnorm_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(nnorm) half @ret_no_nnorm__fptrunc__select_nnorm_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NNORM:%.*]] = call float @returns_nnorm_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NNORM]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %nnorm = call float @returns_nnorm_f32()
+  %select = select i1 %cond, float %nnorm, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(pnorm) half @ret_no_pnorm__fptrunc__select_pnorm_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(pnorm) half @ret_no_pnorm__fptrunc__select_pnorm_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[PNORM:%.*]] = call float @returns_pnorm_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[PNORM]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %pnorm = call float @returns_pnorm_f32()
+  %select = select i1 %cond, float %pnorm, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
+
+define nofpclass(norm) half @ret_no_norm__fptrunc__select_norm_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(norm) half @ret_no_norm__fptrunc__select_norm_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NORM:%.*]] = call float @returns_norm_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NORM]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fptrunc.round.f16.f32(float [[SELECT]], metadata !"round.downward")
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %norm = call float @returns_norm_f32()
+  %select = select i1 %cond, float %norm, float %unknown
+  %result = call half @llvm.fptrunc.round.f16.f32(float %select, metadata !"round.downward")
+  ret half %result
+}
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fptrunc.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fptrunc.ll
new file mode 100644
index 0000000000000..b777ad82b67d8
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fptrunc.ll
@@ -0,0 +1,533 @@
+; 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(inf norm sub zero) float @returns_nan_f32()
+declare nofpclass(nan ninf norm sub zero) float @returns_pinf_f32()
+declare nofpclass(nan pinf norm sub zero) float @returns_ninf_f32()
+declare nofpclass(nan norm sub zero) float @returns_inf_f32()
+declare nofpclass(norm sub zero) float @returns_inf_or_nan_f32()
+
+declare nofpclass(inf nan norm psub zero) float @returns_nsub_f32()
+declare nofpclass(inf nan norm nsub zero) float @returns_psub_f32()
+declare nofpclass(inf nan norm zero) float @returns_sub_f32()
+
+declare nofpclass(nan pinf pnorm psub pzero) float @returns_negative_f32()
+declare nofpclass(pinf pnorm psub pzero) float @returns_negative_or_nan_f32()
+
+declare nofpclass(nan ninf nnorm nsub nzero) float @returns_positive_f32()
+declare nofpclass(ninf nnorm nsub nzero) float @returns_positive_or_nan_f32()
+
+declare nofpclass(nan inf norm sub) float @returns_zero_f32()
+declare nofpclass(nan inf norm sub nzero) float @returns_pzero_f32()
+declare nofpclass(nan inf norm sub pzero) float @returns_nzero_f32()
+declare nofpclass(inf norm sub) float @returns_zero_or_nan_f32()
+
+declare nofpclass(nan inf sub zero) float @returns_norm_f32()
+declare nofpclass(nan inf nnorm sub zero) float @returns_pnorm_f32()
+declare nofpclass(nan inf pnorm sub zero) float @returns_nnorm_f32()
+
+
+define nofpclass(inf norm sub zero qnan) half @ret_only_snan__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(qnan inf zero sub norm) half @ret_only_snan__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[X]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = fptrunc float %x to half
+  ret half %result
+}
+
+define nofpclass(inf norm sub zero snan) half @ret_only_qnan__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(snan inf zero sub norm) half @ret_only_qnan__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[X]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = fptrunc float %x to half
+  ret half %result
+}
+
+define nofpclass(inf norm sub zero) half @ret_only_nan__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(inf zero sub norm) half @ret_only_nan__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[X]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = fptrunc float %x to half
+  ret half %result
+}
+
+define nofpclass(nan norm sub zero) half @ret_only_inf__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan zero sub norm) half @ret_only_inf__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[X]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = fptrunc float %x to half
+  ret half %result
+}
+
+define nofpclass(nan pinf norm sub zero) half @ret_only_ninf__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan pinf zero sub norm) half @ret_only_ninf__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    ret half 0xHFC00
+;
+  %result = fptrunc float %x to half
+  ret half %result
+}
+
+define nofpclass(nan ninf norm sub zero) half @ret_only_pinf__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan ninf zero sub norm) half @ret_only_pinf__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    ret half 0xH7C00
+;
+  %result = fptrunc float %x to half
+  ret half %result
+}
+
+define nofpclass(inf nan norm sub) half @ret_only_zero__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) half @ret_only_zero__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[X]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = fptrunc float %x to half
+  ret half %result
+}
+
+define nofpclass(inf nan norm sub nzero) half @ret_only_pzero__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf nzero sub norm) half @ret_only_pzero__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    ret half 0xH0000
+;
+  %result = fptrunc float %x to half
+  ret half %result
+}
+
+define nofpclass(inf nan norm sub pzero) half @ret_only_nzero__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf pzero sub norm) half @ret_only_nzero__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    ret half 0xH8000
+;
+  %result = fptrunc float %x to half
+  ret half %result
+}
+
+; Fold out select
+define nofpclass(nan) half @ret_no_nan__fptrunc__select_nan_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_no_nan__fptrunc__select_nan_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NAN:%.*]] = call float @returns_nan_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %nan = call float @returns_nan_f32()
+  %select = select i1 %cond, float %nan, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}
+
+; Fold out select
+define nofpclass(pinf) half @ret_no_pinf__fptrunc__select_pinf_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(pinf) half @ret_no_pinf__fptrunc__select_pinf_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[PINF:%.*]] = call float @returns_pinf_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[PINF]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %pinf = call float @returns_pinf_f32()
+  %select = select i1 %cond, float %pinf, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}
+
+; Fold out select
+define nofpclass(ninf) half @ret_no_ninf__fptrunc__select_ninf_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(ninf) half @ret_no_ninf__fptrunc__select_ninf_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NINF:%.*]] = call float @returns_ninf_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NINF]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %ninf = call float @returns_ninf_f32()
+  %select = select i1 %cond, float %ninf, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}
+
+; Fold out select
+define nofpclass(inf) half @ret_no_inf__fptrunc__select_inf_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_no_inf__fptrunc__select_inf_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[INF:%.*]] = call float @returns_inf_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[INF]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %inf = call float @returns_inf_f32()
+  %select = select i1 %cond, float %inf, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}
+
+; Fold out select
+define nofpclass(nan inf) half @ret_no_inf_no_nan__fptrunc__select_inf_or_nan_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(nan inf) half @ret_no_inf_no_nan__fptrunc__select_inf_or_nan_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[INF_OR_NAN:%.*]] = call float @returns_inf_or_nan_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[INF_OR_NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %inf.or.nan = call float @returns_inf_or_nan_f32()
+  %select = select i1 %cond, float %inf.or.nan, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}
+
+define nofpclass(nsub) half @ret_no_nsub__fptrunc__select_nsub_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(nsub) half @ret_no_nsub__fptrunc__select_nsub_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NSUB:%.*]] = call float @returns_nsub_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NSUB]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %nsub = call float @returns_nsub_f32()
+  %select = select i1 %cond, float %nsub, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}
+
+define nofpclass(psub) half @ret_no_psub__fptrunc__select_psub_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(psub) half @ret_no_psub__fptrunc__select_psub_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[PSUB:%.*]] = call float @returns_psub_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[PSUB]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %psub = call float @returns_psub_f32()
+  %select = select i1 %cond, float %psub, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}
+
+define nofpclass(sub) half @ret_no_sub__fptrunc__select_sub_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(sub) half @ret_no_sub__fptrunc__select_sub_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SUB:%.*]] = call float @returns_sub_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[SUB]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %sub = call float @returns_sub_f32()
+  %select = select i1 %cond, float %sub, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}
+
+; Remove select
+define nofpclass(pinf pnorm psub pzero) half @ret_no_positive__fptrunc__select_positive_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) half @ret_no_positive__fptrunc__select_positive_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[POSITIVE:%.*]] = call float @returns_positive_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[POSITIVE]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %positive = call float @returns_positive_f32()
+  %select = select i1 %cond, float %positive, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}
+
+; No remove select
+define nofpclass(pinf pnorm psub pzero) half @ret_no_positive__fptrunc__select_positive_nan_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) half @ret_no_positive__fptrunc__select_positive_nan_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[POSITIVE_OR_NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %positive.or.nan = call float @returns_positive_or_nan_f32()
+  %select = select i1 %cond, float %positive.or.nan, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}
+
+; Remove select
+define nofpclass(nan pinf pnorm psub pzero) half @ret_no_positive_no_nan__fptrunc__select_positive_nan_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) half @ret_no_positive_no_nan__fptrunc__select_positive_nan_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[POSITIVE_OR_NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %positive.or.nan = call float @returns_positive_or_nan_f32()
+  %select = select i1 %cond, float %positive.or.nan, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}
+
+; Remove select
+define nofpclass(ninf nnorm nsub nzero) half @ret_no_negative__fptrunc__select_negative_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) half @ret_no_negative__fptrunc__select_negative_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NEGATIVE:%.*]] = call float @returns_negative_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NEGATIVE]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %negative = call float @returns_negative_f32()
+  %select = select i1 %cond, float %negative, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}
+
+; No remove select
+define nofpclass(ninf nnorm nsub nzero) half @ret_no_negative__fptrunc__select_negative_nan_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) half @ret_no_negative__fptrunc__select_negative_nan_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NEGATIVE_OR_NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %negative.or.nan = call float @returns_negative_or_nan_f32()
+  %select = select i1 %cond, float %negative.or.nan, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}
+
+; Remove select
+define nofpclass(nan ninf nnorm nsub nzero) half @ret_no_negative_no_nan__fptrunc__select_negative_nan_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) half @ret_no_negative_no_nan__fptrunc__select_negative_nan_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NEGATIVE_OR_NAN]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %negative.or.nan = call float @returns_negative_or_nan_f32()
+  %select = select i1 %cond, float %negative.or.nan, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}
+
+define nofpclass(snan) half @ret_no_snan__fptrunc__always_zero() {
+; CHECK-LABEL: define nofpclass(snan) half @ret_no_snan__fptrunc__always_zero() {
+; CHECK-NEXT:    [[ZERO:%.*]] = call float @returns_zero_f32()
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[ZERO]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %zero = call float @returns_zero_f32()
+  %result = fptrunc float %zero to half
+  ret half %result
+}
+
+define nofpclass(snan) half @ret_no_snan__fptrunc__always_zero_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) half @ret_no_snan__fptrunc__always_zero_or_nan() {
+; CHECK-NEXT:    [[ZERO_OR_NAN:%.*]] = call float @returns_zero_or_nan_f32()
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[ZERO_OR_NAN]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %zero.or.nan = call float @returns_zero_or_nan_f32()
+  %result = fptrunc float %zero.or.nan to half
+  ret half %result
+}
+
+define nofpclass(snan) half @ret_no_snan__fptrunc__always_inf() {
+; CHECK-LABEL: define nofpclass(snan) half @ret_no_snan__fptrunc__always_inf() {
+; CHECK-NEXT:    [[INF:%.*]] = call float @returns_inf_f32()
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[INF]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %inf = call float @returns_inf_f32()
+  %result = fptrunc float %inf to half
+  ret half %result
+}
+
+define nofpclass(snan) half @ret_no_snan__fptrunc__always_inf_or_nan() {
+; CHECK-LABEL: define nofpclass(snan) half @ret_no_snan__fptrunc__always_inf_or_nan() {
+; CHECK-NEXT:    [[INF_OR_NAN:%.*]] = call float @returns_inf_or_nan_f32()
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[INF_OR_NAN]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %inf.or.nan = call float @returns_inf_or_nan_f32()
+  %result = fptrunc float %inf.or.nan to half
+  ret half %result
+}
+
+define nofpclass(inf nan norm zero) half @ret_only_sub__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf zero norm) half @ret_only_sub__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[X]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = fptrunc float %x to half
+  ret half %result
+}
+
+define nofpclass(inf nan norm zero nsub) half @ret_only_psub__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf zero nsub norm) half @ret_only_psub__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[X]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = fptrunc float %x to half
+  ret half %result
+}
+
+define nofpclass(inf nan norm zero psub) half @ret_only_nsub__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf zero psub norm) half @ret_only_nsub__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[X]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = fptrunc float %x to half
+  ret half %result
+}
+
+define nofpclass(inf nan norm) half @ret_only_sub_zero__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf norm) half @ret_only_sub_zero__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[X]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = fptrunc float %x to half
+  ret half %result
+}
+
+define nofpclass(inf nan norm nzero nsub) half @ret_only_psub_pzero__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf nzero nsub norm) half @ret_only_psub_pzero__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[X]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = fptrunc float %x to half
+  ret half %result
+}
+
+define nofpclass(inf nan norm pzero psub) half @ret_only_nsub_nzero__fptrunc(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf pzero psub norm) half @ret_only_nsub_nzero__fptrunc(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[X]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %result = fptrunc float %x to half
+  ret half %result
+}
+
+; -> +inf
+define nofpclass(ninf) half @ret_no_ninf__fptrunc__inf() {
+; CHECK-LABEL: define nofpclass(ninf) half @ret_no_ninf__fptrunc__inf() {
+; CHECK-NEXT:    [[INF:%.*]] = call float @returns_inf_f32()
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[INF]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %inf = call float @returns_inf_f32()
+  %result = fptrunc float %inf to half
+  ret half %result
+}
+
+; -> -inf
+define nofpclass(pinf) half @ret_no_pinf__fptrunc__inf() {
+; CHECK-LABEL: define nofpclass(pinf) half @ret_no_pinf__fptrunc__inf() {
+; CHECK-NEXT:    [[INF:%.*]] = call float @returns_inf_f32()
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[INF]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %inf = call float @returns_inf_f32()
+  %result = fptrunc float %inf to half
+  ret half %result
+}
+
+define nofpclass(nzero) half @ret_no_nzero__fptrunc__select_nzero_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(nzero) half @ret_no_nzero__fptrunc__select_nzero_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NZERO:%.*]] = call float @returns_nzero_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NZERO]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %nzero = call float @returns_nzero_f32()
+  %select = select i1 %cond, float %nzero, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}
+
+define nofpclass(pzero) half @ret_no_pzero__fptrunc__select_pzero_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(pzero) half @ret_no_pzero__fptrunc__select_pzero_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[PZERO:%.*]] = call float @returns_pzero_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[PZERO]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %pzero = call float @returns_pzero_f32()
+  %select = select i1 %cond, float %pzero, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}
+
+define nofpclass(zero) half @ret_no_zero__fptrunc__select_zero_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(zero) half @ret_no_zero__fptrunc__select_zero_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[ZERO:%.*]] = call float @returns_zero_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[ZERO]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %zero = call float @returns_zero_f32()
+  %select = select i1 %cond, float %zero, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}
+
+define nofpclass(nnorm) half @ret_no_nnorm__fptrunc__select_nnorm_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(nnorm) half @ret_no_nnorm__fptrunc__select_nnorm_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NNORM:%.*]] = call float @returns_nnorm_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NNORM]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %nnorm = call float @returns_nnorm_f32()
+  %select = select i1 %cond, float %nnorm, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}
+
+define nofpclass(pnorm) half @ret_no_pnorm__fptrunc__select_pnorm_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(pnorm) half @ret_no_pnorm__fptrunc__select_pnorm_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[PNORM:%.*]] = call float @returns_pnorm_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[PNORM]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %pnorm = call float @returns_pnorm_f32()
+  %select = select i1 %cond, float %pnorm, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}
+
+define nofpclass(norm) half @ret_no_norm__fptrunc__select_norm_or_unknown(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(norm) half @ret_no_norm__fptrunc__select_norm_or_unknown(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NORM:%.*]] = call float @returns_norm_f32()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NORM]], float [[UNKNOWN]]
+; CHECK-NEXT:    [[RESULT:%.*]] = fptrunc float [[SELECT]] to half
+; CHECK-NEXT:    ret half [[RESULT]]
+;
+  %norm = call float @returns_norm_f32()
+  %select = select i1 %cond, float %norm, float %unknown
+  %result = fptrunc float %select to half
+  ret half %result
+}



More information about the llvm-branch-commits mailing list