Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -4071,17 +4071,24 @@ KnownFPClass &Known, unsigned Depth, const Query &Q, const TargetLibraryInfo *TLI) { - if ((InterestedClasses & fcNan) == fcNone) + const FPClassTest NegExcept0 = fcNegative & ~fcNegZero; + if ((InterestedClasses & (fcNan | NegExcept0)) == fcNone) return; KnownFPClass KnownSrc; computeKnownFPClass(Op->getOperand(0), DemandedElts, InterestedClasses, KnownSrc, Depth + 1, Q, TLI); - if (KnownSrc.isKnownNeverNaN()) + + // Sign should be preserved + if (KnownSrc.cannotBeOrderedLessThanZero()) + Known.knownNot(NegExcept0); + + if (KnownSrc.isKnownNeverNaN()) { Known.knownNot(fcNan); + Known.SignBit = KnownSrc.SignBit; + } // Infinity needs a range check. - // TODO: Sign bit should be preserved } // TODO: Merge implementation of cannotBeOrderedLessThanZero into here. Index: llvm/test/Transforms/Attributor/nofpclass-fptrunc.ll =================================================================== --- llvm/test/Transforms/Attributor/nofpclass-fptrunc.ll +++ llvm/test/Transforms/Attributor/nofpclass-fptrunc.ll @@ -134,8 +134,8 @@ } define float @ret_fptrunc_posonly(double nofpclass(ninf nnorm nsub nzero) %arg0) { -; CHECK-LABEL: define float @ret_fptrunc_posonly -; CHECK-SAME: (double nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]]) #[[ATTR0]] { +; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @ret_fptrunc_posonly +; CHECK-SAME: (double nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[EXT:%.*]] = fptrunc double [[ARG0]] to float ; CHECK-NEXT: ret float [[EXT]] ; @@ -144,8 +144,8 @@ } define float @ret_fptrunc_posonly_zero(double nofpclass(ninf nnorm nsub) %arg0) { -; CHECK-LABEL: define float @ret_fptrunc_posonly_zero -; CHECK-SAME: (double nofpclass(ninf nsub nnorm) [[ARG0:%.*]]) #[[ATTR0]] { +; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @ret_fptrunc_posonly_zero +; CHECK-SAME: (double nofpclass(ninf nsub nnorm) [[ARG0:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[EXT:%.*]] = fptrunc double [[ARG0]] to float ; CHECK-NEXT: ret float [[EXT]] ; @@ -154,8 +154,8 @@ } define float @ret_fptrunc_posonly_zero_nan(double nofpclass(ninf nnorm nsub nan) %arg0) { -; CHECK-LABEL: define float @ret_fptrunc_posonly_zero_nan -; CHECK-SAME: (double nofpclass(nan ninf nsub nnorm) [[ARG0:%.*]]) #[[ATTR0]] { +; CHECK-LABEL: define nofpclass(nan ninf nsub nnorm) float @ret_fptrunc_posonly_zero_nan +; CHECK-SAME: (double nofpclass(nan ninf nsub nnorm) [[ARG0:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[EXT:%.*]] = fptrunc double [[ARG0]] to float ; CHECK-NEXT: ret float [[EXT]] ; @@ -164,8 +164,8 @@ } define float @ret_fptrunc_posonly_nan(double nofpclass(ninf nnorm nsub nzero nan) %arg0) { -; CHECK-LABEL: define float @ret_fptrunc_posonly_nan -; CHECK-SAME: (double nofpclass(nan ninf nzero nsub nnorm) [[ARG0:%.*]]) #[[ATTR0]] { +; CHECK-LABEL: define nofpclass(nan ninf nsub nnorm) float @ret_fptrunc_posonly_nan +; CHECK-SAME: (double nofpclass(nan ninf nzero nsub nnorm) [[ARG0:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[EXT:%.*]] = fptrunc double [[ARG0]] to float ; CHECK-NEXT: ret float [[EXT]] ; @@ -175,7 +175,7 @@ define float @ret_fptrunc_negonly(double nofpclass(pinf pnorm psub pzero) %arg0) { ; CHECK-LABEL: define float @ret_fptrunc_negonly -; CHECK-SAME: (double nofpclass(pinf pzero psub pnorm) [[ARG0:%.*]]) #[[ATTR0]] { +; CHECK-SAME: (double nofpclass(pinf pzero psub pnorm) [[ARG0:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[EXT:%.*]] = fptrunc double [[ARG0]] to float ; CHECK-NEXT: ret float [[EXT]] ; @@ -185,7 +185,7 @@ define float @ret_fptrunc_negonly_zero(double nofpclass(pinf pnorm psub) %arg0) { ; CHECK-LABEL: define float @ret_fptrunc_negonly_zero -; CHECK-SAME: (double nofpclass(pinf psub pnorm) [[ARG0:%.*]]) #[[ATTR0]] { +; CHECK-SAME: (double nofpclass(pinf psub pnorm) [[ARG0:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[EXT:%.*]] = fptrunc double [[ARG0]] to float ; CHECK-NEXT: ret float [[EXT]] ; @@ -194,8 +194,8 @@ } define float @ret_fptrunc_negonly_zero_nan(double nofpclass(pinf pnorm psub nan) %arg0) { -; CHECK-LABEL: define float @ret_fptrunc_negonly_zero_nan -; CHECK-SAME: (double nofpclass(nan pinf psub pnorm) [[ARG0:%.*]]) #[[ATTR0]] { +; CHECK-LABEL: define nofpclass(nan) float @ret_fptrunc_negonly_zero_nan +; CHECK-SAME: (double nofpclass(nan pinf psub pnorm) [[ARG0:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[EXT:%.*]] = fptrunc double [[ARG0]] to float ; CHECK-NEXT: ret float [[EXT]] ;