https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/174123
>From 69b33a58040c50108e41afe0ea487c488f759a52 Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Wed, 31 Dec 2025 20:50:38 +0100 Subject: [PATCH 1/2] ValueTracking: Improve handling of fadd in computeKnownFPClass. This already recognized that if both inputs are positive, the result is positive. Extend this to the mirror situation with negative inputs. Also special case fadd x, x. Canonically, fmul x, 2 is fadd x, x. We can tell the sign bit won't change, and 0 will propagate. --- llvm/lib/Analysis/ValueTracking.cpp | 28 +++++++++-- llvm/test/Transforms/Attributor/nofpclass.ll | 50 ++++++++++---------- 2 files changed, 49 insertions(+), 29 deletions(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index cf7c6796f76c7..df435df311d0c 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -5619,14 +5619,22 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, computeKnownFPClass(Op->getOperand(1), DemandedElts, InterestedSrcs, KnownRHS, Q, Depth + 1); + // Special case fadd x, x, which is the canonical form of fmul x, 2. + bool SameOperands = Op->getOperand(0) == Op->getOperand(1); + if (SameOperands) + KnownLHS = KnownRHS; + if ((WantNaN && KnownRHS.isKnownNeverNaN()) || (WantNegative && KnownRHS.cannotBeOrderedLessThanZero()) || WantNegZero || Opc == Instruction::FSub) { - // RHS is canonically cheaper to compute. Skip inspecting the LHS if - // there's no point. - computeKnownFPClass(Op->getOperand(0), DemandedElts, InterestedSrcs, - KnownLHS, Q, Depth + 1); + if (!SameOperands) { + // RHS is canonically cheaper to compute. Skip inspecting the LHS if + // there's no point. + computeKnownFPClass(Op->getOperand(0), DemandedElts, InterestedSrcs, + KnownLHS, Q, Depth + 1); + } + // Adding positive and negative infinity produces NaN. // TODO: Check sign of infinities. if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() && @@ -5640,6 +5648,10 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, if (KnownLHS.cannotBeOrderedLessThanZero() && KnownRHS.cannotBeOrderedLessThanZero()) Known.knownNot(KnownFPClass::OrderedLessThanZeroMask); + if (KnownLHS.cannotBeOrderedGreaterThanZero() && + KnownRHS.cannotBeOrderedGreaterThanZero()) + Known.knownNot(KnownFPClass::OrderedGreaterThanZeroMask); + if (!F) break; @@ -5647,6 +5659,14 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, Op->getType()->getScalarType()->getFltSemantics(); DenormalMode Mode = F->getDenormalMode(FltSem); + if (SameOperands) { + // Doubling 0 will give the same 0. + if (KnownRHS.isKnownNeverLogicalPosZero(Mode)) + Known.knownNot(fcPosZero); + if (KnownRHS.isKnownNeverLogicalNegZero(Mode)) + Known.knownNot(fcNegZero); + } + // (fadd x, 0.0) is guaranteed to return +0.0, not -0.0. if ((KnownLHS.isKnownNeverLogicalNegZero(Mode) || KnownRHS.isKnownNeverLogicalNegZero(Mode)) && diff --git a/llvm/test/Transforms/Attributor/nofpclass.ll b/llvm/test/Transforms/Attributor/nofpclass.ll index d6c6e8ad7db32..68206b2e6ff13 100644 --- a/llvm/test/Transforms/Attributor/nofpclass.ll +++ b/llvm/test/Transforms/Attributor/nofpclass.ll @@ -3043,7 +3043,7 @@ define float @fadd_double_no_inf(float noundef nofpclass(inf) %arg) { define float @fadd_double_no_zero(float noundef nofpclass(zero) %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define noundef nofpclass(nzero) float @fadd_double_no_zero +; CHECK-LABEL: define noundef nofpclass(zero) float @fadd_double_no_zero ; CHECK-SAME: (float noundef nofpclass(zero) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] @@ -3076,7 +3076,7 @@ define float @fadd_double_known_positive(float noundef nofpclass(ninf nnorm nsub define float @fadd_double_known_positive_non0(float noundef nofpclass(ninf nnorm nsub zero) %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define noundef nofpclass(ninf nzero nsub nnorm) float @fadd_double_known_positive_non0 +; CHECK-LABEL: define noundef nofpclass(ninf zero nsub nnorm) float @fadd_double_known_positive_non0 ; CHECK-SAME: (float noundef nofpclass(ninf zero nsub nnorm) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] @@ -3087,7 +3087,7 @@ define float @fadd_double_known_positive_non0(float noundef nofpclass(ninf nnorm define float @fadd_double_known_negative_or_zero(float noundef nofpclass(pinf pnorm psub) %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define noundef float @fadd_double_known_negative_or_zero +; CHECK-LABEL: define noundef nofpclass(pinf psub pnorm) float @fadd_double_known_negative_or_zero ; CHECK-SAME: (float noundef nofpclass(pinf psub pnorm) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] @@ -3098,7 +3098,7 @@ define float @fadd_double_known_negative_or_zero(float noundef nofpclass(pinf pn define float @fadd_double_known_negative(float noundef nofpclass(pinf pnorm psub pzero) %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define noundef float @fadd_double_known_negative +; CHECK-LABEL: define noundef nofpclass(pinf pzero psub pnorm) float @fadd_double_known_negative ; CHECK-SAME: (float noundef nofpclass(pinf pzero psub pnorm) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] @@ -3109,7 +3109,7 @@ define float @fadd_double_known_negative(float noundef nofpclass(pinf pnorm psub define float @fadd_double_known_negative_non0(float noundef nofpclass(pinf pnorm psub zero) %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define noundef nofpclass(nzero) float @fadd_double_known_negative_non0 +; CHECK-LABEL: define noundef nofpclass(pinf zero psub pnorm) float @fadd_double_known_negative_non0 ; CHECK-SAME: (float noundef nofpclass(pinf zero psub pnorm) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] @@ -3164,7 +3164,7 @@ define float @fadd_double_no_nnorm_nsub(float noundef nofpclass(nnorm nsub) %arg define float @fadd_double_no_nopsub_pzero(float noundef nofpclass(psub pzero) %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define noundef float @fadd_double_no_nopsub_pzero +; CHECK-LABEL: define noundef nofpclass(pzero) float @fadd_double_no_nopsub_pzero ; CHECK-SAME: (float noundef nofpclass(pzero psub) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] @@ -3186,7 +3186,7 @@ define float @fadd_double_no_nonsub_nzero(float noundef nofpclass(nsub nzero) %a define float @fadd_double_no_nopsub_pzero_daz(float noundef nofpclass(psub pzero) %arg) #0 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define noundef float @fadd_double_no_nopsub_pzero_daz +; CHECK-LABEL: define noundef nofpclass(pzero) float @fadd_double_no_nopsub_pzero_daz ; CHECK-SAME: (float noundef nofpclass(pzero psub) [[ARG:%.*]]) #[[ATTR10]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] @@ -3197,7 +3197,7 @@ define float @fadd_double_no_nopsub_pzero_daz(float noundef nofpclass(psub pzero define float @fadd_double_no_nonsub_nzero_daz(float noundef nofpclass(nsub nzero) %arg) #0 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define noundef float @fadd_double_no_nonsub_nzero_daz +; CHECK-LABEL: define noundef nofpclass(nzero) float @fadd_double_no_nonsub_nzero_daz ; CHECK-SAME: (float noundef nofpclass(nzero nsub) [[ARG:%.*]]) #[[ATTR10]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] @@ -3219,7 +3219,7 @@ define float @fadd_double_no_nopsub_pzero_dynamic(float noundef nofpclass(psub p define float @fadd_double_no_nonsub_nzero_dynamic(float noundef nofpclass(nsub nzero) %arg) #6 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define noundef float @fadd_double_no_nonsub_nzero_dynamic +; CHECK-LABEL: define noundef nofpclass(nzero) float @fadd_double_no_nonsub_nzero_dynamic ; CHECK-SAME: (float noundef nofpclass(nzero nsub) [[ARG:%.*]]) #[[ATTR17]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] @@ -3230,7 +3230,7 @@ define float @fadd_double_no_nonsub_nzero_dynamic(float noundef nofpclass(nsub n define float @fadd_double_known_positive_nonsub_ieee(float noundef nofpclass(ninf nnorm sub zero) %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define noundef nofpclass(ninf nzero nsub nnorm) float @fadd_double_known_positive_nonsub_ieee +; CHECK-LABEL: define noundef nofpclass(ninf zero nsub nnorm) float @fadd_double_known_positive_nonsub_ieee ; CHECK-SAME: (float noundef nofpclass(ninf zero sub nnorm) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] @@ -3241,7 +3241,7 @@ define float @fadd_double_known_positive_nonsub_ieee(float noundef nofpclass(nin define float @fadd_double_known_positive_nonsub_daz(float noundef nofpclass(ninf nnorm sub zero) %arg) #0 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define noundef nofpclass(ninf nsub nnorm) float @fadd_double_known_positive_nonsub_daz +; CHECK-LABEL: define noundef nofpclass(ninf zero nsub nnorm) float @fadd_double_known_positive_nonsub_daz ; CHECK-SAME: (float noundef nofpclass(ninf zero sub nnorm) [[ARG:%.*]]) #[[ATTR10]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] @@ -3252,7 +3252,7 @@ define float @fadd_double_known_positive_nonsub_daz(float noundef nofpclass(ninf define float @fadd_double_known_positive_nonsub_dynamic(float noundef nofpclass(ninf nnorm sub zero) %arg) #6 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define noundef nofpclass(ninf nsub nnorm) float @fadd_double_known_positive_nonsub_dynamic +; CHECK-LABEL: define noundef nofpclass(ninf zero nsub nnorm) float @fadd_double_known_positive_nonsub_dynamic ; CHECK-SAME: (float noundef nofpclass(ninf zero sub nnorm) [[ARG:%.*]]) #[[ATTR17]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] @@ -3263,7 +3263,7 @@ define float @fadd_double_known_positive_nonsub_dynamic(float noundef nofpclass( define float @fadd_double_known_negative_nonsub_ieee(float noundef nofpclass(pinf pnorm sub zero) %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define noundef nofpclass(nzero) float @fadd_double_known_negative_nonsub_ieee +; CHECK-LABEL: define noundef nofpclass(pinf zero psub pnorm) float @fadd_double_known_negative_nonsub_ieee ; CHECK-SAME: (float noundef nofpclass(pinf zero sub pnorm) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] @@ -3274,7 +3274,7 @@ define float @fadd_double_known_negative_nonsub_ieee(float noundef nofpclass(pin define float @fadd_double_known_negative_nonsub_daz(float noundef nofpclass(pinf pnorm sub zero) %arg) #0 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define noundef float @fadd_double_known_negative_nonsub_daz +; CHECK-LABEL: define noundef nofpclass(pinf zero psub pnorm) float @fadd_double_known_negative_nonsub_daz ; CHECK-SAME: (float noundef nofpclass(pinf zero sub pnorm) [[ARG:%.*]]) #[[ATTR10]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] @@ -3285,7 +3285,7 @@ define float @fadd_double_known_negative_nonsub_daz(float noundef nofpclass(pinf define float @fadd_double_known_negative_nonsub_dynamic(float noundef nofpclass(pinf pnorm sub zero) %arg) #6 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define noundef float @fadd_double_known_negative_nonsub_dynamic +; CHECK-LABEL: define noundef nofpclass(pinf zero psub pnorm) float @fadd_double_known_negative_nonsub_dynamic ; CHECK-SAME: (float noundef nofpclass(pinf zero sub pnorm) [[ARG:%.*]]) #[[ATTR17]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] @@ -3351,7 +3351,7 @@ define float @fadd_known_negative_rhs(float %arg0, float nofpclass(pinf psub pno define float @fadd_known_negative(float nofpclass(pinf psub pnorm) %arg0, float nofpclass(pinf psub pnorm) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define float @fadd_known_negative +; CHECK-LABEL: define nofpclass(pinf psub pnorm) float @fadd_known_negative ; CHECK-SAME: (float nofpclass(pinf psub pnorm) [[ARG0:%.*]], float nofpclass(pinf psub pnorm) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] @@ -3362,7 +3362,7 @@ define float @fadd_known_negative(float nofpclass(pinf psub pnorm) %arg0, float define float @fadd_known_negative_daz(float nofpclass(pinf psub pnorm) %arg0, float nofpclass(pinf psub pnorm) %arg1) #0 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define float @fadd_known_negative_daz +; CHECK-LABEL: define nofpclass(pinf psub pnorm) float @fadd_known_negative_daz ; CHECK-SAME: (float nofpclass(pinf psub pnorm) [[ARG0:%.*]], float nofpclass(pinf psub pnorm) [[ARG1:%.*]]) #[[ATTR10]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] @@ -3373,7 +3373,7 @@ define float @fadd_known_negative_daz(float nofpclass(pinf psub pnorm) %arg0, fl define float @fadd_known_negative_pzero_lhs(float nofpclass(pinf psub pnorm pzero) %arg0, float nofpclass(pinf psub pnorm) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define float @fadd_known_negative_pzero_lhs +; CHECK-LABEL: define nofpclass(pinf psub pnorm) float @fadd_known_negative_pzero_lhs ; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ARG0:%.*]], float nofpclass(pinf psub pnorm) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] @@ -3384,7 +3384,7 @@ define float @fadd_known_negative_pzero_lhs(float nofpclass(pinf psub pnorm pzer define float @fadd_known_negative_pzero_rhs(float nofpclass(pinf psub pnorm) %arg0, float nofpclass(pinf psub pnorm pzero) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define float @fadd_known_negative_pzero_rhs +; CHECK-LABEL: define nofpclass(pinf psub pnorm) float @fadd_known_negative_pzero_rhs ; CHECK-SAME: (float nofpclass(pinf psub pnorm) [[ARG0:%.*]], float nofpclass(pinf pzero psub pnorm) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] @@ -3395,7 +3395,7 @@ define float @fadd_known_negative_pzero_rhs(float nofpclass(pinf psub pnorm) %ar define float @fadd_known_negative_pzero(float nofpclass(pinf psub pnorm pzero) %arg0, float nofpclass(pinf psub pnorm pzero) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define float @fadd_known_negative_pzero +; CHECK-LABEL: define nofpclass(pinf psub pnorm) float @fadd_known_negative_pzero ; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ARG0:%.*]], float nofpclass(pinf pzero psub pnorm) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] @@ -3406,7 +3406,7 @@ define float @fadd_known_negative_pzero(float nofpclass(pinf psub pnorm pzero) % define float @fadd_known_negative_pzero_ftz_daz(float nofpclass(pinf psub pnorm pzero) %arg0, float nofpclass(pinf psub pnorm pzero) %arg1) #0 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define float @fadd_known_negative_pzero_ftz_daz +; CHECK-LABEL: define nofpclass(pinf psub pnorm) float @fadd_known_negative_pzero_ftz_daz ; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ARG0:%.*]], float nofpclass(pinf pzero psub pnorm) [[ARG1:%.*]]) #[[ATTR10]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] @@ -3417,7 +3417,7 @@ define float @fadd_known_negative_pzero_ftz_daz(float nofpclass(pinf psub pnorm define float @fadd_known_negative_pzero_ftz(float nofpclass(pinf psub pnorm pzero) %arg0, float nofpclass(pinf psub pnorm pzero) %arg1) #1 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define float @fadd_known_negative_pzero_ftz +; CHECK-LABEL: define nofpclass(pinf psub pnorm) float @fadd_known_negative_pzero_ftz ; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ARG0:%.*]], float nofpclass(pinf pzero psub pnorm) [[ARG1:%.*]]) #[[ATTR13]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] @@ -3428,7 +3428,7 @@ define float @fadd_known_negative_pzero_ftz(float nofpclass(pinf psub pnorm pzer define float @fadd_known_negative_pzero_daz(float nofpclass(pinf psub pnorm pzero) %arg0, float nofpclass(pinf psub pnorm pzero) %arg1) #2 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define float @fadd_known_negative_pzero_daz +; CHECK-LABEL: define nofpclass(pinf psub pnorm) float @fadd_known_negative_pzero_daz ; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ARG0:%.*]], float nofpclass(pinf pzero psub pnorm) [[ARG1:%.*]]) #[[ATTR11]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] @@ -3484,7 +3484,7 @@ define float @fadd_known_negative_normal_dapz(float nofpclass(pinf pnorm pzero) ; Cannot conclude this can't return +0 due to undef. define float @fadd_double_no_zero_maybe_undef(float nofpclass(zero) %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define nofpclass(nzero) float @fadd_double_no_zero_maybe_undef +; CHECK-LABEL: define nofpclass(zero) float @fadd_double_no_zero_maybe_undef ; CHECK-SAME: (float nofpclass(zero) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] @@ -3506,7 +3506,7 @@ define float @fadd_double_no_nzero_maybe_undef(float nofpclass(nzero) %arg) { define float @fadd_double_no_pzero_maybe_undef(float nofpclass(pzero) %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define float @fadd_double_no_pzero_maybe_undef +; CHECK-LABEL: define nofpclass(pzero) float @fadd_double_no_pzero_maybe_undef ; CHECK-SAME: (float nofpclass(pzero) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] >From e63cc4a41a2f46143c9a71a48852440d13c39f65 Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Fri, 2 Jan 2026 11:42:09 +0100 Subject: [PATCH 2/2] Check isGuaranteedNotToBeUndef --- llvm/lib/Analysis/ValueTracking.cpp | 10 ++++++---- llvm/test/Transforms/Attributor/nofpclass.ll | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index df435df311d0c..6ad04de63b93a 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -5620,15 +5620,17 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, KnownRHS, Q, Depth + 1); // Special case fadd x, x, which is the canonical form of fmul x, 2. - bool SameOperands = Op->getOperand(0) == Op->getOperand(1); - if (SameOperands) + bool SelfAdd = Op->getOperand(0) == Op->getOperand(1) && + isGuaranteedNotToBeUndef(Op->getOperand(0), Q.AC, Q.CxtI, + Q.DT, Depth + 1); + if (SelfAdd) KnownLHS = KnownRHS; if ((WantNaN && KnownRHS.isKnownNeverNaN()) || (WantNegative && KnownRHS.cannotBeOrderedLessThanZero()) || WantNegZero || Opc == Instruction::FSub) { - if (!SameOperands) { + if (!SelfAdd) { // RHS is canonically cheaper to compute. Skip inspecting the LHS if // there's no point. computeKnownFPClass(Op->getOperand(0), DemandedElts, InterestedSrcs, @@ -5659,7 +5661,7 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, Op->getType()->getScalarType()->getFltSemantics(); DenormalMode Mode = F->getDenormalMode(FltSem); - if (SameOperands) { + if (SelfAdd) { // Doubling 0 will give the same 0. if (KnownRHS.isKnownNeverLogicalPosZero(Mode)) Known.knownNot(fcPosZero); diff --git a/llvm/test/Transforms/Attributor/nofpclass.ll b/llvm/test/Transforms/Attributor/nofpclass.ll index 68206b2e6ff13..f5f33547bd19f 100644 --- a/llvm/test/Transforms/Attributor/nofpclass.ll +++ b/llvm/test/Transforms/Attributor/nofpclass.ll @@ -3484,7 +3484,7 @@ define float @fadd_known_negative_normal_dapz(float nofpclass(pinf pnorm pzero) ; Cannot conclude this can't return +0 due to undef. define float @fadd_double_no_zero_maybe_undef(float nofpclass(zero) %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define nofpclass(zero) float @fadd_double_no_zero_maybe_undef +; CHECK-LABEL: define nofpclass(nzero) float @fadd_double_no_zero_maybe_undef ; CHECK-SAME: (float nofpclass(zero) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] @@ -3506,7 +3506,7 @@ define float @fadd_double_no_nzero_maybe_undef(float nofpclass(nzero) %arg) { define float @fadd_double_no_pzero_maybe_undef(float nofpclass(pzero) %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define nofpclass(pzero) float @fadd_double_no_pzero_maybe_undef +; CHECK-LABEL: define float @fadd_double_no_pzero_maybe_undef ; CHECK-SAME: (float nofpclass(pzero) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
