-
Notifications
You must be signed in to change notification settings - Fork 15.7k
InstCombine: Introduce nsz flag on minimum/maximum in SimplifyDemandedFPClass #173898
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: users/arsenm/instcombine/simplify-demanded-fpclass-minimum-maximum
Are you sure you want to change the base?
Conversation
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
@llvm/pr-subscribers-llvm-analysis Author: Matt Arsenault (arsenm) ChangesAlive isn't particularly happy with this in the case where nsz shouldn't permit introducing a -0 result where Patch is 43.56 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/173898.diff 3 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 762f7421631b3..588aeffff8a8d 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2211,9 +2211,25 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
auto *FPOp = cast<FPMathOperator>(CI);
bool ChangedFlags = false;
+ if (!FPOp->hasNoSignedZeros()) {
+ // Add NSZ flag if we know the result will not be sensitive on the sign
+ // of 0.
+ FPClassTest ZeroMask = fcZero;
+
+ if (Mode != DenormalMode::getIEEE())
+ ZeroMask |= fcSubnormal;
+
+ bool ResultNotLogical0 = (ValidResults & ZeroMask) == fcNone;
+ if (ResultNotLogical0 ||
+ ((KnownLHS.isKnownNeverLogicalNegZero(Mode) ||
+ KnownRHS.isKnownNeverLogicalPosZero(Mode)) &&
+ (KnownLHS.isKnownNeverLogicalPosZero(Mode) ||
+ KnownRHS.isKnownNeverLogicalNegZero(Mode)))) {
+ CI->setHasNoSignedZeros(true);
+ ChangedFlags = true;
+ }
+ }
- // TODO: Add NSZ flag if we know the result will not be sensitive on the
- // sign of 0.
if (!FPOp->hasNoNaNs() && (ValidResults & fcNan) == fcNone) {
CI->setHasNoNaNs(true);
ChangedFlags = true;
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll
index b7c41ff6c3c64..9a81edbf06b96 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll
@@ -34,7 +34,7 @@ define nofpclass(inf norm sub zero) float @ret_only_nan(float %x, float %y) {
define nofpclass(inf norm sub zero qnan) float @ret_only_snan(float %x, float %y) {
; CHECK-LABEL: define nofpclass(qnan inf zero sub norm) float @ret_only_snan(
; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[X]], float [[Y]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %x, float %y)
@@ -44,7 +44,7 @@ define nofpclass(inf norm sub zero qnan) float @ret_only_snan(float %x, float %y
define nofpclass(inf norm sub zero snan) float @ret_only_qnan(float %x, float %y) {
; CHECK-LABEL: define nofpclass(snan inf zero sub norm) float @ret_only_qnan(
; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[X]], float [[Y]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %x, float %y)
@@ -54,7 +54,7 @@ define nofpclass(inf norm sub zero snan) float @ret_only_qnan(float %x, float %y
define nofpclass(nan norm sub zero) float @ret_only_inf(float %x, float %y) {
; CHECK-LABEL: define nofpclass(nan zero sub norm) float @ret_only_inf(
; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nnan nsz float @llvm.maximum.f32(float [[X]], float [[Y]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %x, float %y)
@@ -364,7 +364,7 @@ define nofpclass(snan) float @cannot_fold_negative_or_zero__positive_or_zero_1()
define nofpclass(nsub) float @lhs_must_be_pinf_or_nan(float %unknown, float nofpclass(ninf norm zero sub) %must.be.pinf.or.nan) {
; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_pinf_or_nan(
; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(ninf zero sub norm) [[MUST_BE_PINF_OR_NAN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[MUST_BE_PINF_OR_NAN]], float [[UNKNOWN]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[MUST_BE_PINF_OR_NAN]], float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %must.be.pinf.or.nan, float %unknown)
@@ -374,7 +374,7 @@ define nofpclass(nsub) float @lhs_must_be_pinf_or_nan(float %unknown, float nofp
define nofpclass(nsub) float @rhs_must_be_pinf_or_nan(float nofpclass(ninf norm zero sub) %must.be.pinf.or.nan, float %unknown) {
; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_pinf_or_nan(
; CHECK-SAME: float nofpclass(ninf zero sub norm) [[MUST_BE_PINF_OR_NAN:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN]], float [[MUST_BE_PINF_OR_NAN]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN]], float [[MUST_BE_PINF_OR_NAN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown, float %must.be.pinf.or.nan)
@@ -384,7 +384,7 @@ define nofpclass(nsub) float @rhs_must_be_pinf_or_nan(float nofpclass(ninf norm
define nofpclass(nsub) float @lhs_must_be_pinf(float %unknown, float nofpclass(nan ninf norm zero sub) %must.be.pinf) {
; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_pinf(
; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN]], float 0x7FF0000000000000)
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN]], float 0x7FF0000000000000)
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %must.be.pinf, float %unknown)
@@ -394,7 +394,7 @@ define nofpclass(nsub) float @lhs_must_be_pinf(float %unknown, float nofpclass(n
define nofpclass(nsub) float @rhs_must_be_pinf(float nofpclass(nan ninf norm zero sub) %must.be.pinf, float %unknown) {
; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_pinf(
; CHECK-SAME: float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN]], float 0x7FF0000000000000)
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN]], float 0x7FF0000000000000)
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown, float %must.be.pinf)
@@ -424,7 +424,7 @@ define nofpclass(nsub) float @rhs_must_be_pinf_lhs_non_nan(float nofpclass(nan n
define nofpclass(nsub) float @lhs_must_be_ninf_or_nan(float %unknown, float nofpclass(pinf norm zero sub) %must.be.ninf.or.nan) {
; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_ninf_or_nan(
; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(pinf zero sub norm) [[MUST_BE_NINF_OR_NAN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[MUST_BE_NINF_OR_NAN]], float [[UNKNOWN]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[MUST_BE_NINF_OR_NAN]], float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %must.be.ninf.or.nan, float %unknown)
@@ -434,7 +434,7 @@ define nofpclass(nsub) float @lhs_must_be_ninf_or_nan(float %unknown, float nofp
define nofpclass(nsub) float @rhs_must_be_ninf_or_nan(float nofpclass(pinf norm zero sub) %must.be.ninf.or.nan, float %unknown) {
; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_ninf_or_nan(
; CHECK-SAME: float nofpclass(pinf zero sub norm) [[MUST_BE_NINF_OR_NAN:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN]], float [[MUST_BE_NINF_OR_NAN]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN]], float [[MUST_BE_NINF_OR_NAN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown, float %must.be.ninf.or.nan)
@@ -503,7 +503,7 @@ define nofpclass(pzero) float @result_not_pzero(float %unknown0, float %unknown1
define nofpclass(zero) float @result_not_zero(float %unknown0, float %unknown1) {
; CHECK-LABEL: define nofpclass(zero) float @result_not_zero(
; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown0, float %unknown1)
@@ -533,7 +533,7 @@ define nofpclass(zero) float @result_not_zero__dynamic(float %unknown0, float %u
define nofpclass(zero) float @result_not_zero_or_sub(float %unknown0, float %unknown1) {
; CHECK-LABEL: define nofpclass(zero) float @result_not_zero_or_sub(
; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown0, float %unknown1)
@@ -543,7 +543,7 @@ define nofpclass(zero) float @result_not_zero_or_sub(float %unknown0, float %unk
define nofpclass(zero sub) float @result_not_zero_or_sub__daz(float %unknown0, float %unknown1) #0 {
; CHECK-LABEL: define nofpclass(zero sub) float @result_not_zero_or_sub__daz(
; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown0, float %unknown1)
@@ -553,7 +553,7 @@ define nofpclass(zero sub) float @result_not_zero_or_sub__daz(float %unknown0, f
define nofpclass(zero sub) float @result_not_zero_or_sub__dynamic(float %unknown0, float %unknown1) #1 {
; CHECK-LABEL: define nofpclass(zero sub) float @result_not_zero_or_sub__dynamic(
; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown0, float %unknown1)
@@ -563,7 +563,7 @@ define nofpclass(zero sub) float @result_not_zero_or_sub__dynamic(float %unknown
define nofpclass(snan) float @lhs_not_zero(float nofpclass(zero) %not.zero, float %unknown) {
; CHECK-LABEL: define nofpclass(snan) float @lhs_not_zero(
; CHECK-SAME: float nofpclass(zero) [[NOT_ZERO:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_ZERO]], float [[UNKNOWN]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_ZERO]], float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.zero, float %unknown)
@@ -573,7 +573,7 @@ define nofpclass(snan) float @lhs_not_zero(float nofpclass(zero) %not.zero, floa
define nofpclass(snan) float @rhs_not_zero(float %unknown, float nofpclass(zero) %not.zero) {
; CHECK-LABEL: define nofpclass(snan) float @rhs_not_zero(
; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(zero) [[NOT_ZERO:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN]], float [[NOT_ZERO]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN]], float [[NOT_ZERO]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown, float %not.zero)
@@ -583,7 +583,7 @@ define nofpclass(snan) float @rhs_not_zero(float %unknown, float nofpclass(zero)
define nofpclass(snan) float @sources_not_zero(float nofpclass(zero) %not.zero0, float nofpclass(zero) %not.zero1) {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero(
; CHECK-SAME: float nofpclass(zero) [[NOT_ZERO0:%.*]], float nofpclass(zero) [[NOT_ZERO1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_ZERO0]], float [[NOT_ZERO1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_ZERO0]], float [[NOT_ZERO1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.zero0, float %not.zero1)
@@ -603,7 +603,7 @@ define nofpclass(snan) float @sources_not_zero__daz(float nofpclass(zero) %not.z
define nofpclass(snan) float @sources_not_zero__dynamic(float nofpclass(zero) %not.zero0, float nofpclass(zero) %not.zero1) #2 {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero__dynamic(
; CHECK-SAME: float nofpclass(zero) [[NOT_ZERO0:%.*]], float nofpclass(zero) [[NOT_ZERO1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_ZERO0]], float [[NOT_ZERO1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_ZERO0]], float [[NOT_ZERO1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.zero0, float %not.zero1)
@@ -613,7 +613,7 @@ define nofpclass(snan) float @sources_not_zero__dynamic(float nofpclass(zero) %n
define nofpclass(snan) float @sources_not_zero_or_sub(float nofpclass(zero sub) %not.zero.sub.0, float nofpclass(zero sub) %not.zero.sub.1) {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero_or_sub(
; CHECK-SAME: float nofpclass(zero sub) [[NOT_ZERO_SUB_0:%.*]], float nofpclass(zero sub) [[NOT_ZERO_SUB_1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.zero.sub.0, float %not.zero.sub.1)
@@ -623,7 +623,7 @@ define nofpclass(snan) float @sources_not_zero_or_sub(float nofpclass(zero sub)
define nofpclass(snan) float @sources_not_zero_or_sub__daz(float nofpclass(zero sub) %not.zero.sub.0, float nofpclass(zero sub) %not.zero.sub.1) #1 {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero_or_sub__daz(
; CHECK-SAME: float nofpclass(zero sub) [[NOT_ZERO_SUB_0:%.*]], float nofpclass(zero sub) [[NOT_ZERO_SUB_1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.zero.sub.0, float %not.zero.sub.1)
@@ -633,7 +633,7 @@ define nofpclass(snan) float @sources_not_zero_or_sub__daz(float nofpclass(zero
define nofpclass(snan) float @sources_not_zero_or_sub__dynamic(float nofpclass(zero sub) %not.zero.sub.0, float nofpclass(zero sub) %not.zero.sub.1) #2 {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero_or_sub__dynamic(
; CHECK-SAME: float nofpclass(zero sub) [[NOT_ZERO_SUB_0:%.*]], float nofpclass(zero sub) [[NOT_ZERO_SUB_1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.zero.sub.0, float %not.zero.sub.1)
@@ -643,7 +643,7 @@ define nofpclass(snan) float @sources_not_zero_or_sub__dynamic(float nofpclass(z
define nofpclass(snan) float @sources_not_nzero(float nofpclass(nzero) %not.nzero0, float nofpclass(nzero) %not.nzero1) {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_nzero(
; CHECK-SAME: float nofpclass(nzero) [[NOT_NZERO0:%.*]], float nofpclass(nzero) [[NOT_NZERO1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_NZERO0]], float [[NOT_NZERO1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_NZERO0]], float [[NOT_NZERO1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.nzero0, float %not.nzero1)
@@ -653,7 +653,7 @@ define nofpclass(snan) float @sources_not_nzero(float nofpclass(nzero) %not.nzer
define nofpclass(snan) float @sources_not_pzero(float nofpclass(pzero) %not.pzero0, float nofpclass(pzero) %not.pzero1) {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_pzero(
; CHECK-SAME: float nofpclass(pzero) [[NOT_PZERO0:%.*]], float nofpclass(pzero) [[NOT_PZERO1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_PZERO0]], float [[NOT_PZERO1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_PZERO0]], float [[NOT_PZERO1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.pzero0, float %not.pzero1)
@@ -723,7 +723,7 @@ define nofpclass(snan) float @rhs_not_nzero_lhs_not_pzero__dynamic(float nofpcla
define nofpclass(snan) float @sources_not_nzero_nsub__dynamic(float nofpclass(nzero nsub) %not.nzero0, float nofpclass(nzero nsub) %not.nzero1) #1 {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_nzero_nsub__dynamic(
; CHECK-SAME: float nofpclass(nzero nsub) [[NOT_NZERO0:%.*]], float nofpclass(nzero nsub) [[NOT_NZERO1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_NZERO0]], float [[NOT_NZERO1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_NZERO0]], float [[NOT_NZERO1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.nzero0, float %not.nzero1)
@@ -916,7 +916,7 @@ define nofpclass(snan) float @known_positive__maximum__only_pzero() {
; CHECK-LABEL: define nofpclass(snan) float @known_positive__maximum__only_pzero() {
; CHECK-NEXT: [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
; CHECK-NEXT: [[KNOWN_PZERO:%.*]] = call float @returns_pzero()
-; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[KNOWN_POSITIVE]], float 0.000000e+00)
+; CHECK-NEXT: [[RESULT:%.*]] = call nnan nsz float @llvm.maximum.f32(float [[KNOWN_POSITIVE]], float 0.000000e+00)
; CHECK-NEXT: ret float [[RESULT]]
;
%known.positive = call float @returns_positive()
@@ -929,7 +929,7 @@ define nofpclass(snan) float @only_pzero__maximum__known_positive() {
; CHECK-LABEL: define nofpclass(snan) float @only_pzero__maximum__known_positive() {
; CHECK-NEXT: [[KNOWN_PZERO:%.*]] = call float @returns_pzero()
; CHECK-NEXT: [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
-; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[KNOWN_POSITIVE]], float 0.000000e+00)
+; CHECK-NEXT: [[RESULT:%.*]] = call nnan nsz float @llvm.maximum.f32(float [[KNOWN_POSITIVE]], float 0.000000e+00)
; CHECK-NEXT: ret float [[RESULT]]
;
%known.pzero = call float @returns_pzero()
@@ -1018,7 +1018,7 @@ define nofpclass(snan) float @known_negative__maximum__only_nzero_or_nan() {
; CHECK-LABEL: define nofpclass(snan) float @known_negative__maximum__only_nzero_or_nan() {
; CHECK-NEXT: [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
; CHECK-NEXT: [[KNOWN_NZERO_OR_NAN:%.*]] = call float @returns_nzero_or_nan()
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[KNOWN_NEGATIVE]], float [[KNOWN_NZERO_OR_NAN]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[KNOWN_NEGATIVE]], float [[KNOWN_NZERO_OR_NAN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%known.negative = call float @returns_negative()
@@ -1031,7 +1031,7 @@ define nofpclass(snan) float @only_nzero_or_nan__maximum__known_negative() {
; CHECK-LABEL: define nofpclass(snan) float @only_nzero_or_nan__maximum__known_negative() {
; CHECK-NEXT: [[KNOWN_NZERO_O...
[truncated]
|
|
@llvm/pr-subscribers-llvm-transforms Author: Matt Arsenault (arsenm) ChangesAlive isn't particularly happy with this in the case where nsz shouldn't permit introducing a -0 result where Patch is 43.56 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/173898.diff 3 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 762f7421631b3..588aeffff8a8d 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2211,9 +2211,25 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
auto *FPOp = cast<FPMathOperator>(CI);
bool ChangedFlags = false;
+ if (!FPOp->hasNoSignedZeros()) {
+ // Add NSZ flag if we know the result will not be sensitive on the sign
+ // of 0.
+ FPClassTest ZeroMask = fcZero;
+
+ if (Mode != DenormalMode::getIEEE())
+ ZeroMask |= fcSubnormal;
+
+ bool ResultNotLogical0 = (ValidResults & ZeroMask) == fcNone;
+ if (ResultNotLogical0 ||
+ ((KnownLHS.isKnownNeverLogicalNegZero(Mode) ||
+ KnownRHS.isKnownNeverLogicalPosZero(Mode)) &&
+ (KnownLHS.isKnownNeverLogicalPosZero(Mode) ||
+ KnownRHS.isKnownNeverLogicalNegZero(Mode)))) {
+ CI->setHasNoSignedZeros(true);
+ ChangedFlags = true;
+ }
+ }
- // TODO: Add NSZ flag if we know the result will not be sensitive on the
- // sign of 0.
if (!FPOp->hasNoNaNs() && (ValidResults & fcNan) == fcNone) {
CI->setHasNoNaNs(true);
ChangedFlags = true;
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll
index b7c41ff6c3c64..9a81edbf06b96 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll
@@ -34,7 +34,7 @@ define nofpclass(inf norm sub zero) float @ret_only_nan(float %x, float %y) {
define nofpclass(inf norm sub zero qnan) float @ret_only_snan(float %x, float %y) {
; CHECK-LABEL: define nofpclass(qnan inf zero sub norm) float @ret_only_snan(
; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[X]], float [[Y]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %x, float %y)
@@ -44,7 +44,7 @@ define nofpclass(inf norm sub zero qnan) float @ret_only_snan(float %x, float %y
define nofpclass(inf norm sub zero snan) float @ret_only_qnan(float %x, float %y) {
; CHECK-LABEL: define nofpclass(snan inf zero sub norm) float @ret_only_qnan(
; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[X]], float [[Y]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %x, float %y)
@@ -54,7 +54,7 @@ define nofpclass(inf norm sub zero snan) float @ret_only_qnan(float %x, float %y
define nofpclass(nan norm sub zero) float @ret_only_inf(float %x, float %y) {
; CHECK-LABEL: define nofpclass(nan zero sub norm) float @ret_only_inf(
; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nnan nsz float @llvm.maximum.f32(float [[X]], float [[Y]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %x, float %y)
@@ -364,7 +364,7 @@ define nofpclass(snan) float @cannot_fold_negative_or_zero__positive_or_zero_1()
define nofpclass(nsub) float @lhs_must_be_pinf_or_nan(float %unknown, float nofpclass(ninf norm zero sub) %must.be.pinf.or.nan) {
; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_pinf_or_nan(
; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(ninf zero sub norm) [[MUST_BE_PINF_OR_NAN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[MUST_BE_PINF_OR_NAN]], float [[UNKNOWN]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[MUST_BE_PINF_OR_NAN]], float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %must.be.pinf.or.nan, float %unknown)
@@ -374,7 +374,7 @@ define nofpclass(nsub) float @lhs_must_be_pinf_or_nan(float %unknown, float nofp
define nofpclass(nsub) float @rhs_must_be_pinf_or_nan(float nofpclass(ninf norm zero sub) %must.be.pinf.or.nan, float %unknown) {
; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_pinf_or_nan(
; CHECK-SAME: float nofpclass(ninf zero sub norm) [[MUST_BE_PINF_OR_NAN:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN]], float [[MUST_BE_PINF_OR_NAN]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN]], float [[MUST_BE_PINF_OR_NAN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown, float %must.be.pinf.or.nan)
@@ -384,7 +384,7 @@ define nofpclass(nsub) float @rhs_must_be_pinf_or_nan(float nofpclass(ninf norm
define nofpclass(nsub) float @lhs_must_be_pinf(float %unknown, float nofpclass(nan ninf norm zero sub) %must.be.pinf) {
; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_pinf(
; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN]], float 0x7FF0000000000000)
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN]], float 0x7FF0000000000000)
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %must.be.pinf, float %unknown)
@@ -394,7 +394,7 @@ define nofpclass(nsub) float @lhs_must_be_pinf(float %unknown, float nofpclass(n
define nofpclass(nsub) float @rhs_must_be_pinf(float nofpclass(nan ninf norm zero sub) %must.be.pinf, float %unknown) {
; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_pinf(
; CHECK-SAME: float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN]], float 0x7FF0000000000000)
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN]], float 0x7FF0000000000000)
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown, float %must.be.pinf)
@@ -424,7 +424,7 @@ define nofpclass(nsub) float @rhs_must_be_pinf_lhs_non_nan(float nofpclass(nan n
define nofpclass(nsub) float @lhs_must_be_ninf_or_nan(float %unknown, float nofpclass(pinf norm zero sub) %must.be.ninf.or.nan) {
; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_ninf_or_nan(
; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(pinf zero sub norm) [[MUST_BE_NINF_OR_NAN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[MUST_BE_NINF_OR_NAN]], float [[UNKNOWN]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[MUST_BE_NINF_OR_NAN]], float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %must.be.ninf.or.nan, float %unknown)
@@ -434,7 +434,7 @@ define nofpclass(nsub) float @lhs_must_be_ninf_or_nan(float %unknown, float nofp
define nofpclass(nsub) float @rhs_must_be_ninf_or_nan(float nofpclass(pinf norm zero sub) %must.be.ninf.or.nan, float %unknown) {
; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_ninf_or_nan(
; CHECK-SAME: float nofpclass(pinf zero sub norm) [[MUST_BE_NINF_OR_NAN:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN]], float [[MUST_BE_NINF_OR_NAN]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN]], float [[MUST_BE_NINF_OR_NAN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown, float %must.be.ninf.or.nan)
@@ -503,7 +503,7 @@ define nofpclass(pzero) float @result_not_pzero(float %unknown0, float %unknown1
define nofpclass(zero) float @result_not_zero(float %unknown0, float %unknown1) {
; CHECK-LABEL: define nofpclass(zero) float @result_not_zero(
; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown0, float %unknown1)
@@ -533,7 +533,7 @@ define nofpclass(zero) float @result_not_zero__dynamic(float %unknown0, float %u
define nofpclass(zero) float @result_not_zero_or_sub(float %unknown0, float %unknown1) {
; CHECK-LABEL: define nofpclass(zero) float @result_not_zero_or_sub(
; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown0, float %unknown1)
@@ -543,7 +543,7 @@ define nofpclass(zero) float @result_not_zero_or_sub(float %unknown0, float %unk
define nofpclass(zero sub) float @result_not_zero_or_sub__daz(float %unknown0, float %unknown1) #0 {
; CHECK-LABEL: define nofpclass(zero sub) float @result_not_zero_or_sub__daz(
; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown0, float %unknown1)
@@ -553,7 +553,7 @@ define nofpclass(zero sub) float @result_not_zero_or_sub__daz(float %unknown0, f
define nofpclass(zero sub) float @result_not_zero_or_sub__dynamic(float %unknown0, float %unknown1) #1 {
; CHECK-LABEL: define nofpclass(zero sub) float @result_not_zero_or_sub__dynamic(
; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown0, float %unknown1)
@@ -563,7 +563,7 @@ define nofpclass(zero sub) float @result_not_zero_or_sub__dynamic(float %unknown
define nofpclass(snan) float @lhs_not_zero(float nofpclass(zero) %not.zero, float %unknown) {
; CHECK-LABEL: define nofpclass(snan) float @lhs_not_zero(
; CHECK-SAME: float nofpclass(zero) [[NOT_ZERO:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_ZERO]], float [[UNKNOWN]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_ZERO]], float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.zero, float %unknown)
@@ -573,7 +573,7 @@ define nofpclass(snan) float @lhs_not_zero(float nofpclass(zero) %not.zero, floa
define nofpclass(snan) float @rhs_not_zero(float %unknown, float nofpclass(zero) %not.zero) {
; CHECK-LABEL: define nofpclass(snan) float @rhs_not_zero(
; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(zero) [[NOT_ZERO:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN]], float [[NOT_ZERO]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN]], float [[NOT_ZERO]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown, float %not.zero)
@@ -583,7 +583,7 @@ define nofpclass(snan) float @rhs_not_zero(float %unknown, float nofpclass(zero)
define nofpclass(snan) float @sources_not_zero(float nofpclass(zero) %not.zero0, float nofpclass(zero) %not.zero1) {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero(
; CHECK-SAME: float nofpclass(zero) [[NOT_ZERO0:%.*]], float nofpclass(zero) [[NOT_ZERO1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_ZERO0]], float [[NOT_ZERO1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_ZERO0]], float [[NOT_ZERO1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.zero0, float %not.zero1)
@@ -603,7 +603,7 @@ define nofpclass(snan) float @sources_not_zero__daz(float nofpclass(zero) %not.z
define nofpclass(snan) float @sources_not_zero__dynamic(float nofpclass(zero) %not.zero0, float nofpclass(zero) %not.zero1) #2 {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero__dynamic(
; CHECK-SAME: float nofpclass(zero) [[NOT_ZERO0:%.*]], float nofpclass(zero) [[NOT_ZERO1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_ZERO0]], float [[NOT_ZERO1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_ZERO0]], float [[NOT_ZERO1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.zero0, float %not.zero1)
@@ -613,7 +613,7 @@ define nofpclass(snan) float @sources_not_zero__dynamic(float nofpclass(zero) %n
define nofpclass(snan) float @sources_not_zero_or_sub(float nofpclass(zero sub) %not.zero.sub.0, float nofpclass(zero sub) %not.zero.sub.1) {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero_or_sub(
; CHECK-SAME: float nofpclass(zero sub) [[NOT_ZERO_SUB_0:%.*]], float nofpclass(zero sub) [[NOT_ZERO_SUB_1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.zero.sub.0, float %not.zero.sub.1)
@@ -623,7 +623,7 @@ define nofpclass(snan) float @sources_not_zero_or_sub(float nofpclass(zero sub)
define nofpclass(snan) float @sources_not_zero_or_sub__daz(float nofpclass(zero sub) %not.zero.sub.0, float nofpclass(zero sub) %not.zero.sub.1) #1 {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero_or_sub__daz(
; CHECK-SAME: float nofpclass(zero sub) [[NOT_ZERO_SUB_0:%.*]], float nofpclass(zero sub) [[NOT_ZERO_SUB_1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.zero.sub.0, float %not.zero.sub.1)
@@ -633,7 +633,7 @@ define nofpclass(snan) float @sources_not_zero_or_sub__daz(float nofpclass(zero
define nofpclass(snan) float @sources_not_zero_or_sub__dynamic(float nofpclass(zero sub) %not.zero.sub.0, float nofpclass(zero sub) %not.zero.sub.1) #2 {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero_or_sub__dynamic(
; CHECK-SAME: float nofpclass(zero sub) [[NOT_ZERO_SUB_0:%.*]], float nofpclass(zero sub) [[NOT_ZERO_SUB_1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.zero.sub.0, float %not.zero.sub.1)
@@ -643,7 +643,7 @@ define nofpclass(snan) float @sources_not_zero_or_sub__dynamic(float nofpclass(z
define nofpclass(snan) float @sources_not_nzero(float nofpclass(nzero) %not.nzero0, float nofpclass(nzero) %not.nzero1) {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_nzero(
; CHECK-SAME: float nofpclass(nzero) [[NOT_NZERO0:%.*]], float nofpclass(nzero) [[NOT_NZERO1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_NZERO0]], float [[NOT_NZERO1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_NZERO0]], float [[NOT_NZERO1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.nzero0, float %not.nzero1)
@@ -653,7 +653,7 @@ define nofpclass(snan) float @sources_not_nzero(float nofpclass(nzero) %not.nzer
define nofpclass(snan) float @sources_not_pzero(float nofpclass(pzero) %not.pzero0, float nofpclass(pzero) %not.pzero1) {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_pzero(
; CHECK-SAME: float nofpclass(pzero) [[NOT_PZERO0:%.*]], float nofpclass(pzero) [[NOT_PZERO1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_PZERO0]], float [[NOT_PZERO1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_PZERO0]], float [[NOT_PZERO1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.pzero0, float %not.pzero1)
@@ -723,7 +723,7 @@ define nofpclass(snan) float @rhs_not_nzero_lhs_not_pzero__dynamic(float nofpcla
define nofpclass(snan) float @sources_not_nzero_nsub__dynamic(float nofpclass(nzero nsub) %not.nzero0, float nofpclass(nzero nsub) %not.nzero1) #1 {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_nzero_nsub__dynamic(
; CHECK-SAME: float nofpclass(nzero nsub) [[NOT_NZERO0:%.*]], float nofpclass(nzero nsub) [[NOT_NZERO1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_NZERO0]], float [[NOT_NZERO1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_NZERO0]], float [[NOT_NZERO1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.nzero0, float %not.nzero1)
@@ -916,7 +916,7 @@ define nofpclass(snan) float @known_positive__maximum__only_pzero() {
; CHECK-LABEL: define nofpclass(snan) float @known_positive__maximum__only_pzero() {
; CHECK-NEXT: [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
; CHECK-NEXT: [[KNOWN_PZERO:%.*]] = call float @returns_pzero()
-; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[KNOWN_POSITIVE]], float 0.000000e+00)
+; CHECK-NEXT: [[RESULT:%.*]] = call nnan nsz float @llvm.maximum.f32(float [[KNOWN_POSITIVE]], float 0.000000e+00)
; CHECK-NEXT: ret float [[RESULT]]
;
%known.positive = call float @returns_positive()
@@ -929,7 +929,7 @@ define nofpclass(snan) float @only_pzero__maximum__known_positive() {
; CHECK-LABEL: define nofpclass(snan) float @only_pzero__maximum__known_positive() {
; CHECK-NEXT: [[KNOWN_PZERO:%.*]] = call float @returns_pzero()
; CHECK-NEXT: [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
-; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[KNOWN_POSITIVE]], float 0.000000e+00)
+; CHECK-NEXT: [[RESULT:%.*]] = call nnan nsz float @llvm.maximum.f32(float [[KNOWN_POSITIVE]], float 0.000000e+00)
; CHECK-NEXT: ret float [[RESULT]]
;
%known.pzero = call float @returns_pzero()
@@ -1018,7 +1018,7 @@ define nofpclass(snan) float @known_negative__maximum__only_nzero_or_nan() {
; CHECK-LABEL: define nofpclass(snan) float @known_negative__maximum__only_nzero_or_nan() {
; CHECK-NEXT: [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
; CHECK-NEXT: [[KNOWN_NZERO_OR_NAN:%.*]] = call float @returns_nzero_or_nan()
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[KNOWN_NEGATIVE]], float [[KNOWN_NZERO_OR_NAN]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[KNOWN_NEGATIVE]], float [[KNOWN_NZERO_OR_NAN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%known.negative = call float @returns_negative()
@@ -1031,7 +1031,7 @@ define nofpclass(snan) float @only_nzero_or_nan__maximum__known_negative() {
; CHECK-LABEL: define nofpclass(snan) float @only_nzero_or_nan__maximum__known_negative() {
; CHECK-NEXT: [[KNOWN_NZERO_O...
[truncated]
|
|
@llvm/pr-subscribers-llvm-support Author: Matt Arsenault (arsenm) ChangesAlive isn't particularly happy with this in the case where nsz shouldn't permit introducing a -0 result where Patch is 43.56 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/173898.diff 3 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 762f7421631b3..588aeffff8a8d 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2211,9 +2211,25 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
auto *FPOp = cast<FPMathOperator>(CI);
bool ChangedFlags = false;
+ if (!FPOp->hasNoSignedZeros()) {
+ // Add NSZ flag if we know the result will not be sensitive on the sign
+ // of 0.
+ FPClassTest ZeroMask = fcZero;
+
+ if (Mode != DenormalMode::getIEEE())
+ ZeroMask |= fcSubnormal;
+
+ bool ResultNotLogical0 = (ValidResults & ZeroMask) == fcNone;
+ if (ResultNotLogical0 ||
+ ((KnownLHS.isKnownNeverLogicalNegZero(Mode) ||
+ KnownRHS.isKnownNeverLogicalPosZero(Mode)) &&
+ (KnownLHS.isKnownNeverLogicalPosZero(Mode) ||
+ KnownRHS.isKnownNeverLogicalNegZero(Mode)))) {
+ CI->setHasNoSignedZeros(true);
+ ChangedFlags = true;
+ }
+ }
- // TODO: Add NSZ flag if we know the result will not be sensitive on the
- // sign of 0.
if (!FPOp->hasNoNaNs() && (ValidResults & fcNan) == fcNone) {
CI->setHasNoNaNs(true);
ChangedFlags = true;
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll
index b7c41ff6c3c64..9a81edbf06b96 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll
@@ -34,7 +34,7 @@ define nofpclass(inf norm sub zero) float @ret_only_nan(float %x, float %y) {
define nofpclass(inf norm sub zero qnan) float @ret_only_snan(float %x, float %y) {
; CHECK-LABEL: define nofpclass(qnan inf zero sub norm) float @ret_only_snan(
; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[X]], float [[Y]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %x, float %y)
@@ -44,7 +44,7 @@ define nofpclass(inf norm sub zero qnan) float @ret_only_snan(float %x, float %y
define nofpclass(inf norm sub zero snan) float @ret_only_qnan(float %x, float %y) {
; CHECK-LABEL: define nofpclass(snan inf zero sub norm) float @ret_only_qnan(
; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[X]], float [[Y]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %x, float %y)
@@ -54,7 +54,7 @@ define nofpclass(inf norm sub zero snan) float @ret_only_qnan(float %x, float %y
define nofpclass(nan norm sub zero) float @ret_only_inf(float %x, float %y) {
; CHECK-LABEL: define nofpclass(nan zero sub norm) float @ret_only_inf(
; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nnan nsz float @llvm.maximum.f32(float [[X]], float [[Y]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %x, float %y)
@@ -364,7 +364,7 @@ define nofpclass(snan) float @cannot_fold_negative_or_zero__positive_or_zero_1()
define nofpclass(nsub) float @lhs_must_be_pinf_or_nan(float %unknown, float nofpclass(ninf norm zero sub) %must.be.pinf.or.nan) {
; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_pinf_or_nan(
; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(ninf zero sub norm) [[MUST_BE_PINF_OR_NAN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[MUST_BE_PINF_OR_NAN]], float [[UNKNOWN]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[MUST_BE_PINF_OR_NAN]], float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %must.be.pinf.or.nan, float %unknown)
@@ -374,7 +374,7 @@ define nofpclass(nsub) float @lhs_must_be_pinf_or_nan(float %unknown, float nofp
define nofpclass(nsub) float @rhs_must_be_pinf_or_nan(float nofpclass(ninf norm zero sub) %must.be.pinf.or.nan, float %unknown) {
; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_pinf_or_nan(
; CHECK-SAME: float nofpclass(ninf zero sub norm) [[MUST_BE_PINF_OR_NAN:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN]], float [[MUST_BE_PINF_OR_NAN]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN]], float [[MUST_BE_PINF_OR_NAN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown, float %must.be.pinf.or.nan)
@@ -384,7 +384,7 @@ define nofpclass(nsub) float @rhs_must_be_pinf_or_nan(float nofpclass(ninf norm
define nofpclass(nsub) float @lhs_must_be_pinf(float %unknown, float nofpclass(nan ninf norm zero sub) %must.be.pinf) {
; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_pinf(
; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN]], float 0x7FF0000000000000)
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN]], float 0x7FF0000000000000)
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %must.be.pinf, float %unknown)
@@ -394,7 +394,7 @@ define nofpclass(nsub) float @lhs_must_be_pinf(float %unknown, float nofpclass(n
define nofpclass(nsub) float @rhs_must_be_pinf(float nofpclass(nan ninf norm zero sub) %must.be.pinf, float %unknown) {
; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_pinf(
; CHECK-SAME: float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN]], float 0x7FF0000000000000)
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN]], float 0x7FF0000000000000)
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown, float %must.be.pinf)
@@ -424,7 +424,7 @@ define nofpclass(nsub) float @rhs_must_be_pinf_lhs_non_nan(float nofpclass(nan n
define nofpclass(nsub) float @lhs_must_be_ninf_or_nan(float %unknown, float nofpclass(pinf norm zero sub) %must.be.ninf.or.nan) {
; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_ninf_or_nan(
; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(pinf zero sub norm) [[MUST_BE_NINF_OR_NAN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[MUST_BE_NINF_OR_NAN]], float [[UNKNOWN]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[MUST_BE_NINF_OR_NAN]], float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %must.be.ninf.or.nan, float %unknown)
@@ -434,7 +434,7 @@ define nofpclass(nsub) float @lhs_must_be_ninf_or_nan(float %unknown, float nofp
define nofpclass(nsub) float @rhs_must_be_ninf_or_nan(float nofpclass(pinf norm zero sub) %must.be.ninf.or.nan, float %unknown) {
; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_ninf_or_nan(
; CHECK-SAME: float nofpclass(pinf zero sub norm) [[MUST_BE_NINF_OR_NAN:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN]], float [[MUST_BE_NINF_OR_NAN]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN]], float [[MUST_BE_NINF_OR_NAN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown, float %must.be.ninf.or.nan)
@@ -503,7 +503,7 @@ define nofpclass(pzero) float @result_not_pzero(float %unknown0, float %unknown1
define nofpclass(zero) float @result_not_zero(float %unknown0, float %unknown1) {
; CHECK-LABEL: define nofpclass(zero) float @result_not_zero(
; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown0, float %unknown1)
@@ -533,7 +533,7 @@ define nofpclass(zero) float @result_not_zero__dynamic(float %unknown0, float %u
define nofpclass(zero) float @result_not_zero_or_sub(float %unknown0, float %unknown1) {
; CHECK-LABEL: define nofpclass(zero) float @result_not_zero_or_sub(
; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown0, float %unknown1)
@@ -543,7 +543,7 @@ define nofpclass(zero) float @result_not_zero_or_sub(float %unknown0, float %unk
define nofpclass(zero sub) float @result_not_zero_or_sub__daz(float %unknown0, float %unknown1) #0 {
; CHECK-LABEL: define nofpclass(zero sub) float @result_not_zero_or_sub__daz(
; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown0, float %unknown1)
@@ -553,7 +553,7 @@ define nofpclass(zero sub) float @result_not_zero_or_sub__daz(float %unknown0, f
define nofpclass(zero sub) float @result_not_zero_or_sub__dynamic(float %unknown0, float %unknown1) #1 {
; CHECK-LABEL: define nofpclass(zero sub) float @result_not_zero_or_sub__dynamic(
; CHECK-SAME: float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown0, float %unknown1)
@@ -563,7 +563,7 @@ define nofpclass(zero sub) float @result_not_zero_or_sub__dynamic(float %unknown
define nofpclass(snan) float @lhs_not_zero(float nofpclass(zero) %not.zero, float %unknown) {
; CHECK-LABEL: define nofpclass(snan) float @lhs_not_zero(
; CHECK-SAME: float nofpclass(zero) [[NOT_ZERO:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_ZERO]], float [[UNKNOWN]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_ZERO]], float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.zero, float %unknown)
@@ -573,7 +573,7 @@ define nofpclass(snan) float @lhs_not_zero(float nofpclass(zero) %not.zero, floa
define nofpclass(snan) float @rhs_not_zero(float %unknown, float nofpclass(zero) %not.zero) {
; CHECK-LABEL: define nofpclass(snan) float @rhs_not_zero(
; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(zero) [[NOT_ZERO:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN]], float [[NOT_ZERO]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[UNKNOWN]], float [[NOT_ZERO]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %unknown, float %not.zero)
@@ -583,7 +583,7 @@ define nofpclass(snan) float @rhs_not_zero(float %unknown, float nofpclass(zero)
define nofpclass(snan) float @sources_not_zero(float nofpclass(zero) %not.zero0, float nofpclass(zero) %not.zero1) {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero(
; CHECK-SAME: float nofpclass(zero) [[NOT_ZERO0:%.*]], float nofpclass(zero) [[NOT_ZERO1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_ZERO0]], float [[NOT_ZERO1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_ZERO0]], float [[NOT_ZERO1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.zero0, float %not.zero1)
@@ -603,7 +603,7 @@ define nofpclass(snan) float @sources_not_zero__daz(float nofpclass(zero) %not.z
define nofpclass(snan) float @sources_not_zero__dynamic(float nofpclass(zero) %not.zero0, float nofpclass(zero) %not.zero1) #2 {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero__dynamic(
; CHECK-SAME: float nofpclass(zero) [[NOT_ZERO0:%.*]], float nofpclass(zero) [[NOT_ZERO1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_ZERO0]], float [[NOT_ZERO1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_ZERO0]], float [[NOT_ZERO1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.zero0, float %not.zero1)
@@ -613,7 +613,7 @@ define nofpclass(snan) float @sources_not_zero__dynamic(float nofpclass(zero) %n
define nofpclass(snan) float @sources_not_zero_or_sub(float nofpclass(zero sub) %not.zero.sub.0, float nofpclass(zero sub) %not.zero.sub.1) {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero_or_sub(
; CHECK-SAME: float nofpclass(zero sub) [[NOT_ZERO_SUB_0:%.*]], float nofpclass(zero sub) [[NOT_ZERO_SUB_1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.zero.sub.0, float %not.zero.sub.1)
@@ -623,7 +623,7 @@ define nofpclass(snan) float @sources_not_zero_or_sub(float nofpclass(zero sub)
define nofpclass(snan) float @sources_not_zero_or_sub__daz(float nofpclass(zero sub) %not.zero.sub.0, float nofpclass(zero sub) %not.zero.sub.1) #1 {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero_or_sub__daz(
; CHECK-SAME: float nofpclass(zero sub) [[NOT_ZERO_SUB_0:%.*]], float nofpclass(zero sub) [[NOT_ZERO_SUB_1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.zero.sub.0, float %not.zero.sub.1)
@@ -633,7 +633,7 @@ define nofpclass(snan) float @sources_not_zero_or_sub__daz(float nofpclass(zero
define nofpclass(snan) float @sources_not_zero_or_sub__dynamic(float nofpclass(zero sub) %not.zero.sub.0, float nofpclass(zero sub) %not.zero.sub.1) #2 {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_zero_or_sub__dynamic(
; CHECK-SAME: float nofpclass(zero sub) [[NOT_ZERO_SUB_0:%.*]], float nofpclass(zero sub) [[NOT_ZERO_SUB_1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_ZERO_SUB_0]], float [[NOT_ZERO_SUB_1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.zero.sub.0, float %not.zero.sub.1)
@@ -643,7 +643,7 @@ define nofpclass(snan) float @sources_not_zero_or_sub__dynamic(float nofpclass(z
define nofpclass(snan) float @sources_not_nzero(float nofpclass(nzero) %not.nzero0, float nofpclass(nzero) %not.nzero1) {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_nzero(
; CHECK-SAME: float nofpclass(nzero) [[NOT_NZERO0:%.*]], float nofpclass(nzero) [[NOT_NZERO1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_NZERO0]], float [[NOT_NZERO1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_NZERO0]], float [[NOT_NZERO1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.nzero0, float %not.nzero1)
@@ -653,7 +653,7 @@ define nofpclass(snan) float @sources_not_nzero(float nofpclass(nzero) %not.nzer
define nofpclass(snan) float @sources_not_pzero(float nofpclass(pzero) %not.pzero0, float nofpclass(pzero) %not.pzero1) {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_pzero(
; CHECK-SAME: float nofpclass(pzero) [[NOT_PZERO0:%.*]], float nofpclass(pzero) [[NOT_PZERO1:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_PZERO0]], float [[NOT_PZERO1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_PZERO0]], float [[NOT_PZERO1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.pzero0, float %not.pzero1)
@@ -723,7 +723,7 @@ define nofpclass(snan) float @rhs_not_nzero_lhs_not_pzero__dynamic(float nofpcla
define nofpclass(snan) float @sources_not_nzero_nsub__dynamic(float nofpclass(nzero nsub) %not.nzero0, float nofpclass(nzero nsub) %not.nzero1) #1 {
; CHECK-LABEL: define nofpclass(snan) float @sources_not_nzero_nsub__dynamic(
; CHECK-SAME: float nofpclass(nzero nsub) [[NOT_NZERO0:%.*]], float nofpclass(nzero nsub) [[NOT_NZERO1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_NZERO0]], float [[NOT_NZERO1]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_NZERO0]], float [[NOT_NZERO1]])
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.maximum.f32(float %not.nzero0, float %not.nzero1)
@@ -916,7 +916,7 @@ define nofpclass(snan) float @known_positive__maximum__only_pzero() {
; CHECK-LABEL: define nofpclass(snan) float @known_positive__maximum__only_pzero() {
; CHECK-NEXT: [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
; CHECK-NEXT: [[KNOWN_PZERO:%.*]] = call float @returns_pzero()
-; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[KNOWN_POSITIVE]], float 0.000000e+00)
+; CHECK-NEXT: [[RESULT:%.*]] = call nnan nsz float @llvm.maximum.f32(float [[KNOWN_POSITIVE]], float 0.000000e+00)
; CHECK-NEXT: ret float [[RESULT]]
;
%known.positive = call float @returns_positive()
@@ -929,7 +929,7 @@ define nofpclass(snan) float @only_pzero__maximum__known_positive() {
; CHECK-LABEL: define nofpclass(snan) float @only_pzero__maximum__known_positive() {
; CHECK-NEXT: [[KNOWN_PZERO:%.*]] = call float @returns_pzero()
; CHECK-NEXT: [[KNOWN_POSITIVE:%.*]] = call float @returns_positive()
-; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[KNOWN_POSITIVE]], float 0.000000e+00)
+; CHECK-NEXT: [[RESULT:%.*]] = call nnan nsz float @llvm.maximum.f32(float [[KNOWN_POSITIVE]], float 0.000000e+00)
; CHECK-NEXT: ret float [[RESULT]]
;
%known.pzero = call float @returns_pzero()
@@ -1018,7 +1018,7 @@ define nofpclass(snan) float @known_negative__maximum__only_nzero_or_nan() {
; CHECK-LABEL: define nofpclass(snan) float @known_negative__maximum__only_nzero_or_nan() {
; CHECK-NEXT: [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
; CHECK-NEXT: [[KNOWN_NZERO_OR_NAN:%.*]] = call float @returns_nzero_or_nan()
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[KNOWN_NEGATIVE]], float [[KNOWN_NZERO_OR_NAN]])
+; CHECK-NEXT: [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[KNOWN_NEGATIVE]], float [[KNOWN_NZERO_OR_NAN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%known.negative = call float @returns_negative()
@@ -1031,7 +1031,7 @@ define nofpclass(snan) float @only_nzero_or_nan__maximum__known_negative() {
; CHECK-LABEL: define nofpclass(snan) float @only_nzero_or_nan__maximum__known_negative() {
; CHECK-NEXT: [[KNOWN_NZERO_O...
[truncated]
|
8cd331d to
7deebfa
Compare
9df16ea to
d72a2f9
Compare
7deebfa to
2ba4cb9
Compare
🪟 Windows x64 Test Results
✅ The build succeeded and all tests passed. |
🐧 Linux x64 Test Results
✅ The build succeeded and all tests passed. |
d72a2f9 to
89561bd
Compare
3b3f609 to
dd20a77
Compare
89561bd to
e89e4a6
Compare
dd20a77 to
9744178
Compare
e89e4a6 to
10f04e1
Compare
9744178 to
9550f8e
Compare
10f04e1 to
f1624b0
Compare
dtcxzyw
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
…dFPClass Alive isn't particularly happy with this in the case where one of the inputs could be zero, but I think it's wrong: https://alive2.llvm.org/ce/z/dF7V6k nsz shouldn't permit introducing a -0 result where there wasn't one in the input here.
f1624b0 to
e23c934
Compare
9550f8e to
4eb7778
Compare

Alive isn't particularly happy with this in the case where
one of the inputs could be zero, but I think
it's wrong: https://alive2.llvm.org/ce/z/dF7V6k
nsz shouldn't permit introducing a -0 result where
there wasn't one in the input here.