[llvm] [KnownFPClass] Add sign preserving deductions to `atan2(y, x)` (PR #223176)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Sep 12 14:32:47 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-globalisel
Author: Eric Ross (ZERICO2005)
<details>
<summary>Changes</summary>
`atan2(y, x)` should return the same sign as `y` (up to the denormal mode):
- If `y >= +0.0`, then `atan2(y, x) >= +0.0`
- If `y <= -0.0`, then `atan2(y, x) <= -0.0`
AI Disclosure:
I used ChatGPT Codex (5.6 sol) to help write the tests.
---
Patch is 40.41 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/223176.diff
6 Files Affected:
- (modified) llvm/lib/Analysis/ValueTracking.cpp (+8)
- (modified) llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp (+8)
- (modified) llvm/lib/Support/KnownFPClass.cpp (+18-2)
- (modified) llvm/test/Transforms/Attributor/nofpclass-atan2.ll (+428-30)
- (modified) llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-atan2.ll (+25)
- (modified) llvm/unittests/CodeGen/GlobalISel/KnownFPClassTest.cpp (+3-3)
``````````diff
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 1580571a01451..f0e86a3bf9905 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5503,6 +5503,14 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
FPClassTest InterestedY = InterestedClasses;
FPClassTest InterestedX = InterestedClasses;
+ // We can rule out negative values if y cannot have a negative value.
+ if ((InterestedClasses & fcNegFinite) != fcNone)
+ InterestedY |= fcNegative;
+
+ // We can rule out positive values if y cannot have a positive value.
+ if ((InterestedClasses & fcPosFinite) != fcNone)
+ InterestedY |= fcPositive | fcNegSubnormal;
+
// We can rule out zero and subnormal if x cannot have a positive value.
if ((InterestedClasses & (fcZero | fcSubnormal)) != fcNone)
InterestedX |= fcPositive | fcNegSubnormal;
diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 0bbafeb6dca41..ad07e0055fc7a 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -1406,6 +1406,14 @@ void GISelValueTracking::computeKnownFPClass(Register R,
FPClassTest InterestedY = InterestedClasses;
FPClassTest InterestedX = InterestedClasses;
+ // We can rule out negative values if y cannot have a negative value.
+ if ((InterestedClasses & fcNegFinite) != fcNone)
+ InterestedY |= fcNegative;
+
+ // We can rule out positive values if y cannot have a positive value.
+ if ((InterestedClasses & fcPosFinite) != fcNone)
+ InterestedY |= fcPositive | fcNegSubnormal;
+
// We can rule out zero and subnormal if x cannot have a positive value.
if ((InterestedClasses & (fcZero | fcSubnormal)) != fcNone)
InterestedX |= fcPositive | fcNegSubnormal;
diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp
index 75636ffc73361..930d91be93045 100644
--- a/llvm/lib/Support/KnownFPClass.cpp
+++ b/llvm/lib/Support/KnownFPClass.cpp
@@ -798,13 +798,29 @@ KnownFPClass KnownFPClass::atan2(const KnownFPClass &KnownY,
Known.propagateNonNaN(KnownY, KnownX);
// Negative subnormals could be treated like positive zero.
- const bool XCannotHavePositiveValue = KnownX.isKnownNever(fcPositive) &&
+ const bool XCannotHavePositiveInput = KnownX.isKnownNever(fcPositive) &&
KnownX.isKnownNeverLogicalPosZero(Mode);
+ const bool YCannotHavePositiveInput = KnownY.isKnownNever(fcPositive) &&
+ KnownY.isKnownNeverLogicalPosZero(Mode);
// If x <= -0.0, then |atan2(y, x)| >= pi/2
- if (XCannotHavePositiveValue)
+ if (XCannotHavePositiveInput)
Known.knownNot(fcZero | fcSubnormal);
+ // If y >= +0.0, then atan2(y, x) >= +0.0
+ if (KnownY.isKnownNever(fcNegative))
+ Known.knownNot(fcNegative);
+
+ // If y <= -0.0, then atan2(y, x) <= -0.0
+ // We do this deduction last in case we were able to rule out a negative
+ // subnormal result earlier.
+ if (YCannotHavePositiveInput) {
+ Known.knownNot(fcPosSubnormal | fcPosNormal | fcPosInf);
+ // Negative subnormal results can flush to +0.0.
+ if (Known.isKnownNever(fcNegSubnormal) || !Mode.outputsMayBePositiveZero())
+ Known.knownNot(fcPosZero);
+ }
+
return Known;
}
diff --git a/llvm/test/Transforms/Attributor/nofpclass-atan2.ll b/llvm/test/Transforms/Attributor/nofpclass-atan2.ll
index feb4a7075b435..ae0e7c6f34ea2 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-atan2.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-atan2.ll
@@ -7,7 +7,7 @@ declare float @llvm.atan2.f32(float, float)
define float @ret_atan2(float %arg0, float %arg1) {
; CHECK-LABEL: define nofpclass(inf) float @ret_atan2(
; CHECK-SAME: float [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR1:[0-9]+]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf) float @llvm.atan2.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR6:[0-9]+]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf) float @llvm.atan2.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR10:[0-9]+]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.atan2.f32(float %arg0, float %arg1)
@@ -17,7 +17,7 @@ define float @ret_atan2(float %arg0, float %arg1) {
define float @ret_atan2_nonan(float nofpclass(nan) %arg0, float nofpclass(nan) %arg1) {
; CHECK-LABEL: define nofpclass(nan inf) float @ret_atan2_nonan(
; CHECK-SAME: float nofpclass(nan) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan inf) float @llvm.atan2.f32(float nofpclass(nan) [[ARG0]], float nofpclass(nan) [[ARG1]]) #[[ATTR6]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan inf) float @llvm.atan2.f32(float nofpclass(nan) [[ARG0]], float nofpclass(nan) [[ARG1]]) #[[ATTR10]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.atan2.f32(float %arg0, float %arg1)
@@ -27,18 +27,180 @@ define float @ret_atan2_nonan(float nofpclass(nan) %arg0, float nofpclass(nan) %
define float @ret_atan2_nosnan(float nofpclass(snan) %arg0, float nofpclass(snan) %arg1) {
; CHECK-LABEL: define nofpclass(snan inf) float @ret_atan2_nosnan(
; CHECK-SAME: float nofpclass(snan) [[ARG0:%.*]], float nofpclass(snan) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(snan inf) float @llvm.atan2.f32(float nofpclass(snan) [[ARG0]], float nofpclass(snan) [[ARG1]]) #[[ATTR6]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(snan inf) float @llvm.atan2.f32(float nofpclass(snan) [[ARG0]], float nofpclass(snan) [[ARG1]]) #[[ATTR10]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.atan2.f32(float %arg0, float %arg1)
ret float %call
}
+; Quadrant tests
+
+define float @ret_atan2_normal_quad_1(float nofpclass(nan inf zero sub nnorm) %y, float nofpclass(nan inf zero sub nnorm) %x) {
+; CHECK-LABEL: define nofpclass(nan inf nzero nsub nnorm) float @ret_atan2_normal_quad_1(
+; CHECK-SAME: float nofpclass(nan inf zero sub nnorm) [[Y:%.*]], float nofpclass(nan inf zero sub nnorm) [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan inf nzero nsub nnorm) float @llvm.atan2.f32(float nofpclass(nan inf zero sub nnorm) [[Y]], float nofpclass(nan inf zero sub nnorm) [[X]]) #[[ATTR10]]
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = call float @llvm.atan2.f32(float %y, float %x)
+ ret float %call
+}
+
+define float @ret_atan2_normal_quad_2(float nofpclass(nan inf zero sub nnorm) %y, float nofpclass(nan inf zero sub pnorm) %x) {
+; CHECK-LABEL: define nofpclass(nan inf zero sub nnorm) float @ret_atan2_normal_quad_2(
+; CHECK-SAME: float nofpclass(nan inf zero sub nnorm) [[Y:%.*]], float nofpclass(nan inf zero sub pnorm) [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan inf zero sub nnorm) float @llvm.atan2.f32(float nofpclass(nan inf zero sub nnorm) [[Y]], float nofpclass(nan inf zero sub pnorm) [[X]]) #[[ATTR10]]
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = call float @llvm.atan2.f32(float %y, float %x)
+ ret float %call
+}
+
+define float @ret_atan2_normal_quad_3(float nofpclass(nan inf zero sub pnorm) %y, float nofpclass(nan inf zero sub pnorm) %x) {
+; CHECK-LABEL: define nofpclass(nan inf zero sub pnorm) float @ret_atan2_normal_quad_3(
+; CHECK-SAME: float nofpclass(nan inf zero sub pnorm) [[Y:%.*]], float nofpclass(nan inf zero sub pnorm) [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan inf zero sub pnorm) float @llvm.atan2.f32(float nofpclass(nan inf zero sub pnorm) [[Y]], float nofpclass(nan inf zero sub pnorm) [[X]]) #[[ATTR10]]
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = call float @llvm.atan2.f32(float %y, float %x)
+ ret float %call
+}
+
+define float @ret_atan2_normal_quad_4(float nofpclass(nan inf zero sub pnorm) %y, float nofpclass(nan inf zero sub nnorm) %x) {
+; CHECK-LABEL: define nofpclass(nan inf pzero psub pnorm) float @ret_atan2_normal_quad_4(
+; CHECK-SAME: float nofpclass(nan inf zero sub pnorm) [[Y:%.*]], float nofpclass(nan inf zero sub nnorm) [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan inf pzero psub pnorm) float @llvm.atan2.f32(float nofpclass(nan inf zero sub pnorm) [[Y]], float nofpclass(nan inf zero sub nnorm) [[X]]) #[[ATTR10]]
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = call float @llvm.atan2.f32(float %y, float %x)
+ ret float %call
+}
+
+define float @ret_atan2_normal_subnormal_quad_1(float nofpclass(nan inf zero nsub nnorm) %y, float nofpclass(nan inf zero nsub nnorm) %x) {
+; CHECK-LABEL: define nofpclass(nan inf nzero nsub nnorm) float @ret_atan2_normal_subnormal_quad_1(
+; CHECK-SAME: float nofpclass(nan inf zero nsub nnorm) [[Y:%.*]], float nofpclass(nan inf zero nsub nnorm) [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan inf nzero nsub nnorm) float @llvm.atan2.f32(float nofpclass(nan inf zero nsub nnorm) [[Y]], float nofpclass(nan inf zero nsub nnorm) [[X]]) #[[ATTR10]]
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = call float @llvm.atan2.f32(float %y, float %x)
+ ret float %call
+}
+
+define float @ret_atan2_normal_subnormal_quad_2(float nofpclass(nan inf zero nsub nnorm) %y, float nofpclass(nan inf zero psub pnorm) %x) {
+; CHECK-LABEL: define nofpclass(nan inf zero sub nnorm) float @ret_atan2_normal_subnormal_quad_2(
+; CHECK-SAME: float nofpclass(nan inf zero nsub nnorm) [[Y:%.*]], float nofpclass(nan inf zero psub pnorm) [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan inf zero sub nnorm) float @llvm.atan2.f32(float nofpclass(nan inf zero nsub nnorm) [[Y]], float nofpclass(nan inf zero psub pnorm) [[X]]) #[[ATTR10]]
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = call float @llvm.atan2.f32(float %y, float %x)
+ ret float %call
+}
+
+define float @ret_atan2_normal_subnormal_quad_3(float nofpclass(nan inf zero psub pnorm) %y, float nofpclass(nan inf zero psub pnorm) %x) {
+; CHECK-LABEL: define nofpclass(nan inf zero sub pnorm) float @ret_atan2_normal_subnormal_quad_3(
+; CHECK-SAME: float nofpclass(nan inf zero psub pnorm) [[Y:%.*]], float nofpclass(nan inf zero psub pnorm) [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan inf zero sub pnorm) float @llvm.atan2.f32(float nofpclass(nan inf zero psub pnorm) [[Y]], float nofpclass(nan inf zero psub pnorm) [[X]]) #[[ATTR10]]
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = call float @llvm.atan2.f32(float %y, float %x)
+ ret float %call
+}
+
+define float @ret_atan2_normal_subnormal_quad_4(float nofpclass(nan inf zero psub pnorm) %y, float nofpclass(nan inf zero nsub nnorm) %x) {
+; CHECK-LABEL: define nofpclass(nan inf pzero psub pnorm) float @ret_atan2_normal_subnormal_quad_4(
+; CHECK-SAME: float nofpclass(nan inf zero psub pnorm) [[Y:%.*]], float nofpclass(nan inf zero nsub nnorm) [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan inf pzero psub pnorm) float @llvm.atan2.f32(float nofpclass(nan inf zero psub pnorm) [[Y]], float nofpclass(nan inf zero nsub nnorm) [[X]]) #[[ATTR10]]
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = call float @llvm.atan2.f32(float %y, float %x)
+ ret float %call
+}
+
+define float @ret_atan2_normal_subnormal_quad_1_mode_dynamic_dynamic(float nofpclass(nan inf zero nsub nnorm) %y, float nofpclass(nan inf zero nsub nnorm) %x) denormal_fpenv(float: dynamic|dynamic) {
+; CHECK-LABEL: define nofpclass(nan inf nzero nsub nnorm) float @ret_atan2_normal_subnormal_quad_1_mode_dynamic_dynamic(
+; CHECK-SAME: float nofpclass(nan inf zero nsub nnorm) [[Y:%.*]], float nofpclass(nan inf zero nsub nnorm) [[X:%.*]]) #[[ATTR2:[0-9]+]] {
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan inf nzero nsub nnorm) float @llvm.atan2.f32(float nofpclass(nan inf zero nsub nnorm) [[Y]], float nofpclass(nan inf zero nsub nnorm) [[X]]) #[[ATTR10]]
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = call float @llvm.atan2.f32(float %y, float %x)
+ ret float %call
+}
+
+define float @ret_atan2_normal_subnormal_quad_2_mode_dynamic_dynamic(float nofpclass(nan inf zero nsub nnorm) %y, float nofpclass(nan inf zero psub pnorm) %x) denormal_fpenv(float: dynamic|dynamic) {
+; CHECK-LABEL: define nofpclass(nan inf nzero nsub nnorm) float @ret_atan2_normal_subnormal_quad_2_mode_dynamic_dynamic(
+; CHECK-SAME: float nofpclass(nan inf zero nsub nnorm) [[Y:%.*]], float nofpclass(nan inf zero psub pnorm) [[X:%.*]]) #[[ATTR2]] {
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan inf nzero nsub nnorm) float @llvm.atan2.f32(float nofpclass(nan inf zero nsub nnorm) [[Y]], float nofpclass(nan inf zero psub pnorm) [[X]]) #[[ATTR10]]
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = call float @llvm.atan2.f32(float %y, float %x)
+ ret float %call
+}
+
+define float @ret_atan2_normal_subnormal_quad_3_mode_dynamic_dynamic(float nofpclass(nan inf zero psub pnorm) %y, float nofpclass(nan inf zero psub pnorm) %x) denormal_fpenv(float: dynamic|dynamic) {
+; CHECK-LABEL: define nofpclass(nan inf) float @ret_atan2_normal_subnormal_quad_3_mode_dynamic_dynamic(
+; CHECK-SAME: float nofpclass(nan inf zero psub pnorm) [[Y:%.*]], float nofpclass(nan inf zero psub pnorm) [[X:%.*]]) #[[ATTR2]] {
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan inf) float @llvm.atan2.f32(float nofpclass(nan inf zero psub pnorm) [[Y]], float nofpclass(nan inf zero psub pnorm) [[X]]) #[[ATTR10]]
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = call float @llvm.atan2.f32(float %y, float %x)
+ ret float %call
+}
+
+define float @ret_atan2_normal_subnormal_quad_4_mode_dynamic_dynamic(float nofpclass(nan inf zero psub pnorm) %y, float nofpclass(nan inf zero nsub nnorm) %x) denormal_fpenv(float: dynamic|dynamic) {
+; CHECK-LABEL: define nofpclass(nan inf) float @ret_atan2_normal_subnormal_quad_4_mode_dynamic_dynamic(
+; CHECK-SAME: float nofpclass(nan inf zero psub pnorm) [[Y:%.*]], float nofpclass(nan inf zero nsub nnorm) [[X:%.*]]) #[[ATTR2]] {
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan inf) float @llvm.atan2.f32(float nofpclass(nan inf zero psub pnorm) [[Y]], float nofpclass(nan inf zero nsub nnorm) [[X]]) #[[ATTR10]]
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = call float @llvm.atan2.f32(float %y, float %x)
+ ret float %call
+}
+
+define float @ret_atan2_normal_subnormal_quad_1_mode_ftpz_dapz(float nofpclass(nan inf zero nsub nnorm) %y, float nofpclass(nan inf zero nsub nnorm) %x) denormal_fpenv(float: positivezero|positivezero) {
+; CHECK-LABEL: define nofpclass(nan inf nzero nsub nnorm) float @ret_atan2_normal_subnormal_quad_1_mode_ftpz_dapz(
+; CHECK-SAME: float nofpclass(nan inf zero nsub nnorm) [[Y:%.*]], float nofpclass(nan inf zero nsub nnorm) [[X:%.*]]) #[[ATTR3:[0-9]+]] {
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan inf nzero nsub nnorm) float @llvm.atan2.f32(float nofpclass(nan inf zero nsub nnorm) [[Y]], float nofpclass(nan inf zero nsub nnorm) [[X]]) #[[ATTR10]]
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = call float @llvm.atan2.f32(float %y, float %x)
+ ret float %call
+}
+
+define float @ret_atan2_normal_subnormal_quad_2_mode_ftpz_dapz(float nofpclass(nan inf zero nsub nnorm) %y, float nofpclass(nan inf zero psub pnorm) %x) denormal_fpenv(float: positivezero|positivezero) {
+; CHECK-LABEL: define nofpclass(nan inf nzero nsub nnorm) float @ret_atan2_normal_subnormal_quad_2_mode_ftpz_dapz(
+; CHECK-SAME: float nofpclass(nan inf zero nsub nnorm) [[Y:%.*]], float nofpclass(nan inf zero psub pnorm) [[X:%.*]]) #[[ATTR3]] {
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan inf nzero nsub nnorm) float @llvm.atan2.f32(float nofpclass(nan inf zero nsub nnorm) [[Y]], float nofpclass(nan inf zero psub pnorm) [[X]]) #[[ATTR10]]
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = call float @llvm.atan2.f32(float %y, float %x)
+ ret float %call
+}
+
+define float @ret_atan2_normal_subnormal_quad_3_mode_ftpz_dapz(float nofpclass(nan inf zero psub pnorm) %y, float nofpclass(nan inf zero psub pnorm) %x) denormal_fpenv(float: positivezero|positivezero) {
+; CHECK-LABEL: define nofpclass(nan inf) float @ret_atan2_normal_subnormal_quad_3_mode_ftpz_dapz(
+; CHECK-SAME: float nofpclass(nan inf zero psub pnorm) [[Y:%.*]], float nofpclass(nan inf zero psub pnorm) [[X:%.*]]) #[[ATTR3]] {
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan inf) float @llvm.atan2.f32(float nofpclass(nan inf zero psub pnorm) [[Y]], float nofpclass(nan inf zero psub pnorm) [[X]]) #[[ATTR10]]
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = call float @llvm.atan2.f32(float %y, float %x)
+ ret float %call
+}
+
+define float @ret_atan2_normal_subnormal_quad_4_mode_ftpz_dapz(float nofpclass(nan inf zero psub pnorm) %y, float nofpclass(nan inf zero nsub nnorm) %x) denormal_fpenv(float: positivezero|positivezero) {
+; CHECK-LABEL: define nofpclass(nan inf) float @ret_atan2_normal_subnormal_quad_4_mode_ftpz_dapz(
+; CHECK-SAME: float nofpclass(nan inf zero psub pnorm) [[Y:%.*]], float nofpclass(nan inf zero nsub nnorm) [[X:%.*]]) #[[ATTR3]] {
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan inf) float @llvm.atan2.f32(float nofpclass(nan inf zero psub pnorm) [[Y]], float nofpclass(nan inf zero nsub nnorm) [[X]]) #[[ATTR10]]
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = call float @llvm.atan2.f32(float %y, float %x)
+ ret float %call
+}
+
; |atan2(y, x)| >= pi/2 when x is a negative normal or negative infinity.
-define float @ret_atan2_neg_normal_x(float %y, float nofpclass(nan pinf zero sub pnorm) %x) {
-; CHECK-LABEL: define nofpclass(inf zero sub) float @ret_atan2_neg_normal_x(
+define float @ret_atan2_negnormal_neginf_x(float %y, float nofpclass(nan pinf zero sub pnorm) %x) {
+; CHECK-LABEL: define nofpclass(inf zero sub) float @ret_atan2_negnormal_neginf_x(
; CHECK-SAME: float [[Y:%.*]], float nofpclass(nan pinf zero sub pnorm) [[X:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf zero sub) float @llvm.atan2.f32(float [[Y]], float nofpclass(nan pinf zero sub pnorm) [[X]]) #[[ATTR6]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf zero sub) float @llvm.atan2.f32(float [[Y]], float nofpclass(nan pinf zero sub pnorm) [[X]]) #[[ATTR10]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.atan2.f32(float %y, float %x)
@@ -49,50 +211,286 @@ define float @ret_atan2_neg_normal_x(float %y, float nofpclass(nan pinf zero sub
; be zero or subnormal. However, a negative subnormal may be treated as a
; logical positive zero depending on how the floating point environment handles
; denormals. Here we make sure to test every input denormal-mode combination.
-define float @ret_atan2_neg_subnormal_x_ieee_ieee(
-; CHECK-LABEL: define nofpclass(inf zero sub) float @ret_atan2_neg_subnormal_x_ieee_ieee(
-; CHECK-SAME: float [[Y:%.*]], float nofpclass(nan inf zero psub norm) [[X:%.*]]) #[[ATTR2:[0-9]+]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf zero sub) float @llvm.atan2.f32(float [[Y]], float nofpclass(nan inf zero psub norm) [[X]]) #[[ATTR6]]
+define float @ret_atan2_negsubnormal_x_mode_ieee_ieee(float %y, float nofpclass(nan inf zero psub norm) %x) denormal_fpenv(float: ieee|ieee) {
+; CHECK-LABEL: define nofpclass(inf zero sub) float @ret_atan2_negsubnormal_x_mode_ieee_ieee(
+; CHECK-SAME: float [[Y:%.*]], float nofpclass(nan inf zero psub norm) [[X:%.*]]) #[[ATTR4:[0-9]+]] {
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf zero sub) float @llvm.atan2.f32(float [[Y]], float nofpclass(nan inf zero psub norm) [[X]]) #[[ATTR10]]
; CHECK-NEXT: ret float [[CALL]]
;
- float %y, float nofpclass(nan inf zero norm psub) %x)
- denormal_fpenv(float: ieee|ieee) {
%call = call float @llvm.atan2.f32(float %y, float %x)
ret float %call
}
-define float @ret_atan2_neg_subnormal_x_ieee_preservesign(
-; CHECK-LABEL: define nofpclass(inf zero sub) float @ret_atan2_neg_subnormal_x_ieee_preservesign(
-; CHECK-SAME: float [[Y:%.*]], float nofpclass(nan inf zero psub norm) [[X:%.*]]) #[[ATTR3:[0-9]+]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf zero sub) float @llvm.atan2.f32(float [[Y]], float nofpclass(nan inf zero psub norm) [[X]]) #[[ATTR6]]
+define float @ret_atan2_negsubnormal_x_mode_ieee_daz(float %y, float nofpclass(nan inf zero psub norm) %x) denormal_fpenv(float: ieee|preservesign) {
+; CHECK-LABEL...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/223176
More information about the llvm-commits
mailing list