case Instruction::FAdd:
case Instruction::FSub: {
KnownFPClass KnownLHS, KnownRHS;
- computeKnownFPClass(Op->getOperand(1), DemandedElts, fcNan | fcInf,
+ bool WantNegative =
+ Op->getOpcode() == Instruction::FAdd &&
+ (InterestedClasses & KnownFPClass::OrderedLessThanZeroMask) != fcNone;
+ bool WantNaN = (InterestedClasses & fcNan) != fcNone;
+ bool WantNegZero = (InterestedClasses & fcNegZero) != fcNone;
+
+ if (!WantNaN && !WantNegative && !WantNegZero)
+ break;
+
+ FPClassTest InterestedSrcs = InterestedClasses;
+ if (WantNegative)
+ InterestedSrcs |= KnownFPClass::OrderedLessThanZeroMask;
+ if (InterestedClasses & fcNan)
+ InterestedSrcs |= fcInf;
+ computeKnownFPClass(Op->getOperand(1), DemandedElts, InterestedSrcs,
KnownRHS, Depth + 1, Q);
- if (KnownRHS.isKnownNeverNaN() || KnownRHS.isKnownNeverNegZero() ||
- (Opc == Instruction::FSub && KnownRHS.isKnownNeverPosZero())) {
+ 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, fcNan | fcInf,
+ computeKnownFPClass(Op->getOperand(0), DemandedElts, InterestedSrcs,
KnownLHS, Depth + 1, Q);
// Adding positive and negative infinity produces NaN.
// TODO: Check sign of infinities.
// FIXME: Context function should always be passed in separately
const Function *F = cast<Instruction>(Op)->getFunction();
- if (!F)
- break;
if (Op->getOpcode() == Instruction::FAdd) {
+ if (KnownLHS.cannotBeOrderedLessThanZero() &&
+ KnownRHS.cannotBeOrderedLessThanZero())
+ Known.knownNot(KnownFPClass::OrderedLessThanZeroMask);
+ if (!F)
+ break;
+
// (fadd x, 0.0) is guaranteed to return +0.0, not -0.0.
if ((KnownLHS.isKnownNeverLogicalNegZero(*F, Op->getType()) ||
KnownRHS.isKnownNeverLogicalNegZero(*F, Op->getType())) &&
outputDenormalIsIEEEOrPosZero(*F, Op->getType()))
Known.knownNot(fcNegZero);
} else {
+ if (!F)
+ break;
+
// Only fsub -0, +0 can return -0
if ((KnownLHS.isKnownNeverLogicalNegZero(*F, Op->getType()) ||
KnownRHS.isKnownNeverLogicalPosZero(*F, Op->getType())) &&
define float @fsub_p0_commute(float %arg0) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
-; CHECK-LABEL: define float @fsub_p0_commute
+; CHECK-LABEL: define nofpclass(nzero) float @fsub_p0_commute
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[SUB:%.*]] = fsub float 0.000000e+00, [[ARG0]]
; CHECK-NEXT: ret float [[SUB]]
define float @fsub_p0_commute_ieee_daz(float %arg0) #2 {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
-; CHECK-LABEL: define float @fsub_p0_commute_ieee_daz
+; CHECK-LABEL: define nofpclass(nzero) float @fsub_p0_commute_ieee_daz
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR8]] {
; CHECK-NEXT: [[SUB:%.*]] = fsub float 0.000000e+00, [[ARG0]]
; CHECK-NEXT: ret float [[SUB]]
define float @fadd_known_positive(float nofpclass(ninf nsub nnorm) %arg0, float nofpclass(ninf nsub nnorm) %arg1) {
; CHECK: Function Attrs: mustprogress 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]]
define float @fadd_known_positive_daz(float nofpclass(ninf nsub nnorm) %arg0, float nofpclass(ninf nsub nnorm) %arg1) #0 {
; CHECK: Function Attrs: mustprogress 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:%.*]]) #[[ATTR7]] {
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
; CHECK-NEXT: ret float [[ADD]]
define float @fadd_known_positive_nzero_lhs(float nofpclass(ninf nsub nnorm nzero) %arg0, float nofpclass(ninf nsub nnorm) %arg1) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
-; CHECK-LABEL: define float @fadd_known_positive_nzero_lhs
+; CHECK-LABEL: define nofpclass(ninf nzero 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]]
define float @fadd_known_positive_nzero_rhs(float nofpclass(ninf nsub nnorm) %arg0, float nofpclass(ninf nsub nnorm nzero) %arg1) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
-; CHECK-LABEL: define nofpclass(nzero) float @fadd_known_positive_nzero_rhs
+; CHECK-LABEL: define nofpclass(ninf nzero 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]]
define float @fadd_known_positive_nzero(float nofpclass(ninf nsub nnorm nzero) %arg0, float nofpclass(ninf nsub nnorm nzero) %arg1) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
-; CHECK-LABEL: define nofpclass(nzero) 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]]
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: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
-; CHECK-LABEL: define float @fadd_known_positive_nzero_ftz_daz
+; CHECK-LABEL: define nofpclass(ninf 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:%.*]]) #[[ATTR7]] {
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
; CHECK-NEXT: ret float [[ADD]]
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: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
-; CHECK-LABEL: define float @fadd_known_positive_nzero_ftz
+; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @fadd_known_positive_nzero_ftz
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ARG1:%.*]]) #[[ATTR10]] {
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
; CHECK-NEXT: ret float [[ADD]]
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: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
-; CHECK-LABEL: define nofpclass(nzero) 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]] {
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
; CHECK-NEXT: ret float [[ADD]]