Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -4450,6 +4450,15 @@ case Instruction::FAdd: case Instruction::FSub: { KnownFPClass KnownLHS, KnownRHS; + + bool WantNegative = + Op->getOpcode() == Instruction::FAdd && + (InterestedClasses & (fcNegative & ~fcNegZero)) != fcNone; + bool WantNaN = (InterestedClasses & fcNan) != fcNone; + + if (!WantNaN && !WantNegative) + break; + computeKnownFPClass(Op->getOperand(1), DemandedElts, fcNan | fcInf, KnownRHS, Depth + 1, Q, TLI); @@ -4457,7 +4466,8 @@ if (KnownRHS.KnownFPClasses == fcPosZero) Known.knownNot(fcNegZero); - if (KnownRHS.isKnownNeverNaN()) { + if ((WantNaN && KnownRHS.isKnownNeverNaN()) || + (WantNegative && KnownRHS.cannotBeOrderedLessThanZero())) { // RHS is canonically cheaper to compute. Skip inspecting the LHS if // there's no point. computeKnownFPClass(Op->getOperand(0), DemandedElts, fcNan | fcInf, @@ -4467,6 +4477,20 @@ if (KnownLHS.isKnownNeverNaN() && (KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverInfinity())) Known.knownNot(fcNan); + + // TODO: Handle fsub + if (Op->getOpcode() == Instruction::FAdd) { + if (KnownLHS.cannotBeOrderedLessThanZero() && + KnownRHS.cannotBeOrderedLessThanZero()) + Known.knownNot(fcNegative & ~fcNegZero); + + // Only fadd -0, -0 can return -0 + // + // TODO: With denormals are zero, could be more optimistic and ignore + // subnormal inputs. + if (KnownLHS.isKnownNeverNegZero() && KnownRHS.isKnownNeverNegZero()) + Known.knownNot(fcNegZero); + } } break; Index: llvm/test/Transforms/Attributor/nofpclass.ll =================================================================== --- llvm/test/Transforms/Attributor/nofpclass.ll +++ llvm/test/Transforms/Attributor/nofpclass.ll @@ -1276,7 +1276,7 @@ define float @fadd_known_positive(float nofpclass(ninf nsub nnorm) %arg0, float nofpclass(ninf nsub nnorm) %arg1) { ; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define float @fadd_known_positive +; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @fadd_known_positive ; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nsub nnorm) [[ARG1:%.*]]) #[[ATTR2]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] @@ -1287,7 +1287,7 @@ define float @fadd_known_positive_daz(float nofpclass(ninf nsub nnorm) %arg0, float nofpclass(ninf nsub nnorm) %arg1) #0 { ; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define float @fadd_known_positive_daz +; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @fadd_known_positive_daz ; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nsub nnorm) [[ARG1:%.*]]) #[[ATTR6:[0-9]+]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] @@ -1298,7 +1298,7 @@ define float @fadd_known_positive_nzero_lhs(float nofpclass(ninf nsub nnorm nzero) %arg0, float nofpclass(ninf nsub nnorm) %arg1) { ; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define float @fadd_known_positive_nzero_lhs +; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @fadd_known_positive_nzero_lhs ; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nsub nnorm) [[ARG1:%.*]]) #[[ATTR2]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] @@ -1309,7 +1309,7 @@ define float @fadd_known_positive_nzero_rhs(float nofpclass(ninf nsub nnorm) %arg0, float nofpclass(ninf nsub nnorm nzero) %arg1) { ; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define float @fadd_known_positive_nzero_rhs +; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @fadd_known_positive_nzero_rhs ; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ARG1:%.*]]) #[[ATTR2]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] @@ -1320,7 +1320,7 @@ define float @fadd_known_positive_nzero(float nofpclass(ninf nsub nnorm nzero) %arg0, float nofpclass(ninf nsub nnorm nzero) %arg1) { ; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define float @fadd_known_positive_nzero +; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @fadd_known_positive_nzero ; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ARG1:%.*]]) #[[ATTR2]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] @@ -1331,7 +1331,7 @@ define float @fadd_known_positive_nzero_ftz_daz(float nofpclass(ninf nsub nnorm nzero) %arg0, float nofpclass(ninf nsub nnorm nzero) %arg1) #0 { ; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define float @fadd_known_positive_nzero_ftz_daz +; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @fadd_known_positive_nzero_ftz_daz ; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ARG1:%.*]]) #[[ATTR6]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] @@ -1342,7 +1342,7 @@ define float @fadd_known_positive_nzero_ftz(float nofpclass(ninf nsub nnorm nzero) %arg0, float nofpclass(ninf nsub nnorm nzero) %arg1) #1 { ; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define float @fadd_known_positive_nzero_ftz +; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @fadd_known_positive_nzero_ftz ; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ARG1:%.*]]) #[[ATTR7:[0-9]+]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] @@ -1353,7 +1353,7 @@ define float @fadd_known_positive_nzero_daz(float nofpclass(ninf nsub nnorm nzero) %arg0, float nofpclass(ninf nsub nnorm nzero) %arg1) #2 { ; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define float @fadd_known_positive_nzero_daz +; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @fadd_known_positive_nzero_daz ; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ARG1:%.*]]) #[[ATTR8:[0-9]+]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]]