[llvm] InstCombine: Add baseline fdiv SimplifyDemandedFPClass tests (PR #175945)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 14 11:09:26 PST 2026


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

>From 9544105398bdf01fc3125fc78be7f1e1181da3de Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Mon, 5 Jan 2026 18:52:25 +0100
Subject: [PATCH] InstCombine: Add baseline fdiv SimplifyDemandedFPClass tests

---
 .../simplify-demanded-fpclass-fdiv.ll         | 2321 +++++++++++++++++
 1 file changed, 2321 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fdiv.ll

diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fdiv.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fdiv.ll
new file mode 100644
index 0000000000000..c6fe600290d37
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fdiv.ll
@@ -0,0 +1,2321 @@
+; 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(nan inf sub norm) half @returns_zero()
+declare nofpclass(nan inf nzero sub norm) half @returns_pzero()
+declare nofpclass(nan inf pzero sub norm) half @returns_nzero()
+declare nofpclass(nan inf zero sub nnorm) half @returns_pnorm()
+declare nofpclass(nan inf zero sub pnorm) half @returns_nnorm()
+declare nofpclass(nan inf norm zero) half @returns_sub()
+declare nofpclass(nan inf norm nsub zero) half @returns_psub()
+declare nofpclass(nan inf norm psub zero) half @returns_nsub()
+declare nofpclass(nan inf sub zero) half @returns_norm()
+declare nofpclass(nan norm sub zero) half @returns_inf()
+declare void @use(half)
+
+define nofpclass(pinf) half @ret_nofpclass_pinf__fdiv_unknown_or_pinf(i1 %cond, half %x, half %y) {
+; CHECK-LABEL: define nofpclass(pinf) half @ret_nofpclass_pinf__fdiv_unknown_or_pinf(
+; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half [[Y:%.*]]) {
+; CHECK-NEXT:    [[X_OR_PINF:%.*]] = select i1 [[COND]], half [[X]], half 0xH7C00
+; CHECK-NEXT:    [[Y_OR_PINF:%.*]] = select i1 [[COND]], half [[Y]], half 0xH7C00
+; CHECK-NEXT:    [[TMP1:%.*]] = fdiv half [[X_OR_PINF]], [[Y_OR_PINF]]
+; CHECK-NEXT:    ret half [[TMP1]]
+;
+  %x.or.pinf = select i1 %cond, half %x, half 0x7FF0000000000000
+  %y.or.pinf = select i1 %cond, half %y, half 0x7FF0000000000000
+  %div = fdiv half %x.or.pinf, %y.or.pinf
+  ret half %div
+}
+
+define nofpclass(ninf) half @ret_nofpclass_pinf__fdiv_unknown_or_ninf(i1 %cond, half %x, half %y) {
+; CHECK-LABEL: define nofpclass(ninf) half @ret_nofpclass_pinf__fdiv_unknown_or_ninf(
+; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half [[Y:%.*]]) {
+; CHECK-NEXT:    [[X_OR_NINF:%.*]] = select i1 [[COND]], half [[X]], half 0xHFC00
+; CHECK-NEXT:    [[Y_OR_NINF:%.*]] = select i1 [[COND]], half [[Y]], half 0xHFC00
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X_OR_NINF]], [[Y_OR_NINF]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %x.or.ninf = select i1 %cond, half %x, half 0xFFF0000000000000
+  %y.or.ninf = select i1 %cond, half %y, half 0xFFF0000000000000
+  %div = fdiv half %x.or.ninf, %y.or.ninf
+  ret half %div
+}
+
+define nofpclass(inf) half @ret_nofpclass_inf__fdiv_unknown_or_pinf(i1 %cond, half %x, half %y) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_nofpclass_inf__fdiv_unknown_or_pinf(
+; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half [[Y:%.*]]) {
+; CHECK-NEXT:    [[X_OR_PINF:%.*]] = select i1 [[COND]], half [[X]], half 0xH7C00
+; CHECK-NEXT:    [[Y_OR_PINF:%.*]] = select i1 [[COND]], half [[Y]], half 0xH7C00
+; CHECK-NEXT:    [[TMP1:%.*]] = fdiv half [[X_OR_PINF]], [[Y_OR_PINF]]
+; CHECK-NEXT:    ret half [[TMP1]]
+;
+  %x.or.pinf = select i1 %cond, half %x, half 0x7FF0000000000000
+  %y.or.pinf = select i1 %cond, half %y, half 0x7FF0000000000000
+  %div = fdiv half %x.or.pinf, %y.or.pinf
+  ret half %div
+}
+
+; -> Only propagate nan %x
+define nofpclass(pinf pnorm psub pzero) half @ret_only_negative_results_or_nan_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) half @ret_only_negative_results_or_nan_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+; -> poison
+define nofpclass(pinf pnorm psub pzero nan) half @ret_only_negative_results_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) half @ret_only_negative_results_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    ret half poison
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+; Cannot fold if undef
+define nofpclass(pinf pnorm psub pzero nan) half @ret_only_negative_results_self_maybe_undef(half %x) {
+; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) half @ret_only_negative_results_self_maybe_undef(
+; CHECK-SAME: half [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(inf norm sub) half @ret_only_zero_or_nan_results_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(inf sub norm) half @ret_only_zero_or_nan_results_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(inf norm sub nan) half @ret_only_zero_results_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) half @ret_only_zero_results_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    ret half poison
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(inf norm sub zero) half @ret_only_nan_results_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(inf zero sub norm) half @ret_only_nan_results_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(inf norm sub zero snan) half @ret_only_qnan_results_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(snan inf zero sub norm) half @ret_only_qnan_results_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(inf norm sub zero qnan) half @ret_only_snan_results_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(qnan inf zero sub norm) half @ret_only_snan_results_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(norm sub zero) half @ret_only_inf_or_nan_results_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(zero sub norm) half @ret_only_inf_or_nan_results_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(norm sub zero nan) half @ret_only_inf_results_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(nan zero sub norm) half @ret_only_inf_results_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    ret half poison
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(ninf norm sub zero) half @ret_only_pinf_or_nan_results_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(ninf zero sub norm) half @ret_only_pinf_or_nan_results_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(ninf norm sub zero nan) half @ret_only_pinf_results_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(nan ninf zero sub norm) half @ret_only_pinf_results_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    ret half poison
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+; -> poison
+define nofpclass(pinf norm sub zero nan) half @ret_only_ninf_results_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(nan pinf zero sub norm) half @ret_only_ninf_results_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    ret half poison
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(inf) half @ret_src_must_be_zero_self(half noundef nofpclass(nan inf norm sub) %x) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_src_must_be_zero_self(
+; CHECK-SAME: half noundef nofpclass(nan inf sub norm) [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(inf) half @ret_src_must_be_pzero(half noundef nofpclass(nan inf norm sub nzero) %x) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_src_must_be_pzero(
+; CHECK-SAME: half noundef nofpclass(nan inf nzero sub norm) [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(inf) half @ret_src_must_be_nzero(half noundef nofpclass(nan inf norm sub pzero) %x) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_src_must_be_nzero(
+; CHECK-SAME: half noundef nofpclass(nan inf pzero sub norm) [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(inf) half @ret_src_must_be_zero_or_nan_self(half noundef nofpclass(inf norm sub) %x) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_src_must_be_zero_or_nan_self(
+; CHECK-SAME: half noundef nofpclass(inf sub norm) [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(inf) half @ret_src_must_be_zero_or_nan_self__preserve_flags(half noundef nofpclass(inf norm sub) %x) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_src_must_be_zero_or_nan_self__preserve_flags(
+; CHECK-SAME: half noundef nofpclass(inf sub norm) [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv contract half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv contract half %x, %x
+  ret half %div
+}
+
+define nofpclass(inf) half @ret_src_must_be_zero_or_nan_self_other_use_input0(half noundef nofpclass(inf norm sub) %x) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_src_must_be_zero_or_nan_self_other_use_input0(
+; CHECK-SAME: half noundef nofpclass(inf sub norm) [[X:%.*]]) {
+; CHECK-NEXT:    call void @use(half [[X]])
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  call void @use(half %x)
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(inf) half @ret_src_must_be_zero_or_nan_self_other_use_input1(half noundef nofpclass(inf norm sub) %x) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_src_must_be_zero_or_nan_self_other_use_input1(
+; CHECK-SAME: half noundef nofpclass(inf sub norm) [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    call void @use(half [[X]])
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  call void @use(half %x)
+  ret half %div
+}
+
+define nofpclass(snan) half @ret_src_nonan_self(half noundef nofpclass(nan) %x) {
+; CHECK-LABEL: define nofpclass(snan) half @ret_src_nonan_self(
+; CHECK-SAME: half noundef nofpclass(nan) [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(nan) half @ret_nonan_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_nonan_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(snan) half @ret_src_noinf_self(half noundef nofpclass(inf) %x) {
+; CHECK-LABEL: define nofpclass(snan) half @ret_src_noinf_self(
+; CHECK-SAME: half noundef nofpclass(inf) [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(inf) half @ret_noinf_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_noinf_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(snan) half @ret_src_nonan_noinf_self(half noundef nofpclass(nan inf) %x) {
+; CHECK-LABEL: define nofpclass(snan) half @ret_src_nonan_noinf_self(
+; CHECK-SAME: half noundef nofpclass(nan inf) [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(snan) half @ret_src_nozero_self(half noundef nofpclass(zero) %x) {
+; CHECK-LABEL: define nofpclass(snan) half @ret_src_nozero_self(
+; CHECK-SAME: half noundef nofpclass(zero) [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(snan) half @ret_src_nozero_self__daz(half noundef nofpclass(zero) %x) #2 {
+; CHECK-LABEL: define nofpclass(snan) half @ret_src_nozero_self__daz(
+; CHECK-SAME: half noundef nofpclass(zero) [[X:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(snan) half @ret_src_nozero_nosub_self(half noundef nofpclass(sub zero) %x) {
+; CHECK-LABEL: define nofpclass(snan) half @ret_src_nozero_nosub_self(
+; CHECK-SAME: half noundef nofpclass(zero sub) [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(snan) half @ret_src_nozero_nosub_self__daz(half noundef nofpclass(sub zero) %x) #2 {
+; CHECK-LABEL: define nofpclass(snan) half @ret_src_nozero_nosub_self__daz(
+; CHECK-SAME: half noundef nofpclass(zero sub) [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(snan) half @ret_fdiv_nnan_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(snan) half @ret_fdiv_nnan_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    ret half 0xH3C00
+;
+  %div = fdiv nnan half %x, %x
+  ret half %div
+}
+
+define nofpclass(snan) half @ret_fdiv_ninf_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(snan) half @ret_fdiv_ninf_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv ninf half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv ninf half %x, %x
+  ret half %div
+}
+
+define nofpclass(snan) half @ret_fdiv_nnan_ninf_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(snan) half @ret_fdiv_nnan_ninf_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    ret half 0xH3C00
+;
+  %div = fdiv nnan ninf half %x, %x
+  ret half %div
+}
+
+define nofpclass(pnorm) half @ret_nopnorm_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(pnorm) half @ret_nopnorm_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(ninf) half @ret_noninf_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(ninf) half @ret_noninf_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(pinf) half @ret_nopinf_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(pinf) half @ret_nopinf_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(zero) half @ret_nozero_self(half noundef %x) {
+; CHECK-LABEL: define nofpclass(zero) half @ret_nozero_self(
+; CHECK-SAME: half noundef [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+define nofpclass(ninf norm sub zero) half @pinf_result_demands__self__pnorm_source(i1 %cond, half nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(ninf zero sub norm) half @pinf_result_demands__self__pnorm_source(
+; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[PNORM:%.*]] = call half @returns_pnorm()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[PNORM]], half [[NOT_NAN]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SELECT]], [[SELECT]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %pnorm = call half @returns_pnorm()
+  %select = select i1 %cond, half %pnorm, half %not.nan
+  %div = fdiv half %select, %select
+  ret half %div
+}
+
+define nofpclass(pinf) half @ret_nofpclass_pinf__fdiv_self_unknown_or_pinf(i1 %cond, half %x) {
+; CHECK-LABEL: define nofpclass(pinf) half @ret_nofpclass_pinf__fdiv_self_unknown_or_pinf(
+; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]]) {
+; CHECK-NEXT:    [[X_OR_PINF:%.*]] = select i1 [[COND]], half [[X]], half 0xH7C00
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X_OR_PINF]], [[X_OR_PINF]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %x.or.pinf = select i1 %cond, half %x, half 0x7FF0000000000000
+  %div = fdiv half %x.or.pinf, %x.or.pinf
+  ret half %div
+}
+
+define nofpclass(pinf) half @ret_nofpclass_pinf__fdiv_self_unknown_or_pinf__other_use0(i1 %cond, half %x) {
+; CHECK-LABEL: define nofpclass(pinf) half @ret_nofpclass_pinf__fdiv_self_unknown_or_pinf__other_use0(
+; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]]) {
+; CHECK-NEXT:    [[X_OR_PINF:%.*]] = select i1 [[COND]], half [[X]], half 0xH7C00
+; CHECK-NEXT:    call void @use(half [[X_OR_PINF]])
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X_OR_PINF]], [[X_OR_PINF]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %x.or.pinf = select i1 %cond, half %x, half 0x7FF0000000000000
+  call void @use(half %x.or.pinf)
+  %div = fdiv half %x.or.pinf, %x.or.pinf
+  ret half %div
+}
+
+define nofpclass(pinf) half @ret_nofpclass_pinf__fdiv_self_unknown_or_pinf__other_use1(i1 %cond, half %x) {
+; CHECK-LABEL: define nofpclass(pinf) half @ret_nofpclass_pinf__fdiv_self_unknown_or_pinf__other_use1(
+; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]]) {
+; CHECK-NEXT:    [[X_OR_PINF:%.*]] = select i1 [[COND]], half [[X]], half 0xH7C00
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X_OR_PINF]], [[X_OR_PINF]]
+; CHECK-NEXT:    call void @use(half [[X_OR_PINF]])
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %x.or.pinf = select i1 %cond, half %x, half 0x7FF0000000000000
+  %div = fdiv half %x.or.pinf, %x.or.pinf
+  call void @use(half %x.or.pinf)
+  ret half %div
+}
+
+; -> qnan
+define nofpclass(nzero) half @ret_src_must_be_nan_self(half noundef nofpclass(inf norm sub zero) %x) {
+; CHECK-LABEL: define nofpclass(nzero) half @ret_src_must_be_nan_self(
+; CHECK-SAME: half noundef nofpclass(inf zero sub norm) [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[X]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %x
+  ret half %div
+}
+
+; -> qnan
+define nofpclass(pinf pnorm psub pzero) half @ret_only_negative_results_or_nan_fabs_xy(half %x, half nofpclass(ninf nnorm nsub nzero) %y.pos.or.nan) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) half @ret_only_negative_results_or_nan_fabs_xy(
+; CHECK-SAME: half [[X:%.*]], half nofpclass(ninf nzero nsub nnorm) [[Y_POS_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[X_FABS:%.*]] = call half @llvm.fabs.f16(half [[X]])
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X_FABS]], [[Y_POS_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %x.fabs = call half @llvm.fabs.f32(half %x)
+  %div = fdiv half %x.fabs, %y.pos.or.nan
+  ret half %div
+}
+
+; -> poison
+define nofpclass(pinf pnorm psub pzero nan) half @ret_only_negative_results_fabs_xy(half %x,half nofpclass(ninf nnorm nsub nzero) %y.pos.or.nan) {
+; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) half @ret_only_negative_results_fabs_xy(
+; CHECK-SAME: half [[X:%.*]], half nofpclass(ninf nzero nsub nnorm) [[Y_POS_OR_NAN:%.*]]) {
+; CHECK-NEXT:    ret half poison
+;
+  %x.fabs = call half @llvm.fabs.f32(half %x)
+  %div = fdiv half %x.fabs, %y.pos.or.nan
+  ret half %div
+}
+
+define nofpclass(zero) half @ret_only_zero_results__rhs_non0_const(half %x) {
+; CHECK-LABEL: define nofpclass(zero) half @ret_only_zero_results__rhs_non0_const(
+; CHECK-SAME: half [[X:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fmul half [[X]], 0xH3800
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, 2.0
+  ret half %div
+}
+
+define nofpclass(zero) half @ret_only_zero_results__lhs_known_nonzero_nonsub(half nofpclass(zero sub) %x, half %y) {
+; CHECK-LABEL: define nofpclass(zero) half @ret_only_zero_results__lhs_known_nonzero_nonsub(
+; CHECK-SAME: half nofpclass(zero sub) [[X:%.*]], half [[Y:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[Y]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %y
+  ret half %div
+}
+
+define nofpclass(zero) half @ret_only_zero_results__lhs_known_nonzero_nonsub_daz(half nofpclass(zero sub) %x, half %y) #0 {
+; CHECK-LABEL: define nofpclass(zero) half @ret_only_zero_results__lhs_known_nonzero_nonsub_daz(
+; CHECK-SAME: half nofpclass(zero sub) [[X:%.*]], half [[Y:%.*]]) #[[ATTR1:[0-9]+]] {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[Y]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %y
+  ret half %div
+}
+
+define nofpclass(zero) half @ret_only_zero_results__lhs_known_nonzero_nonsub_dynamic(half nofpclass(zero sub) %x, half %y) #1 {
+; CHECK-LABEL: define nofpclass(zero) half @ret_only_zero_results__lhs_known_nonzero_nonsub_dynamic(
+; CHECK-SAME: half nofpclass(zero sub) [[X:%.*]], half [[Y:%.*]]) #[[ATTR2:[0-9]+]] {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[Y]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %y
+  ret half %div
+}
+
+define nofpclass(zero) half @ret_only_zero_results__lhs_known_nonzero(half nofpclass(zero) %x, half %y) {
+; CHECK-LABEL: define nofpclass(zero) half @ret_only_zero_results__lhs_known_nonzero(
+; CHECK-SAME: half nofpclass(zero) [[X:%.*]], half [[Y:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[Y]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %y
+  ret half %div
+}
+
+define nofpclass(zero) half @ret_only_zero_results__lhs_known_nonzero_daz(half nofpclass(zero) %x, half %y) #1 {
+; CHECK-LABEL: define nofpclass(zero) half @ret_only_zero_results__lhs_known_nonzero_daz(
+; CHECK-SAME: half nofpclass(zero) [[X:%.*]], half [[Y:%.*]]) #[[ATTR2]] {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[Y]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %y
+  ret half %div
+}
+
+define nofpclass(inf) half @ret_only_inf_results__lhs_known_non_inf(i1 %cond, half %x, half nofpclass(inf) %y) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_only_inf_results__lhs_known_non_inf(
+; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half nofpclass(inf) [[Y:%.*]]) {
+; CHECK-NEXT:    [[X_OR_PINF:%.*]] = select i1 [[COND]], half [[X]], half 0xH7C00
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X_OR_PINF]], [[Y]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %x.or.pinf = select i1 %cond, half %x, half 0x7FF0000000000000
+  %div = fdiv half %x.or.pinf, %y
+  ret half %div
+}
+
+define nofpclass(inf) half @ret_no_inf_results__rhs_known_non_inf(i1 %cond, half %x, half nofpclass(inf) %y) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_no_inf_results__rhs_known_non_inf(
+; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half nofpclass(inf) [[Y:%.*]]) {
+; CHECK-NEXT:    [[Y_OR_PINF:%.*]] = select i1 [[COND]], half [[Y]], half 0xH7C00
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[Y_OR_PINF]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %y.or.pinf = select i1 %cond, half %y, half 0x7FF0000000000000
+  %div = fdiv half %x, %y.or.pinf
+  ret half %div
+}
+
+; Do nothing, this could still be -inf
+define nofpclass(ninf nan) half @ret_no_ninf_or_nan_results__lhs_known_non_inf(i1 %cond, half %x, half nofpclass(inf) %y) {
+; CHECK-LABEL: define nofpclass(nan ninf) half @ret_no_ninf_or_nan_results__lhs_known_non_inf(
+; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half nofpclass(inf) [[Y:%.*]]) {
+; CHECK-NEXT:    [[X_OR_PINF:%.*]] = select i1 [[COND]], half [[X]], half 0xH7C00
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X_OR_PINF]], [[Y]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %x.or.pinf = select i1 %cond, half %x, half 0x7FF0000000000000
+  %div = fdiv half %x.or.pinf, %y
+  ret half %div
+}
+
+; Do nothing, this could still be -inf
+define nofpclass(pinf nan) half @ret_no_pinf_or_nan_results__lhs_known_non_inf(i1 %cond, half %x, half nofpclass(inf) %y) {
+; CHECK-LABEL: define nofpclass(nan pinf) half @ret_no_pinf_or_nan_results__lhs_known_non_inf(
+; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half nofpclass(inf) [[Y:%.*]]) {
+; CHECK-NEXT:    [[X_OR_PINF:%.*]] = select i1 [[COND]], half [[X]], half 0xH7C00
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X_OR_PINF]], [[Y]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %x.or.pinf = select i1 %cond, half %x, half 0x7FF0000000000000
+  %div = fdiv half %x.or.pinf, %y
+  ret half %div
+}
+
+; fold to fdiv
+define nofpclass(inf nan) half @ret_no_inf_or_nan_results__lhs_known_non_inf(i1 %cond, half %x, half nofpclass(inf) %y) {
+; CHECK-LABEL: define nofpclass(nan inf) half @ret_no_inf_or_nan_results__lhs_known_non_inf(
+; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half nofpclass(inf) [[Y:%.*]]) {
+; CHECK-NEXT:    [[X_OR_PINF:%.*]] = select i1 [[COND]], half [[X]], half 0xH7C00
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X_OR_PINF]], [[Y]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %x.or.pinf = select i1 %cond, half %x, half 0x7FF0000000000000
+  %div = fdiv half %x.or.pinf, %y
+  ret half %div
+}
+
+; fold to fdiv
+define nofpclass(inf nan) half @ret_no_inf_or_nan_results__rhs_known_non_inf(i1 %cond, half %x, half nofpclass(inf) %y) {
+; CHECK-LABEL: define nofpclass(nan inf) half @ret_no_inf_or_nan_results__rhs_known_non_inf(
+; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half nofpclass(inf) [[Y:%.*]]) {
+; CHECK-NEXT:    [[Y_OR_PINF:%.*]] = select i1 [[COND]], half [[Y]], half 0xH7C00
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[Y_OR_PINF]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %y.or.pinf = select i1 %cond, half %y, half 0x7FF0000000000000
+  %div = fdiv half %x, %y.or.pinf
+  ret half %div
+}
+
+; -> nan
+define nofpclass(ninf nnorm nsub nzero) half @ret_only_positive_results_or_nan_known_negative_fdiv(half nofpclass(ninf nnorm nsub nzero) %only.positive.or.nan, half nofpclass(pinf pnorm psub pzero) %only.negative.or.nan) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) half @ret_only_positive_results_or_nan_known_negative_fdiv(
+; CHECK-SAME: half nofpclass(ninf nzero nsub nnorm) [[ONLY_POSITIVE_OR_NAN:%.*]], half nofpclass(pinf pzero psub pnorm) [[ONLY_NEGATIVE_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[ONLY_NEGATIVE_OR_NAN]], [[ONLY_POSITIVE_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %only.negative.or.nan, %only.positive.or.nan
+  ret half %div
+}
+
+; -> poison
+define nofpclass(ninf nnorm nsub nzero nan) half @ret_only_positive_results_known_negative_fdiv(half nofpclass(ninf nnorm nsub nzero) %only.positive.or.nan, half nofpclass(pinf pnorm psub pzero) %only.negative.or.nan) {
+; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) half @ret_only_positive_results_known_negative_fdiv(
+; CHECK-SAME: half nofpclass(ninf nzero nsub nnorm) [[ONLY_POSITIVE_OR_NAN:%.*]], half nofpclass(pinf pzero psub pnorm) [[ONLY_NEGATIVE_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[ONLY_NEGATIVE_OR_NAN]], [[ONLY_POSITIVE_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %only.negative.or.nan, %only.positive.or.nan
+  ret half %div
+}
+
+; missing nnan rhs
+define nofpclass(nsub) half @ret__known_zero_or_nan__fdiv__not_inf(half nofpclass(inf sub norm) %zero.or.nan, half nofpclass(inf) %not.inf) {
+; CHECK-LABEL: define nofpclass(nsub) half @ret__known_zero_or_nan__fdiv__not_inf(
+; CHECK-SAME: half nofpclass(inf sub norm) [[ZERO_OR_NAN:%.*]], half nofpclass(inf) [[NOT_INF:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[ZERO_OR_NAN]], [[NOT_INF]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %zero.or.nan, %not.inf
+  ret half %div
+}
+
+; Needs to be pzero to replace with copysign
+define nofpclass(nsub) half @ret__known_zero_or_nan__fdiv__not_inf_or_nan(half nofpclass(inf sub norm) %zero.or.nan, half nofpclass(inf nan) %not.inf.or.nan) {
+; CHECK-LABEL: define nofpclass(nsub) half @ret__known_zero_or_nan__fdiv__not_inf_or_nan(
+; CHECK-SAME: half nofpclass(inf sub norm) [[ZERO_OR_NAN:%.*]], half nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[ZERO_OR_NAN]], [[NOT_INF_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %zero.or.nan, %not.inf.or.nan
+  ret half %div
+}
+
+; Needs to be pzero to replace with copysign
+define nofpclass(nsub) half @ret__not_inf_or_nan__fdiv__known_zero_or_nan(half nofpclass(inf nan) %not.inf.or.nan, half nofpclass(inf sub norm) %zero.or.nan) {
+; CHECK-LABEL: define nofpclass(nsub) half @ret__not_inf_or_nan__fdiv__known_zero_or_nan(
+; CHECK-SAME: half nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]], half nofpclass(inf sub norm) [[ZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NOT_INF_OR_NAN]], [[ZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %not.inf.or.nan, %zero.or.nan
+  ret half %div
+}
+
+; -> copysign
+define nofpclass(nsub) half @ret__known_pzero_or_nan__fdiv__not_inf_or_nan(half nofpclass(inf sub norm nzero) %pzero.or.nan, half nofpclass(inf nan) %not.inf.or.nan) {
+; CHECK-LABEL: define nofpclass(nsub) half @ret__known_pzero_or_nan__fdiv__not_inf_or_nan(
+; CHECK-SAME: half nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], half nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[PZERO_OR_NAN]], [[NOT_INF_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %pzero.or.nan, %not.inf.or.nan
+  ret half %div
+}
+
+; missing nnan lhs
+define nofpclass(nsub) half @ret__not_inf__fdiv__known_pzero_or_nan(half nofpclass(inf) %not.inf, half nofpclass(inf sub norm nzero) %pzero.or.nan) {
+; CHECK-LABEL: define nofpclass(nsub) half @ret__not_inf__fdiv__known_pzero_or_nan(
+; CHECK-SAME: half nofpclass(inf) [[NOT_INF:%.*]], half nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NOT_INF]], [[PZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %not.inf, %pzero.or.nan
+  ret half %div
+}
+
+; -> copysign
+define nofpclass(nsub) half @ret__not_inf_or_nan__fdiv__known_pzero_or_nan(half nofpclass(inf nan) %not.inf.or.nan, half nofpclass(inf sub norm nzero) %pzero.or.nan) {
+; CHECK-LABEL: define nofpclass(nsub) half @ret__not_inf_or_nan__fdiv__known_pzero_or_nan(
+; CHECK-SAME: half nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]], half nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NOT_INF_OR_NAN]], [[PZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %not.inf.or.nan, %pzero.or.nan
+  ret half %div
+}
+
+; Missing no-nan on RHS to turn into fneg
+define nofpclass(nsub) half @ret__known_inf_or_nan__fdiv__known_negative_non0_or_nan(half nofpclass(zero sub norm) %inf.or.nan, half nofpclass(zero pinf pnorm psub) %negative.non0.or.nan) {
+; CHECK-LABEL: define nofpclass(nsub) half @ret__known_inf_or_nan__fdiv__known_negative_non0_or_nan(
+; CHECK-SAME: half nofpclass(zero sub norm) [[INF_OR_NAN:%.*]], half nofpclass(pinf zero psub pnorm) [[NEGATIVE_NON0_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[INF_OR_NAN]], [[NEGATIVE_NON0_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %inf.or.nan, %negative.non0.or.nan
+  ret half %div
+}
+
+; Missing no-nan on LHS to turn into fneg
+define nofpclass(nsub) half @ret__known_negative_non0_or_nan__fdiv__known_inf_or_nan(half nofpclass(zero pinf pnorm psub) %negative.non0.or.nan, half nofpclass(zero sub norm) %inf.or.nan) {
+; CHECK-LABEL: define nofpclass(nsub) half @ret__known_negative_non0_or_nan__fdiv__known_inf_or_nan(
+; CHECK-SAME: half nofpclass(pinf zero psub pnorm) [[NEGATIVE_NON0_OR_NAN:%.*]], half nofpclass(zero sub norm) [[INF_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NEGATIVE_NON0_OR_NAN]], [[INF_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %negative.non0.or.nan, %inf.or.nan
+  ret half %div
+}
+
+; -> fneg
+define nofpclass(nsub) half @ret__known_inf_or_nan__fdiv__known_negative_non0(half nofpclass(zero sub norm) %inf.or.nan, half nofpclass(nan zero pinf pnorm psub) %negative.non0) {
+; CHECK-LABEL: define nofpclass(nsub) half @ret__known_inf_or_nan__fdiv__known_negative_non0(
+; CHECK-SAME: half nofpclass(zero sub norm) [[INF_OR_NAN:%.*]], half nofpclass(nan pinf zero psub pnorm) [[NEGATIVE_NON0:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[INF_OR_NAN]], [[NEGATIVE_NON0]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %inf.or.nan, %negative.non0
+  ret half %div
+}
+
+; -> fneg
+define nofpclass(nsub) half @ret__known_negative_non0__fdiv__known_inf_or_nan(half nofpclass(nan zero pinf pnorm psub) %negative.non0, half nofpclass(zero sub norm) %inf.or.nan) {
+; CHECK-LABEL: define nofpclass(nsub) half @ret__known_negative_non0__fdiv__known_inf_or_nan(
+; CHECK-SAME: half nofpclass(nan pinf zero psub pnorm) [[NEGATIVE_NON0:%.*]], half nofpclass(zero sub norm) [[INF_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NEGATIVE_NON0]], [[INF_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %negative.non0, %inf.or.nan
+  ret half %div
+}
+
+; Cannot fold to fneg due to possible nsub input
+define nofpclass(nsub) half @ret__known_inf_or_nan__fdiv__known_negative_non0__daz(half nofpclass(zero sub norm) %inf.or.nan, half nofpclass(nan zero pinf pnorm psub) %negative.non0) #1 {
+; CHECK-LABEL: define nofpclass(nsub) half @ret__known_inf_or_nan__fdiv__known_negative_non0__daz(
+; CHECK-SAME: half nofpclass(zero sub norm) [[INF_OR_NAN:%.*]], half nofpclass(nan pinf zero psub pnorm) [[NEGATIVE_NON0:%.*]]) #[[ATTR2]] {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[INF_OR_NAN]], [[NEGATIVE_NON0]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %inf.or.nan, %negative.non0
+  ret half %div
+}
+
+; Cannot fold to fneg due to possible nsub input
+define nofpclass(nsub) half @ret__known_negative_non0__fdiv__known_inf_or_nan__daz(half nofpclass(nan zero pinf pnorm psub) %negative.non0, half nofpclass(zero sub norm) %inf.or.nan) #1 {
+; CHECK-LABEL: define nofpclass(nsub) half @ret__known_negative_non0__fdiv__known_inf_or_nan__daz(
+; CHECK-SAME: half nofpclass(nan pinf zero psub pnorm) [[NEGATIVE_NON0:%.*]], half nofpclass(zero sub norm) [[INF_OR_NAN:%.*]]) #[[ATTR2]] {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NEGATIVE_NON0]], [[INF_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %negative.non0, %inf.or.nan
+  ret half %div
+}
+
+; -> fneg
+define nofpclass(nsub) half @ret__known_inf_or_nan__fdiv__known_negative_nonlogical0__daz(half nofpclass(zero sub norm) %inf.or.nan, half nofpclass(nan zero pinf pnorm sub) %negative.nonlogical0) #1 {
+; CHECK-LABEL: define nofpclass(nsub) half @ret__known_inf_or_nan__fdiv__known_negative_nonlogical0__daz(
+; CHECK-SAME: half nofpclass(zero sub norm) [[INF_OR_NAN:%.*]], half nofpclass(nan pinf zero sub pnorm) [[NEGATIVE_NONLOGICAL0:%.*]]) #[[ATTR2]] {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[INF_OR_NAN]], [[NEGATIVE_NONLOGICAL0]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %inf.or.nan, %negative.nonlogical0
+  ret half %div
+}
+
+; -> fneg
+define nofpclass(nsub) half @ret__known_negative_nonlogical0__fdiv__known_inf_or_nan__daz(half nofpclass(nan zero pinf pnorm sub) %negative.nonlogical0, half nofpclass(zero sub norm) %inf.or.nan) #1 {
+; CHECK-LABEL: define nofpclass(nsub) half @ret__known_negative_nonlogical0__fdiv__known_inf_or_nan__daz(
+; CHECK-SAME: half nofpclass(nan pinf zero sub pnorm) [[NEGATIVE_NONLOGICAL0:%.*]], half nofpclass(zero sub norm) [[INF_OR_NAN:%.*]]) #[[ATTR2]] {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NEGATIVE_NONLOGICAL0]], [[INF_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %negative.nonlogical0, %inf.or.nan
+  ret half %div
+}
+
+; Should be able to fold to copysign, helped by the lack of nan results.
+define nofpclass(nan) half @ret_no_nan_result__known_pzero__fdiv__not_inf(half nofpclass(inf sub norm nzero) %pzero.or.nan, half nofpclass(inf nan) %not.inf.or.nan) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_no_nan_result__known_pzero__fdiv__not_inf(
+; CHECK-SAME: half nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], half nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[PZERO_OR_NAN]], [[NOT_INF_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %pzero.or.nan, %not.inf.or.nan
+  ret half %div
+}
+
+; Should be able to fold to copysign, helped by the lack of nan results.
+define nofpclass(nan) half @ret_no_nan_result__not_inf_or_nan__fdiv__known_pzero_or_nan(half nofpclass(inf) %not.inf.or.nan, half nofpclass(inf sub norm nzero) %pzero.or.nan) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_no_nan_result__not_inf_or_nan__fdiv__known_pzero_or_nan(
+; CHECK-SAME: half nofpclass(inf) [[NOT_INF_OR_NAN:%.*]], half nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NOT_INF_OR_NAN]], [[PZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %not.inf.or.nan, %pzero.or.nan
+  ret half %div
+}
+
+; -> fneg, with help of no nan results
+define nofpclass(nan) half @ret_no_nan_result__known_inf_or_nan__fdiv__known_negative_non0(half nofpclass(zero sub norm) %inf.or.nan, half nofpclass(zero pinf pnorm psub) %negative.non0) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_no_nan_result__known_inf_or_nan__fdiv__known_negative_non0(
+; CHECK-SAME: half nofpclass(zero sub norm) [[INF_OR_NAN:%.*]], half nofpclass(pinf zero psub pnorm) [[NEGATIVE_NON0:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[INF_OR_NAN]], [[NEGATIVE_NON0]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %inf.or.nan, %negative.non0
+  ret half %div
+}
+
+; -> fneg, with help of no nan results
+define nofpclass(nan) half @ret_no_nan_result__known_negative_non0__fdiv__known_inf_or_nan(half nofpclass(zero pinf pnorm psub) %negative.non0, half nofpclass(zero sub norm) %inf.or.nan) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_no_nan_result__known_negative_non0__fdiv__known_inf_or_nan(
+; CHECK-SAME: half nofpclass(pinf zero psub pnorm) [[NEGATIVE_NON0:%.*]], half nofpclass(zero sub norm) [[INF_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NEGATIVE_NON0]], [[INF_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %negative.non0, %inf.or.nan
+  ret half %div
+}
+
+; -> copysign, take no-infs-no-nans from invalid return
+define nofpclass(inf nan) half @ret_noinf_nonan__known_pzero_or_nan__fdiv__not_inf_or_nan(half nofpclass(inf sub norm nzero) %pzero.or.nan, half %unknown) {
+; CHECK-LABEL: define nofpclass(nan inf) half @ret_noinf_nonan__known_pzero_or_nan__fdiv__not_inf_or_nan(
+; CHECK-SAME: half nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], half [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[PZERO_OR_NAN]], [[UNKNOWN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %pzero.or.nan, %unknown
+  ret half %div
+}
+
+; -> copysign, take no-infs-no-nans from invalid return, commuted
+define nofpclass(inf nan) half @ret_noinf_nonan__not_inf_or_nan__fdiv__known_pzero_or_nan(half nofpclass(inf sub norm nzero) %pzero.or.nan, half %unknown) {
+; CHECK-LABEL: define nofpclass(nan inf) half @ret_noinf_nonan__not_inf_or_nan__fdiv__known_pzero_or_nan(
+; CHECK-SAME: half nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], half [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[PZERO_OR_NAN]], [[UNKNOWN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %pzero.or.nan, %unknown
+  ret half %div
+}
+
+; -> copysign, take no-infs from invalid return
+define nofpclass(inf) half @ret_noinf__known_zero_or_nan__fdiv__not_nan(half nofpclass(nan sub norm nzero) %pzero.or.inf, half nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_noinf__known_zero_or_nan__fdiv__not_nan(
+; CHECK-SAME: half nofpclass(nan nzero sub norm) [[PZERO_OR_INF:%.*]], half nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[PZERO_OR_INF]], [[NOT_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %pzero.or.inf, %not.nan
+  ret half %div
+}
+
+; -> copysign, take no-infs from invalid return, commuted
+define nofpclass(inf) half @ret_noinf__noinf_or_nan__fdiv__known_pzero_or_nan(half nofpclass(nan) %not.nan, half nofpclass(nan sub norm nzero) %pzero.or.inf) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_noinf__noinf_or_nan__fdiv__known_pzero_or_nan(
+; CHECK-SAME: half nofpclass(nan) [[NOT_NAN:%.*]], half nofpclass(nan nzero sub norm) [[PZERO_OR_INF:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NOT_NAN]], [[PZERO_OR_INF]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %not.nan, %pzero.or.inf
+  ret half %div
+}
+
+; -> copysign, take no-nans from invalid return
+define nofpclass(nan) half @ret_nonan__known_zero_or_nan__fdiv__not_nan(half nofpclass(nan sub norm nzero) %pzero.or.inf, half nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__known_zero_or_nan__fdiv__not_nan(
+; CHECK-SAME: half nofpclass(nan nzero sub norm) [[PZERO_OR_INF:%.*]], half nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[PZERO_OR_INF]], [[NOT_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %pzero.or.inf, %not.nan
+  ret half %div
+}
+
+; -> copysign, take no-nans from invalid return, commuted
+define nofpclass(nan) half @ret_nonan__noinf_or_nan__fdiv__known_pzero_or_nan(half nofpclass(nan) %not.nan, half nofpclass(nan sub norm nzero) %pzero.or.inf) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__noinf_or_nan__fdiv__known_pzero_or_nan(
+; CHECK-SAME: half nofpclass(nan) [[NOT_NAN:%.*]], half nofpclass(nan nzero sub norm) [[PZERO_OR_INF:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NOT_NAN]], [[PZERO_OR_INF]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %not.nan, %pzero.or.inf
+  ret half %div
+}
+
+define nofpclass(pinf) half @ret_nopinf__known_pzero_or_nan__fdiv__not_nan(half nofpclass(nan sub norm nzero) %pzero.or.inf, half nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(pinf) half @ret_nopinf__known_pzero_or_nan__fdiv__not_nan(
+; CHECK-SAME: half nofpclass(nan nzero sub norm) [[PZERO_OR_INF:%.*]], half nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[PZERO_OR_INF]], [[NOT_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %pzero.or.inf, %not.nan
+  ret half %div
+}
+
+define nofpclass(pinf) half @ret_nopinf__not_nan__fdiv__known_zero_or_nan(half nofpclass(nan) %not.nan, half nofpclass(nan sub norm nzero) %pzero.or.inf) {
+; CHECK-LABEL: define nofpclass(pinf) half @ret_nopinf__not_nan__fdiv__known_zero_or_nan(
+; CHECK-SAME: half nofpclass(nan) [[NOT_NAN:%.*]], half nofpclass(nan nzero sub norm) [[PZERO_OR_INF:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NOT_NAN]], [[PZERO_OR_INF]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %not.nan, %pzero.or.inf
+  ret half %div
+}
+
+define nofpclass(ninf) half @ret_noninf__known_pzero_or_nan__fdiv__not_nan(half nofpclass(nan sub norm nzero) %pzero.or.inf, half nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(ninf) half @ret_noninf__known_pzero_or_nan__fdiv__not_nan(
+; CHECK-SAME: half nofpclass(nan nzero sub norm) [[PZERO_OR_INF:%.*]], half nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[PZERO_OR_INF]], [[NOT_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %pzero.or.inf, %not.nan
+  ret half %div
+}
+
+define nofpclass(ninf) half @ret_noninf__not_nan__fdiv__known_zero_or_nan(half nofpclass(nan) %not.nan, half nofpclass(nan sub norm nzero) %pzero.or.inf) {
+; CHECK-LABEL: define nofpclass(ninf) half @ret_noninf__not_nan__fdiv__known_zero_or_nan(
+; CHECK-SAME: half nofpclass(nan) [[NOT_NAN:%.*]], half nofpclass(nan nzero sub norm) [[PZERO_OR_INF:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NOT_NAN]], [[PZERO_OR_INF]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %not.nan, %pzero.or.inf
+  ret half %div
+}
+
+; no pinf result implies no infs if the signs of each operand are the same, must be +0
+define nofpclass(pinf) half @ret_nopinf__known_zero_or_pos_nan__fdiv__not_nan_pos(half nofpclass(nan ninf sub norm) %zero.or.not.neg, half nofpclass(nan ninf nzero nsub nnorm) %not.nan.not.neg) {
+; CHECK-LABEL: define nofpclass(pinf) half @ret_nopinf__known_zero_or_pos_nan__fdiv__not_nan_pos(
+; CHECK-SAME: half nofpclass(nan ninf sub norm) [[ZERO_OR_NOT_NEG:%.*]], half nofpclass(nan ninf nzero nsub nnorm) [[NOT_NAN_NOT_NEG:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[ZERO_OR_NOT_NEG]], [[NOT_NAN_NOT_NEG]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %zero.or.not.neg, %not.nan.not.neg
+  ret half %div
+}
+
+define nofpclass(pinf) half @ret_nopinf__not_nan_pos__fdiv__known_zero_or_pos_nan(half nofpclass(nan ninf nsub nnorm) %not.nan.not.neg, half nofpclass(nan ninf nzero sub norm) %zero.or.not.neg) {
+; CHECK-LABEL: define nofpclass(pinf) half @ret_nopinf__not_nan_pos__fdiv__known_zero_or_pos_nan(
+; CHECK-SAME: half nofpclass(nan ninf nsub nnorm) [[NOT_NAN_NOT_NEG:%.*]], half nofpclass(nan ninf nzero sub norm) [[ZERO_OR_NOT_NEG:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NOT_NAN_NOT_NEG]], [[ZERO_OR_NOT_NEG]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %not.nan.not.neg, %zero.or.not.neg
+  ret half %div
+}
+
+define nofpclass(pinf) half @ret_nopinf__known_zero_or_neg_nan__fdiv__not_nan_neg(half nofpclass(nan pinf sub norm) %zero.or.not.pos, half nofpclass(nan pinf pzero psub pnorm) %not.nan.not.pos) {
+; CHECK-LABEL: define nofpclass(pinf) half @ret_nopinf__known_zero_or_neg_nan__fdiv__not_nan_neg(
+; CHECK-SAME: half nofpclass(nan pinf sub norm) [[ZERO_OR_NOT_POS:%.*]], half nofpclass(nan pinf pzero psub pnorm) [[NOT_NAN_NOT_POS:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[ZERO_OR_NOT_POS]], [[NOT_NAN_NOT_POS]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %zero.or.not.pos, %not.nan.not.pos
+  ret half %div
+}
+
+define nofpclass(pinf) half @ret_nopinf__not_nan_neg__fdiv__known_zero_or_neg_nan(half nofpclass(nan pinf pzero psub pnorm) %not.nan.not.pos, half nofpclass(nan pinf sub norm) %zero.or.not.pos) {
+; CHECK-LABEL: define nofpclass(pinf) half @ret_nopinf__not_nan_neg__fdiv__known_zero_or_neg_nan(
+; CHECK-SAME: half nofpclass(nan pinf pzero psub pnorm) [[NOT_NAN_NOT_POS:%.*]], half nofpclass(nan pinf sub norm) [[ZERO_OR_NOT_POS:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NOT_NAN_NOT_POS]], [[ZERO_OR_NOT_POS]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %not.nan.not.pos, %zero.or.not.pos
+  ret half %div
+}
+
+define nofpclass(ninf) half @ret_noninf__known_zero_or_pos_nan__fdiv__not_nan_pos(half nofpclass(nan ninf sub norm) %zero.or.not.neg, half nofpclass(nan ninf nzero nsub nnorm) %not.nan.not.neg) {
+; CHECK-LABEL: define nofpclass(ninf) half @ret_noninf__known_zero_or_pos_nan__fdiv__not_nan_pos(
+; CHECK-SAME: half nofpclass(nan ninf sub norm) [[ZERO_OR_NOT_NEG:%.*]], half nofpclass(nan ninf nzero nsub nnorm) [[NOT_NAN_NOT_NEG:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[ZERO_OR_NOT_NEG]], [[NOT_NAN_NOT_NEG]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %zero.or.not.neg, %not.nan.not.neg
+  ret half %div
+}
+
+define nofpclass(ninf) half @ret_noninf__not_nan_pos__fdiv__known_zero_or_pos_nan(half nofpclass(nan ninf nzero nsub nnorm) %not.nan.not.neg, half nofpclass(nan ninf sub norm) %zero.or.not.neg) {
+; CHECK-LABEL: define nofpclass(ninf) half @ret_noninf__not_nan_pos__fdiv__known_zero_or_pos_nan(
+; CHECK-SAME: half nofpclass(nan ninf nzero nsub nnorm) [[NOT_NAN_NOT_NEG:%.*]], half nofpclass(nan ninf sub norm) [[ZERO_OR_NOT_NEG:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NOT_NAN_NOT_NEG]], [[ZERO_OR_NOT_NEG]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %not.nan.not.neg, %zero.or.not.neg
+  ret half %div
+}
+
+define nofpclass(ninf) half @ret_noninf__known_zero_or_pos_nan__fdiv__not_nan_neg(half nofpclass(nan ninf sub norm) %zero.or.not.neg, half nofpclass(nan pinf pzero psub pnorm) %not.nan.not.pos) {
+; CHECK-LABEL: define nofpclass(ninf) half @ret_noninf__known_zero_or_pos_nan__fdiv__not_nan_neg(
+; CHECK-SAME: half nofpclass(nan ninf sub norm) [[ZERO_OR_NOT_NEG:%.*]], half nofpclass(nan pinf pzero psub pnorm) [[NOT_NAN_NOT_POS:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[ZERO_OR_NOT_NEG]], [[NOT_NAN_NOT_POS]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %zero.or.not.neg, %not.nan.not.pos
+  ret half %div
+}
+
+define nofpclass(ninf) half @ret_noninf__not_nan_neg__fdiv__known_zero_or_pos_nan(half nofpclass(nan pinf pzero psub pnorm) %not.nan.not.pos, half nofpclass(nan ninf sub norm) %zero.or.not.neg) {
+; CHECK-LABEL: define nofpclass(ninf) half @ret_noninf__not_nan_neg__fdiv__known_zero_or_pos_nan(
+; CHECK-SAME: half nofpclass(nan pinf pzero psub pnorm) [[NOT_NAN_NOT_POS:%.*]], half nofpclass(nan ninf sub norm) [[ZERO_OR_NOT_NEG:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NOT_NAN_NOT_POS]], [[ZERO_OR_NOT_NEG]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %not.nan.not.pos, %zero.or.not.neg
+  ret half %div
+}
+
+define nofpclass(inf norm sub zero) half @ret_only_nan_results_fdiv(half %x, half %y) {
+; CHECK-LABEL: define nofpclass(inf zero sub norm) half @ret_only_nan_results_fdiv(
+; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[Y]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %y
+  ret half %div
+}
+
+define nofpclass(inf norm sub zero snan) half @ret_only_qnan_results_fdiv(half %x, half %y) {
+; CHECK-LABEL: define nofpclass(snan inf zero sub norm) half @ret_only_qnan_results_fdiv(
+; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[Y]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %y
+  ret half %div
+}
+
+define nofpclass(inf norm sub zero qnan) half @ret_only_snan_results_fdiv(half %x, half %y) {
+; CHECK-LABEL: define nofpclass(qnan inf zero sub norm) half @ret_only_snan_results_fdiv(
+; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[X]], [[Y]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %x, %y
+  ret half %div
+}
+
+define nofpclass(nan inf) half @ret_no_nan_no_inf__fdiv_nonan_noinf__nonan_noinf(half nofpclass(inf nan) %x, half nofpclass(inf nan) %y) {
+; CHECK-LABEL: define nofpclass(nan inf) half @ret_no_nan_no_inf__fdiv_nonan_noinf__nonan_noinf(
+; CHECK-SAME: half nofpclass(nan inf) [[X:%.*]], half nofpclass(nan inf) [[Y:%.*]]) {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv half [[X]], [[Y]]
+; CHECK-NEXT:    ret half [[FDIV]]
+;
+  %fdiv = fdiv half %x, %y
+  ret half %fdiv
+}
+
+define nofpclass(nan inf) half @ret_no_nan_no_inf__fdiv_no_nan__normal_constant(half nofpclass(inf nan) %x) {
+; CHECK-LABEL: define nofpclass(nan inf) half @ret_no_nan_no_inf__fdiv_no_nan__normal_constant(
+; CHECK-SAME: half nofpclass(nan inf) [[X:%.*]]) {
+; CHECK-NEXT:    [[FDIV:%.*]] = fmul nnan ninf half [[X]], 0xH3400
+; CHECK-NEXT:    ret half [[FDIV]]
+;
+  %fdiv = fdiv half %x, 4.0
+  ret half %fdiv
+}
+
+define nofpclass(nan) half @ret_no_nan__fdiv_zero__unknown(half %unknown) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_no_nan__fdiv_zero__unknown(
+; CHECK-SAME: half [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[ZERO:%.*]] = call half @returns_zero()
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv half [[ZERO]], [[UNKNOWN]]
+; CHECK-NEXT:    ret half [[FDIV]]
+;
+  %zero = call half @returns_zero()
+  %fdiv = fdiv half %zero, %unknown
+  ret half %fdiv
+}
+
+define nofpclass(nan) half @ret_no_nan__fdiv_unknown__zero(half %unknown) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_no_nan__fdiv_unknown__zero(
+; CHECK-SAME: half [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[ZERO:%.*]] = call half @returns_zero()
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv half [[UNKNOWN]], [[ZERO]]
+; CHECK-NEXT:    ret half [[FDIV]]
+;
+  %zero = call half @returns_zero()
+  %fdiv = fdiv half %unknown, %zero
+  ret half %fdiv
+}
+
+define nofpclass(nan) half @ret_no_nan__fdiv_pzero__unknown(half %unknown) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_no_nan__fdiv_pzero__unknown(
+; CHECK-SAME: half [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[PZERO:%.*]] = call half @returns_pzero()
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv half [[PZERO]], [[UNKNOWN]]
+; CHECK-NEXT:    ret half [[FDIV]]
+;
+  %pzero = call half @returns_pzero()
+  %fdiv = fdiv half %pzero, %unknown
+  ret half %fdiv
+}
+
+define nofpclass(nan) half @ret_no_nan__fdiv_unknown__pzero(half %unknown) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_no_nan__fdiv_unknown__pzero(
+; CHECK-SAME: half [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[PZERO:%.*]] = call half @returns_pzero()
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv half [[UNKNOWN]], [[PZERO]]
+; CHECK-NEXT:    ret half [[FDIV]]
+;
+  %pzero = call half @returns_pzero()
+  %fdiv = fdiv half %unknown, %pzero
+  ret half %fdiv
+}
+
+define nofpclass(nan) half @ret_no_nan__fdiv_nzero__unknown(half %unknown) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_no_nan__fdiv_nzero__unknown(
+; CHECK-SAME: half [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NZERO:%.*]] = call half @returns_nzero()
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv half [[NZERO]], [[UNKNOWN]]
+; CHECK-NEXT:    ret half [[FDIV]]
+;
+  %nzero = call half @returns_nzero()
+  %fdiv = fdiv half %nzero, %unknown
+  ret half %fdiv
+}
+
+define nofpclass(nan) half @ret_no_nan__fdiv_unknown__nzero(half %unknown) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_no_nan__fdiv_unknown__nzero(
+; CHECK-SAME: half [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[NZERO:%.*]] = call half @returns_nzero()
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv half [[UNKNOWN]], [[NZERO]]
+; CHECK-NEXT:    ret half [[FDIV]]
+;
+  %nzero = call half @returns_nzero()
+  %fdiv = fdiv half %unknown, %nzero
+  ret half %fdiv
+}
+
+define nofpclass(ninf) half @ret_ninf__fdiv_nnan_zero__unknown(half %unknown) {
+; CHECK-LABEL: define nofpclass(ninf) half @ret_ninf__fdiv_nnan_zero__unknown(
+; CHECK-SAME: half [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[ZERO:%.*]] = call half @returns_zero()
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv nnan half [[ZERO]], [[UNKNOWN]]
+; CHECK-NEXT:    ret half [[FDIV]]
+;
+  %zero = call half @returns_zero()
+  %fdiv = fdiv nnan half %zero, %unknown
+  ret half %fdiv
+}
+
+define nofpclass(ninf) half @ret_ninf__fdiv_nnan_unknown__zero(half %unknown) {
+; CHECK-LABEL: define nofpclass(ninf) half @ret_ninf__fdiv_nnan_unknown__zero(
+; CHECK-SAME: half [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[ZERO:%.*]] = call half @returns_zero()
+; CHECK-NEXT:    ret half 0xH7C00
+;
+  %zero = call half @returns_zero()
+  %fdiv = fdiv nnan half %unknown, %zero
+  ret half %fdiv
+}
+
+; -> copysign + fneg
+define nofpclass(snan) half @known__nzero_or_nan__fdiv__not_inf_or_nan(half nofpclass(inf sub norm pzero) %nzero.or.nan, half nofpclass(inf nan) %not.inf.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @known__nzero_or_nan__fdiv__not_inf_or_nan(
+; CHECK-SAME: half nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]], half nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv contract half [[NZERO_OR_NAN]], [[NOT_INF_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv contract half %nzero.or.nan, %not.inf.or.nan
+  ret half %div
+}
+
+; -> copysign + fneg
+define nofpclass(snan) half @known__not_inf_or_nan__fdiv__nzero_or_nan(half nofpclass(inf nan) %not.inf.or.nan, half nofpclass(inf sub norm pzero) %nzero.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @known__not_inf_or_nan__fdiv__nzero_or_nan(
+; CHECK-SAME: half nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]], half nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv contract half [[NOT_INF_OR_NAN]], [[NZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv contract half %not.inf.or.nan, %nzero.or.nan
+  ret half %div
+}
+
+; cannot replace with copysign + fneg
+define nofpclass(snan) half @known__nzero_or_nan__fdiv__not_inf(half nofpclass(inf sub norm pzero) %nzero.or.nan, half nofpclass(inf) %not.inf) {
+; CHECK-LABEL: define nofpclass(snan) half @known__nzero_or_nan__fdiv__not_inf(
+; CHECK-SAME: half nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]], half nofpclass(inf) [[NOT_INF:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NZERO_OR_NAN]], [[NOT_INF]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %nzero.or.nan, %not.inf
+  ret half %div
+}
+
+; cannot replace with copysign + fneg
+define nofpclass(snan) half @known__not_inf__fdiv__nzero_or_nan(half nofpclass(inf) %not.inf, half nofpclass(inf sub norm pzero) %nzero.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @known__not_inf__fdiv__nzero_or_nan(
+; CHECK-SAME: half nofpclass(inf) [[NOT_INF:%.*]], half nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NOT_INF]], [[NZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %not.inf, %nzero.or.nan
+  ret half %div
+}
+
+; cannot replace with copysign + fneg
+define nofpclass(snan) half @known__nzero_or_nan__fdiv__not_nan(half nofpclass(inf sub norm pzero) %nzero.or.nan, half nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @known__nzero_or_nan__fdiv__not_nan(
+; CHECK-SAME: half nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]], half nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv contract half [[NZERO_OR_NAN]], [[NOT_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv contract half %nzero.or.nan, %not.nan
+  ret half %div
+}
+
+; cannot replace with copysign + fneg
+define nofpclass(snan) half @known__not_nan__fdiv__nzero_or_nan(half nofpclass(nan) %not.nan, half nofpclass(inf sub norm pzero) %nzero.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @known__not_nan__fdiv__nzero_or_nan(
+; CHECK-SAME: half nofpclass(nan) [[NOT_NAN:%.*]], half nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv contract half [[NOT_NAN]], [[NZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv contract half %not.nan, %nzero.or.nan
+  ret half %div
+}
+
+; -> copysign + fneg, no infinity from return
+define nofpclass(inf) half @ret_noinf__nzero_or_nan__fdiv__not_inf_or_nan(half nofpclass(inf sub norm pzero) %nzero.or.nan, half nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_noinf__nzero_or_nan__fdiv__not_inf_or_nan(
+; CHECK-SAME: half nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]], half nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NZERO_OR_NAN]], [[NOT_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %nzero.or.nan, %not.nan
+  ret half %div
+}
+
+; -> copysign + fneg, no infinity from return
+define nofpclass(inf) half @ret_noinf__not_inf_or_nan__fdiv__nzero_or_nan(half nofpclass(nan) %not.nan, half nofpclass(inf sub norm pzero) %nzero.or.nan) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_noinf__not_inf_or_nan__fdiv__nzero_or_nan(
+; CHECK-SAME: half nofpclass(nan) [[NOT_NAN:%.*]], half nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NOT_NAN]], [[NZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %not.nan, %nzero.or.nan
+  ret half %div
+}
+
+; -> copysign + fneg, no nans from return
+define nofpclass(nan) half @ret_nonan__nzero_or_nan__fdiv__not_inf_or_nan(half nofpclass(inf sub norm pzero) %nzero.or.nan, half nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__nzero_or_nan__fdiv__not_inf_or_nan(
+; CHECK-SAME: half nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]], half nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NZERO_OR_NAN]], [[NOT_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %nzero.or.nan, %not.nan
+  ret half %div
+}
+
+; -> copysign + fneg, no nans from return
+define nofpclass(nan) half @ret_nonan__not_inf_or_nan__fdiv__nzero_or_nan(half nofpclass(nan) %not.nan, half nofpclass(inf sub norm pzero) %nzero.or.nan) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__not_inf_or_nan__fdiv__nzero_or_nan(
+; CHECK-SAME: half nofpclass(nan) [[NOT_NAN:%.*]], half nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NOT_NAN]], [[NZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %not.nan, %nzero.or.nan
+  ret half %div
+}
+
+; -> copysign + fneg, no infinity from flag
+define nofpclass(snan) half @ret__nzero_or_nan__fdiv_ninf__not_inf_or_nan(half nofpclass(inf sub norm pzero) %nzero.or.nan, half nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @ret__nzero_or_nan__fdiv_ninf__not_inf_or_nan(
+; CHECK-SAME: half nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]], half nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv ninf half [[NZERO_OR_NAN]], [[NOT_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv ninf half %nzero.or.nan, %not.nan
+  ret half %div
+}
+
+; -> copysign + fneg, no infinity from flag
+define nofpclass(snan) half @ret_not_inf_or_nan__fdiv_ninf__nzero_or_nan(half nofpclass(nan) %not.nan, half nofpclass(inf sub norm pzero) %nzero.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @ret_not_inf_or_nan__fdiv_ninf__nzero_or_nan(
+; CHECK-SAME: half nofpclass(nan) [[NOT_NAN:%.*]], half nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv ninf half [[NOT_NAN]], [[NZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv ninf half %not.nan, %nzero.or.nan
+  ret half %div
+}
+
+; -> copysign + fneg, no nan from flag
+define nofpclass(snan) half @ret__nzero_or_nan__fdiv_nnan__not_inf_or_nan(half nofpclass(inf sub norm pzero) %nzero.or.nan, half %unknown) {
+; CHECK-LABEL: define nofpclass(snan) half @ret__nzero_or_nan__fdiv_nnan__not_inf_or_nan(
+; CHECK-SAME: half nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]], half [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nnan half [[NZERO_OR_NAN]], [[UNKNOWN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv nnan half %nzero.or.nan, %unknown
+  ret half %div
+}
+
+; -> copysign + fneg, no nan from flag
+define nofpclass(snan) half @not_inf_or_nan__fdiv_nnan__nzero_or_nan(half %unknown, half nofpclass(inf sub norm pzero) %nzero.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @not_inf_or_nan__fdiv_nnan__nzero_or_nan(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nnan half [[UNKNOWN]], [[NZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv nnan half %unknown, %nzero.or.nan
+  ret half %div
+}
+
+; -> copysign
+define nofpclass(snan) half @known__pzero_or_nan__fdiv__not_inf_or_nan(half nofpclass(inf sub norm nzero) %pzero.or.nan, half nofpclass(inf nan) %not.inf.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @known__pzero_or_nan__fdiv__not_inf_or_nan(
+; CHECK-SAME: half nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], half nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv contract half [[PZERO_OR_NAN]], [[NOT_INF_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv contract half %pzero.or.nan, %not.inf.or.nan
+  ret half %div
+}
+
+; -> copysign
+define nofpclass(snan) half @known__not_inf_or_nan__fdiv__pzero_or_nan(half nofpclass(inf nan) %not.inf.or.nan, half nofpclass(inf sub norm nzero) %pzero.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @known__not_inf_or_nan__fdiv__pzero_or_nan(
+; CHECK-SAME: half nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]], half nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv contract half [[NOT_INF_OR_NAN]], [[PZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv contract half %not.inf.or.nan, %pzero.or.nan
+  ret half %div
+}
+
+; cannot replace with copysign
+define nofpclass(snan) half @known__pzero_or_nan__fdiv__not_inf(half nofpclass(inf sub norm nzero) %pzero.or.nan, half nofpclass(inf) %not.inf) {
+; CHECK-LABEL: define nofpclass(snan) half @known__pzero_or_nan__fdiv__not_inf(
+; CHECK-SAME: half nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], half nofpclass(inf) [[NOT_INF:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[PZERO_OR_NAN]], [[NOT_INF]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %pzero.or.nan, %not.inf
+  ret half %div
+}
+
+; cannot replace with copysign
+define nofpclass(snan) half @known__not_inf__fdiv__pzero_or_nan(half nofpclass(inf) %not.inf, half nofpclass(inf sub norm nzero) %pzero.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @known__not_inf__fdiv__pzero_or_nan(
+; CHECK-SAME: half nofpclass(inf) [[NOT_INF:%.*]], half nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NOT_INF]], [[PZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %not.inf, %pzero.or.nan
+  ret half %div
+}
+
+; cannot replace with copysign
+define nofpclass(snan) half @known__pzero_or_nan__fdiv__not_nan(half nofpclass(inf sub norm nzero) %pzero.or.nan, half nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @known__pzero_or_nan__fdiv__not_nan(
+; CHECK-SAME: half nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], half nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv contract half [[PZERO_OR_NAN]], [[NOT_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv contract half %pzero.or.nan, %not.nan
+  ret half %div
+}
+
+; cannot replace with copysign
+define nofpclass(snan) half @known__not_nan__fdiv__pzero_or_nan(half nofpclass(nan) %not.nan, half nofpclass(inf sub norm nzero) %pzero.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @known__not_nan__fdiv__pzero_or_nan(
+; CHECK-SAME: half nofpclass(nan) [[NOT_NAN:%.*]], half nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv contract half [[NOT_NAN]], [[PZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv contract half %not.nan, %pzero.or.nan
+  ret half %div
+}
+
+; -> copysign, no infinity from return
+define nofpclass(inf) half @ret_noinf__pzero_or_nan__fdiv__not_inf_or_nan(half nofpclass(inf sub norm nzero) %pzero.or.nan, half nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_noinf__pzero_or_nan__fdiv__not_inf_or_nan(
+; CHECK-SAME: half nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], half nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[PZERO_OR_NAN]], [[NOT_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %pzero.or.nan, %not.nan
+  ret half %div
+}
+
+; -> copysign, no infinity from return
+define nofpclass(inf) half @ret_noinf__not_inf_or_nan__fdiv__pzero_or_nan(half nofpclass(nan) %not.nan, half nofpclass(inf sub norm nzero) %pzero.or.nan) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_noinf__not_inf_or_nan__fdiv__pzero_or_nan(
+; CHECK-SAME: half nofpclass(nan) [[NOT_NAN:%.*]], half nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[NOT_NAN]], [[PZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %not.nan, %pzero.or.nan
+  ret half %div
+}
+
+; -> copysign, no infinity from flag
+define nofpclass(snan) half @ret__pzero_or_nan__fdiv_ninf__not_inf_or_nan(half nofpclass(inf sub norm nzero) %pzero.or.nan, half nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @ret__pzero_or_nan__fdiv_ninf__not_inf_or_nan(
+; CHECK-SAME: half nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], half nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv ninf half [[PZERO_OR_NAN]], [[NOT_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv ninf half %pzero.or.nan, %not.nan
+  ret half %div
+}
+
+; -> copysign, no infinity from flag
+define nofpclass(snan) half @ret_not_inf_or_nan__fdiv_ninf__pzero_or_nan(half nofpclass(nan) %not.nan, half nofpclass(inf sub norm nzero) %pzero.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @ret_not_inf_or_nan__fdiv_ninf__pzero_or_nan(
+; CHECK-SAME: half nofpclass(nan) [[NOT_NAN:%.*]], half nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv ninf half [[NOT_NAN]], [[PZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv ninf half %not.nan, %pzero.or.nan
+  ret half %div
+}
+
+define nofpclass(nan inf norm sub) half @zero_result_demands_sub_source_lhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) half @zero_result_demands_sub_source_lhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[SUB:%.*]] = call half @returns_sub()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[SUB]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SELECT]], [[UNKNOWN1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %sub = call half @returns_sub()
+  %select = select i1 %cond, half %sub, half %unknown0
+  %div = fdiv half %select, %unknown1
+  ret half %div
+}
+
+define nofpclass(nan inf norm sub) half @zero_result_demands_sub_source_rhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) half @zero_result_demands_sub_source_rhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[SUB:%.*]] = call half @returns_sub()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[SUB]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN1]], [[SELECT]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %sub = call half @returns_sub()
+  %select = select i1 %cond, half %sub, half %unknown0
+  %div = fdiv half %unknown1, %select
+  ret half %div
+}
+
+define nofpclass(nan inf norm sub) half @zero_result_demands_norm_source_lhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) half @zero_result_demands_norm_source_lhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[NORM:%.*]] = call half @returns_norm()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[NORM]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SELECT]], [[UNKNOWN1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %norm = call half @returns_norm()
+  %select = select i1 %cond, half %norm, half %unknown0
+  %div = fdiv half %select, %unknown1
+  ret half %div
+}
+
+define nofpclass(nan inf norm sub) half @zero_result_demands_norm_source_rhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) half @zero_result_demands_norm_source_rhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[NORM:%.*]] = call half @returns_norm()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[NORM]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN1]], [[SELECT]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %norm = call half @returns_norm()
+  %select = select i1 %cond, half %norm, half %unknown0
+  %div = fdiv half %unknown1, %select
+  ret half %div
+}
+
+define nofpclass(nan inf norm zero) half @sub_result_demands_norm_source_lhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf zero norm) half @sub_result_demands_norm_source_lhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[NORM:%.*]] = call half @returns_norm()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[NORM]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SELECT]], [[UNKNOWN1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %norm = call half @returns_norm()
+  %select = select i1 %cond, half %norm, half %unknown0
+  %div = fdiv half %select, %unknown1
+  ret half %div
+}
+
+define nofpclass(nan inf norm zero) half @sub_result_demands_norm_source_rhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf zero norm) half @sub_result_demands_norm_source_rhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[NORM:%.*]] = call half @returns_norm()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[NORM]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN1]], [[SELECT]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %norm = call half @returns_norm()
+  %select = select i1 %cond, half %norm, half %unknown0
+  %div = fdiv half %unknown1, %select
+  ret half %div
+}
+
+define nofpclass(inf zero sub) half @nan_result_demands_zero_lhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(inf zero sub) half @nan_result_demands_zero_lhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ZERO:%.*]] = call half @returns_zero()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[ZERO]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SELECT]], [[UNKNOWN1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %zero = call half @returns_zero()
+  %select = select i1 %cond, half %zero, half %unknown0
+  %div = fdiv half %select, %unknown1
+  ret half %div
+}
+
+define nofpclass(inf zero sub) half @nan_result_demands_zero_rhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(inf zero sub) half @nan_result_demands_zero_rhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ZERO:%.*]] = call half @returns_zero()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[ZERO]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN1]], [[SELECT]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %zero = call half @returns_zero()
+  %select = select i1 %cond, half %zero, half %unknown0
+  %div = fdiv half %unknown1, %select
+  ret half %div
+}
+
+define nofpclass(inf zero sub) half @nan_result_demands_inf_lhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(inf zero sub) half @nan_result_demands_inf_lhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[INF:%.*]] = call half @returns_inf()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[INF]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SELECT]], [[UNKNOWN1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %inf = call half @returns_inf()
+  %select = select i1 %cond, half %inf, half %unknown0
+  %div = fdiv half %select, %unknown1
+  ret half %div
+}
+
+define nofpclass(inf zero sub) half @nan_result_demands_inf_rhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(inf zero sub) half @nan_result_demands_inf_rhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[INF:%.*]] = call half @returns_inf()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[INF]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN1]], [[SELECT]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %inf = call half @returns_inf()
+  %select = select i1 %cond, half %inf, half %unknown0
+  %div = fdiv half %unknown1, %select
+  ret half %div
+}
+
+define nofpclass(ninf nan zero sub) half @pinf_result_demands_zero_rhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan ninf zero sub) half @pinf_result_demands_zero_rhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ZERO:%.*]] = call half @returns_zero()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[ZERO]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN1]], [[SELECT]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %zero = call half @returns_zero()
+  %select = select i1 %cond, half %zero, half %unknown0
+  %div = fdiv half %unknown1, %select
+  ret half %div
+}
+
+define nofpclass(pinf nan zero sub) half @ninf_result_demands_zero_rhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan pinf zero sub) half @ninf_result_demands_zero_rhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ZERO:%.*]] = call half @returns_zero()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[ZERO]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN1]], [[SELECT]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %zero = call half @returns_zero()
+  %select = select i1 %cond, half %zero, half %unknown0
+  %div = fdiv half %unknown1, %select
+  ret half %div
+}
+
+define nofpclass(nan zero sub) half @inf_result_demands_zero_rhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan zero sub) half @inf_result_demands_zero_rhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[ZERO:%.*]] = call half @returns_zero()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[ZERO]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN1]], [[SELECT]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %zero = call half @returns_zero()
+  %select = select i1 %cond, half %zero, half %unknown0
+  %div = fdiv half %unknown1, %select
+  ret half %div
+}
+
+define nofpclass(inf nan zero nnorm) half @pnorm_result_demands_pnorm_lhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf zero nnorm) half @pnorm_result_demands_pnorm_lhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[PNORM:%.*]] = call half @returns_pnorm()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[PNORM]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SELECT]], [[UNKNOWN1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %pnorm = call half @returns_pnorm()
+  %select = select i1 %cond, half %pnorm, half %unknown0
+  %div = fdiv half %select, %unknown1
+  ret half %div
+}
+
+define nofpclass(inf nan zero nnorm) half @pnorm_result_demands_nnorm_lhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf zero nnorm) half @pnorm_result_demands_nnorm_lhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[NNORM:%.*]] = call half @returns_nnorm()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[NNORM]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SELECT]], [[UNKNOWN1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %nnorm = call half @returns_nnorm()
+  %select = select i1 %cond, half %nnorm, half %unknown0
+  %div = fdiv half %select, %unknown1
+  ret half %div
+}
+
+define nofpclass(inf nan zero nnorm) half @pnorm_result_demands_psub_lhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf zero nnorm) half @pnorm_result_demands_psub_lhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[PSUB:%.*]] = call half @returns_psub()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[PSUB]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SELECT]], [[UNKNOWN1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %psub = call half @returns_psub()
+  %select = select i1 %cond, half %psub, half %unknown0
+  %div = fdiv half %select, %unknown1
+  ret half %div
+}
+
+define nofpclass(inf nan zero nnorm) half @pnorm_result_demands_nsub_lhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf zero nnorm) half @pnorm_result_demands_nsub_lhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[NSUB:%.*]] = call half @returns_nsub()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[NSUB]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SELECT]], [[UNKNOWN1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %nsub = call half @returns_nsub()
+  %select = select i1 %cond, half %nsub, half %unknown0
+  %div = fdiv half %select, %unknown1
+  ret half %div
+}
+
+define nofpclass(inf nan zero nnorm) half @pnorm_result_demands_pnorm_rhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf zero nnorm) half @pnorm_result_demands_pnorm_rhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[PNORM:%.*]] = call half @returns_pnorm()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[PNORM]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN1]], [[SELECT]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %pnorm = call half @returns_pnorm()
+  %select = select i1 %cond, half %pnorm, half %unknown0
+  %div = fdiv half %unknown1, %select
+  ret half %div
+}
+
+define nofpclass(inf nan zero nnorm) half @pnorm_result_demands_nnorm_rhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf zero nnorm) half @pnorm_result_demands_nnorm_rhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[NNORM:%.*]] = call half @returns_nnorm()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[NNORM]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN1]], [[SELECT]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %nnorm = call half @returns_nnorm()
+  %select = select i1 %cond, half %nnorm, half %unknown0
+  %div = fdiv half %unknown1, %select
+  ret half %div
+}
+
+define nofpclass(inf nan zero nnorm) half @pnorm_result_demands_psub_rhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf zero nnorm) half @pnorm_result_demands_psub_rhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[PSUB:%.*]] = call half @returns_psub()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[PSUB]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN1]], [[SELECT]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %psub = call half @returns_psub()
+  %select = select i1 %cond, half %psub, half %unknown0
+  %div = fdiv half %unknown1, %select
+  ret half %div
+}
+
+define nofpclass(inf nan zero nnorm) half @pnorm_result_demands_nsub_rhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf zero nnorm) half @pnorm_result_demands_nsub_rhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[NSUB:%.*]] = call half @returns_nsub()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[NSUB]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN1]], [[SELECT]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %nsub = call half @returns_nsub()
+  %select = select i1 %cond, half %nsub, half %unknown0
+  %div = fdiv half %unknown1, %select
+  ret half %div
+}
+
+define nofpclass(inf nan zero pnorm) half @nnorm_result_demands_pnorm_lhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf zero pnorm) half @nnorm_result_demands_pnorm_lhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[PNORM:%.*]] = call half @returns_pnorm()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[PNORM]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SELECT]], [[UNKNOWN1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %pnorm = call half @returns_pnorm()
+  %select = select i1 %cond, half %pnorm, half %unknown0
+  %div = fdiv half %select, %unknown1
+  ret half %div
+}
+
+; Remove selects
+define nofpclass(inf zero norm) half @nan_result_no_demand_subnorm_sources_if_ieee(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(inf zero norm) half @nan_result_no_demand_subnorm_sources_if_ieee(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[SUB0:%.*]] = call half @returns_sub()
+; CHECK-NEXT:    [[SUB1:%.*]] = call half @returns_sub()
+; CHECK-NEXT:    [[SELECT0:%.*]] = select i1 [[COND]], half [[SUB0]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[SELECT1:%.*]] = select i1 [[COND]], half [[SUB1]], half [[UNKNOWN1]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SELECT0]], [[SELECT1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %sub0 = call half @returns_sub()
+  %sub1 = call half @returns_sub()
+  %select0 = select i1 %cond, half %sub0, half %unknown0
+  %select1 = select i1 %cond, half %sub1, half %unknown1
+  %div = fdiv half %select0, %select1
+  ret half %div
+}
+
+; Keep selects
+define nofpclass(inf zero norm) half @nan_result_demands_subnorm_sources_if_daz(i1 %cond, half %unknown0, half %unknown1) #2 {
+; CHECK-LABEL: define nofpclass(inf zero norm) half @nan_result_demands_subnorm_sources_if_daz(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[SUB0:%.*]] = call half @returns_sub()
+; CHECK-NEXT:    [[SUB1:%.*]] = call half @returns_sub()
+; CHECK-NEXT:    [[SELECT0:%.*]] = select i1 [[COND]], half [[SUB0]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[SELECT1:%.*]] = select i1 [[COND]], half [[SUB1]], half [[UNKNOWN1]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SELECT0]], [[SELECT1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %sub0 = call half @returns_sub()
+  %sub1 = call half @returns_sub()
+  %select0 = select i1 %cond, half %sub0, half %unknown0
+  %select1 = select i1 %cond, half %sub1, half %unknown1
+  %div = fdiv half %select0, %select1
+  ret half %div
+}
+
+; Keep selects
+define nofpclass(inf zero norm) half @nan_result_demands_subnorm_sources_if_dynamic_input(i1 %cond, half %unknown0, half %unknown1) #3 {
+; CHECK-LABEL: define nofpclass(inf zero norm) half @nan_result_demands_subnorm_sources_if_dynamic_input(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) #[[ATTR3:[0-9]+]] {
+; CHECK-NEXT:    [[SUB0:%.*]] = call half @returns_sub()
+; CHECK-NEXT:    [[SUB1:%.*]] = call half @returns_sub()
+; CHECK-NEXT:    [[SELECT0:%.*]] = select i1 [[COND]], half [[SUB0]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[SELECT1:%.*]] = select i1 [[COND]], half [[SUB1]], half [[UNKNOWN1]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SELECT0]], [[SELECT1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %sub0 = call half @returns_sub()
+  %sub1 = call half @returns_sub()
+  %select0 = select i1 %cond, half %sub0, half %unknown0
+  %select1 = select i1 %cond, half %sub1, half %unknown1
+  %div = fdiv half %select0, %select1
+  ret half %div
+}
+
+; Keep select
+define nofpclass(nan inf norm) half @zero_result_demand_inf_rhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf norm) half @zero_result_demand_inf_rhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[INF:%.*]] = call half @returns_inf()
+; CHECK-NEXT:    [[INF_OR_UNKNOWN:%.*]] = select i1 [[COND]], half [[INF]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN1]], [[INF_OR_UNKNOWN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %inf = call half @returns_inf()
+  %inf.or.unknown = select i1 %cond, half %inf, half %unknown0
+  %div = fdiv half %unknown1, %inf.or.unknown
+  ret half %div
+}
+
+; Eliminate select
+define nofpclass(nan inf norm) half @zero_result_no_demand_inf_lhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf norm) half @zero_result_no_demand_inf_lhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[INF:%.*]] = call half @returns_inf()
+; CHECK-NEXT:    [[INF_OR_UNKNOWN:%.*]] = select i1 [[COND]], half [[INF]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[INF_OR_UNKNOWN]], [[UNKNOWN1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %inf = call half @returns_inf()
+  %inf.or.unknown = select i1 %cond, half %inf, half %unknown0
+  %div = fdiv half %inf.or.unknown, %unknown1
+  ret half %div
+}
+
+define nofpclass(nan inf sub zero) half @norm_result_demands_sub_source_lhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf zero sub) half @norm_result_demands_sub_source_lhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[SUB:%.*]] = call half @returns_sub()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[SUB]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SELECT]], [[UNKNOWN1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %sub = call half @returns_sub()
+  %select = select i1 %cond, half %sub, half %unknown0
+  %div = fdiv half %select, %unknown1
+  ret half %div
+}
+
+define nofpclass(nan inf sub zero) half @norm_result_demands_sub_source_rhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf zero sub) half @norm_result_demands_sub_source_rhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[SUB:%.*]] = call half @returns_sub()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[SUB]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN1]], [[SELECT]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %sub = call half @returns_sub()
+  %select = select i1 %cond, half %sub, half %unknown0
+  %div = fdiv half %unknown1, %select
+  ret half %div
+}
+
+define nofpclass(inf nan norm zero) half @sub_result_demands_sub_lhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf zero norm) half @sub_result_demands_sub_lhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[SUB:%.*]] = call half @returns_sub()
+; CHECK-NEXT:    [[SUB_OR_UNKNOWN:%.*]] = select i1 [[COND]], half [[SUB]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SUB_OR_UNKNOWN]], [[UNKNOWN1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %sub = call half @returns_sub()
+  %sub.or.unknown = select i1 %cond, half %sub, half %unknown0
+  %div = fdiv half %sub.or.unknown, %unknown1
+  ret half %div
+}
+
+define nofpclass(inf nan norm zero) half @sub_result_demands_sub_rhs(i1 %cond, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(nan inf zero norm) half @sub_result_demands_sub_rhs(
+; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[SUB:%.*]] = call half @returns_sub()
+; CHECK-NEXT:    [[SUB_OR_UNKNOWN:%.*]] = select i1 [[COND]], half [[SUB]], half [[UNKNOWN0]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN1]], [[SUB_OR_UNKNOWN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %sub = call half @returns_sub()
+  %sub.or.unknown = select i1 %cond, half %sub, half %unknown0
+  %div = fdiv half %unknown1, %sub.or.unknown
+  ret half %div
+}
+
+define nofpclass(snan) half @ret__known_zero_or_nan__fdiv__not_nan(half nofpclass(inf sub norm) %zero.or.nan, half nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @ret__known_zero_or_nan__fdiv__not_nan(
+; CHECK-SAME: half nofpclass(inf sub norm) [[ZERO_OR_NAN:%.*]], half nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[ZERO_OR_NAN]], [[NOT_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %zero.or.nan, %not.nan
+  ret half %div
+}
+
+define nofpclass(snan) half @ret__known_zero_or_nan__fdiv_nsz__not_nan(half nofpclass(inf sub norm) %zero.or.nan, half nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @ret__known_zero_or_nan__fdiv_nsz__not_nan(
+; CHECK-SAME: half nofpclass(inf sub norm) [[ZERO_OR_NAN:%.*]], half nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz contract half [[ZERO_OR_NAN]], [[NOT_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv nsz contract half %zero.or.nan, %not.nan
+  ret half %div
+}
+
+define nofpclass(snan) <2 x half> @ret__known_zero_or_nan__fdiv_nsz__not_nan_vec(<2 x half> nofpclass(inf sub norm) %zero.or.nan, <2 x half> nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(snan) <2 x half> @ret__known_zero_or_nan__fdiv_nsz__not_nan_vec(
+; CHECK-SAME: <2 x half> nofpclass(inf sub norm) [[ZERO_OR_NAN:%.*]], <2 x half> nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz contract <2 x half> [[ZERO_OR_NAN]], [[NOT_NAN]]
+; CHECK-NEXT:    ret <2 x half> [[DIV]]
+;
+  %div = fdiv nsz contract <2 x half> %zero.or.nan, %not.nan
+  ret <2 x half> %div
+}
+
+define nofpclass(nan) half @ret_nonan__known_zero_or_nan__fdiv__unknown(half nofpclass(inf sub norm) %zero.or.nan, half %unknown) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__known_zero_or_nan__fdiv__unknown(
+; CHECK-SAME: half nofpclass(inf sub norm) [[ZERO_OR_NAN:%.*]], half [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[ZERO_OR_NAN]], [[UNKNOWN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %zero.or.nan, %unknown
+  ret half %div
+}
+
+define nofpclass(nan) half @ret_nonan__zero_or_nan__fdiv_nsz__unknown(half nofpclass(inf sub norm) %zero.or.nan, half %unknown) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__zero_or_nan__fdiv_nsz__unknown(
+; CHECK-SAME: half nofpclass(inf sub norm) [[ZERO_OR_NAN:%.*]], half [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz contract half [[ZERO_OR_NAN]], [[UNKNOWN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv nsz contract half %zero.or.nan, %unknown
+  ret half %div
+}
+
+
+define nofpclass(snan) half @ret__unknown__fdiv__zero_or_nan(half %unknown, half nofpclass(inf sub norm) %zero.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @ret__unknown__fdiv__zero_or_nan(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(inf sub norm) [[ZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN]], [[ZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %unknown, %zero.or.nan
+  ret half %div
+}
+
+define nofpclass(snan) half @ret__unknown__fdiv_nsz__zero_or_nan(half %unknown, half nofpclass(inf sub norm) %zero.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @ret__unknown__fdiv_nsz__zero_or_nan(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(inf sub norm) [[ZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz contract half [[UNKNOWN]], [[ZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv nsz contract half %unknown, %zero.or.nan
+  ret half %div
+}
+
+define nofpclass(snan) half @ret__unknown__fdiv__pzero_or_nan(half %unknown, half nofpclass(inf sub norm nzero) %pzero.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @ret__unknown__fdiv__pzero_or_nan(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN]], [[PZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %unknown, %pzero.or.nan
+  ret half %div
+}
+
+define nofpclass(snan) half @ret__unknown__fdiv_nsz__pzero_or_nan(half %unknown, half nofpclass(inf sub norm nzero) %pzero.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @ret__unknown__fdiv_nsz__pzero_or_nan(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz contract half [[UNKNOWN]], [[PZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv nsz contract half %unknown, %pzero.or.nan
+  ret half %div
+}
+
+define nofpclass(snan) half @ret__unknown__fdiv__nzero_or_nan(half %unknown, half nofpclass(inf sub norm pzero) %nzero.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @ret__unknown__fdiv__nzero_or_nan(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN]], [[NZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %unknown, %nzero.or.nan
+  ret half %div
+}
+
+define nofpclass(snan) half @ret__unknown__fdiv_nsz__nzero_or_nan(half %unknown, half nofpclass(inf sub norm pzero) %nzero.or.nan) {
+; CHECK-LABEL: define nofpclass(snan) half @ret__unknown__fdiv_nsz__nzero_or_nan(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz contract half [[UNKNOWN]], [[NZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv contract nsz half %unknown, %nzero.or.nan
+  ret half %div
+}
+
+
+define nofpclass(snan) half @ret__unknown__fdiv__zero(half %unknown, half nofpclass(nan inf sub norm) %zero) {
+; CHECK-LABEL: define nofpclass(snan) half @ret__unknown__fdiv__zero(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(nan inf sub norm) [[ZERO:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN]], [[ZERO]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %unknown, %zero
+  ret half %div
+}
+
+define nofpclass(snan) half @ret__unknown__fdiv_nsz__zero(half %unknown, half nofpclass(nan inf sub norm) %zero) {
+; CHECK-LABEL: define nofpclass(snan) half @ret__unknown__fdiv_nsz__zero(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(nan inf sub norm) [[ZERO:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz contract half [[UNKNOWN]], [[ZERO]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv nsz contract half %unknown, %zero
+  ret half %div
+}
+
+define nofpclass(snan) half @ret__unknown__fdiv__pzero(half %unknown, half nofpclass(inf nan sub norm nzero) %pzero) {
+; CHECK-LABEL: define nofpclass(snan) half @ret__unknown__fdiv__pzero(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(nan inf nzero sub norm) [[PZERO:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN]], [[PZERO]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %unknown, %pzero
+  ret half %div
+}
+
+define nofpclass(snan) half @ret__unknown__fdiv_nsz__pzero(half %unknown, half nofpclass(nan inf sub norm nzero) %pzero) {
+; CHECK-LABEL: define nofpclass(snan) half @ret__unknown__fdiv_nsz__pzero(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(nan inf nzero sub norm) [[PZERO:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz contract half [[UNKNOWN]], [[PZERO]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv nsz contract half %unknown, %pzero
+  ret half %div
+}
+
+define nofpclass(snan) half @ret__unknown__fdiv__nzero(half %unknown, half nofpclass(nan inf sub norm pzero) %nzero) {
+; CHECK-LABEL: define nofpclass(snan) half @ret__unknown__fdiv__nzero(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(nan inf pzero sub norm) [[NZERO:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN]], [[NZERO]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %unknown, %nzero
+  ret half %div
+}
+
+define nofpclass(snan) half @ret__unknown__fdiv_nsz__nzero(half %unknown, half nofpclass(nan inf sub norm pzero) %nzero) {
+; CHECK-LABEL: define nofpclass(snan) half @ret__unknown__fdiv_nsz__nzero(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(nan inf pzero sub norm) [[NZERO:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz contract half [[UNKNOWN]], [[NZERO]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv nsz contract half %unknown, %nzero
+  ret half %div
+}
+
+define nofpclass(nan) half @ret_nonan__unknown__fdiv__zero(half %unknown, half nofpclass(nan inf sub norm) %zero) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fdiv__zero(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(nan inf sub norm) [[ZERO:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN]], [[ZERO]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %unknown, %zero
+  ret half %div
+}
+
+define nofpclass(nan) half @ret_nonan__unknown__fdiv_nsz__zero(half %unknown, half nofpclass(nan inf sub norm) %zero) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fdiv_nsz__zero(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(nan inf sub norm) [[ZERO:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz contract half [[UNKNOWN]], [[ZERO]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv nsz contract half %unknown, %zero
+  ret half %div
+}
+
+define nofpclass(nan) half @ret_nonan__unknown__fdiv__pzero(half %unknown, half nofpclass(inf nan sub norm nzero) %pzero) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fdiv__pzero(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(nan inf nzero sub norm) [[PZERO:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN]], [[PZERO]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %unknown, %pzero
+  ret half %div
+}
+
+define nofpclass(nan) half @ret_nonan__unknown__fdiv_nsz__pzero(half %unknown, half nofpclass(nan inf sub norm nzero) %pzero) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fdiv_nsz__pzero(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(nan inf nzero sub norm) [[PZERO:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz contract half [[UNKNOWN]], [[PZERO]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv nsz contract half %unknown, %pzero
+  ret half %div
+}
+
+define nofpclass(nan) half @ret_nonan__unknown__fdiv__nzero(half %unknown, half nofpclass(nan inf sub norm pzero) %nzero) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fdiv__nzero(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(nan inf pzero sub norm) [[NZERO:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN]], [[NZERO]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %unknown, %nzero
+  ret half %div
+}
+
+define nofpclass(nan) half @ret_nonan__unknown__fdiv_nsz__nzero(half %unknown, half nofpclass(nan inf sub norm pzero) %nzero) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fdiv_nsz__nzero(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(nan inf pzero sub norm) [[NZERO:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz contract half [[UNKNOWN]], [[NZERO]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv nsz contract half %unknown, %nzero
+  ret half %div
+}
+
+define nofpclass(snan) half @ret__not_nan__fdiv_nsz__zero(half nofpclass(nan) %not.nan, half nofpclass(nan inf sub norm) %zero) {
+; CHECK-LABEL: define nofpclass(snan) half @ret__not_nan__fdiv_nsz__zero(
+; CHECK-SAME: half nofpclass(nan) [[NOT_NAN:%.*]], half nofpclass(nan inf sub norm) [[ZERO:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz contract half [[NOT_NAN]], [[ZERO]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv nsz contract half %not.nan, %zero
+  ret half %div
+}
+
+define nofpclass(snan) half @ret__not_nan_not_zero__fdiv_nsz__zero(half nofpclass(nan zero) %not.nan.or.zero, half nofpclass(nan inf sub norm) %zero) {
+; CHECK-LABEL: define nofpclass(snan) half @ret__not_nan_not_zero__fdiv_nsz__zero(
+; CHECK-SAME: half nofpclass(nan zero) [[NOT_NAN_OR_ZERO:%.*]], half nofpclass(nan inf sub norm) [[ZERO:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz contract half [[NOT_NAN_OR_ZERO]], [[ZERO]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv nsz contract half %not.nan.or.zero, %zero
+  ret half %div
+}
+
+define nofpclass(snan) half @ret__not_nan_not_zero__fdiv_nsz__zero__daz(half nofpclass(nan zero) %not.nan.or.zero, half nofpclass(nan inf sub norm) %zero) #2 {
+; CHECK-LABEL: define nofpclass(snan) half @ret__not_nan_not_zero__fdiv_nsz__zero__daz(
+; CHECK-SAME: half nofpclass(nan zero) [[NOT_NAN_OR_ZERO:%.*]], half nofpclass(nan inf sub norm) [[ZERO:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz contract half [[NOT_NAN_OR_ZERO]], [[ZERO]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv nsz contract half %not.nan.or.zero, %zero
+  ret half %div
+}
+
+define nofpclass(snan) half @ret__not_nan_not_zero__fdiv_nsz__zero__dynamic(half nofpclass(nan zero) %not.nan.or.zero.or.sub, half nofpclass(nan inf sub norm) %zero) #3 {
+; CHECK-LABEL: define nofpclass(snan) half @ret__not_nan_not_zero__fdiv_nsz__zero__dynamic(
+; CHECK-SAME: half nofpclass(nan zero) [[NOT_NAN_OR_ZERO_OR_SUB:%.*]], half nofpclass(nan inf sub norm) [[ZERO:%.*]]) #[[ATTR3]] {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz contract half [[NOT_NAN_OR_ZERO_OR_SUB]], [[ZERO]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv nsz contract half %not.nan.or.zero.or.sub, %zero
+  ret half %div
+}
+
+define nofpclass(snan) half @ret__not_nan_not_zero_not_sub__fdiv_nsz__zero__daz(half nofpclass(nan zero sub) %not.nan.or.zero.or.sub, half nofpclass(nan inf sub norm) %zero) #2 {
+; CHECK-LABEL: define nofpclass(snan) half @ret__not_nan_not_zero_not_sub__fdiv_nsz__zero__daz(
+; CHECK-SAME: half nofpclass(nan zero sub) [[NOT_NAN_OR_ZERO_OR_SUB:%.*]], half nofpclass(nan inf sub norm) [[ZERO:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz contract half [[NOT_NAN_OR_ZERO_OR_SUB]], [[ZERO]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv nsz contract half %not.nan.or.zero.or.sub, %zero
+  ret half %div
+}
+
+define nofpclass(snan) half @ret__not_nan_not_zero_not_sub__fdiv_nsz__zero__dynamic(half nofpclass(nan zero sub) %not.nan.or.zero.or.sub, half nofpclass(nan inf sub norm) %zero) #3 {
+; CHECK-LABEL: define nofpclass(snan) half @ret__not_nan_not_zero_not_sub__fdiv_nsz__zero__dynamic(
+; CHECK-SAME: half nofpclass(nan zero sub) [[NOT_NAN_OR_ZERO_OR_SUB:%.*]], half nofpclass(nan inf sub norm) [[ZERO:%.*]]) #[[ATTR3]] {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv nsz contract half [[NOT_NAN_OR_ZERO_OR_SUB]], [[ZERO]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv nsz contract half %not.nan.or.zero.or.sub, %zero
+  ret half %div
+}
+
+; -> poison
+define nofpclass(nan inf) half @ret_nonan_noinf__unknown__fdiv__zero_or_nan(half %unknown, half nofpclass(inf sub norm) %zero.or.nan) {
+; CHECK-LABEL: define nofpclass(nan inf) half @ret_nonan_noinf__unknown__fdiv__zero_or_nan(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(inf sub norm) [[ZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN]], [[ZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %unknown, %zero.or.nan
+  ret half %div
+}
+
+define nofpclass(nan) half @ret_nonan__unknown__fdiv__zero_or_nan(half %unknown, half nofpclass(inf sub norm) %zero.or.nan) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fdiv__zero_or_nan(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(inf sub norm) [[ZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN]], [[ZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %unknown, %zero.or.nan
+  ret half %div
+}
+
+define nofpclass(inf) half @ret_noinf__unknown__fdiv__zero_or_nan(half %unknown, half nofpclass(inf sub norm) %zero.or.nan) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_noinf__unknown__fdiv__zero_or_nan(
+; CHECK-SAME: half [[UNKNOWN:%.*]], half nofpclass(inf sub norm) [[ZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN]], [[ZERO_OR_NAN]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %div = fdiv half %unknown, %zero.or.nan
+  ret half %div
+}
+
+define nofpclass(nan inf norm sub) half @zero_result_demands_subnorm_lhs__daz(i1 %cond, half nofpclass(nan inf zero norm) %only.sub, half %unknown0, half %unknown1) #0 {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) half @zero_result_demands_subnorm_lhs__daz(
+; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(nan inf zero norm) [[ONLY_SUB:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN0]], half [[ONLY_SUB]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SELECT]], [[UNKNOWN1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %select = select i1 %cond, half %unknown0, half %only.sub
+  %div = fdiv half %select, %unknown1
+  ret half %div
+}
+
+define nofpclass(inf norm sub zero) half @nan_result_demands_subnorm_lhs__ieee(i1 %cond, half nofpclass(nan inf zero norm) %only.sub, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(inf zero sub norm) half @nan_result_demands_subnorm_lhs__ieee(
+; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(nan inf zero norm) [[ONLY_SUB:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN0]], half [[ONLY_SUB]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SELECT]], [[UNKNOWN1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %select = select i1 %cond, half %unknown0, half %only.sub
+  %div = fdiv half %select, %unknown1
+  ret half %div
+}
+
+define nofpclass(inf norm sub zero) half @nan_result_demands_subnorm_rhs__ieee(i1 %cond, half nofpclass(nan inf zero norm) %only.sub, half %unknown0, half %unknown1) {
+; CHECK-LABEL: define nofpclass(inf zero sub norm) half @nan_result_demands_subnorm_rhs__ieee(
+; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(nan inf zero norm) [[ONLY_SUB:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN0]], half [[ONLY_SUB]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN1]], [[SELECT]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %select = select i1 %cond, half %unknown0, half %only.sub
+  %div = fdiv half %unknown1, %select
+  ret half %div
+}
+
+define nofpclass(inf norm sub zero) half @nan_result_demands_subnorm_lhs__daz(i1 %cond, half nofpclass(nan inf zero norm) %only.sub, half %unknown0, half %unknown1) #2 {
+; CHECK-LABEL: define nofpclass(inf zero sub norm) half @nan_result_demands_subnorm_lhs__daz(
+; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(nan inf zero norm) [[ONLY_SUB:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN0]], half [[ONLY_SUB]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SELECT]], [[UNKNOWN1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %select = select i1 %cond, half %unknown0, half %only.sub
+  %div = fdiv half %select, %unknown1
+  ret half %div
+}
+
+define nofpclass(inf norm sub zero) half @nan_result_demands_subnorm_rhs__daz(i1 %cond, half nofpclass(nan inf zero norm) %only.sub, half %unknown0, half %unknown1) #2 {
+; CHECK-LABEL: define nofpclass(inf zero sub norm) half @nan_result_demands_subnorm_rhs__daz(
+; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(nan inf zero norm) [[ONLY_SUB:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN0]], half [[ONLY_SUB]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN1]], [[SELECT]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %select = select i1 %cond, half %unknown0, half %only.sub
+  %div = fdiv half %unknown1, %select
+  ret half %div
+}
+
+define nofpclass(inf norm sub zero) half @nan_result_demands_subnorm_lhs__dynamic(i1 %cond, half nofpclass(nan inf zero norm) %only.sub, half %unknown0, half %unknown1) #3 {
+; CHECK-LABEL: define nofpclass(inf zero sub norm) half @nan_result_demands_subnorm_lhs__dynamic(
+; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(nan inf zero norm) [[ONLY_SUB:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) #[[ATTR3]] {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN0]], half [[ONLY_SUB]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[SELECT]], [[UNKNOWN1]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %select = select i1 %cond, half %unknown0, half %only.sub
+  %div = fdiv half %select, %unknown1
+  ret half %div
+}
+
+define nofpclass(inf norm sub zero) half @nan_result_demands_subnorm_rhs__dynamic(i1 %cond, half nofpclass(nan inf zero norm) %only.sub, half %unknown0, half %unknown1) #3 {
+; CHECK-LABEL: define nofpclass(inf zero sub norm) half @nan_result_demands_subnorm_rhs__dynamic(
+; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(nan inf zero norm) [[ONLY_SUB:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) #[[ATTR3]] {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN0]], half [[ONLY_SUB]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv half [[UNKNOWN1]], [[SELECT]]
+; CHECK-NEXT:    ret half [[DIV]]
+;
+  %select = select i1 %cond, half %unknown0, half %only.sub
+  %div = fdiv half %unknown1, %select
+  ret half %div
+}
+
+attributes #0 = { "denormal-fp-math"="preserve-sign,preserve-sign" }
+attributes #1 = { "denormal-fp-math"="dynamic,dynamic" }
+attributes #2 = { "denormal-fp-math"="ieee,preserve-sign" }
+attributes #3 = { "denormal-fp-math"="ieee,dynamic" }



More information about the llvm-commits mailing list