18void ConstantFPRange::makeEmpty() {
19 auto &Sem = Lower.getSemantics();
26void ConstantFPRange::makeFull() {
27 auto &Sem = Lower.getSemantics();
35 return Lower.isPosInfinity() && Upper.isNegInfinity();
38ConstantFPRange::ConstantFPRange(
const fltSemantics &Sem,
bool IsFullSet)
42 MayBeQNaN = IsFullSet;
43 MayBeSNaN = IsFullSet;
51 bool IsSNaN = Value.isSignaling();
55 Lower = Upper = Value;
56 MayBeQNaN = MayBeSNaN = false;
63 assert(!
LHS.isNaN() && !
RHS.isNaN() &&
"Unordered compare");
64 if (
LHS.isZero() &&
RHS.isZero()) {
65 if (
LHS.isNegative() ==
RHS.isNegative())
85 bool MayBeQNaNVal,
bool MayBeSNaNVal)
87 MayBeQNaN(MayBeQNaNVal), MayBeSNaN(MayBeSNaNVal) {
88 assert(&Lower.getSemantics() == &Upper.getSemantics() &&
89 "Should only use the same semantics");
100 bool MayBeQNaN,
bool MayBeSNaN) {
121 if (V.isNegInfinity())
122 return ConstantFPRange::getEmpty(Sem);
133 if (V.isPosInfinity())
134 return ConstantFPRange::getEmpty(Sem);
149 if (
Lower.isPosZero())
151 if (
Upper.isNegZero())
161 ContainsNaN, ContainsNaN);
166 const ConstantFPRange &
Other) {
167 if (
Other.isEmptySet())
170 return getFull(
Other.getSemantics());
172 return getEmpty(
Other.getSemantics());
176 return getFull(
Other.getSemantics());
178 return getEmpty(
Other.getSemantics());
189 if (
const APFloat *SingleElement =
190 Other.getSingleElement(
true)) {
191 const fltSemantics &Sem = SingleElement->getSemantics();
192 if (SingleElement->isPosInfinity())
197 if (SingleElement->isNegInfinity())
204 : getFull(
Other.getSemantics());
224 const ConstantFPRange &
Other) {
225 if (
Other.isEmptySet())
226 return getFull(
Other.getSemantics());
228 return getEmpty(
Other.getSemantics());
230 return getFull(
Other.getSemantics());
234 return getFull(
Other.getSemantics());
236 return getEmpty(
Other.getSemantics());
247 : getEmpty(
Other.getSemantics()),
251 return getEmpty(
Other.getSemantics());
269std::optional<ConstantFPRange>
279 const ConstantFPRange &
Other)
const {
284 return Lower.isNegInfinity() && Upper.isPosInfinity() && MayBeQNaN &&
289 return Lower.isPosInfinity() && Upper.isNegInfinity() && !MayBeQNaN &&
295 "Should only use the same semantics");
305 "Should only use the same semantics");
307 if (CR.MayBeQNaN && !MayBeQNaN)
310 if (CR.MayBeSNaN && !MayBeSNaN)
318 if (!ExcludesNaN && (MayBeSNaN || MayBeQNaN))
324 if (!MayBeSNaN && !MayBeQNaN && Lower.isNegative() == Upper.isNegative())
325 return Lower.isNegative();
331 "Should only use the same semantics");
332 if (MayBeSNaN != CR.MayBeSNaN || MayBeQNaN != CR.MayBeQNaN)
334 return Lower.bitwiseIsEqual(CR.Lower) && Upper.bitwiseIsEqual(CR.Upper);
346 assert(LowerMask <= UpperMask &&
"Range is nan-only.");
348 Mask |= (UpperMask << 1) - LowerMask;
361 OS <<
'[' << Lower <<
", " << Upper <<
']';
363 if (MayBeSNaN || MayBeQNaN) {
366 if (MayBeSNaN && MayBeQNaN)
376#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
383 "Should only use the same semantics");
387 return ConstantFPRange(std::move(NewLower), std::move(NewUpper),
388 MayBeQNaN & CR.MayBeQNaN, MayBeSNaN & CR.MayBeSNaN);
393 "Should only use the same semantics");
394 return ConstantFPRange(
minnum(Lower, CR.Lower),
maxnum(Upper, CR.Upper),
395 MayBeQNaN | CR.MayBeQNaN, MayBeSNaN | CR.MayBeSNaN);
402 if (Lower.isNegative() == Upper.isNegative()) {
403 if (Lower.isNegative())
410 return ConstantFPRange(std::move(NewLower), std::move(NewUpper), MayBeQNaN,
415 return ConstantFPRange(-Upper, -Lower, MayBeQNaN, MayBeSNaN);
422 "Non-NaN part is empty.");
423 auto &Sem =
Lower.getSemantics();
424 if (
Lower.isNegInfinity()) {
428 if (
Upper.isPosInfinity()) {
441 removeInf(NewLower, NewUpper, UnusedFlag,
444 return ConstantFPRange(std::move(NewLower), std::move(NewUpper), MayBeQNaN,
456 return getFull(DstSem);
459 return getFull(DstSem);
460 return ConstantFPRange(std::move(NewLower), std::move(NewUpper),
461 MayBeQNaN || MayBeSNaN,
466 bool ResMayBeQNaN = ((MayBeQNaN || MayBeSNaN) && !
Other.isEmptySet()) ||
471 bool LHSHasNegInf =
false, LHSHasPosInf =
false;
472 APFloat LHSLower = Lower, LHSUpper = Upper;
473 bool LHSFiniteIsNonEmpty =
474 removeInf(LHSLower, LHSUpper, LHSHasPosInf, LHSHasNegInf);
475 bool RHSHasNegInf =
false, RHSHasPosInf =
false;
477 bool RHSFiniteIsNonEmpty =
478 removeInf(RHSLower, RHSUpper, RHSHasPosInf, RHSHasNegInf);
481 (LHSHasNegInf && RHSHasPosInf) || (LHSHasPosInf && RHSHasNegInf);
483 bool HasNegInf = (LHSHasNegInf && (RHSFiniteIsNonEmpty || RHSHasNegInf)) ||
484 (RHSHasNegInf && (LHSFiniteIsNonEmpty || LHSHasNegInf));
485 bool HasPosInf = (LHSHasPosInf && (RHSFiniteIsNonEmpty || RHSHasPosInf)) ||
486 (RHSHasPosInf && (LHSFiniteIsNonEmpty || LHSHasPosInf));
487 if (LHSFiniteIsNonEmpty && RHSFiniteIsNonEmpty) {
490 : LHSLower + RHSLower;
493 : LHSUpper + RHSUpper;
494 return ConstantFPRange(NewLower, NewUpper, ResMayBeQNaN,
499 return ConstantFPRange(
522 bool ZeroLowerNegative =
524 bool ZeroUpperNegative =
526 assert((ZeroLowerNegative || !ZeroUpperNegative) &&
527 "ZeroLower is greater than ZeroUpper.");
545 "The sign should be dropped.");
548 if (!
Lower.isInfinity())
556 std::optional<SameSignRange> &NegPart,
557 std::optional<SameSignRange> &PosPart) {
559 "Non-NaN part is empty.");
560 if (
Lower.isNegative() ==
Upper.isNegative()) {
561 if (
Lower.isNegative())
567 auto &Sem =
Lower.getSemantics();
574 bool ResMayBeQNaN = ((MayBeQNaN || MayBeSNaN) && !
Other.isEmptySet()) ||
579 std::optional<SameSignRange> LHSNeg, LHSPos, RHSNeg, RHSPos;
584 auto Update = [&](std::optional<SameSignRange> &LHS,
585 std::optional<SameSignRange> &RHS,
bool Negative) {
589 ResMayBeQNaN |= LHS->HasZero && RHS->HasInf;
590 ResMayBeQNaN |= RHS->HasZero && LHS->HasInf;
592 if ((LHS->HasInf && RHS->HasNonZero) || (RHS->HasInf && LHS->HasNonZero))
595 if (LHS->FinitePart && RHS->FinitePart) {
596 APFloat NewLower = LHS->FinitePart->first * RHS->FinitePart->first;
597 APFloat NewUpper = LHS->FinitePart->second * RHS->FinitePart->second;
599 ResLower =
minnum(ResLower, -NewUpper);
600 ResUpper =
maxnum(ResUpper, -NewLower);
602 ResLower =
minnum(ResLower, NewLower);
603 ResUpper =
maxnum(ResUpper, NewUpper);
607 Update(LHSNeg, RHSNeg,
false);
608 Update(LHSNeg, RHSPos,
true);
609 Update(LHSPos, RHSNeg,
true);
610 Update(LHSPos, RHSPos,
false);
611 return ConstantFPRange(ResLower, ResUpper, ResMayBeQNaN,
false);
616 bool ResMayBeQNaN = ((MayBeQNaN || MayBeSNaN) && !
Other.isEmptySet()) ||
621 std::optional<SameSignRange> LHSNeg, LHSPos, RHSNeg, RHSPos;
626 auto Update = [&](std::optional<SameSignRange> &LHS,
627 std::optional<SameSignRange> &RHS,
bool Negative) {
631 ResMayBeQNaN |= LHS->HasInf && RHS->HasInf;
632 ResMayBeQNaN |= LHS->HasZero && RHS->HasZero;
639 bool LHSHasNonZeroFinite = LHS->FinitePart && LHS->HasNonZero;
640 bool RHSHasNonZeroFinite = RHS->FinitePart && RHS->HasNonZero;
642 if ((LHS->HasInf && RHS->FinitePart) ||
643 (LHSHasNonZeroFinite && RHS->HasZero))
646 if (LHS->FinitePart && RHS->HasInf) {
648 ResLower =
minnum(ResLower, Zero);
649 ResUpper =
maxnum(ResUpper, Zero);
652 if (LHS->FinitePart && RHSHasNonZeroFinite) {
653 assert(!RHS->FinitePart->second.isZero() &&
654 "Divisor should be non-zero.");
655 APFloat NewLower = LHS->FinitePart->first / RHS->FinitePart->second;
656 APFloat NewUpper = LHS->FinitePart->second /
657 (RHS->FinitePart->first.isZero()
659 : RHS->FinitePart->first);
661 ResLower =
minnum(ResLower, -NewUpper);
662 ResUpper =
maxnum(ResUpper, -NewLower);
664 ResLower =
minnum(ResLower, NewLower);
665 ResUpper =
maxnum(ResUpper, NewUpper);
669 Update(LHSNeg, RHSNeg,
false);
670 Update(LHSNeg, RHSPos,
true);
671 Update(LHSPos, RHSNeg,
true);
672 Update(LHSPos, RHSPos,
false);
673 return ConstantFPRange(ResLower, ResUpper, ResMayBeQNaN,
false);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file declares a class to represent arbitrary precision floating point values and provide a varie...
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
static APFloat::cmpResult strictCompare(const APFloat &LHS, const APFloat &RHS)
static ConstantFPRange extendZeroIfEqual(const ConstantFPRange &CR, FCmpInst::Predicate Pred)
Make sure that +0/-0 are both included in the range.
static bool fcmpPredExcludesEqual(FCmpInst::Predicate Pred)
Return true for ULT/UGT/OLT/OGT.
static void splitPosNeg(const APFloat &Lower, const APFloat &Upper, std::optional< SameSignRange > &NegPart, std::optional< SameSignRange > &PosPart)
Split the range into positive and negative components.
static bool removeInf(APFloat &Lower, APFloat &Upper, bool &HasPosInf, bool &HasNegInf)
Return true if the finite part is not empty after removing infinities.
static ConstantFPRange makeLessThan(APFloat V, FCmpInst::Predicate Pred)
Return [-inf, V) or [-inf, V].
static void canonicalizeRange(APFloat &Lower, APFloat &Upper)
static ConstantFPRange makeGreaterThan(APFloat V, FCmpInst::Predicate Pred)
Return (V, +inf] or [V, +inf].
static bool isNonCanonicalEmptySet(const APFloat &Lower, const APFloat &Upper)
static ConstantFPRange setNaNField(const ConstantFPRange &CR, FCmpInst::Predicate Pred)
Utilities for dealing with flags related to floating point properties and mode controls.
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
bool bitwiseIsEqual(const APFloat &RHS) const
const fltSemantics & getSemantics() const
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APFloat getSmallest(const fltSemantics &Sem, bool Negative=false)
Returns the smallest (by magnitude) finite number in the given semantics.
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
static LLVM_ABI bool isUnordered(Predicate predicate)
Determine if the predicate is an unordered operation.
static LLVM_ABI bool isOrdered(Predicate predicate)
Determine if the predicate is an ordered operation.
This class represents a range of floating-point values.
LLVM_ABI ConstantFPRange add(const ConstantFPRange &Other) const
Return a new range representing the possible values resulting from an addition of a value in this ran...
LLVM_ABI ConstantFPRange abs() const
Calculate absolute value range.
LLVM_ABI bool isFullSet() const
Return true if this set contains all of the elements possible for this data-type.
bool containsQNaN() const
static LLVM_ABI ConstantFPRange getNonNaN(const fltSemantics &Sem)
Helper for [-inf, inf] to represent all non-NaN values.
bool containsSNaN() const
LLVM_ABI const APFloat * getSingleElement(bool ExcludesNaN=false) const
If this set contains a single element, return it, otherwise return null.
static LLVM_ABI ConstantFPRange makeSatisfyingFCmpRegion(FCmpInst::Predicate Pred, const ConstantFPRange &Other)
Produce the largest range such that all values in the returned range satisfy the given predicate with...
LLVM_ABI bool operator==(const ConstantFPRange &CR) const
Return true if this range is equal to another range.
static LLVM_ABI ConstantFPRange getNaNOnly(const fltSemantics &Sem, bool MayBeQNaN, bool MayBeSNaN)
Create a range which only contains NaNs.
LLVM_ABI ConstantFPRange unionWith(const ConstantFPRange &CR) const
Return the smallest range that results from the union of this range with another range.
LLVM_ABI void flushDenormals(DenormalMode::DenormalModeKind Mode)
Flush denormal values to zero according to the specified mode.
LLVM_ABI ConstantFPRange sub(const ConstantFPRange &Other) const
Return a new range representing the possible values resulting from a subtraction of a value in this r...
LLVM_ABI std::optional< bool > getSignBit() const
Return true if the sign bit of all values in this range is 1.
static LLVM_ABI ConstantFPRange makeAllowedFCmpRegion(FCmpInst::Predicate Pred, const ConstantFPRange &Other)
Produce the smallest range such that all values that may satisfy the given predicate with any value c...
LLVM_ABI bool isNaNOnly() const
LLVM_ABI bool isEmptySet() const
Return true if this set contains no members.
LLVM_ABI ConstantFPRange mul(const ConstantFPRange &Other) const
Return a new range representing the possible values resulting from a multiplication of a value in thi...
static LLVM_ABI ConstantFPRange getFinite(const fltSemantics &Sem)
Helper for (-inf, inf) to represent all finite values.
LLVM_ABI void print(raw_ostream &OS) const
Print out the bounds to a stream.
LLVM_ABI ConstantFPRange cast(const fltSemantics &DstSem, APFloat::roundingMode RM=APFloat::rmNearestTiesToEven) const
Return a new range in the specified format with the specified rounding mode.
LLVM_ABI ConstantFPRange intersectWith(const ConstantFPRange &CR) const
Return the range that results from the intersection of this range with another range.
LLVM_ABI ConstantFPRange div(const ConstantFPRange &Other) const
Return a new range representing the possible values resulting from a division of a value in this rang...
LLVM_ABI void dump() const
Allow printing from a debugger easily.
LLVM_ABI ConstantFPRange negate() const
Calculate range of negated values.
LLVM_ABI FPClassTest classify() const
Return the FPClassTest which will return true for the value.
LLVM_ABI ConstantFPRange getWithoutInf() const
Get the range without infinities.
LLVM_ABI bool fcmp(FCmpInst::Predicate Pred, const ConstantFPRange &Other) const
Does the predicate Pred hold between ranges this and Other?
LLVM_ABI bool contains(const APFloat &Val) const
Return true if the specified value is in the set.
const APFloat & getUpper() const
Return the upper value for this range.
const APFloat & getLower() const
Return the lower value for this range.
static LLVM_ABI std::optional< ConstantFPRange > makeExactFCmpRegion(FCmpInst::Predicate Pred, const APFloat &Other)
Produce the exact range such that all values in the returned range satisfy the given predicate with a...
const fltSemantics & getSemantics() const
Get the semantics of this ConstantFPRange.
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
APFloat abs(APFloat X)
Returns the absolute value of the argument.
LLVM_READONLY APFloat maxnum(const APFloat &A, const APFloat &B)
Implements IEEE-754 2008 maxNum semantics.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_READONLY APFloat minnum(const APFloat &A, const APFloat &B)
Implements IEEE-754 2008 minNum semantics.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Implement std::hash so that hash_code can be used in STL containers.
Represent a contiguous range of values sharing the same sign.
SameSignRange(const APFloat &Lower, const APFloat &Upper)
std::optional< std::pair< APFloat, APFloat > > FinitePart
cmpResult
IEEE-754R 5.11: Floating Point Comparison Relations.
llvm::RoundingMode roundingMode
IEEE-754R 4.3: Rounding-direction attributes.
DenormalModeKind
Represent handled modes for denormal (aka subnormal) modes in the floating point environment.
@ PreserveSign
The sign of a flushed-to-zero number is preserved in the sign of 0.
@ PositiveZero
Denormals are flushed to positive zero.
@ IEEE
IEEE-754 denormal numbers preserved.