[llvm-branch-commits] [llvm] ValueTracking: Add more baseline tests for fdiv sign tracking (PR #174651)

Matt Arsenault via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Jan 6 13:26:56 PST 2026


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

This is the fmul version of 08b1403228953866cb052a3fdb34719a7f4e87e2

>From 059276fadcc53eb266c4916292d48039c1e49d1b Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Mon, 5 Jan 2026 23:31:10 +0100
Subject: [PATCH] ValueTracking: Add more baseline tests for fdiv sign tracking

This is the fmul version of 08b1403228953866cb052a3fdb34719a7f4e87e2
---
 .../Transforms/Attributor/nofpclass-fdiv.ll   | 581 ++++++++++++++++++
 .../Transforms/Attributor/nofpclass-frem.ll   | 549 +++++++++++++++++
 2 files changed, 1130 insertions(+)

diff --git a/llvm/test/Transforms/Attributor/nofpclass-fdiv.ll b/llvm/test/Transforms/Attributor/nofpclass-fdiv.ll
index b533c5a0cd2da..228be4ae748fa 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-fdiv.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-fdiv.ll
@@ -405,6 +405,79 @@ define float @ret_fdiv_same_operands_nonan(float noundef nofpclass(nan) %arg) #0
   ret float %fdiv
 }
 
+define float @ret_fdiv_same_operands_nonan_noinf(float noundef nofpclass(nan inf) %arg) #0 {
+; CHECK-LABEL: define noundef nofpclass(inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_noinf
+; CHECK-SAME: (float noundef nofpclass(nan inf) [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG]], [[ARG]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg, %arg
+  ret float %fdiv
+}
+
+define float @ret_fdiv_same_operands_nonan_nozero(float noundef nofpclass(nan zero) %arg) #0 {
+; CHECK-LABEL: define noundef nofpclass(inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_nozero
+; CHECK-SAME: (float noundef nofpclass(nan zero) [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG]], [[ARG]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg, %arg
+  ret float %fdiv
+}
+
+define float @ret_fdiv_same_operands_nonan_noinf_nozero(float noundef nofpclass(nan inf zero) %arg) #0 {
+; CHECK-LABEL: define noundef nofpclass(inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_noinf_nozero
+; CHECK-SAME: (float noundef nofpclass(nan inf zero) [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG]], [[ARG]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg, %arg
+  ret float %fdiv
+}
+
+define float @ret_fdiv_same_operands_nonan_noinf_nozero_nosub(float noundef nofpclass(nan inf zero) %arg) #0 {
+; CHECK-LABEL: define noundef nofpclass(inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_noinf_nozero_nosub
+; CHECK-SAME: (float noundef nofpclass(nan inf zero) [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG]], [[ARG]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg, %arg
+  ret float %fdiv
+}
+
+; May be nan if denormal is flushed
+define float @ret_fdiv_same_operands_nonan_noinf_nozero__daz(float noundef nofpclass(nan inf zero) %arg) #1 {
+; CHECK-LABEL: define noundef nofpclass(inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_noinf_nozero__daz
+; CHECK-SAME: (float noundef nofpclass(nan inf zero) [[ARG:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG]], [[ARG]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg, %arg
+  ret float %fdiv
+}
+
+; Can't have a flushed input
+define float @ret_fdiv_same_operands_nonan_noinf_nozero_nosub__daz(float noundef nofpclass(nan inf sub zero) %arg) #1 {
+; CHECK-LABEL: define noundef nofpclass(inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_noinf_nozero_nosub__daz
+; CHECK-SAME: (float noundef nofpclass(nan inf zero sub) [[ARG:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG]], [[ARG]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg, %arg
+  ret float %fdiv
+}
+
+; Can't have a flushed input
+define float @ret_fdiv_same_operands_nonan_noinf_nozero_nosub__dynamic(float noundef nofpclass(nan inf sub zero) %arg) #3 {
+; CHECK-LABEL: define noundef nofpclass(inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_noinf_nozero_nosub__dynamic
+; CHECK-SAME: (float noundef nofpclass(nan inf zero sub) [[ARG:%.*]]) #[[ATTR3]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG]], [[ARG]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg, %arg
+  ret float %fdiv
+}
+
 define float @ret_fdiv_no_neg_lhs(float nofpclass(ninf nsub nnorm) %arg0, float %arg1) #0 {
 ; CHECK-LABEL: define float @ret_fdiv_no_neg_lhs
 ; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR0]] {
@@ -475,6 +548,514 @@ define float @ret_fdiv_no_neg_no_zero_rhs(float nofpclass(ninf nsub nnorm nzero)
   ret float %fdiv
 }
 
+define float @ret_fdiv_no_pos_lhs(float nofpclass(pinf psub pnorm) %arg0, float %arg1) #0 {
+; CHECK-LABEL: define float @ret_fdiv_no_pos_lhs
+; CHECK-SAME: (float nofpclass(pinf psub pnorm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_no_pos_rhs(float %arg0, float nofpclass(pinf psub pnorm) %arg1) #0 {
+; CHECK-LABEL: define float @ret_fdiv_no_pos_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(pinf psub pnorm) [[ARG1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_no_pos(float nofpclass(pinf psub pnorm) %arg0, float nofpclass(pinf psub pnorm) %arg1) #0 {
+; CHECK-LABEL: define float @ret_fdiv_no_pos
+; CHECK-SAME: (float nofpclass(pinf psub pnorm) [[ARG0:%.*]], float nofpclass(pinf psub pnorm) [[ARG1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_zero_or_nan_lhs(float nofpclass(inf norm sub) %arg0, float %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_zero_or_nan_lhs
+; CHECK-SAME: (float nofpclass(inf sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4:[0-9]+]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_zero_or_nan_rhs(float %arg0, float nofpclass(inf norm sub) %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_zero_or_nan_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_zero_lhs(float nofpclass(nan inf norm sub) %arg0, float %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_zero_lhs
+; CHECK-SAME: (float nofpclass(nan inf sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_zero_rhs(float %arg0, float nofpclass(nan inf norm sub) %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_zero_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(nan inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_pzero_or_nan_lhs(float nofpclass(inf norm sub nzero) %arg0, float %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_pzero_or_nan_lhs
+; CHECK-SAME: (float nofpclass(inf nzero sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_pzero_or_nan_rhs(float %arg0, float nofpclass(inf norm sub nzero) %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_pzero_or_nan_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(inf nzero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_pzero_lhs(float nofpclass(nan inf norm sub nzero) %arg0, float %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_pzero_lhs
+; CHECK-SAME: (float nofpclass(nan inf nzero sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_pzero_rhs(float %arg0, float nofpclass(nan inf norm sub nzero) %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_pzero_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(nan inf nzero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_nzero_or_nan_lhs(float nofpclass(inf norm sub pzero) %arg0, float %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_nzero_or_nan_lhs
+; CHECK-SAME: (float nofpclass(inf pzero sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_nzero_or_nan_rhs(float %arg0, float nofpclass(inf norm sub pzero) %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_nzero_or_nan_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(inf pzero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_nzero_lhs(float nofpclass(nan inf norm sub pzero) %arg0, float %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_nzero_lhs
+; CHECK-SAME: (float nofpclass(nan inf pzero sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_nzero_rhs(float %arg0, float nofpclass(nan inf norm sub pzero) %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_nzero_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(nan inf pzero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_inf_or_nan_lhs(float nofpclass(zero norm sub) %arg0, float %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_inf_or_nan_lhs
+; CHECK-SAME: (float nofpclass(zero sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_inf_or_nan_rhs(float %arg0, float nofpclass(zero norm sub) %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_inf_or_nan_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_inf_lhs(float nofpclass(nan zero norm sub) %arg0, float %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_inf_lhs
+; CHECK-SAME: (float nofpclass(nan zero sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_inf_rhs(float %arg0, float nofpclass(nan zero norm sub) %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_inf_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(nan zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_pinf_or_nan_lhs(float nofpclass(ninf zero norm sub) %arg0, float %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_pinf_or_nan_lhs
+; CHECK-SAME: (float nofpclass(ninf zero sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_pinf_or_nan_rhs(float %arg0, float nofpclass(ninf zero norm sub) %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_pinf_or_nan_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(ninf zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_ninf_or_nan_lhs(float nofpclass(pinf zero norm sub) %arg0, float %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_ninf_or_nan_lhs
+; CHECK-SAME: (float nofpclass(pinf zero sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_fdiv_f32_known_ninf_or_nan_rhs(float %arg0, float nofpclass(pinf zero norm sub) %arg1) {
+; CHECK-LABEL: define float @ret_fdiv_f32_known_ninf_or_nan_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(pinf zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+; -> nan
+define float @ret_known_inf_fdiv_known_zero(float nofpclass(nan norm sub zero) %arg0, float nofpclass(nan inf norm sub) %arg1) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_known_inf_fdiv_known_zero
+; CHECK-SAME: (float nofpclass(nan zero sub norm) [[ARG0:%.*]], float nofpclass(nan inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+; -> nan
+define float @ret_known_inf_or_nan_fdiv_known_zero(float nofpclass(norm sub zero) %arg0, float nofpclass(nan inf norm sub) %arg1) {
+; CHECK-LABEL: define float @ret_known_inf_or_nan_fdiv_known_zero
+; CHECK-SAME: (float nofpclass(zero sub norm) [[ARG0:%.*]], float nofpclass(nan inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+; -> nan
+define float @ret_known_inf_fdiv_known_zero_or_nan(float nofpclass(nan norm sub zero) %arg0, float nofpclass(inf norm sub) %arg1) {
+; CHECK-LABEL: define float @ret_known_inf_fdiv_known_zero_or_nan
+; CHECK-SAME: (float nofpclass(nan zero sub norm) [[ARG0:%.*]], float nofpclass(inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+; -> nan
+define float @ret_known_ninf_fdiv_known_zero(float nofpclass(nan pinf norm sub zero) %arg0, float nofpclass(nan inf norm sub) %arg1) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_known_ninf_fdiv_known_zero
+; CHECK-SAME: (float nofpclass(nan pinf zero sub norm) [[ARG0:%.*]], float nofpclass(nan inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+; -> nan
+define float @ret_known_pinf_fdiv_known_zero(float nofpclass(nan ninf norm sub zero) %arg0, float nofpclass(nan inf norm sub) %arg1) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_known_pinf_fdiv_known_zero
+; CHECK-SAME: (float nofpclass(nan ninf zero sub norm) [[ARG0:%.*]], float nofpclass(nan inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+; -> nan
+define float @ret_known_zero_fdiv_known_inf(float nofpclass(nan inf norm sub) %arg0, float nofpclass(nan norm sub zero) %arg1) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_known_zero_fdiv_known_inf
+; CHECK-SAME: (float nofpclass(nan inf sub norm) [[ARG0:%.*]], float nofpclass(nan zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+; -> nan
+define float @ret_known_zero_fdiv_known_inf_or_nan(float nofpclass(nan inf norm sub) %arg0, float nofpclass(norm sub zero) %arg1) {
+; CHECK-LABEL: define float @ret_known_zero_fdiv_known_inf_or_nan
+; CHECK-SAME: (float nofpclass(nan inf sub norm) [[ARG0:%.*]], float nofpclass(zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+; -> nan
+define float @ret_known_zero_or_nan_fdiv_known_inf(float nofpclass(inf norm sub) %arg0, float nofpclass(nan norm sub zero) %arg1) {
+; CHECK-LABEL: define float @ret_known_zero_or_nan_fdiv_known_inf
+; CHECK-SAME: (float nofpclass(inf sub norm) [[ARG0:%.*]], float nofpclass(nan zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+; Know nothing
+define float @ret_fdiv_lhs_known_positive_or_nan(float %lhs, float %rhs) {
+; CHECK-LABEL: define float @ret_fdiv_lhs_known_positive_or_nan
+; CHECK-SAME: (float [[LHS:%.*]], float [[RHS:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[LHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[LHS]]) #[[ATTR6:[0-9]+]]
+; CHECK-NEXT:    [[MUL:%.*]] = fdiv float [[LHS_FABS]], [[RHS]]
+; CHECK-NEXT:    ret float [[MUL]]
+;
+  %lhs.fabs = call float @llvm.fabs.f32(float %lhs)
+  %mul = fdiv float %lhs.fabs, %rhs
+  ret float %mul
+}
+
+; Know nothing
+define float @ret_fdiv_rhs_known_positive_or_nan(float %lhs, float %rhs) {
+; CHECK-LABEL: define float @ret_fdiv_rhs_known_positive_or_nan
+; CHECK-SAME: (float [[LHS:%.*]], float [[RHS:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[RHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[RHS]]) #[[ATTR6]]
+; CHECK-NEXT:    [[MUL:%.*]] = fdiv float [[LHS]], [[RHS_FABS]]
+; CHECK-NEXT:    ret float [[MUL]]
+;
+  %rhs.fabs = call float @llvm.fabs.f32(float %rhs)
+  %mul = fdiv float %lhs, %rhs.fabs
+  ret float %mul
+}
+
+; Result must be positive or nan
+define float @ret_fdiv_both_signs_positive_or_nan(float %lhs, float %rhs) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_fdiv_both_signs_positive_or_nan
+; CHECK-SAME: (float [[LHS:%.*]], float [[RHS:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[LHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[LHS]]) #[[ATTR6]]
+; CHECK-NEXT:    [[RHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[RHS]]) #[[ATTR6]]
+; CHECK-NEXT:    [[MUL:%.*]] = fdiv float [[LHS_FABS]], [[RHS_FABS]]
+; CHECK-NEXT:    ret float [[MUL]]
+;
+  %lhs.fabs = call float @llvm.fabs.f32(float %lhs)
+  %rhs.fabs = call float @llvm.fabs.f32(float %rhs)
+  %mul = fdiv float %lhs.fabs, %rhs.fabs
+  ret float %mul
+}
+
+; Result must be positive or nan
+define float @ret_fdiv_both_signs_negative_or_nan(float %lhs, float %rhs) {
+; CHECK-LABEL: define float @ret_fdiv_both_signs_negative_or_nan
+; CHECK-SAME: (float [[LHS:%.*]], float [[RHS:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[LHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[LHS]]) #[[ATTR6]]
+; CHECK-NEXT:    [[RHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[RHS]]) #[[ATTR6]]
+; CHECK-NEXT:    [[LHS_NEG_FABS:%.*]] = fneg float [[LHS_FABS]]
+; CHECK-NEXT:    [[RHS_NEG_FABS:%.*]] = fneg float [[RHS_FABS]]
+; CHECK-NEXT:    [[MUL:%.*]] = fdiv float [[LHS_NEG_FABS]], [[RHS_NEG_FABS]]
+; CHECK-NEXT:    ret float [[MUL]]
+;
+  %lhs.fabs = call float @llvm.fabs.f32(float %lhs)
+  %rhs.fabs = call float @llvm.fabs.f32(float %rhs)
+  %lhs.neg.fabs = fneg float %lhs.fabs
+  %rhs.neg.fabs = fneg float %rhs.fabs
+  %mul = fdiv float %lhs.neg.fabs, %rhs.neg.fabs
+  ret float %mul
+}
+
+; Result must be negative or nan
+define float @ret_fdiv_lhs_negative_rhs_positive(float %lhs, float %rhs) {
+; CHECK-LABEL: define float @ret_fdiv_lhs_negative_rhs_positive
+; CHECK-SAME: (float [[LHS:%.*]], float [[RHS:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[LHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[LHS]]) #[[ATTR6]]
+; CHECK-NEXT:    [[RHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[RHS]]) #[[ATTR6]]
+; CHECK-NEXT:    [[LHS_NEG_FABS:%.*]] = fneg float [[LHS_FABS]]
+; CHECK-NEXT:    [[MUL:%.*]] = fdiv float [[LHS_NEG_FABS]], [[RHS_FABS]]
+; CHECK-NEXT:    ret float [[MUL]]
+;
+  %lhs.fabs = call float @llvm.fabs.f32(float %lhs)
+  %rhs.fabs = call float @llvm.fabs.f32(float %rhs)
+  %lhs.neg.fabs = fneg float %lhs.fabs
+  %mul = fdiv float %lhs.neg.fabs, %rhs.fabs
+  ret float %mul
+}
+
+; Result must be negative or nan
+define float @ret_fdiv_rhs_negative_lhs_positive(float %lhs, float %rhs) {
+; CHECK-LABEL: define float @ret_fdiv_rhs_negative_lhs_positive
+; CHECK-SAME: (float [[LHS:%.*]], float [[RHS:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[LHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[LHS]]) #[[ATTR6]]
+; CHECK-NEXT:    [[RHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[RHS]]) #[[ATTR6]]
+; CHECK-NEXT:    [[RHS_NEG_FABS:%.*]] = fneg float [[RHS_FABS]]
+; CHECK-NEXT:    [[MUL:%.*]] = fdiv float [[LHS_FABS]], [[RHS_NEG_FABS]]
+; CHECK-NEXT:    ret float [[MUL]]
+;
+  %lhs.fabs = call float @llvm.fabs.f32(float %lhs)
+  %rhs.fabs = call float @llvm.fabs.f32(float %rhs)
+  %rhs.neg.fabs = fneg float %rhs.fabs
+  %mul = fdiv float %lhs.fabs, %rhs.neg.fabs
+  ret float %mul
+}
+
+; Could be inf of either sign
+define float @ret_known_inf_fdiv_known_inf(float nofpclass(norm sub zero nan) %arg0, float nofpclass(norm sub zero nan) %arg1) {
+; CHECK-LABEL: define float @ret_known_inf_fdiv_known_inf
+; CHECK-SAME: (float nofpclass(nan zero sub norm) [[ARG0:%.*]], float nofpclass(nan zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+; Could be inf of either sign, or nan
+define float @ret_known_inf_fdiv_known_inf_or_nan(float nofpclass(norm sub zero nan) %arg0, float nofpclass(norm sub zero) %arg1) {
+; CHECK-LABEL: define float @ret_known_inf_fdiv_known_inf_or_nan
+; CHECK-SAME: (float nofpclass(nan zero sub norm) [[ARG0:%.*]], float nofpclass(zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+; Could be inf of either sign, or nan
+define float @ret_known_inf_or_nan_fdiv_known_inf(float nofpclass(norm sub zero) %arg0, float nofpclass(norm sub zero nan) %arg1) {
+; CHECK-LABEL: define float @ret_known_inf_or_nan_fdiv_known_inf
+; CHECK-SAME: (float nofpclass(zero sub norm) [[ARG0:%.*]], float nofpclass(nan zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+; Could be zero of either sign
+define float @ret_known_zero_fdiv_known_zero(float nofpclass(inf norm sub nan) %arg0, float nofpclass(inf norm sub nan) %arg1) {
+; CHECK-LABEL: define float @ret_known_zero_fdiv_known_zero
+; CHECK-SAME: (float nofpclass(nan inf sub norm) [[ARG0:%.*]], float nofpclass(nan inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+; Could be zero of either sign, or nan
+define float @ret_known_zero_fdiv_known_zero_or_nan(float nofpclass(inf norm sub nan) %arg0, float nofpclass(inf norm sub) %arg1) {
+; CHECK-LABEL: define float @ret_known_zero_fdiv_known_zero_or_nan
+; CHECK-SAME: (float nofpclass(nan inf sub norm) [[ARG0:%.*]], float nofpclass(inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+; Could be zero of either sign, or nan
+define float @ret_known_zero_or_nan_fdiv_known_zero(float nofpclass(inf norm sub) %arg0, float nofpclass(inf norm sub nan) %arg1) {
+; CHECK-LABEL: define float @ret_known_zero_or_nan_fdiv_known_zero
+; CHECK-SAME: (float nofpclass(inf sub norm) [[ARG0:%.*]], float nofpclass(nan inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_known_inf_or_nan_fdiv_unknown(float nofpclass(norm sub zero) %arg0, float %arg1) {
+; CHECK-LABEL: define float @ret_known_inf_or_nan_fdiv_unknown
+; CHECK-SAME: (float nofpclass(zero sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_unknown_fdiv_known_inf_or_nan(float %arg0, float nofpclass(norm sub zero) %arg1) {
+; CHECK-LABEL: define float @ret_unknown_fdiv_known_inf_or_nan
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @ret_known_inf_or_nan_fdiv_known_inf_or_nan(float nofpclass(norm sub zero) %arg0, float nofpclass(norm sub zero) %arg1) {
+; CHECK-LABEL: define float @ret_known_inf_or_nan_fdiv_known_inf_or_nan
+; CHECK-SAME: (float nofpclass(zero sub norm) [[ARG0:%.*]], float nofpclass(zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
 attributes #0 = { "denormal-fp-math"="ieee,ieee" }
 attributes #1 = { "denormal-fp-math"="ieee,preserve-sign" }
 attributes #2 = { "denormal-fp-math"="ieee,positive-zero" }
diff --git a/llvm/test/Transforms/Attributor/nofpclass-frem.ll b/llvm/test/Transforms/Attributor/nofpclass-frem.ll
index 5e574faad8045..36c3ae108c1f8 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-frem.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-frem.ll
@@ -405,6 +405,79 @@ define float @ret_frem_same_operands_nonan(float noundef nofpclass(nan) %arg) #0
   ret float %frem
 }
 
+define float @ret_frem_same_operands_nonan_noinf(float noundef nofpclass(nan inf) %arg) #0 {
+; CHECK-LABEL: define noundef nofpclass(inf sub norm) float @ret_frem_same_operands_nonan_noinf
+; CHECK-SAME: (float noundef nofpclass(nan inf) [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG]], [[ARG]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg, %arg
+  ret float %frem
+}
+
+define float @ret_frem_same_operands_nonan_nozero(float noundef nofpclass(nan zero) %arg) #0 {
+; CHECK-LABEL: define noundef nofpclass(inf sub norm) float @ret_frem_same_operands_nonan_nozero
+; CHECK-SAME: (float noundef nofpclass(nan zero) [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG]], [[ARG]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg, %arg
+  ret float %frem
+}
+
+define float @ret_frem_same_operands_nonan_noinf_nozero(float noundef nofpclass(nan inf zero) %arg) #0 {
+; CHECK-LABEL: define noundef nofpclass(inf sub norm) float @ret_frem_same_operands_nonan_noinf_nozero
+; CHECK-SAME: (float noundef nofpclass(nan inf zero) [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG]], [[ARG]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg, %arg
+  ret float %frem
+}
+
+define float @ret_frem_same_operands_nonan_noinf_nozero_nosub(float noundef nofpclass(nan inf zero) %arg) #0 {
+; CHECK-LABEL: define noundef nofpclass(inf sub norm) float @ret_frem_same_operands_nonan_noinf_nozero_nosub
+; CHECK-SAME: (float noundef nofpclass(nan inf zero) [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG]], [[ARG]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg, %arg
+  ret float %frem
+}
+
+; May be nan if denormal is flushed
+define float @ret_frem_same_operands_nonan_noinf_nozero__daz(float noundef nofpclass(nan inf zero) %arg) #1 {
+; CHECK-LABEL: define noundef nofpclass(inf sub norm) float @ret_frem_same_operands_nonan_noinf_nozero__daz
+; CHECK-SAME: (float noundef nofpclass(nan inf zero) [[ARG:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG]], [[ARG]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg, %arg
+  ret float %frem
+}
+
+; Can't have a flushed input
+define float @ret_frem_same_operands_nonan_noinf_nozero_nosub__daz(float noundef nofpclass(nan inf sub zero) %arg) #1 {
+; CHECK-LABEL: define noundef nofpclass(inf sub norm) float @ret_frem_same_operands_nonan_noinf_nozero_nosub__daz
+; CHECK-SAME: (float noundef nofpclass(nan inf zero sub) [[ARG:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG]], [[ARG]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg, %arg
+  ret float %frem
+}
+
+; Can't have a flushed input
+define float @ret_frem_same_operands_nonan_noinf_nozero_nosub__dynamic(float noundef nofpclass(nan inf sub zero) %arg) #3 {
+; CHECK-LABEL: define noundef nofpclass(inf sub norm) float @ret_frem_same_operands_nonan_noinf_nozero_nosub__dynamic
+; CHECK-SAME: (float noundef nofpclass(nan inf zero sub) [[ARG:%.*]]) #[[ATTR3]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG]], [[ARG]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg, %arg
+  ret float %frem
+}
+
 define float @ret_frem_no_neg_lhs(float nofpclass(ninf nsub nnorm) %arg0, float %arg1) #0 {
 ; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @ret_frem_no_neg_lhs
 ; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR0]] {
@@ -515,6 +588,482 @@ define float @ret_frem_no_pos_zero_rhs(float %arg0, float nofpclass(pinf psub pn
   ret float %frem
 }
 
+define float @ret_frem_no_pos(float nofpclass(pinf psub pnorm) %arg0, float nofpclass(pinf psub pnorm) %arg1) #0 {
+; CHECK-LABEL: define nofpclass(pinf psub pnorm) float @ret_frem_no_pos
+; CHECK-SAME: (float nofpclass(pinf psub pnorm) [[ARG0:%.*]], float nofpclass(pinf psub pnorm) [[ARG1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_zero_or_nan_lhs(float nofpclass(inf norm sub) %arg0, float %arg1) {
+; CHECK-LABEL: define nofpclass(inf sub norm) float @ret_frem_f32_known_zero_or_nan_lhs
+; CHECK-SAME: (float nofpclass(inf sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4:[0-9]+]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_zero_or_nan_rhs(float %arg0, float nofpclass(inf norm sub) %arg1) {
+; CHECK-LABEL: define float @ret_frem_f32_known_zero_or_nan_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_zero_lhs(float nofpclass(nan inf norm sub) %arg0, float %arg1) {
+; CHECK-LABEL: define nofpclass(inf sub norm) float @ret_frem_f32_known_zero_lhs
+; CHECK-SAME: (float nofpclass(nan inf sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_zero_rhs(float %arg0, float nofpclass(nan inf norm sub) %arg1) {
+; CHECK-LABEL: define float @ret_frem_f32_known_zero_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(nan inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_pzero_or_nan_lhs(float nofpclass(inf norm sub nzero) %arg0, float %arg1) {
+; CHECK-LABEL: define nofpclass(inf nzero sub norm) float @ret_frem_f32_known_pzero_or_nan_lhs
+; CHECK-SAME: (float nofpclass(inf nzero sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_pzero_or_nan_rhs(float %arg0, float nofpclass(inf norm sub nzero) %arg1) {
+; CHECK-LABEL: define float @ret_frem_f32_known_pzero_or_nan_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(inf nzero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_pzero_lhs(float nofpclass(nan inf norm sub nzero) %arg0, float %arg1) {
+; CHECK-LABEL: define nofpclass(inf nzero sub norm) float @ret_frem_f32_known_pzero_lhs
+; CHECK-SAME: (float nofpclass(nan inf nzero sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_pzero_rhs(float %arg0, float nofpclass(nan inf norm sub nzero) %arg1) {
+; CHECK-LABEL: define float @ret_frem_f32_known_pzero_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(nan inf nzero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_nzero_or_nan_lhs(float nofpclass(inf norm sub pzero) %arg0, float %arg1) {
+; CHECK-LABEL: define nofpclass(inf pzero sub norm) float @ret_frem_f32_known_nzero_or_nan_lhs
+; CHECK-SAME: (float nofpclass(inf pzero sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_nzero_or_nan_rhs(float %arg0, float nofpclass(inf norm sub pzero) %arg1) {
+; CHECK-LABEL: define float @ret_frem_f32_known_nzero_or_nan_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(inf pzero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_nzero_lhs(float nofpclass(nan inf norm sub pzero) %arg0, float %arg1) {
+; CHECK-LABEL: define nofpclass(inf pzero sub norm) float @ret_frem_f32_known_nzero_lhs
+; CHECK-SAME: (float nofpclass(nan inf pzero sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_nzero_rhs(float %arg0, float nofpclass(nan inf norm sub pzero) %arg1) {
+; CHECK-LABEL: define float @ret_frem_f32_known_nzero_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(nan inf pzero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_inf_or_nan_lhs(float nofpclass(zero norm sub) %arg0, float %arg1) {
+; CHECK-LABEL: define float @ret_frem_f32_known_inf_or_nan_lhs
+; CHECK-SAME: (float nofpclass(zero sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_inf_or_nan_rhs(float %arg0, float nofpclass(zero norm sub) %arg1) {
+; CHECK-LABEL: define float @ret_frem_f32_known_inf_or_nan_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_inf_lhs(float nofpclass(nan zero norm sub) %arg0, float %arg1) {
+; CHECK-LABEL: define float @ret_frem_f32_known_inf_lhs
+; CHECK-SAME: (float nofpclass(nan zero sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_inf_rhs(float %arg0, float nofpclass(nan zero norm sub) %arg1) {
+; CHECK-LABEL: define float @ret_frem_f32_known_inf_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(nan zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_pinf_or_nan_lhs(float nofpclass(ninf zero norm sub) %arg0, float %arg1) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_frem_f32_known_pinf_or_nan_lhs
+; CHECK-SAME: (float nofpclass(ninf zero sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_pinf_or_nan_rhs(float %arg0, float nofpclass(ninf zero norm sub) %arg1) {
+; CHECK-LABEL: define float @ret_frem_f32_known_pinf_or_nan_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(ninf zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_ninf_or_nan_lhs(float nofpclass(pinf zero norm sub) %arg0, float %arg1) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_frem_f32_known_ninf_or_nan_lhs
+; CHECK-SAME: (float nofpclass(pinf zero sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_f32_known_ninf_or_nan_rhs(float %arg0, float nofpclass(pinf zero norm sub) %arg1) {
+; CHECK-LABEL: define float @ret_frem_f32_known_ninf_or_nan_rhs
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(pinf zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+; -> nan
+define float @ret_known_inf_frem_known_zero(float nofpclass(nan norm sub zero) %arg0, float nofpclass(nan inf norm sub) %arg1) {
+; CHECK-LABEL: define float @ret_known_inf_frem_known_zero
+; CHECK-SAME: (float nofpclass(nan zero sub norm) [[ARG0:%.*]], float nofpclass(nan inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+; -> nan
+define float @ret_known_inf_or_nan_frem_known_zero(float nofpclass(norm sub zero) %arg0, float nofpclass(nan inf norm sub) %arg1) {
+; CHECK-LABEL: define float @ret_known_inf_or_nan_frem_known_zero
+; CHECK-SAME: (float nofpclass(zero sub norm) [[ARG0:%.*]], float nofpclass(nan inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+; -> nan
+define float @ret_known_inf_frem_known_zero_or_nan(float nofpclass(nan norm sub zero) %arg0, float nofpclass(inf norm sub) %arg1) {
+; CHECK-LABEL: define float @ret_known_inf_frem_known_zero_or_nan
+; CHECK-SAME: (float nofpclass(nan zero sub norm) [[ARG0:%.*]], float nofpclass(inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+; -> nan
+define float @ret_known_ninf_frem_known_zero(float nofpclass(nan pinf norm sub zero) %arg0, float nofpclass(nan inf norm sub) %arg1) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_known_ninf_frem_known_zero
+; CHECK-SAME: (float nofpclass(nan pinf zero sub norm) [[ARG0:%.*]], float nofpclass(nan inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+; -> nan
+define float @ret_known_pinf_frem_known_zero(float nofpclass(nan ninf norm sub zero) %arg0, float nofpclass(nan inf norm sub) %arg1) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_known_pinf_frem_known_zero
+; CHECK-SAME: (float nofpclass(nan ninf zero sub norm) [[ARG0:%.*]], float nofpclass(nan inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+; -> nan
+define float @ret_known_zero_frem_known_inf(float nofpclass(nan inf norm sub) %arg0, float nofpclass(nan norm sub zero) %arg1) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) float @ret_known_zero_frem_known_inf
+; CHECK-SAME: (float nofpclass(nan inf sub norm) [[ARG0:%.*]], float nofpclass(nan zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+; -> nan
+define float @ret_known_zero_frem_known_inf_or_nan(float nofpclass(nan inf norm sub) %arg0, float nofpclass(norm sub zero) %arg1) {
+; CHECK-LABEL: define nofpclass(inf sub norm) float @ret_known_zero_frem_known_inf_or_nan
+; CHECK-SAME: (float nofpclass(nan inf sub norm) [[ARG0:%.*]], float nofpclass(zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+; -> nan
+define float @ret_known_zero_or_nan_frem_known_inf(float nofpclass(inf norm sub) %arg0, float nofpclass(nan norm sub zero) %arg1) {
+; CHECK-LABEL: define nofpclass(inf sub norm) float @ret_known_zero_or_nan_frem_known_inf
+; CHECK-SAME: (float nofpclass(inf sub norm) [[ARG0:%.*]], float nofpclass(nan zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_frem_lhs_known_positive_or_nan(float %lhs, float %rhs) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_frem_lhs_known_positive_or_nan
+; CHECK-SAME: (float [[LHS:%.*]], float [[RHS:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[LHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[LHS]]) #[[ATTR6:[0-9]+]]
+; CHECK-NEXT:    [[MUL:%.*]] = frem float [[LHS_FABS]], [[RHS]]
+; CHECK-NEXT:    ret float [[MUL]]
+;
+  %lhs.fabs = call float @llvm.fabs.f32(float %lhs)
+  %mul = frem float %lhs.fabs, %rhs
+  ret float %mul
+}
+
+define float @ret_frem_rhs_known_positive_or_nan(float %lhs, float %rhs) {
+; CHECK-LABEL: define float @ret_frem_rhs_known_positive_or_nan
+; CHECK-SAME: (float [[LHS:%.*]], float [[RHS:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[RHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[RHS]]) #[[ATTR6]]
+; CHECK-NEXT:    [[MUL:%.*]] = frem float [[LHS]], [[RHS_FABS]]
+; CHECK-NEXT:    ret float [[MUL]]
+;
+  %rhs.fabs = call float @llvm.fabs.f32(float %rhs)
+  %mul = frem float %lhs, %rhs.fabs
+  ret float %mul
+}
+
+define float @ret_frem_both_signs_positive_or_nan(float %lhs, float %rhs) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_frem_both_signs_positive_or_nan
+; CHECK-SAME: (float [[LHS:%.*]], float [[RHS:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[LHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[LHS]]) #[[ATTR6]]
+; CHECK-NEXT:    [[RHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[RHS]]) #[[ATTR6]]
+; CHECK-NEXT:    [[MUL:%.*]] = frem float [[LHS_FABS]], [[RHS_FABS]]
+; CHECK-NEXT:    ret float [[MUL]]
+;
+  %lhs.fabs = call float @llvm.fabs.f32(float %lhs)
+  %rhs.fabs = call float @llvm.fabs.f32(float %rhs)
+  %mul = frem float %lhs.fabs, %rhs.fabs
+  ret float %mul
+}
+
+define float @ret_frem_both_signs_negative_or_nan(float %lhs, float %rhs) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_frem_both_signs_negative_or_nan
+; CHECK-SAME: (float [[LHS:%.*]], float [[RHS:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[LHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[LHS]]) #[[ATTR6]]
+; CHECK-NEXT:    [[RHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[RHS]]) #[[ATTR6]]
+; CHECK-NEXT:    [[LHS_NEG_FABS:%.*]] = fneg float [[LHS_FABS]]
+; CHECK-NEXT:    [[RHS_NEG_FABS:%.*]] = fneg float [[RHS_FABS]]
+; CHECK-NEXT:    [[MUL:%.*]] = frem float [[LHS_NEG_FABS]], [[RHS_NEG_FABS]]
+; CHECK-NEXT:    ret float [[MUL]]
+;
+  %lhs.fabs = call float @llvm.fabs.f32(float %lhs)
+  %rhs.fabs = call float @llvm.fabs.f32(float %rhs)
+  %lhs.neg.fabs = fneg float %lhs.fabs
+  %rhs.neg.fabs = fneg float %rhs.fabs
+  %mul = frem float %lhs.neg.fabs, %rhs.neg.fabs
+  ret float %mul
+}
+
+define float @ret_frem_lhs_negative_rhs_positive(float %lhs, float %rhs) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_frem_lhs_negative_rhs_positive
+; CHECK-SAME: (float [[LHS:%.*]], float [[RHS:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[LHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[LHS]]) #[[ATTR6]]
+; CHECK-NEXT:    [[RHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[RHS]]) #[[ATTR6]]
+; CHECK-NEXT:    [[LHS_NEG_FABS:%.*]] = fneg float [[LHS_FABS]]
+; CHECK-NEXT:    [[MUL:%.*]] = frem float [[LHS_NEG_FABS]], [[RHS_FABS]]
+; CHECK-NEXT:    ret float [[MUL]]
+;
+  %lhs.fabs = call float @llvm.fabs.f32(float %lhs)
+  %rhs.fabs = call float @llvm.fabs.f32(float %rhs)
+  %lhs.neg.fabs = fneg float %lhs.fabs
+  %mul = frem float %lhs.neg.fabs, %rhs.fabs
+  ret float %mul
+}
+
+define float @ret_frem_rhs_negative_lhs_positive(float %lhs, float %rhs) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_frem_rhs_negative_lhs_positive
+; CHECK-SAME: (float [[LHS:%.*]], float [[RHS:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[LHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[LHS]]) #[[ATTR6]]
+; CHECK-NEXT:    [[RHS_FABS:%.*]] = call float @llvm.fabs.f32(float [[RHS]]) #[[ATTR6]]
+; CHECK-NEXT:    [[RHS_NEG_FABS:%.*]] = fneg float [[RHS_FABS]]
+; CHECK-NEXT:    [[MUL:%.*]] = frem float [[LHS_FABS]], [[RHS_NEG_FABS]]
+; CHECK-NEXT:    ret float [[MUL]]
+;
+  %lhs.fabs = call float @llvm.fabs.f32(float %lhs)
+  %rhs.fabs = call float @llvm.fabs.f32(float %rhs)
+  %rhs.neg.fabs = fneg float %rhs.fabs
+  %mul = frem float %lhs.fabs, %rhs.neg.fabs
+  ret float %mul
+}
+
+define float @ret_known_inf_frem_known_inf(float nofpclass(norm sub zero nan) %arg0, float nofpclass(norm sub zero nan) %arg1) {
+; CHECK-LABEL: define float @ret_known_inf_frem_known_inf
+; CHECK-SAME: (float nofpclass(nan zero sub norm) [[ARG0:%.*]], float nofpclass(nan zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_known_inf_frem_known_inf_or_nan(float nofpclass(norm sub zero nan) %arg0, float nofpclass(norm sub zero) %arg1) {
+; CHECK-LABEL: define float @ret_known_inf_frem_known_inf_or_nan
+; CHECK-SAME: (float nofpclass(nan zero sub norm) [[ARG0:%.*]], float nofpclass(zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_known_inf_or_nan_frem_known_inf(float nofpclass(norm sub zero) %arg0, float nofpclass(norm sub zero nan) %arg1) {
+; CHECK-LABEL: define float @ret_known_inf_or_nan_frem_known_inf
+; CHECK-SAME: (float nofpclass(zero sub norm) [[ARG0:%.*]], float nofpclass(nan zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_known_zero_frem_known_zero(float nofpclass(inf norm sub nan) %arg0, float nofpclass(inf norm sub nan) %arg1) {
+; CHECK-LABEL: define nofpclass(inf sub norm) float @ret_known_zero_frem_known_zero
+; CHECK-SAME: (float nofpclass(nan inf sub norm) [[ARG0:%.*]], float nofpclass(nan inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_known_zero_frem_known_zero_or_nan(float nofpclass(inf norm sub nan) %arg0, float nofpclass(inf norm sub) %arg1) {
+; CHECK-LABEL: define nofpclass(inf sub norm) float @ret_known_zero_frem_known_zero_or_nan
+; CHECK-SAME: (float nofpclass(nan inf sub norm) [[ARG0:%.*]], float nofpclass(inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_known_zero_or_nan_frem_known_zero(float nofpclass(inf norm sub) %arg0, float nofpclass(inf norm sub nan) %arg1) {
+; CHECK-LABEL: define nofpclass(inf sub norm) float @ret_known_zero_or_nan_frem_known_zero
+; CHECK-SAME: (float nofpclass(inf sub norm) [[ARG0:%.*]], float nofpclass(nan inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_known_inf_or_nan_frem_unknown(float nofpclass(norm sub zero) %arg0, float %arg1) {
+; CHECK-LABEL: define float @ret_known_inf_or_nan_frem_unknown
+; CHECK-SAME: (float nofpclass(zero sub norm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_unknown_frem_known_inf_or_nan(float %arg0, float nofpclass(norm sub zero) %arg1) {
+; CHECK-LABEL: define float @ret_unknown_frem_known_inf_or_nan
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
+define float @ret_known_inf_or_nan_frem_known_inf_or_nan(float nofpclass(norm sub zero) %arg0, float nofpclass(norm sub zero) %arg1) {
+; CHECK-LABEL: define float @ret_known_inf_or_nan_frem_known_inf_or_nan
+; CHECK-SAME: (float nofpclass(zero sub norm) [[ARG0:%.*]], float nofpclass(zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FREM]]
+;
+  %frem = frem float %arg0, %arg1
+  ret float %frem
+}
+
 attributes #0 = { "denormal-fp-math"="ieee,ieee" }
 attributes #1 = { "denormal-fp-math"="ieee,preserve-sign" }
 attributes #2 = { "denormal-fp-math"="ieee,positive-zero" }



More information about the llvm-branch-commits mailing list