Conversation
This was referenced Dec 24, 2025
Contributor
Author
This was referenced Dec 24, 2025
Member
|
@llvm/pr-subscribers-backend-amdgpu @llvm/pr-subscribers-llvm-transforms Author: Matt Arsenault (arsenm) ChangesTeach exp handling that positive inputs cannot introduce overflow, Full diff: https://github.com/llvm/llvm-project/pull/173430.diff 2 Files Affected:
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index d866446051fe2..9a3d11eaa38c8 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5362,6 +5362,22 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
Known.signBitMustBeZero();
}
+ if (KnownSrc.cannotBeOrderedLessThanZero()) {
+ // If the source is positive, and cannot be ~0, this cannot underflow.
+ Known.knownNot(fcPosZero);
+
+ // Cannot introduce new denormal values.
+ if (KnownSrc.isKnownNever(fcPosSubnormal))
+ Known.knownNot(fcPosSubnormal);
+ }
+
+ if (KnownSrc.cannotBeOrderedGreaterThanZero()) {
+ // If the source is negative, and cannot be infinity, this cannot
+ // overflow to infinity.
+ if (KnownSrc.isKnownNeverPosInfinity())
+ Known.knownNot(fcPosInf);
+ }
+
break;
}
case Intrinsic::fptrunc_round: {
diff --git a/llvm/test/Transforms/Attributor/nofpclass-exp.ll b/llvm/test/Transforms/Attributor/nofpclass-exp.ll
index ea5c26d101186..941e1d3981af5 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-exp.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-exp.ll
@@ -96,10 +96,10 @@ define float @ret_exp_noinf_nonegzero(float nofpclass(inf nzero) %arg0) {
}
define float @ret_exp_positive_source(i32 %arg) {
-; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_exp_positive_source
+; CHECK-LABEL: define nofpclass(nan ninf zero sub nnorm) float @ret_exp_positive_source
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[UITOFP:%.*]] = uitofp i32 [[ARG]] to float
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.exp.f32(float [[UITOFP]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan ninf zero sub nnorm) float @llvm.exp.f32(float [[UITOFP]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%uitofp = uitofp i32 %arg to float
@@ -211,10 +211,10 @@ define float @ret_exp2_noinf_nonegzero(float nofpclass(inf nzero) %arg0) {
}
define float @ret_exp2_positive_source(i32 %arg) {
-; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_exp2_positive_source
+; CHECK-LABEL: define nofpclass(nan ninf zero sub nnorm) float @ret_exp2_positive_source
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[UITOFP:%.*]] = uitofp i32 [[ARG]] to float
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.exp2.f32(float [[UITOFP]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan ninf zero sub nnorm) float @llvm.exp2.f32(float [[UITOFP]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%uitofp = uitofp i32 %arg to float
@@ -326,10 +326,10 @@ define float @ret_exp10_noinf_nonegzero(float nofpclass(inf nzero) %arg0) {
}
define float @ret_exp10_positive_source(i32 %arg) {
-; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_exp10_positive_source
+; CHECK-LABEL: define nofpclass(nan ninf zero sub nnorm) float @ret_exp10_positive_source
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[UITOFP:%.*]] = uitofp i32 [[ARG]] to float
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.exp10.f32(float [[UITOFP]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan ninf zero sub nnorm) float @llvm.exp10.f32(float [[UITOFP]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%uitofp = uitofp i32 %arg to float
@@ -352,9 +352,9 @@ define float @ret_exp10_unknown_sign(float nofpclass(nan) %arg0, float nofpclass
; Can infer this doesn't return any inf
define float @ret_exp_src_known_negative_or_zero_or_nan(float nofpclass(pinf psub pnorm) %arg0) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_exp_src_known_negative_or_zero_or_nan
+; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) float @ret_exp_src_known_negative_or_zero_or_nan
; CHECK-SAME: (float nofpclass(pinf psub pnorm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.exp.f32(float nofpclass(pinf psub pnorm) [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf nzero nsub nnorm) float @llvm.exp.f32(float nofpclass(pinf psub pnorm) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.exp.f32(float %arg0)
@@ -363,9 +363,9 @@ define float @ret_exp_src_known_negative_or_zero_or_nan(float nofpclass(pinf psu
; Can infer this doesn't return any inf
define float @ret_exp_src_known_negative_nonzero_or_nan(float nofpclass(pinf psub pnorm zero) %arg0) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_exp_src_known_negative_nonzero_or_nan
+; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) float @ret_exp_src_known_negative_nonzero_or_nan
; CHECK-SAME: (float nofpclass(pinf zero psub pnorm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.exp.f32(float nofpclass(pinf zero psub pnorm) [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf nzero nsub nnorm) float @llvm.exp.f32(float nofpclass(pinf zero psub pnorm) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.exp.f32(float %arg0)
@@ -373,9 +373,9 @@ define float @ret_exp_src_known_negative_nonzero_or_nan(float nofpclass(pinf psu
}
define float @ret_exp_src_known_positive_or_zero_or_nan(float nofpclass(ninf nsub nnorm) %arg0) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_exp_src_known_positive_or_zero_or_nan
+; CHECK-LABEL: define nofpclass(ninf zero nsub nnorm) float @ret_exp_src_known_positive_or_zero_or_nan
; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.exp.f32(float nofpclass(ninf nsub nnorm) [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf zero nsub nnorm) float @llvm.exp.f32(float nofpclass(ninf nsub nnorm) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.exp.f32(float %arg0)
@@ -383,9 +383,9 @@ define float @ret_exp_src_known_positive_or_zero_or_nan(float nofpclass(ninf nsu
}
define float @ret_exp_src_known_positive_non0_or_nan(float nofpclass(ninf nsub nnorm zero) %arg0) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_exp_src_known_positive_non0_or_nan
+; CHECK-LABEL: define nofpclass(ninf zero nsub nnorm) float @ret_exp_src_known_positive_non0_or_nan
; CHECK-SAME: (float nofpclass(ninf zero nsub nnorm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.exp.f32(float nofpclass(ninf zero nsub nnorm) [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf zero nsub nnorm) float @llvm.exp.f32(float nofpclass(ninf zero nsub nnorm) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.exp.f32(float %arg0)
@@ -394,9 +394,9 @@ define float @ret_exp_src_known_positive_non0_or_nan(float nofpclass(ninf nsub n
; Can't underflow to 0, can't be denormal.
define float @ret_exp_src_known_positive_non0_nonsub_or_nan(float nofpclass(ninf sub nnorm zero) %arg0) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_exp_src_known_positive_non0_nonsub_or_nan
+; CHECK-LABEL: define nofpclass(ninf zero sub nnorm) float @ret_exp_src_known_positive_non0_nonsub_or_nan
; CHECK-SAME: (float nofpclass(ninf zero sub nnorm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.exp.f32(float nofpclass(ninf zero sub nnorm) [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf zero sub nnorm) float @llvm.exp.f32(float nofpclass(ninf zero sub nnorm) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.exp.f32(float %arg0)
@@ -405,9 +405,9 @@ define float @ret_exp_src_known_positive_non0_nonsub_or_nan(float nofpclass(ninf
; Can't underflow to denormal, but can have an input denormal stay denormal.
define float @ret_exp_src_known_positive_or_nan(float nofpclass(ninf nsub nnorm) %arg0) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_exp_src_known_positive_or_nan
+; CHECK-LABEL: define nofpclass(ninf zero nsub nnorm) float @ret_exp_src_known_positive_or_nan
; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.exp.f32(float nofpclass(ninf nsub nnorm) [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf zero nsub nnorm) float @llvm.exp.f32(float nofpclass(ninf nsub nnorm) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.exp.f32(float %arg0)
@@ -415,9 +415,9 @@ define float @ret_exp_src_known_positive_or_nan(float nofpclass(ninf nsub nnorm)
}
define float @ret_exp_src_known_positive_nonsub_or_nan(float nofpclass(ninf sub nnorm) %arg0) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_exp_src_known_positive_nonsub_or_nan
+; CHECK-LABEL: define nofpclass(ninf zero sub nnorm) float @ret_exp_src_known_positive_nonsub_or_nan
; CHECK-SAME: (float nofpclass(ninf sub nnorm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.exp.f32(float nofpclass(ninf sub nnorm) [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf zero sub nnorm) float @llvm.exp.f32(float nofpclass(ninf sub nnorm) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.exp.f32(float %arg0)
@@ -425,10 +425,10 @@ define float @ret_exp_src_known_positive_nonsub_or_nan(float nofpclass(ninf sub
}
define float @ret_exp_fabs(float %arg) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_exp_fabs
+; CHECK-LABEL: define nofpclass(ninf zero nsub nnorm) float @ret_exp_fabs
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[ARG_FABS:%.*]] = call float @llvm.fabs.f32(float [[ARG]]) #[[ATTR2]]
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.exp.f32(float [[ARG_FABS]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf zero nsub nnorm) float @llvm.exp.f32(float [[ARG_FABS]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%arg.fabs = call float @llvm.fabs.f32(float %arg)
@@ -437,11 +437,11 @@ define float @ret_exp_fabs(float %arg) {
}
define float @ret_exp_fneg_fabs(float %arg) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_exp_fneg_fabs
+; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) float @ret_exp_fneg_fabs
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[ARG_FABS:%.*]] = call float @llvm.fabs.f32(float [[ARG]]) #[[ATTR2]]
; CHECK-NEXT: [[ARG_NEG_FABS:%.*]] = fneg float [[ARG_FABS]]
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.exp.f32(float [[ARG_NEG_FABS]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf nzero nsub nnorm) float @llvm.exp.f32(float [[ARG_NEG_FABS]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%arg.fabs = call float @llvm.fabs.f32(float %arg)
|
Member
|
@llvm/pr-subscribers-llvm-analysis Author: Matt Arsenault (arsenm) ChangesTeach exp handling that positive inputs cannot introduce overflow, Full diff: https://github.com/llvm/llvm-project/pull/173430.diff 2 Files Affected:
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index d866446051fe2..9a3d11eaa38c8 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5362,6 +5362,22 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
Known.signBitMustBeZero();
}
+ if (KnownSrc.cannotBeOrderedLessThanZero()) {
+ // If the source is positive, and cannot be ~0, this cannot underflow.
+ Known.knownNot(fcPosZero);
+
+ // Cannot introduce new denormal values.
+ if (KnownSrc.isKnownNever(fcPosSubnormal))
+ Known.knownNot(fcPosSubnormal);
+ }
+
+ if (KnownSrc.cannotBeOrderedGreaterThanZero()) {
+ // If the source is negative, and cannot be infinity, this cannot
+ // overflow to infinity.
+ if (KnownSrc.isKnownNeverPosInfinity())
+ Known.knownNot(fcPosInf);
+ }
+
break;
}
case Intrinsic::fptrunc_round: {
diff --git a/llvm/test/Transforms/Attributor/nofpclass-exp.ll b/llvm/test/Transforms/Attributor/nofpclass-exp.ll
index ea5c26d101186..941e1d3981af5 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-exp.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-exp.ll
@@ -96,10 +96,10 @@ define float @ret_exp_noinf_nonegzero(float nofpclass(inf nzero) %arg0) {
}
define float @ret_exp_positive_source(i32 %arg) {
-; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_exp_positive_source
+; CHECK-LABEL: define nofpclass(nan ninf zero sub nnorm) float @ret_exp_positive_source
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[UITOFP:%.*]] = uitofp i32 [[ARG]] to float
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.exp.f32(float [[UITOFP]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan ninf zero sub nnorm) float @llvm.exp.f32(float [[UITOFP]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%uitofp = uitofp i32 %arg to float
@@ -211,10 +211,10 @@ define float @ret_exp2_noinf_nonegzero(float nofpclass(inf nzero) %arg0) {
}
define float @ret_exp2_positive_source(i32 %arg) {
-; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_exp2_positive_source
+; CHECK-LABEL: define nofpclass(nan ninf zero sub nnorm) float @ret_exp2_positive_source
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[UITOFP:%.*]] = uitofp i32 [[ARG]] to float
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.exp2.f32(float [[UITOFP]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan ninf zero sub nnorm) float @llvm.exp2.f32(float [[UITOFP]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%uitofp = uitofp i32 %arg to float
@@ -326,10 +326,10 @@ define float @ret_exp10_noinf_nonegzero(float nofpclass(inf nzero) %arg0) {
}
define float @ret_exp10_positive_source(i32 %arg) {
-; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_exp10_positive_source
+; CHECK-LABEL: define nofpclass(nan ninf zero sub nnorm) float @ret_exp10_positive_source
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[UITOFP:%.*]] = uitofp i32 [[ARG]] to float
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.exp10.f32(float [[UITOFP]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan ninf zero sub nnorm) float @llvm.exp10.f32(float [[UITOFP]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%uitofp = uitofp i32 %arg to float
@@ -352,9 +352,9 @@ define float @ret_exp10_unknown_sign(float nofpclass(nan) %arg0, float nofpclass
; Can infer this doesn't return any inf
define float @ret_exp_src_known_negative_or_zero_or_nan(float nofpclass(pinf psub pnorm) %arg0) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_exp_src_known_negative_or_zero_or_nan
+; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) float @ret_exp_src_known_negative_or_zero_or_nan
; CHECK-SAME: (float nofpclass(pinf psub pnorm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.exp.f32(float nofpclass(pinf psub pnorm) [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf nzero nsub nnorm) float @llvm.exp.f32(float nofpclass(pinf psub pnorm) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.exp.f32(float %arg0)
@@ -363,9 +363,9 @@ define float @ret_exp_src_known_negative_or_zero_or_nan(float nofpclass(pinf psu
; Can infer this doesn't return any inf
define float @ret_exp_src_known_negative_nonzero_or_nan(float nofpclass(pinf psub pnorm zero) %arg0) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_exp_src_known_negative_nonzero_or_nan
+; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) float @ret_exp_src_known_negative_nonzero_or_nan
; CHECK-SAME: (float nofpclass(pinf zero psub pnorm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.exp.f32(float nofpclass(pinf zero psub pnorm) [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf nzero nsub nnorm) float @llvm.exp.f32(float nofpclass(pinf zero psub pnorm) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.exp.f32(float %arg0)
@@ -373,9 +373,9 @@ define float @ret_exp_src_known_negative_nonzero_or_nan(float nofpclass(pinf psu
}
define float @ret_exp_src_known_positive_or_zero_or_nan(float nofpclass(ninf nsub nnorm) %arg0) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_exp_src_known_positive_or_zero_or_nan
+; CHECK-LABEL: define nofpclass(ninf zero nsub nnorm) float @ret_exp_src_known_positive_or_zero_or_nan
; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.exp.f32(float nofpclass(ninf nsub nnorm) [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf zero nsub nnorm) float @llvm.exp.f32(float nofpclass(ninf nsub nnorm) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.exp.f32(float %arg0)
@@ -383,9 +383,9 @@ define float @ret_exp_src_known_positive_or_zero_or_nan(float nofpclass(ninf nsu
}
define float @ret_exp_src_known_positive_non0_or_nan(float nofpclass(ninf nsub nnorm zero) %arg0) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_exp_src_known_positive_non0_or_nan
+; CHECK-LABEL: define nofpclass(ninf zero nsub nnorm) float @ret_exp_src_known_positive_non0_or_nan
; CHECK-SAME: (float nofpclass(ninf zero nsub nnorm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.exp.f32(float nofpclass(ninf zero nsub nnorm) [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf zero nsub nnorm) float @llvm.exp.f32(float nofpclass(ninf zero nsub nnorm) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.exp.f32(float %arg0)
@@ -394,9 +394,9 @@ define float @ret_exp_src_known_positive_non0_or_nan(float nofpclass(ninf nsub n
; Can't underflow to 0, can't be denormal.
define float @ret_exp_src_known_positive_non0_nonsub_or_nan(float nofpclass(ninf sub nnorm zero) %arg0) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_exp_src_known_positive_non0_nonsub_or_nan
+; CHECK-LABEL: define nofpclass(ninf zero sub nnorm) float @ret_exp_src_known_positive_non0_nonsub_or_nan
; CHECK-SAME: (float nofpclass(ninf zero sub nnorm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.exp.f32(float nofpclass(ninf zero sub nnorm) [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf zero sub nnorm) float @llvm.exp.f32(float nofpclass(ninf zero sub nnorm) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.exp.f32(float %arg0)
@@ -405,9 +405,9 @@ define float @ret_exp_src_known_positive_non0_nonsub_or_nan(float nofpclass(ninf
; Can't underflow to denormal, but can have an input denormal stay denormal.
define float @ret_exp_src_known_positive_or_nan(float nofpclass(ninf nsub nnorm) %arg0) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_exp_src_known_positive_or_nan
+; CHECK-LABEL: define nofpclass(ninf zero nsub nnorm) float @ret_exp_src_known_positive_or_nan
; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.exp.f32(float nofpclass(ninf nsub nnorm) [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf zero nsub nnorm) float @llvm.exp.f32(float nofpclass(ninf nsub nnorm) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.exp.f32(float %arg0)
@@ -415,9 +415,9 @@ define float @ret_exp_src_known_positive_or_nan(float nofpclass(ninf nsub nnorm)
}
define float @ret_exp_src_known_positive_nonsub_or_nan(float nofpclass(ninf sub nnorm) %arg0) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_exp_src_known_positive_nonsub_or_nan
+; CHECK-LABEL: define nofpclass(ninf zero sub nnorm) float @ret_exp_src_known_positive_nonsub_or_nan
; CHECK-SAME: (float nofpclass(ninf sub nnorm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.exp.f32(float nofpclass(ninf sub nnorm) [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf zero sub nnorm) float @llvm.exp.f32(float nofpclass(ninf sub nnorm) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.exp.f32(float %arg0)
@@ -425,10 +425,10 @@ define float @ret_exp_src_known_positive_nonsub_or_nan(float nofpclass(ninf sub
}
define float @ret_exp_fabs(float %arg) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_exp_fabs
+; CHECK-LABEL: define nofpclass(ninf zero nsub nnorm) float @ret_exp_fabs
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[ARG_FABS:%.*]] = call float @llvm.fabs.f32(float [[ARG]]) #[[ATTR2]]
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.exp.f32(float [[ARG_FABS]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf zero nsub nnorm) float @llvm.exp.f32(float [[ARG_FABS]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%arg.fabs = call float @llvm.fabs.f32(float %arg)
@@ -437,11 +437,11 @@ define float @ret_exp_fabs(float %arg) {
}
define float @ret_exp_fneg_fabs(float %arg) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_exp_fneg_fabs
+; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) float @ret_exp_fneg_fabs
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[ARG_FABS:%.*]] = call float @llvm.fabs.f32(float [[ARG]]) #[[ATTR2]]
; CHECK-NEXT: [[ARG_NEG_FABS:%.*]] = fneg float [[ARG_FABS]]
-; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.exp.f32(float [[ARG_NEG_FABS]]) #[[ATTR2]]
+; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf nzero nsub nnorm) float @llvm.exp.f32(float [[ARG_NEG_FABS]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%arg.fabs = call float @llvm.fabs.f32(float %arg)
|
🪟 Windows x64 Test Results
✅ The build succeeded and all tests passed. |
🐧 Linux x64 Test Results
✅ The build succeeded and all tests passed. |
d8af1dc to
9632f32
Compare
9435649 to
9c56f96
Compare
dtcxzyw
reviewed
Dec 24, 2025
9632f32 to
bb978d6
Compare
9c56f96 to
174db36
Compare
174db36 to
650471c
Compare
bb978d6 to
50298d2
Compare
Base automatically changed from
users/arsenm/valuetracking/add-tests-computeknownfpclass-exp-positive-negative
to
main
December 29, 2025 13:45
Teach exp handling that positive inputs cannot introduce overflow, and negative inputs cannot introduce underflow.
650471c to
d45cd7d
Compare
mahesh-attarde
pushed a commit
to mahesh-attarde/llvm-project
that referenced
this pull request
Jan 6, 2026
…73430) Teach exp handling that positive inputs cannot introduce overflow, and negative inputs cannot introduce underflow.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Teach exp handling that positive inputs cannot introduce overflow,
and negative inputs cannot introduce underflow.