Index: llvm/include/llvm/Analysis/ValueTracking.h =================================================================== --- llvm/include/llvm/Analysis/ValueTracking.h +++ llvm/include/llvm/Analysis/ValueTracking.h @@ -293,7 +293,8 @@ return isKnownNever(fcPosZero); } - /// Return true if it's known this can never be a literal negative zero. + /// Return true if it's known this can never be a negative zero. This means a + /// literal -0 and does not include denormal inputs implicitly treated as -0. bool isKnownNeverNegZero() const { return isKnownNever(fcNegZero); } @@ -471,10 +472,19 @@ bool UseInstrInfo = true); /// Return true if we can prove that the specified FP value is never equal to -/// -0.0. -bool CannotBeNegativeZero(const Value *V, const TargetLibraryInfo *TLI, - unsigned Depth = 0); - +/// -0.0. Users should use caution when considering PreserveSign +/// denormal-fp-math. +inline bool cannotBeNegativeZero(const Value *V, const DataLayout &DL, + const TargetLibraryInfo *TLI = nullptr, + unsigned Depth = 0, + AssumptionCache *AC = nullptr, + const Instruction *CtxI = nullptr, + const DominatorTree *DT = nullptr, + bool UseInstrInfo = true) { + KnownFPClass Known = computeKnownFPClass(V, DL, fcNegZero, Depth, TLI, AC, + CtxI, DT, UseInstrInfo); + return Known.isKnownNeverNegZero(); +} bool CannotBeOrderedLessThanZero(const Value *V, const DataLayout &DL, const TargetLibraryInfo *TLI); Index: llvm/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/lib/Analysis/InstructionSimplify.cpp +++ llvm/lib/Analysis/InstructionSimplify.cpp @@ -5555,7 +5555,7 @@ // fadd X, 0 ==> X, when we know X is not -0 if (canIgnoreSNaN(ExBehavior, FMF)) if (match(Op1, m_PosZeroFP()) && - (FMF.noSignedZeros() || CannotBeNegativeZero(Op0, Q.TLI))) + (FMF.noSignedZeros() || cannotBeNegativeZero(Op0, Q.DL, Q.TLI))) return Op0; if (!isDefaultFPEnvironment(ExBehavior, Rounding)) @@ -5617,7 +5617,7 @@ // fsub X, -0 ==> X, when we know X is not -0 if (canIgnoreSNaN(ExBehavior, FMF)) if (match(Op1, m_NegZeroFP()) && - (FMF.noSignedZeros() || CannotBeNegativeZero(Op0, Q.TLI))) + (FMF.noSignedZeros() || cannotBeNegativeZero(Op0, Q.DL, Q.TLI))) return Op0; // fsub -0.0, (fsub -0.0, X) ==> X Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -3627,55 +3627,6 @@ return Intrinsic::not_intrinsic; } -/// Return true if we can prove that the specified FP value is never equal to -/// -0.0. -/// NOTE: Do not check 'nsz' here because that fast-math-flag does not guarantee -/// that a value is not -0.0. It only guarantees that -0.0 may be treated -/// the same as +0.0 in floating-point ops. -bool llvm::CannotBeNegativeZero(const Value *V, const TargetLibraryInfo *TLI, - unsigned Depth) { - if (auto *CFP = dyn_cast(V)) - return !CFP->getValueAPF().isNegZero(); - - if (Depth == MaxAnalysisRecursionDepth) - return false; - - auto *Op = dyn_cast(V); - if (!Op) - return false; - - // (fadd x, 0.0) is guaranteed to return +0.0, not -0.0. - if (match(Op, m_FAdd(m_Value(), m_PosZeroFP()))) - return true; - - // sitofp and uitofp turn into +0.0 for zero. - if (isa(Op) || isa(Op)) - return true; - - if (auto *Call = dyn_cast(Op)) { - Intrinsic::ID IID = getIntrinsicForCallSite(*Call, TLI); - switch (IID) { - default: - break; - case Intrinsic::sqrt: - case Intrinsic::experimental_constrained_sqrt: - // sqrt(-0.0) = -0.0, no other negative results are possible. - // FIXME: Account for denormal-fp-math=preserve-sign denormal inputs - case Intrinsic::canonicalize: - return CannotBeNegativeZero(Call->getArgOperand(0), TLI, Depth + 1); - // fabs(x) != -0.0 - case Intrinsic::fabs: - return true; - // sitofp and uitofp turn into +0.0 for zero. - case Intrinsic::experimental_constrained_sitofp: - case Intrinsic::experimental_constrained_uitofp: - return true; - } - } - - return false; -} - /// If \p SignBitOnly is true, test for a known 0 sign bit rather than a /// standard ordered compare. e.g. make -0.0 olt 0.0 be true because of the sign /// bit despite comparing equal. @@ -3828,8 +3779,9 @@ // sqrt(x) is always >= -0 or NaN. Moreover, sqrt(x) == -0 iff x == -0. if (!SignBitOnly) return true; - return CI->hasNoNaNs() && (CI->hasNoSignedZeros() || - CannotBeNegativeZero(CI->getOperand(0), TLI)); + return CI->hasNoNaNs() && + (CI->hasNoSignedZeros() || + cannotBeNegativeZero(CI->getOperand(0), DL, TLI)); case Intrinsic::powi: if (ConstantInt *Exponent = dyn_cast(I->getOperand(1))) { @@ -4262,8 +4214,7 @@ // Infinity needs a range check. } -// TODO: Merge implementations of CannotBeNegativeZero, -// cannotBeOrderedLessThanZero into here. +// TODO: Merge implementation of cannotBeOrderedLessThanZero into here. void computeKnownFPClass(const Value *V, const APInt &DemandedElts, FPClassTest InterestedClasses, KnownFPClass &Known, unsigned Depth, const SimplifyQuery &Q) { Index: llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -2640,7 +2640,7 @@ // Note that if this fsub was really an fneg, the fadd with -0.0 will get // killed later. We still limit that particular transform with 'hasOneUse' // because an fneg is assumed better/cheaper than a generic fsub. - if (I.hasNoSignedZeros() || CannotBeNegativeZero(Op0, SQ.TLI)) { + if (I.hasNoSignedZeros() || cannotBeNegativeZero(Op0, SQ.DL, SQ.TLI)) { if (match(Op1, m_OneUse(m_FSub(m_Value(X), m_Value(Y))))) { Value *NewSub = Builder.CreateFSubFMF(Y, X, &I); return BinaryOperator::CreateFAddFMF(Op0, NewSub, &I); Index: llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -98,7 +98,8 @@ // +0.0 compares equal to -0.0, and so it does not behave as required for this // transform. Bail out if we can not exclude that possibility. if (isa(BO)) - if (!BO->hasNoSignedZeros() && !CannotBeNegativeZero(Y, &TLI)) + if (!BO->hasNoSignedZeros() && + !cannotBeNegativeZero(Y, IC.getDataLayout(), &TLI)) return nullptr; // BO = binop Y, X