https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/173165
If the source value is known not subnormal and not zero with the same sign, we can infer the result is also not zero with the same sign. >From 6d76e9020a125084693c03619d93387585fed74f Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Sat, 20 Dec 2025 20:44:43 +0100 Subject: [PATCH] ValueTracking: Improve accuracy of 0 handling with PreserveSign If the source value is known not subnormal and not zero with the same sign, we can infer the result is also not zero with the same sign. --- llvm/lib/Analysis/ValueTracking.cpp | 8 +++ .../Attributor/nofpclass-canonicalize.ll | 52 +++++++++---------- 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index d3d2a3db66ddc..0321c08f55776 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -5308,6 +5308,14 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, if (DenormMode.inputsAreZero() || DenormMode.outputsAreZero()) Known.knownNot(fcSubnormal); + if (DenormMode == DenormalMode::getPreserveSign()) { + if (KnownSrc.isKnownNever(fcPosZero | fcPosSubnormal)) + Known.knownNot(fcPosZero); + if (KnownSrc.isKnownNever(fcNegZero | fcNegSubnormal)) + Known.knownNot(fcNegZero); + break; + } + if (DenormMode.Input == DenormalMode::PositiveZero || (DenormMode.Output == DenormalMode::PositiveZero && DenormMode.Input == DenormalMode::IEEE)) diff --git a/llvm/test/Transforms/Attributor/nofpclass-canonicalize.ll b/llvm/test/Transforms/Attributor/nofpclass-canonicalize.ll index 8a31bef83b68e..d1879cbb9add9 100644 --- a/llvm/test/Transforms/Attributor/nofpclass-canonicalize.ll +++ b/llvm/test/Transforms/Attributor/nofpclass-canonicalize.ll @@ -204,9 +204,9 @@ define float @ret_canonicalize_ieee_constant_snan() "denormal-fp-math"="ieee,iee } define float @ret_canonicalize_daz_constant_pos_denormal() "denormal-fp-math"="preserve-sign,preserve-sign" { -; CHECK-LABEL: define noundef nofpclass(nan inf sub norm) float @ret_canonicalize_daz_constant_pos_denormal +; CHECK-LABEL: define noundef nofpclass(nan inf nzero sub norm) float @ret_canonicalize_daz_constant_pos_denormal ; CHECK-SAME: () #[[ATTR10:[0-9]+]] { -; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(nan inf sub norm) float @llvm.canonicalize.f32(float noundef 0x36A0000000000000) #[[ATTR12]] +; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(nan inf nzero sub norm) float @llvm.canonicalize.f32(float noundef 0x36A0000000000000) #[[ATTR12]] ; CHECK-NEXT: ret float [[CALL]] ; %call = call float @llvm.canonicalize.f32(float 0x36A0000000000000) @@ -214,9 +214,9 @@ define float @ret_canonicalize_daz_constant_pos_denormal() "denormal-fp-math"="p } define float @ret_canonicalize_daz_constant_neg_denormal() "denormal-fp-math"="preserve-sign,preserve-sign" { -; CHECK-LABEL: define noundef nofpclass(nan inf sub norm) float @ret_canonicalize_daz_constant_neg_denormal +; CHECK-LABEL: define noundef nofpclass(nan inf pzero sub norm) float @ret_canonicalize_daz_constant_neg_denormal ; CHECK-SAME: () #[[ATTR10]] { -; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(nan inf sub norm) float @llvm.canonicalize.f32(float noundef 0xB6A0000000000000) #[[ATTR12]] +; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(nan inf pzero sub norm) float @llvm.canonicalize.f32(float noundef 0xB6A0000000000000) #[[ATTR12]] ; CHECK-NEXT: ret float [[CALL]] ; %call = call float @llvm.canonicalize.f32(float 0xb6A0000000000000) @@ -224,9 +224,9 @@ define float @ret_canonicalize_daz_constant_neg_denormal() "denormal-fp-math"="p } define float @ret_canonicalize_daz_constant_pos_zero() "denormal-fp-math"="preserve-sign,preserve-sign" { -; CHECK-LABEL: define noundef nofpclass(nan inf sub norm) float @ret_canonicalize_daz_constant_pos_zero +; CHECK-LABEL: define noundef nofpclass(nan inf nzero sub norm) float @ret_canonicalize_daz_constant_pos_zero ; CHECK-SAME: () #[[ATTR10]] { -; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(nan inf sub norm) float @llvm.canonicalize.f32(float noundef 0.000000e+00) #[[ATTR12]] +; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(nan inf nzero sub norm) float @llvm.canonicalize.f32(float noundef 0.000000e+00) #[[ATTR12]] ; CHECK-NEXT: ret float [[CALL]] ; %call = call float @llvm.canonicalize.f32(float 0.0) @@ -234,9 +234,9 @@ define float @ret_canonicalize_daz_constant_pos_zero() "denormal-fp-math"="prese } define float @ret_canonicalize_daz_constant_neg_zero() "denormal-fp-math"="preserve-sign,preserve-sign" { -; CHECK-LABEL: define noundef nofpclass(nan inf sub norm) float @ret_canonicalize_daz_constant_neg_zero +; CHECK-LABEL: define noundef nofpclass(nan inf pzero sub norm) float @ret_canonicalize_daz_constant_neg_zero ; CHECK-SAME: () #[[ATTR10]] { -; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(nan inf sub norm) float @llvm.canonicalize.f32(float noundef -0.000000e+00) #[[ATTR12]] +; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(nan inf pzero sub norm) float @llvm.canonicalize.f32(float noundef -0.000000e+00) #[[ATTR12]] ; CHECK-NEXT: ret float [[CALL]] ; %call = call float @llvm.canonicalize.f32(float -0.0) @@ -244,9 +244,9 @@ define float @ret_canonicalize_daz_constant_neg_zero() "denormal-fp-math"="prese } define float @ret_canonicalize_daz_constant_pos_normal() "denormal-fp-math"="preserve-sign,preserve-sign" { -; CHECK-LABEL: define noundef nofpclass(nan inf sub nnorm) float @ret_canonicalize_daz_constant_pos_normal +; CHECK-LABEL: define noundef nofpclass(nan inf zero sub nnorm) float @ret_canonicalize_daz_constant_pos_normal ; CHECK-SAME: () #[[ATTR10]] { -; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(nan inf sub nnorm) float @llvm.canonicalize.f32(float noundef 8.000000e+00) #[[ATTR12]] +; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(nan inf zero sub nnorm) float @llvm.canonicalize.f32(float noundef 8.000000e+00) #[[ATTR12]] ; CHECK-NEXT: ret float [[CALL]] ; %call = call float @llvm.canonicalize.f32(float 8.0) @@ -254,9 +254,9 @@ define float @ret_canonicalize_daz_constant_pos_normal() "denormal-fp-math"="pre } define float @ret_canonicalize_daz_constant_neg_normal() "denormal-fp-math"="preserve-sign,preserve-sign" { -; CHECK-LABEL: define noundef nofpclass(nan inf sub pnorm) float @ret_canonicalize_daz_constant_neg_normal +; CHECK-LABEL: define noundef nofpclass(nan inf zero sub pnorm) float @ret_canonicalize_daz_constant_neg_normal ; CHECK-SAME: () #[[ATTR10]] { -; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(nan inf sub pnorm) float @llvm.canonicalize.f32(float noundef -8.000000e+00) #[[ATTR12]] +; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(nan inf zero sub pnorm) float @llvm.canonicalize.f32(float noundef -8.000000e+00) #[[ATTR12]] ; CHECK-NEXT: ret float [[CALL]] ; %call = call float @llvm.canonicalize.f32(float -8.0) @@ -264,9 +264,9 @@ define float @ret_canonicalize_daz_constant_neg_normal() "denormal-fp-math"="pre } define float @ret_canonicalize_daz_constant_pos_inf() "denormal-fp-math"="preserve-sign,preserve-sign" { -; CHECK-LABEL: define noundef nofpclass(nan ninf sub norm) float @ret_canonicalize_daz_constant_pos_inf +; CHECK-LABEL: define noundef nofpclass(nan ninf zero sub norm) float @ret_canonicalize_daz_constant_pos_inf ; CHECK-SAME: () #[[ATTR10]] { -; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(nan ninf sub norm) float @llvm.canonicalize.f32(float noundef 0x7FF0000000000000) #[[ATTR12]] +; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(nan ninf zero sub norm) float @llvm.canonicalize.f32(float noundef 0x7FF0000000000000) #[[ATTR12]] ; CHECK-NEXT: ret float [[CALL]] ; %call = call float @llvm.canonicalize.f32(float 0x7FF0000000000000) @@ -274,9 +274,9 @@ define float @ret_canonicalize_daz_constant_pos_inf() "denormal-fp-math"="preser } define float @ret_canonicalize_daz_constant_neg_inf() "denormal-fp-math"="preserve-sign,preserve-sign" { -; CHECK-LABEL: define noundef nofpclass(nan pinf sub norm) float @ret_canonicalize_daz_constant_neg_inf +; CHECK-LABEL: define noundef nofpclass(nan pinf zero sub norm) float @ret_canonicalize_daz_constant_neg_inf ; CHECK-SAME: () #[[ATTR10]] { -; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(nan pinf sub norm) float @llvm.canonicalize.f32(float noundef 0xFFF0000000000000) #[[ATTR12]] +; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(nan pinf zero sub norm) float @llvm.canonicalize.f32(float noundef 0xFFF0000000000000) #[[ATTR12]] ; CHECK-NEXT: ret float [[CALL]] ; %call = call float @llvm.canonicalize.f32(float 0xFFF0000000000000) @@ -284,9 +284,9 @@ define float @ret_canonicalize_daz_constant_neg_inf() "denormal-fp-math"="preser } define float @ret_canonicalize_daz_constant_qnan() "denormal-fp-math"="preserve-sign,preserve-sign" { -; CHECK-LABEL: define noundef nofpclass(snan inf sub norm) float @ret_canonicalize_daz_constant_qnan +; CHECK-LABEL: define noundef nofpclass(snan inf zero sub norm) float @ret_canonicalize_daz_constant_qnan ; CHECK-SAME: () #[[ATTR10]] { -; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(snan inf sub norm) float @llvm.canonicalize.f32(float noundef 0x7FF8000000000000) #[[ATTR12]] +; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(snan inf zero sub norm) float @llvm.canonicalize.f32(float noundef 0x7FF8000000000000) #[[ATTR12]] ; CHECK-NEXT: ret float [[CALL]] ; %call = call float @llvm.canonicalize.f32(float 0x7FF8000000000000) @@ -294,9 +294,9 @@ define float @ret_canonicalize_daz_constant_qnan() "denormal-fp-math"="preserve- } define float @ret_canonicalize_daz_constant_snan() "denormal-fp-math"="preserve-sign,preserve-sign" { -; CHECK-LABEL: define noundef nofpclass(snan inf sub norm) float @ret_canonicalize_daz_constant_snan +; CHECK-LABEL: define noundef nofpclass(snan inf zero sub norm) float @ret_canonicalize_daz_constant_snan ; CHECK-SAME: () #[[ATTR10]] { -; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(snan inf sub norm) float @llvm.canonicalize.f32(float noundef 0x7FF1000000000000) #[[ATTR12]] +; CHECK-NEXT: [[CALL:%.*]] = call noundef nofpclass(snan inf zero sub norm) float @llvm.canonicalize.f32(float noundef 0x7FF1000000000000) #[[ATTR12]] ; CHECK-NEXT: ret float [[CALL]] ; %call = call float @llvm.canonicalize.f32(float 0x7FF1000000000000) @@ -504,9 +504,9 @@ define float @ret_canonicalize_dynamic_constant_snan() "denormal-fp-math"="dynam } define float @ret_canonicalize_daz_not_nzero_not_nsub(float nofpclass(nzero nsub) %x) "denormal-fp-math"="preserve-sign,preserve-sign" { -; CHECK-LABEL: define nofpclass(snan sub) float @ret_canonicalize_daz_not_nzero_not_nsub +; CHECK-LABEL: define nofpclass(snan nzero sub) float @ret_canonicalize_daz_not_nzero_not_nsub ; CHECK-SAME: (float nofpclass(nzero nsub) [[X:%.*]]) #[[ATTR10]] { -; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(snan sub) float @llvm.canonicalize.f32(float nofpclass(nzero nsub) [[X]]) #[[ATTR12]] +; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(snan nzero sub) float @llvm.canonicalize.f32(float nofpclass(nzero nsub) [[X]]) #[[ATTR12]] ; CHECK-NEXT: ret float [[CALL]] ; %call = call float @llvm.canonicalize.f32(float %x) @@ -534,9 +534,9 @@ define float @ret_canonicalize_daz_not_nzero(float nofpclass(nzero) %x) "denorma } define float @ret_canonicalize_daz_not_pzero_not_psub(float nofpclass(pzero psub) %x) "denormal-fp-math"="preserve-sign,preserve-sign" { -; CHECK-LABEL: define nofpclass(snan sub) float @ret_canonicalize_daz_not_pzero_not_psub +; CHECK-LABEL: define nofpclass(snan pzero sub) float @ret_canonicalize_daz_not_pzero_not_psub ; CHECK-SAME: (float nofpclass(pzero psub) [[X:%.*]]) #[[ATTR10]] { -; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(snan sub) float @llvm.canonicalize.f32(float nofpclass(pzero psub) [[X]]) #[[ATTR12]] +; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(snan pzero sub) float @llvm.canonicalize.f32(float nofpclass(pzero psub) [[X]]) #[[ATTR12]] ; CHECK-NEXT: ret float [[CALL]] ; %call = call float @llvm.canonicalize.f32(float %x) @@ -584,9 +584,9 @@ define float @ret_canonicalize_daz_not_sub(float nofpclass(sub) %x) "denormal-fp } define float @ret_canonicalize_daz_not_sub_not_nzero(float nofpclass(sub nzero) %x) "denormal-fp-math"="preserve-sign,preserve-sign" { -; CHECK-LABEL: define nofpclass(snan sub) float @ret_canonicalize_daz_not_sub_not_nzero +; CHECK-LABEL: define nofpclass(snan nzero sub) float @ret_canonicalize_daz_not_sub_not_nzero ; CHECK-SAME: (float nofpclass(nzero sub) [[X:%.*]]) #[[ATTR10]] { -; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(snan sub) float @llvm.canonicalize.f32(float nofpclass(nzero sub) [[X]]) #[[ATTR12]] +; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(snan nzero sub) float @llvm.canonicalize.f32(float nofpclass(nzero sub) [[X]]) #[[ATTR12]] ; CHECK-NEXT: ret float [[CALL]] ; %call = call float @llvm.canonicalize.f32(float %x) _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
