diff options
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 715 |
1 files changed, 354 insertions, 361 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index b350274..8bae935 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -4377,427 +4377,420 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, break; } case Instruction::Call: { - if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(Op)) { - const Intrinsic::ID IID = II->getIntrinsicID(); - switch (IID) { - case Intrinsic::fabs: { - if ((InterestedClasses & (fcNan | fcPositive)) != fcNone) { - // If we only care about the sign bit we don't need to inspect the - // operand. - computeKnownFPClass(II->getArgOperand(0), DemandedElts, - InterestedClasses, Known, Depth + 1, Q); - } - - Known.fabs(); - break; - } - case Intrinsic::copysign: { - KnownFPClass KnownSign; - + const CallInst *II = cast<CallInst>(Op); + const Intrinsic::ID IID = II->getIntrinsicID(); + switch (IID) { + case Intrinsic::fabs: { + if ((InterestedClasses & (fcNan | fcPositive)) != fcNone) { + // If we only care about the sign bit we don't need to inspect the + // operand. computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedClasses, Known, Depth + 1, Q); - computeKnownFPClass(II->getArgOperand(1), DemandedElts, - InterestedClasses, KnownSign, Depth + 1, Q); - Known.copysign(KnownSign); - break; } - case Intrinsic::fma: - case Intrinsic::fmuladd: { - if ((InterestedClasses & fcNegative) == fcNone) - break; - if (II->getArgOperand(0) != II->getArgOperand(1)) - break; - - // The multiply cannot be -0 and therefore the add can't be -0 - Known.knownNot(fcNegZero); + Known.fabs(); + break; + } + case Intrinsic::copysign: { + KnownFPClass KnownSign; - // x * x + y is non-negative if y is non-negative. - KnownFPClass KnownAddend; - computeKnownFPClass(II->getArgOperand(2), DemandedElts, - InterestedClasses, KnownAddend, Depth + 1, Q); + computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedClasses, + Known, Depth + 1, Q); + computeKnownFPClass(II->getArgOperand(1), DemandedElts, InterestedClasses, + KnownSign, Depth + 1, Q); + Known.copysign(KnownSign); + break; + } + case Intrinsic::fma: + case Intrinsic::fmuladd: { + if ((InterestedClasses & fcNegative) == fcNone) + break; - // TODO: Known sign bit with no nans - if (KnownAddend.cannotBeOrderedLessThanZero()) - Known.knownNot(fcNegative); + if (II->getArgOperand(0) != II->getArgOperand(1)) break; - } - case Intrinsic::sqrt: - case Intrinsic::experimental_constrained_sqrt: { - KnownFPClass KnownSrc; - FPClassTest InterestedSrcs = InterestedClasses; - if (InterestedClasses & fcNan) - InterestedSrcs |= KnownFPClass::OrderedLessThanZeroMask; - computeKnownFPClass(II->getArgOperand(0), DemandedElts, - InterestedSrcs, KnownSrc, Depth + 1, Q); + // The multiply cannot be -0 and therefore the add can't be -0 + Known.knownNot(fcNegZero); - if (KnownSrc.isKnownNeverPosInfinity()) - Known.knownNot(fcPosInf); - if (KnownSrc.isKnownNever(fcSNan)) - Known.knownNot(fcSNan); - - // Any negative value besides -0 returns a nan. - if (KnownSrc.isKnownNeverNaN() && - KnownSrc.cannotBeOrderedLessThanZero()) - Known.knownNot(fcNan); - - // The only negative value that can be returned is -0 for -0 inputs. - Known.knownNot(fcNegInf | fcNegSubnormal | fcNegNormal); - - // If the input denormal mode could be PreserveSign, a negative - // subnormal input could produce a negative zero output. - const Function *F = II->getFunction(); - if (Q.IIQ.hasNoSignedZeros(II) || - (F && KnownSrc.isKnownNeverLogicalNegZero(*F, II->getType()))) { - Known.knownNot(fcNegZero); - if (KnownSrc.isKnownNeverNaN()) - Known.SignBit = false; - } + // x * x + y is non-negative if y is non-negative. + KnownFPClass KnownAddend; + computeKnownFPClass(II->getArgOperand(2), DemandedElts, InterestedClasses, + KnownAddend, Depth + 1, Q); - break; - } - case Intrinsic::sin: - case Intrinsic::cos: { - // Return NaN on infinite inputs. - KnownFPClass KnownSrc; - computeKnownFPClass(II->getArgOperand(0), DemandedElts, - InterestedClasses, KnownSrc, Depth + 1, Q); - Known.knownNot(fcInf); - if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity()) - Known.knownNot(fcNan); - break; + // TODO: Known sign bit with no nans + if (KnownAddend.cannotBeOrderedLessThanZero()) + Known.knownNot(fcNegative); + break; + } + case Intrinsic::sqrt: + case Intrinsic::experimental_constrained_sqrt: { + KnownFPClass KnownSrc; + FPClassTest InterestedSrcs = InterestedClasses; + if (InterestedClasses & fcNan) + InterestedSrcs |= KnownFPClass::OrderedLessThanZeroMask; + + computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedSrcs, + KnownSrc, Depth + 1, Q); + + if (KnownSrc.isKnownNeverPosInfinity()) + Known.knownNot(fcPosInf); + if (KnownSrc.isKnownNever(fcSNan)) + Known.knownNot(fcSNan); + + // Any negative value besides -0 returns a nan. + if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero()) + Known.knownNot(fcNan); + + // The only negative value that can be returned is -0 for -0 inputs. + Known.knownNot(fcNegInf | fcNegSubnormal | fcNegNormal); + + // If the input denormal mode could be PreserveSign, a negative + // subnormal input could produce a negative zero output. + const Function *F = II->getFunction(); + if (Q.IIQ.hasNoSignedZeros(II) || + (F && KnownSrc.isKnownNeverLogicalNegZero(*F, II->getType()))) { + Known.knownNot(fcNegZero); + if (KnownSrc.isKnownNeverNaN()) + Known.SignBit = false; } - case Intrinsic::maxnum: - case Intrinsic::minnum: - case Intrinsic::minimum: - case Intrinsic::maximum: { - KnownFPClass KnownLHS, KnownRHS; - computeKnownFPClass(II->getArgOperand(0), DemandedElts, - InterestedClasses, KnownLHS, Depth + 1, Q); - computeKnownFPClass(II->getArgOperand(1), DemandedElts, - InterestedClasses, KnownRHS, Depth + 1, Q); - - bool NeverNaN = - KnownLHS.isKnownNeverNaN() || KnownRHS.isKnownNeverNaN(); - Known = KnownLHS | KnownRHS; - - // If either operand is not NaN, the result is not NaN. - if (NeverNaN && (IID == Intrinsic::minnum || IID == Intrinsic::maxnum)) - Known.knownNot(fcNan); - - if (IID == Intrinsic::maxnum) { - // If at least one operand is known to be positive, the result must be - // positive. - if ((KnownLHS.cannotBeOrderedLessThanZero() && - KnownLHS.isKnownNeverNaN()) || - (KnownRHS.cannotBeOrderedLessThanZero() && - KnownRHS.isKnownNeverNaN())) - Known.knownNot(KnownFPClass::OrderedLessThanZeroMask); - } else if (IID == Intrinsic::maximum) { - // If at least one operand is known to be positive, the result must be - // positive. - if (KnownLHS.cannotBeOrderedLessThanZero() || - KnownRHS.cannotBeOrderedLessThanZero()) - Known.knownNot(KnownFPClass::OrderedLessThanZeroMask); - } else if (IID == Intrinsic::minnum) { - // If at least one operand is known to be negative, the result must be - // negative. - if ((KnownLHS.cannotBeOrderedGreaterThanZero() && - KnownLHS.isKnownNeverNaN()) || - (KnownRHS.cannotBeOrderedGreaterThanZero() && - KnownRHS.isKnownNeverNaN())) - Known.knownNot(KnownFPClass::OrderedGreaterThanZeroMask); - } else { - // If at least one operand is known to be negative, the result must be - // negative. - if (KnownLHS.cannotBeOrderedGreaterThanZero() || - KnownRHS.cannotBeOrderedGreaterThanZero()) - Known.knownNot(KnownFPClass::OrderedGreaterThanZeroMask); - } + break; + } + case Intrinsic::sin: + case Intrinsic::cos: { + // Return NaN on infinite inputs. + KnownFPClass KnownSrc; + computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedClasses, + KnownSrc, Depth + 1, Q); + Known.knownNot(fcInf); + if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity()) + Known.knownNot(fcNan); + break; + } + case Intrinsic::maxnum: + case Intrinsic::minnum: + case Intrinsic::minimum: + case Intrinsic::maximum: { + KnownFPClass KnownLHS, KnownRHS; + computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedClasses, + KnownLHS, Depth + 1, Q); + computeKnownFPClass(II->getArgOperand(1), DemandedElts, InterestedClasses, + KnownRHS, Depth + 1, Q); - // Fixup zero handling if denormals could be returned as a zero. - // - // As there's no spec for denormal flushing, be conservative with the - // treatment of denormals that could be flushed to zero. For older - // subtargets on AMDGPU the min/max instructions would not flush the - // output and return the original value. - // - // TODO: This could be refined based on the sign - if ((Known.KnownFPClasses & fcZero) != fcNone && - !Known.isKnownNeverSubnormal()) { - const Function *Parent = II->getFunction(); - if (!Parent) - break; - - DenormalMode Mode = Parent->getDenormalMode( - II->getType()->getScalarType()->getFltSemantics()); - if (Mode != DenormalMode::getIEEE()) - Known.KnownFPClasses |= fcZero; - } + bool NeverNaN = KnownLHS.isKnownNeverNaN() || KnownRHS.isKnownNeverNaN(); + Known = KnownLHS | KnownRHS; - break; + // If either operand is not NaN, the result is not NaN. + if (NeverNaN && (IID == Intrinsic::minnum || IID == Intrinsic::maxnum)) + Known.knownNot(fcNan); + + if (IID == Intrinsic::maxnum) { + // If at least one operand is known to be positive, the result must be + // positive. + if ((KnownLHS.cannotBeOrderedLessThanZero() && + KnownLHS.isKnownNeverNaN()) || + (KnownRHS.cannotBeOrderedLessThanZero() && + KnownRHS.isKnownNeverNaN())) + Known.knownNot(KnownFPClass::OrderedLessThanZeroMask); + } else if (IID == Intrinsic::maximum) { + // If at least one operand is known to be positive, the result must be + // positive. + if (KnownLHS.cannotBeOrderedLessThanZero() || + KnownRHS.cannotBeOrderedLessThanZero()) + Known.knownNot(KnownFPClass::OrderedLessThanZeroMask); + } else if (IID == Intrinsic::minnum) { + // If at least one operand is known to be negative, the result must be + // negative. + if ((KnownLHS.cannotBeOrderedGreaterThanZero() && + KnownLHS.isKnownNeverNaN()) || + (KnownRHS.cannotBeOrderedGreaterThanZero() && + KnownRHS.isKnownNeverNaN())) + Known.knownNot(KnownFPClass::OrderedGreaterThanZeroMask); + } else { + // If at least one operand is known to be negative, the result must be + // negative. + if (KnownLHS.cannotBeOrderedGreaterThanZero() || + KnownRHS.cannotBeOrderedGreaterThanZero()) + Known.knownNot(KnownFPClass::OrderedGreaterThanZeroMask); } - case Intrinsic::canonicalize: { - KnownFPClass KnownSrc; - computeKnownFPClass(II->getArgOperand(0), DemandedElts, - InterestedClasses, KnownSrc, Depth + 1, Q); - // This is essentially a stronger form of - // propagateCanonicalizingSrc. Other "canonicalizing" operations don't - // actually have an IR canonicalization guarantee. + // Fixup zero handling if denormals could be returned as a zero. + // + // As there's no spec for denormal flushing, be conservative with the + // treatment of denormals that could be flushed to zero. For older + // subtargets on AMDGPU the min/max instructions would not flush the + // output and return the original value. + // + // TODO: This could be refined based on the sign + if ((Known.KnownFPClasses & fcZero) != fcNone && + !Known.isKnownNeverSubnormal()) { + const Function *Parent = II->getFunction(); + if (!Parent) + break; - // Canonicalize may flush denormals to zero, so we have to consider the - // denormal mode to preserve known-not-0 knowledge. - Known.KnownFPClasses = KnownSrc.KnownFPClasses | fcZero | fcQNan; + DenormalMode Mode = Parent->getDenormalMode( + II->getType()->getScalarType()->getFltSemantics()); + if (Mode != DenormalMode::getIEEE()) + Known.KnownFPClasses |= fcZero; + } - // Stronger version of propagateNaN - // Canonicalize is guaranteed to quiet signaling nans. - if (KnownSrc.isKnownNeverNaN()) - Known.knownNot(fcNan); - else - Known.knownNot(fcSNan); + break; + } + case Intrinsic::canonicalize: { + KnownFPClass KnownSrc; + computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedClasses, + KnownSrc, Depth + 1, Q); - const Function *F = II->getFunction(); - if (!F) - break; + // This is essentially a stronger form of + // propagateCanonicalizingSrc. Other "canonicalizing" operations don't + // actually have an IR canonicalization guarantee. - // If the parent function flushes denormals, the canonical output cannot - // be a denormal. - const fltSemantics &FPType = - II->getType()->getScalarType()->getFltSemantics(); - DenormalMode DenormMode = F->getDenormalMode(FPType); - if (DenormMode == DenormalMode::getIEEE()) { - if (KnownSrc.isKnownNever(fcPosZero)) - Known.knownNot(fcPosZero); - if (KnownSrc.isKnownNever(fcNegZero)) - Known.knownNot(fcNegZero); - break; - } + // Canonicalize may flush denormals to zero, so we have to consider the + // denormal mode to preserve known-not-0 knowledge. + Known.KnownFPClasses = KnownSrc.KnownFPClasses | fcZero | fcQNan; - if (DenormMode.inputsAreZero() || DenormMode.outputsAreZero()) - Known.knownNot(fcSubnormal); + // Stronger version of propagateNaN + // Canonicalize is guaranteed to quiet signaling nans. + if (KnownSrc.isKnownNeverNaN()) + Known.knownNot(fcNan); + else + Known.knownNot(fcSNan); - if (DenormMode.Input == DenormalMode::PositiveZero || - (DenormMode.Output == DenormalMode::PositiveZero && - DenormMode.Input == DenormalMode::IEEE)) - Known.knownNot(fcNegZero); + const Function *F = II->getFunction(); + if (!F) + break; + // If the parent function flushes denormals, the canonical output cannot + // be a denormal. + const fltSemantics &FPType = + II->getType()->getScalarType()->getFltSemantics(); + DenormalMode DenormMode = F->getDenormalMode(FPType); + if (DenormMode == DenormalMode::getIEEE()) { + if (KnownSrc.isKnownNever(fcPosZero)) + Known.knownNot(fcPosZero); + if (KnownSrc.isKnownNever(fcNegZero)) + Known.knownNot(fcNegZero); break; } - case Intrinsic::trunc: - case Intrinsic::floor: - case Intrinsic::ceil: - case Intrinsic::rint: - case Intrinsic::nearbyint: - case Intrinsic::round: - case Intrinsic::roundeven: { - KnownFPClass KnownSrc; - FPClassTest InterestedSrcs = InterestedClasses; - if (InterestedSrcs & fcPosFinite) - InterestedSrcs |= fcPosFinite; - if (InterestedSrcs & fcNegFinite) - InterestedSrcs |= fcNegFinite; - computeKnownFPClass(II->getArgOperand(0), DemandedElts, - InterestedSrcs, KnownSrc, Depth + 1, Q); - // Integer results cannot be subnormal. + if (DenormMode.inputsAreZero() || DenormMode.outputsAreZero()) Known.knownNot(fcSubnormal); - Known.propagateNaN(KnownSrc, true); + if (DenormMode.Input == DenormalMode::PositiveZero || + (DenormMode.Output == DenormalMode::PositiveZero && + DenormMode.Input == DenormalMode::IEEE)) + Known.knownNot(fcNegZero); - // Pass through infinities, except PPC_FP128 is a special case for - // intrinsics other than trunc. - if (IID == Intrinsic::trunc || !V->getType()->isMultiUnitFPType()) { - if (KnownSrc.isKnownNeverPosInfinity()) - Known.knownNot(fcPosInf); - if (KnownSrc.isKnownNeverNegInfinity()) - Known.knownNot(fcNegInf); - } + break; + } + case Intrinsic::trunc: + case Intrinsic::floor: + case Intrinsic::ceil: + case Intrinsic::rint: + case Intrinsic::nearbyint: + case Intrinsic::round: + case Intrinsic::roundeven: { + KnownFPClass KnownSrc; + FPClassTest InterestedSrcs = InterestedClasses; + if (InterestedSrcs & fcPosFinite) + InterestedSrcs |= fcPosFinite; + if (InterestedSrcs & fcNegFinite) + InterestedSrcs |= fcNegFinite; + computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedSrcs, + KnownSrc, Depth + 1, Q); + + // Integer results cannot be subnormal. + Known.knownNot(fcSubnormal); - // Negative round ups to 0 produce -0 - if (KnownSrc.isKnownNever(fcPosFinite)) - Known.knownNot(fcPosFinite); - if (KnownSrc.isKnownNever(fcNegFinite)) - Known.knownNot(fcNegFinite); + Known.propagateNaN(KnownSrc, true); - break; + // Pass through infinities, except PPC_FP128 is a special case for + // intrinsics other than trunc. + if (IID == Intrinsic::trunc || !V->getType()->isMultiUnitFPType()) { + if (KnownSrc.isKnownNeverPosInfinity()) + Known.knownNot(fcPosInf); + if (KnownSrc.isKnownNeverNegInfinity()) + Known.knownNot(fcNegInf); } - case Intrinsic::exp: - case Intrinsic::exp2: { - Known.knownNot(fcNegative); - if ((InterestedClasses & fcNan) == fcNone) - break; - KnownFPClass KnownSrc; - computeKnownFPClass(II->getArgOperand(0), DemandedElts, - InterestedClasses, KnownSrc, Depth + 1, Q); - if (KnownSrc.isKnownNeverNaN()) { - Known.knownNot(fcNan); - Known.SignBit = false; - } + // Negative round ups to 0 produce -0 + if (KnownSrc.isKnownNever(fcPosFinite)) + Known.knownNot(fcPosFinite); + if (KnownSrc.isKnownNever(fcNegFinite)) + Known.knownNot(fcNegFinite); + break; + } + case Intrinsic::exp: + case Intrinsic::exp2: { + Known.knownNot(fcNegative); + if ((InterestedClasses & fcNan) == fcNone) break; + + KnownFPClass KnownSrc; + computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedClasses, + KnownSrc, Depth + 1, Q); + if (KnownSrc.isKnownNeverNaN()) { + Known.knownNot(fcNan); + Known.SignBit = false; } - case Intrinsic::fptrunc_round: { - computeKnownFPClassForFPTrunc(Op, DemandedElts, InterestedClasses, - Known, Depth, Q); + + break; + } + case Intrinsic::fptrunc_round: { + computeKnownFPClassForFPTrunc(Op, DemandedElts, InterestedClasses, Known, + Depth, Q); + break; + } + case Intrinsic::log: + case Intrinsic::log10: + case Intrinsic::log2: + case Intrinsic::experimental_constrained_log: + case Intrinsic::experimental_constrained_log10: + case Intrinsic::experimental_constrained_log2: { + // log(+inf) -> +inf + // log([+-]0.0) -> -inf + // log(-inf) -> nan + // log(-x) -> nan + if ((InterestedClasses & (fcNan | fcInf)) == fcNone) break; - } - case Intrinsic::log: - case Intrinsic::log10: - case Intrinsic::log2: - case Intrinsic::experimental_constrained_log: - case Intrinsic::experimental_constrained_log10: - case Intrinsic::experimental_constrained_log2: { - // log(+inf) -> +inf - // log([+-]0.0) -> -inf - // log(-inf) -> nan - // log(-x) -> nan - if ((InterestedClasses & (fcNan | fcInf)) == fcNone) - break; - FPClassTest InterestedSrcs = InterestedClasses; - if ((InterestedClasses & fcNegInf) != fcNone) - InterestedSrcs |= fcZero | fcSubnormal; - if ((InterestedClasses & fcNan) != fcNone) - InterestedSrcs |= fcNan | (fcNegative & ~fcNan); + FPClassTest InterestedSrcs = InterestedClasses; + if ((InterestedClasses & fcNegInf) != fcNone) + InterestedSrcs |= fcZero | fcSubnormal; + if ((InterestedClasses & fcNan) != fcNone) + InterestedSrcs |= fcNan | (fcNegative & ~fcNan); - KnownFPClass KnownSrc; - computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedSrcs, - KnownSrc, Depth + 1, Q); + KnownFPClass KnownSrc; + computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedSrcs, + KnownSrc, Depth + 1, Q); - if (KnownSrc.isKnownNeverPosInfinity()) - Known.knownNot(fcPosInf); + if (KnownSrc.isKnownNeverPosInfinity()) + Known.knownNot(fcPosInf); - if (KnownSrc.isKnownNeverNaN() && - KnownSrc.cannotBeOrderedLessThanZero()) - Known.knownNot(fcNan); + if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero()) + Known.knownNot(fcNan); - const Function *F = II->getFunction(); - if (F && KnownSrc.isKnownNeverLogicalZero(*F, II->getType())) - Known.knownNot(fcNegInf); + const Function *F = II->getFunction(); + if (F && KnownSrc.isKnownNeverLogicalZero(*F, II->getType())) + Known.knownNot(fcNegInf); + break; + } + case Intrinsic::powi: { + if ((InterestedClasses & fcNegative) == fcNone) break; - } - case Intrinsic::powi: { - if ((InterestedClasses & fcNegative) == fcNone) - break; - const Value *Exp = II->getArgOperand(1); - Type *ExpTy = Exp->getType(); - unsigned BitWidth = ExpTy->getScalarType()->getIntegerBitWidth(); - KnownBits ExponentKnownBits(BitWidth); - computeKnownBits(Exp, - isa<VectorType>(ExpTy) ? DemandedElts : APInt(1, 1), - ExponentKnownBits, Depth + 1, Q); + const Value *Exp = II->getArgOperand(1); + Type *ExpTy = Exp->getType(); + unsigned BitWidth = ExpTy->getScalarType()->getIntegerBitWidth(); + KnownBits ExponentKnownBits(BitWidth); + computeKnownBits(Exp, isa<VectorType>(ExpTy) ? DemandedElts : APInt(1, 1), + ExponentKnownBits, Depth + 1, Q); - if (ExponentKnownBits.Zero[0]) { // Is even - Known.knownNot(fcNegative); - break; - } - - // Given that exp is an integer, here are the - // ways that pow can return a negative value: - // - // pow(-x, exp) --> negative if exp is odd and x is negative. - // pow(-0, exp) --> -inf if exp is negative odd. - // pow(-0, exp) --> -0 if exp is positive odd. - // pow(-inf, exp) --> -0 if exp is negative odd. - // pow(-inf, exp) --> -inf if exp is positive odd. - KnownFPClass KnownSrc; - computeKnownFPClass(II->getArgOperand(0), DemandedElts, fcNegative, - KnownSrc, Depth + 1, Q); - if (KnownSrc.isKnownNever(fcNegative)) - Known.knownNot(fcNegative); + if (ExponentKnownBits.Zero[0]) { // Is even + Known.knownNot(fcNegative); break; } - case Intrinsic::ldexp: { - KnownFPClass KnownSrc; - computeKnownFPClass(II->getArgOperand(0), DemandedElts, - InterestedClasses, KnownSrc, Depth + 1, Q); - Known.propagateNaN(KnownSrc, /*PropagateSign=*/true); - // Sign is preserved, but underflows may produce zeroes. - if (KnownSrc.isKnownNever(fcNegative)) - Known.knownNot(fcNegative); - else if (KnownSrc.cannotBeOrderedLessThanZero()) - Known.knownNot(KnownFPClass::OrderedLessThanZeroMask); + // Given that exp is an integer, here are the + // ways that pow can return a negative value: + // + // pow(-x, exp) --> negative if exp is odd and x is negative. + // pow(-0, exp) --> -inf if exp is negative odd. + // pow(-0, exp) --> -0 if exp is positive odd. + // pow(-inf, exp) --> -0 if exp is negative odd. + // pow(-inf, exp) --> -inf if exp is positive odd. + KnownFPClass KnownSrc; + computeKnownFPClass(II->getArgOperand(0), DemandedElts, fcNegative, + KnownSrc, Depth + 1, Q); + if (KnownSrc.isKnownNever(fcNegative)) + Known.knownNot(fcNegative); + break; + } + case Intrinsic::ldexp: { + KnownFPClass KnownSrc; + computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedClasses, + KnownSrc, Depth + 1, Q); + Known.propagateNaN(KnownSrc, /*PropagateSign=*/true); - if (KnownSrc.isKnownNever(fcPositive)) - Known.knownNot(fcPositive); - else if (KnownSrc.cannotBeOrderedGreaterThanZero()) - Known.knownNot(KnownFPClass::OrderedGreaterThanZeroMask); + // Sign is preserved, but underflows may produce zeroes. + if (KnownSrc.isKnownNever(fcNegative)) + Known.knownNot(fcNegative); + else if (KnownSrc.cannotBeOrderedLessThanZero()) + Known.knownNot(KnownFPClass::OrderedLessThanZeroMask); - // Can refine inf/zero handling based on the exponent operand. - const FPClassTest ExpInfoMask = fcZero | fcSubnormal | fcInf; - if ((InterestedClasses & ExpInfoMask) == fcNone) - break; - if ((KnownSrc.KnownFPClasses & ExpInfoMask) == fcNone) - break; + if (KnownSrc.isKnownNever(fcPositive)) + Known.knownNot(fcPositive); + else if (KnownSrc.cannotBeOrderedGreaterThanZero()) + Known.knownNot(KnownFPClass::OrderedGreaterThanZeroMask); - const fltSemantics &Flt - = II->getType()->getScalarType()->getFltSemantics(); - unsigned Precision = APFloat::semanticsPrecision(Flt); - const Value *ExpArg = II->getArgOperand(1); - ConstantRange ExpRange = computeConstantRange( - ExpArg, true, Q.IIQ.UseInstrInfo, Q.AC, Q.CxtI, Q.DT, Depth + 1); + // Can refine inf/zero handling based on the exponent operand. + const FPClassTest ExpInfoMask = fcZero | fcSubnormal | fcInf; + if ((InterestedClasses & ExpInfoMask) == fcNone) + break; + if ((KnownSrc.KnownFPClasses & ExpInfoMask) == fcNone) + break; - const int MantissaBits = Precision - 1; - if (ExpRange.getSignedMin().sge(static_cast<int64_t>(MantissaBits))) - Known.knownNot(fcSubnormal); + const fltSemantics &Flt = + II->getType()->getScalarType()->getFltSemantics(); + unsigned Precision = APFloat::semanticsPrecision(Flt); + const Value *ExpArg = II->getArgOperand(1); + ConstantRange ExpRange = computeConstantRange( + ExpArg, true, Q.IIQ.UseInstrInfo, Q.AC, Q.CxtI, Q.DT, Depth + 1); - const Function *F = II->getFunction(); - const APInt *ConstVal = ExpRange.getSingleElement(); - if (ConstVal && ConstVal->isZero()) { - // ldexp(x, 0) -> x, so propagate everything. - Known.propagateCanonicalizingSrc(KnownSrc, *F, - II->getType()); - } else if (ExpRange.isAllNegative()) { - // If we know the power is <= 0, can't introduce inf - if (KnownSrc.isKnownNeverPosInfinity()) - Known.knownNot(fcPosInf); - if (KnownSrc.isKnownNeverNegInfinity()) - Known.knownNot(fcNegInf); - } else if (ExpRange.isAllNonNegative()) { - // If we know the power is >= 0, can't introduce subnormal or zero - if (KnownSrc.isKnownNeverPosSubnormal()) - Known.knownNot(fcPosSubnormal); - if (KnownSrc.isKnownNeverNegSubnormal()) - Known.knownNot(fcNegSubnormal); - if (F && KnownSrc.isKnownNeverLogicalPosZero(*F, II->getType())) - Known.knownNot(fcPosZero); - if (F && KnownSrc.isKnownNeverLogicalNegZero(*F, II->getType())) - Known.knownNot(fcNegZero); - } + const int MantissaBits = Precision - 1; + if (ExpRange.getSignedMin().sge(static_cast<int64_t>(MantissaBits))) + Known.knownNot(fcSubnormal); - break; - } - case Intrinsic::arithmetic_fence: { - computeKnownFPClass(II->getArgOperand(0), DemandedElts, - InterestedClasses, Known, Depth + 1, Q); - break; + const Function *F = II->getFunction(); + const APInt *ConstVal = ExpRange.getSingleElement(); + if (ConstVal && ConstVal->isZero()) { + // ldexp(x, 0) -> x, so propagate everything. + Known.propagateCanonicalizingSrc(KnownSrc, *F, II->getType()); + } else if (ExpRange.isAllNegative()) { + // If we know the power is <= 0, can't introduce inf + if (KnownSrc.isKnownNeverPosInfinity()) + Known.knownNot(fcPosInf); + if (KnownSrc.isKnownNeverNegInfinity()) + Known.knownNot(fcNegInf); + } else if (ExpRange.isAllNonNegative()) { + // If we know the power is >= 0, can't introduce subnormal or zero + if (KnownSrc.isKnownNeverPosSubnormal()) + Known.knownNot(fcPosSubnormal); + if (KnownSrc.isKnownNeverNegSubnormal()) + Known.knownNot(fcNegSubnormal); + if (F && KnownSrc.isKnownNeverLogicalPosZero(*F, II->getType())) + Known.knownNot(fcPosZero); + if (F && KnownSrc.isKnownNeverLogicalNegZero(*F, II->getType())) + Known.knownNot(fcNegZero); } - case Intrinsic::experimental_constrained_sitofp: - case Intrinsic::experimental_constrained_uitofp: - // Cannot produce nan - Known.knownNot(fcNan); - // sitofp and uitofp turn into +0.0 for zero. - Known.knownNot(fcNegZero); + break; + } + case Intrinsic::arithmetic_fence: { + computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedClasses, + Known, Depth + 1, Q); + break; + } + case Intrinsic::experimental_constrained_sitofp: + case Intrinsic::experimental_constrained_uitofp: + // Cannot produce nan + Known.knownNot(fcNan); - // Integers cannot be subnormal - Known.knownNot(fcSubnormal); + // sitofp and uitofp turn into +0.0 for zero. + Known.knownNot(fcNegZero); - if (IID == Intrinsic::experimental_constrained_uitofp) - Known.signBitMustBeZero(); + // Integers cannot be subnormal + Known.knownNot(fcSubnormal); - // TODO: Copy inf handling from instructions - break; - default: - break; - } + if (IID == Intrinsic::experimental_constrained_uitofp) + Known.signBitMustBeZero(); + + // TODO: Copy inf handling from instructions + break; + default: + break; } break; |