1fa824dc0SYingwei Zheng //===- ConstantFPRange.cpp - ConstantFPRange implementation ---------------===// 2fa824dc0SYingwei Zheng // 3fa824dc0SYingwei Zheng // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fa824dc0SYingwei Zheng // See https://llvm.org/LICENSE.txt for license information. 5fa824dc0SYingwei Zheng // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fa824dc0SYingwei Zheng // 7fa824dc0SYingwei Zheng //===----------------------------------------------------------------------===// 8fa824dc0SYingwei Zheng 9fa824dc0SYingwei Zheng #include "llvm/IR/ConstantFPRange.h" 10fa824dc0SYingwei Zheng #include "llvm/ADT/APFloat.h" 11fa824dc0SYingwei Zheng #include "llvm/Support/Debug.h" 12fa824dc0SYingwei Zheng #include "llvm/Support/raw_ostream.h" 13fa824dc0SYingwei Zheng #include <cassert> 14fa824dc0SYingwei Zheng 15fa824dc0SYingwei Zheng using namespace llvm; 16fa824dc0SYingwei Zheng 17fa824dc0SYingwei Zheng void ConstantFPRange::makeEmpty() { 18fa824dc0SYingwei Zheng auto &Sem = Lower.getSemantics(); 19fa824dc0SYingwei Zheng Lower = APFloat::getInf(Sem, /*Negative=*/false); 20fa824dc0SYingwei Zheng Upper = APFloat::getInf(Sem, /*Negative=*/true); 21fa824dc0SYingwei Zheng MayBeQNaN = false; 22fa824dc0SYingwei Zheng MayBeSNaN = false; 23fa824dc0SYingwei Zheng } 24fa824dc0SYingwei Zheng 25fa824dc0SYingwei Zheng void ConstantFPRange::makeFull() { 26fa824dc0SYingwei Zheng auto &Sem = Lower.getSemantics(); 27fa824dc0SYingwei Zheng Lower = APFloat::getInf(Sem, /*Negative=*/true); 28fa824dc0SYingwei Zheng Upper = APFloat::getInf(Sem, /*Negative=*/false); 29fa824dc0SYingwei Zheng MayBeQNaN = true; 30fa824dc0SYingwei Zheng MayBeSNaN = true; 31fa824dc0SYingwei Zheng } 32fa824dc0SYingwei Zheng 33fa824dc0SYingwei Zheng bool ConstantFPRange::isNaNOnly() const { 34fa824dc0SYingwei Zheng return Lower.isPosInfinity() && Upper.isNegInfinity(); 35fa824dc0SYingwei Zheng } 36fa824dc0SYingwei Zheng 37fa824dc0SYingwei Zheng ConstantFPRange::ConstantFPRange(const fltSemantics &Sem, bool IsFullSet) 38fa824dc0SYingwei Zheng : Lower(Sem, APFloat::uninitialized), Upper(Sem, APFloat::uninitialized) { 39fa824dc0SYingwei Zheng Lower = APFloat::getInf(Sem, /*Negative=*/IsFullSet); 40fa824dc0SYingwei Zheng Upper = APFloat::getInf(Sem, /*Negative=*/!IsFullSet); 41fa824dc0SYingwei Zheng MayBeQNaN = IsFullSet; 42fa824dc0SYingwei Zheng MayBeSNaN = IsFullSet; 43fa824dc0SYingwei Zheng } 44fa824dc0SYingwei Zheng 45fa824dc0SYingwei Zheng ConstantFPRange::ConstantFPRange(const APFloat &Value) 46fa824dc0SYingwei Zheng : Lower(Value.getSemantics(), APFloat::uninitialized), 47fa824dc0SYingwei Zheng Upper(Value.getSemantics(), APFloat::uninitialized) { 48fa824dc0SYingwei Zheng if (Value.isNaN()) { 49fa824dc0SYingwei Zheng makeEmpty(); 50fa824dc0SYingwei Zheng bool IsSNaN = Value.isSignaling(); 51fa824dc0SYingwei Zheng MayBeQNaN = !IsSNaN; 52fa824dc0SYingwei Zheng MayBeSNaN = IsSNaN; 53fa824dc0SYingwei Zheng } else { 54fa824dc0SYingwei Zheng Lower = Upper = Value; 55fa824dc0SYingwei Zheng MayBeQNaN = MayBeSNaN = false; 56fa824dc0SYingwei Zheng } 57fa824dc0SYingwei Zheng } 58fa824dc0SYingwei Zheng 59fa824dc0SYingwei Zheng // We treat that -0 is less than 0 here. 60fa824dc0SYingwei Zheng static APFloat::cmpResult strictCompare(const APFloat &LHS, 61fa824dc0SYingwei Zheng const APFloat &RHS) { 62fa824dc0SYingwei Zheng assert(!LHS.isNaN() && !RHS.isNaN() && "Unordered compare"); 63fa824dc0SYingwei Zheng if (LHS.isZero() && RHS.isZero()) { 64fa824dc0SYingwei Zheng if (LHS.isNegative() == RHS.isNegative()) 65fa824dc0SYingwei Zheng return APFloat::cmpEqual; 66fa824dc0SYingwei Zheng return LHS.isNegative() ? APFloat::cmpLessThan : APFloat::cmpGreaterThan; 67fa824dc0SYingwei Zheng } 68fa824dc0SYingwei Zheng return LHS.compare(RHS); 69fa824dc0SYingwei Zheng } 70fa824dc0SYingwei Zheng 71fa824dc0SYingwei Zheng static bool isNonCanonicalEmptySet(const APFloat &Lower, const APFloat &Upper) { 72fa824dc0SYingwei Zheng return strictCompare(Lower, Upper) == APFloat::cmpGreaterThan && 73fa824dc0SYingwei Zheng !(Lower.isInfinity() && Upper.isInfinity()); 74fa824dc0SYingwei Zheng } 75fa824dc0SYingwei Zheng 76fa824dc0SYingwei Zheng static void canonicalizeRange(APFloat &Lower, APFloat &Upper) { 77fa824dc0SYingwei Zheng if (isNonCanonicalEmptySet(Lower, Upper)) { 78fa824dc0SYingwei Zheng Lower = APFloat::getInf(Lower.getSemantics(), /*Negative=*/false); 79fa824dc0SYingwei Zheng Upper = APFloat::getInf(Upper.getSemantics(), /*Negative=*/true); 80fa824dc0SYingwei Zheng } 81fa824dc0SYingwei Zheng } 82fa824dc0SYingwei Zheng 83fa824dc0SYingwei Zheng ConstantFPRange::ConstantFPRange(APFloat LowerVal, APFloat UpperVal, 844db10561SYingwei Zheng bool MayBeQNaNVal, bool MayBeSNaNVal) 854db10561SYingwei Zheng : Lower(std::move(LowerVal)), Upper(std::move(UpperVal)), 864db10561SYingwei Zheng MayBeQNaN(MayBeQNaNVal), MayBeSNaN(MayBeSNaNVal) { 87fa824dc0SYingwei Zheng assert(&Lower.getSemantics() == &Upper.getSemantics() && 88fa824dc0SYingwei Zheng "Should only use the same semantics"); 89fa824dc0SYingwei Zheng assert(!isNonCanonicalEmptySet(Lower, Upper) && "Non-canonical form"); 90fa824dc0SYingwei Zheng } 91fa824dc0SYingwei Zheng 92fa824dc0SYingwei Zheng ConstantFPRange ConstantFPRange::getFinite(const fltSemantics &Sem) { 93fa824dc0SYingwei Zheng return ConstantFPRange(APFloat::getLargest(Sem, /*Negative=*/true), 94fa824dc0SYingwei Zheng APFloat::getLargest(Sem, /*Negative=*/false), 95fa824dc0SYingwei Zheng /*MayBeQNaN=*/false, /*MayBeSNaN=*/false); 96fa824dc0SYingwei Zheng } 97fa824dc0SYingwei Zheng 98fa824dc0SYingwei Zheng ConstantFPRange ConstantFPRange::getNaNOnly(const fltSemantics &Sem, 99fa824dc0SYingwei Zheng bool MayBeQNaN, bool MayBeSNaN) { 100fa824dc0SYingwei Zheng return ConstantFPRange(APFloat::getInf(Sem, /*Negative=*/false), 101fa824dc0SYingwei Zheng APFloat::getInf(Sem, /*Negative=*/true), MayBeQNaN, 102fa824dc0SYingwei Zheng MayBeSNaN); 103fa824dc0SYingwei Zheng } 104fa824dc0SYingwei Zheng 1054db10561SYingwei Zheng ConstantFPRange ConstantFPRange::getNonNaN(const fltSemantics &Sem) { 1064db10561SYingwei Zheng return ConstantFPRange(APFloat::getInf(Sem, /*Negative=*/true), 1074db10561SYingwei Zheng APFloat::getInf(Sem, /*Negative=*/false), 1084db10561SYingwei Zheng /*MayBeQNaN=*/false, /*MayBeSNaN=*/false); 1094db10561SYingwei Zheng } 1104db10561SYingwei Zheng 11158673622SYingwei Zheng /// Return true for ULT/UGT/OLT/OGT 11258673622SYingwei Zheng static bool fcmpPredExcludesEqual(FCmpInst::Predicate Pred) { 11358673622SYingwei Zheng return !(Pred & FCmpInst::FCMP_OEQ); 11458673622SYingwei Zheng } 11558673622SYingwei Zheng 11658673622SYingwei Zheng /// Return [-inf, V) or [-inf, V] 11758673622SYingwei Zheng static ConstantFPRange makeLessThan(APFloat V, FCmpInst::Predicate Pred) { 11858673622SYingwei Zheng const fltSemantics &Sem = V.getSemantics(); 11958673622SYingwei Zheng if (fcmpPredExcludesEqual(Pred)) { 12058673622SYingwei Zheng if (V.isNegInfinity()) 12158673622SYingwei Zheng return ConstantFPRange::getEmpty(Sem); 12258673622SYingwei Zheng V.next(/*nextDown=*/true); 12358673622SYingwei Zheng } 12458673622SYingwei Zheng return ConstantFPRange::getNonNaN(APFloat::getInf(Sem, /*Negative=*/true), 12558673622SYingwei Zheng std::move(V)); 12658673622SYingwei Zheng } 12758673622SYingwei Zheng 12858673622SYingwei Zheng /// Return (V, +inf] or [V, +inf] 12958673622SYingwei Zheng static ConstantFPRange makeGreaterThan(APFloat V, FCmpInst::Predicate Pred) { 13058673622SYingwei Zheng const fltSemantics &Sem = V.getSemantics(); 13158673622SYingwei Zheng if (fcmpPredExcludesEqual(Pred)) { 13258673622SYingwei Zheng if (V.isPosInfinity()) 13358673622SYingwei Zheng return ConstantFPRange::getEmpty(Sem); 13458673622SYingwei Zheng V.next(/*nextDown=*/false); 13558673622SYingwei Zheng } 13658673622SYingwei Zheng return ConstantFPRange::getNonNaN(std::move(V), 13758673622SYingwei Zheng APFloat::getInf(Sem, /*Negative=*/false)); 13858673622SYingwei Zheng } 13958673622SYingwei Zheng 14058673622SYingwei Zheng /// Make sure that +0/-0 are both included in the range. 14158673622SYingwei Zheng static ConstantFPRange extendZeroIfEqual(const ConstantFPRange &CR, 14258673622SYingwei Zheng FCmpInst::Predicate Pred) { 14358673622SYingwei Zheng if (fcmpPredExcludesEqual(Pred)) 14458673622SYingwei Zheng return CR; 14558673622SYingwei Zheng 14658673622SYingwei Zheng APFloat Lower = CR.getLower(); 14758673622SYingwei Zheng APFloat Upper = CR.getUpper(); 14858673622SYingwei Zheng if (Lower.isPosZero()) 14958673622SYingwei Zheng Lower = APFloat::getZero(Lower.getSemantics(), /*Negative=*/true); 15058673622SYingwei Zheng if (Upper.isNegZero()) 15158673622SYingwei Zheng Upper = APFloat::getZero(Upper.getSemantics(), /*Negative=*/false); 15258673622SYingwei Zheng return ConstantFPRange(std::move(Lower), std::move(Upper), CR.containsQNaN(), 15358673622SYingwei Zheng CR.containsSNaN()); 15458673622SYingwei Zheng } 15558673622SYingwei Zheng 15658673622SYingwei Zheng static ConstantFPRange setNaNField(const ConstantFPRange &CR, 15758673622SYingwei Zheng FCmpInst::Predicate Pred) { 15858673622SYingwei Zheng bool ContainsNaN = FCmpInst::isUnordered(Pred); 15958673622SYingwei Zheng return ConstantFPRange(CR.getLower(), CR.getUpper(), 16058673622SYingwei Zheng /*MayBeQNaN=*/ContainsNaN, /*MayBeSNaN=*/ContainsNaN); 16158673622SYingwei Zheng } 16258673622SYingwei Zheng 163fa824dc0SYingwei Zheng ConstantFPRange 164fa824dc0SYingwei Zheng ConstantFPRange::makeAllowedFCmpRegion(FCmpInst::Predicate Pred, 165fa824dc0SYingwei Zheng const ConstantFPRange &Other) { 16658673622SYingwei Zheng if (Other.isEmptySet()) 16758673622SYingwei Zheng return Other; 16858673622SYingwei Zheng if (Other.containsNaN() && FCmpInst::isUnordered(Pred)) 169fa824dc0SYingwei Zheng return getFull(Other.getSemantics()); 17058673622SYingwei Zheng if (Other.isNaNOnly() && FCmpInst::isOrdered(Pred)) 17158673622SYingwei Zheng return getEmpty(Other.getSemantics()); 17258673622SYingwei Zheng 17358673622SYingwei Zheng switch (Pred) { 17458673622SYingwei Zheng case FCmpInst::FCMP_TRUE: 17558673622SYingwei Zheng return getFull(Other.getSemantics()); 17658673622SYingwei Zheng case FCmpInst::FCMP_FALSE: 17758673622SYingwei Zheng return getEmpty(Other.getSemantics()); 17858673622SYingwei Zheng case FCmpInst::FCMP_ORD: 17958673622SYingwei Zheng return getNonNaN(Other.getSemantics()); 18058673622SYingwei Zheng case FCmpInst::FCMP_UNO: 18158673622SYingwei Zheng return getNaNOnly(Other.getSemantics(), /*MayBeQNaN=*/true, 18258673622SYingwei Zheng /*MayBeSNaN=*/true); 18358673622SYingwei Zheng case FCmpInst::FCMP_OEQ: 18458673622SYingwei Zheng case FCmpInst::FCMP_UEQ: 18558673622SYingwei Zheng return setNaNField(extendZeroIfEqual(Other, Pred), Pred); 18658673622SYingwei Zheng case FCmpInst::FCMP_ONE: 18758673622SYingwei Zheng case FCmpInst::FCMP_UNE: 18858673622SYingwei Zheng if (const APFloat *SingleElement = 18958673622SYingwei Zheng Other.getSingleElement(/*ExcludesNaN=*/true)) { 19058673622SYingwei Zheng const fltSemantics &Sem = SingleElement->getSemantics(); 19158673622SYingwei Zheng if (SingleElement->isPosInfinity()) 19258673622SYingwei Zheng return setNaNField( 19358673622SYingwei Zheng getNonNaN(APFloat::getInf(Sem, /*Negative=*/true), 19458673622SYingwei Zheng APFloat::getLargest(Sem, /*Negative=*/false)), 19558673622SYingwei Zheng Pred); 19658673622SYingwei Zheng if (SingleElement->isNegInfinity()) 19758673622SYingwei Zheng return setNaNField( 19858673622SYingwei Zheng getNonNaN(APFloat::getLargest(Sem, /*Negative=*/true), 19958673622SYingwei Zheng APFloat::getInf(Sem, /*Negative=*/false)), 20058673622SYingwei Zheng Pred); 20158673622SYingwei Zheng } 20258673622SYingwei Zheng return Pred == FCmpInst::FCMP_ONE ? getNonNaN(Other.getSemantics()) 20358673622SYingwei Zheng : getFull(Other.getSemantics()); 20458673622SYingwei Zheng case FCmpInst::FCMP_OLT: 20558673622SYingwei Zheng case FCmpInst::FCMP_OLE: 20658673622SYingwei Zheng case FCmpInst::FCMP_ULT: 20758673622SYingwei Zheng case FCmpInst::FCMP_ULE: 20858673622SYingwei Zheng return setNaNField( 20958673622SYingwei Zheng extendZeroIfEqual(makeLessThan(Other.getUpper(), Pred), Pred), Pred); 21058673622SYingwei Zheng case FCmpInst::FCMP_OGT: 21158673622SYingwei Zheng case FCmpInst::FCMP_OGE: 21258673622SYingwei Zheng case FCmpInst::FCMP_UGT: 21358673622SYingwei Zheng case FCmpInst::FCMP_UGE: 21458673622SYingwei Zheng return setNaNField( 21558673622SYingwei Zheng extendZeroIfEqual(makeGreaterThan(Other.getLower(), Pred), Pred), Pred); 21658673622SYingwei Zheng default: 21758673622SYingwei Zheng llvm_unreachable("Unexpected predicate"); 21858673622SYingwei Zheng } 219fa824dc0SYingwei Zheng } 220fa824dc0SYingwei Zheng 221fa824dc0SYingwei Zheng ConstantFPRange 222fa824dc0SYingwei Zheng ConstantFPRange::makeSatisfyingFCmpRegion(FCmpInst::Predicate Pred, 223fa824dc0SYingwei Zheng const ConstantFPRange &Other) { 2244647a466SYingwei Zheng if (Other.isEmptySet()) 2254647a466SYingwei Zheng return getFull(Other.getSemantics()); 2264647a466SYingwei Zheng if (Other.containsNaN() && FCmpInst::isOrdered(Pred)) 227fa824dc0SYingwei Zheng return getEmpty(Other.getSemantics()); 2284647a466SYingwei Zheng if (Other.isNaNOnly() && FCmpInst::isUnordered(Pred)) 2294647a466SYingwei Zheng return getFull(Other.getSemantics()); 2304647a466SYingwei Zheng 2314647a466SYingwei Zheng switch (Pred) { 2324647a466SYingwei Zheng case FCmpInst::FCMP_TRUE: 2334647a466SYingwei Zheng return getFull(Other.getSemantics()); 2344647a466SYingwei Zheng case FCmpInst::FCMP_FALSE: 2354647a466SYingwei Zheng return getEmpty(Other.getSemantics()); 2364647a466SYingwei Zheng case FCmpInst::FCMP_ORD: 2374647a466SYingwei Zheng return getNonNaN(Other.getSemantics()); 2384647a466SYingwei Zheng case FCmpInst::FCMP_UNO: 2394647a466SYingwei Zheng return getNaNOnly(Other.getSemantics(), /*MayBeQNaN=*/true, 2404647a466SYingwei Zheng /*MayBeSNaN=*/true); 2414647a466SYingwei Zheng case FCmpInst::FCMP_OEQ: 2424647a466SYingwei Zheng case FCmpInst::FCMP_UEQ: 2434647a466SYingwei Zheng return setNaNField(Other.isSingleElement(/*ExcludesNaN=*/true) || 2444647a466SYingwei Zheng ((Other.classify() & ~fcNan) == fcZero) 2454647a466SYingwei Zheng ? extendZeroIfEqual(Other, Pred) 2464647a466SYingwei Zheng : getEmpty(Other.getSemantics()), 2474647a466SYingwei Zheng Pred); 2484647a466SYingwei Zheng case FCmpInst::FCMP_ONE: 2494647a466SYingwei Zheng case FCmpInst::FCMP_UNE: 2504647a466SYingwei Zheng return getEmpty(Other.getSemantics()); 2514647a466SYingwei Zheng case FCmpInst::FCMP_OLT: 2524647a466SYingwei Zheng case FCmpInst::FCMP_OLE: 2534647a466SYingwei Zheng case FCmpInst::FCMP_ULT: 2544647a466SYingwei Zheng case FCmpInst::FCMP_ULE: 2554647a466SYingwei Zheng return setNaNField( 2564647a466SYingwei Zheng extendZeroIfEqual(makeLessThan(Other.getLower(), Pred), Pred), Pred); 2574647a466SYingwei Zheng case FCmpInst::FCMP_OGT: 2584647a466SYingwei Zheng case FCmpInst::FCMP_OGE: 2594647a466SYingwei Zheng case FCmpInst::FCMP_UGT: 2604647a466SYingwei Zheng case FCmpInst::FCMP_UGE: 2614647a466SYingwei Zheng return setNaNField( 2624647a466SYingwei Zheng extendZeroIfEqual(makeGreaterThan(Other.getUpper(), Pred), Pred), Pred); 2634647a466SYingwei Zheng default: 2644647a466SYingwei Zheng llvm_unreachable("Unexpected predicate"); 2654647a466SYingwei Zheng } 266fa824dc0SYingwei Zheng } 267fa824dc0SYingwei Zheng 2684db10561SYingwei Zheng std::optional<ConstantFPRange> 2694db10561SYingwei Zheng ConstantFPRange::makeExactFCmpRegion(FCmpInst::Predicate Pred, 270fa824dc0SYingwei Zheng const APFloat &Other) { 271*a3a253d3SYingwei Zheng if ((Pred == FCmpInst::FCMP_UNE || Pred == FCmpInst::FCMP_ONE) && 272*a3a253d3SYingwei Zheng !Other.isNaN()) 2734db10561SYingwei Zheng return std::nullopt; 274*a3a253d3SYingwei Zheng return makeSatisfyingFCmpRegion(Pred, ConstantFPRange(Other)); 275fa824dc0SYingwei Zheng } 276fa824dc0SYingwei Zheng 277fa824dc0SYingwei Zheng bool ConstantFPRange::fcmp(FCmpInst::Predicate Pred, 278fa824dc0SYingwei Zheng const ConstantFPRange &Other) const { 279fa824dc0SYingwei Zheng return makeSatisfyingFCmpRegion(Pred, Other).contains(*this); 280fa824dc0SYingwei Zheng } 281fa824dc0SYingwei Zheng 282fa824dc0SYingwei Zheng bool ConstantFPRange::isFullSet() const { 283fa824dc0SYingwei Zheng return Lower.isNegInfinity() && Upper.isPosInfinity() && MayBeQNaN && 284fa824dc0SYingwei Zheng MayBeSNaN; 285fa824dc0SYingwei Zheng } 286fa824dc0SYingwei Zheng 287fa824dc0SYingwei Zheng bool ConstantFPRange::isEmptySet() const { 288fa824dc0SYingwei Zheng return Lower.isPosInfinity() && Upper.isNegInfinity() && !MayBeQNaN && 289fa824dc0SYingwei Zheng !MayBeSNaN; 290fa824dc0SYingwei Zheng } 291fa824dc0SYingwei Zheng 292fa824dc0SYingwei Zheng bool ConstantFPRange::contains(const APFloat &Val) const { 293fa824dc0SYingwei Zheng assert(&getSemantics() == &Val.getSemantics() && 294fa824dc0SYingwei Zheng "Should only use the same semantics"); 295fa824dc0SYingwei Zheng 296fa824dc0SYingwei Zheng if (Val.isNaN()) 297fa824dc0SYingwei Zheng return Val.isSignaling() ? MayBeSNaN : MayBeQNaN; 298fa824dc0SYingwei Zheng return strictCompare(Lower, Val) != APFloat::cmpGreaterThan && 299fa824dc0SYingwei Zheng strictCompare(Val, Upper) != APFloat::cmpGreaterThan; 300fa824dc0SYingwei Zheng } 301fa824dc0SYingwei Zheng 302fa824dc0SYingwei Zheng bool ConstantFPRange::contains(const ConstantFPRange &CR) const { 303fa824dc0SYingwei Zheng assert(&getSemantics() == &CR.getSemantics() && 304fa824dc0SYingwei Zheng "Should only use the same semantics"); 305fa824dc0SYingwei Zheng 306fa824dc0SYingwei Zheng if (CR.MayBeQNaN && !MayBeQNaN) 307fa824dc0SYingwei Zheng return false; 308fa824dc0SYingwei Zheng 309fa824dc0SYingwei Zheng if (CR.MayBeSNaN && !MayBeSNaN) 310fa824dc0SYingwei Zheng return false; 311fa824dc0SYingwei Zheng 312fa824dc0SYingwei Zheng return strictCompare(Lower, CR.Lower) != APFloat::cmpGreaterThan && 313fa824dc0SYingwei Zheng strictCompare(CR.Upper, Upper) != APFloat::cmpGreaterThan; 314fa824dc0SYingwei Zheng } 315fa824dc0SYingwei Zheng 3164db10561SYingwei Zheng const APFloat *ConstantFPRange::getSingleElement(bool ExcludesNaN) const { 3174db10561SYingwei Zheng if (!ExcludesNaN && (MayBeSNaN || MayBeQNaN)) 318fa824dc0SYingwei Zheng return nullptr; 319fa824dc0SYingwei Zheng return Lower.bitwiseIsEqual(Upper) ? &Lower : nullptr; 320fa824dc0SYingwei Zheng } 321fa824dc0SYingwei Zheng 322fa824dc0SYingwei Zheng std::optional<bool> ConstantFPRange::getSignBit() const { 323fa824dc0SYingwei Zheng if (!MayBeSNaN && !MayBeQNaN && Lower.isNegative() == Upper.isNegative()) 324fa824dc0SYingwei Zheng return Lower.isNegative(); 325fa824dc0SYingwei Zheng return std::nullopt; 326fa824dc0SYingwei Zheng } 327fa824dc0SYingwei Zheng 328fa824dc0SYingwei Zheng bool ConstantFPRange::operator==(const ConstantFPRange &CR) const { 329fa824dc0SYingwei Zheng if (MayBeSNaN != CR.MayBeSNaN || MayBeQNaN != CR.MayBeQNaN) 330fa824dc0SYingwei Zheng return false; 331fa824dc0SYingwei Zheng return Lower.bitwiseIsEqual(CR.Lower) && Upper.bitwiseIsEqual(CR.Upper); 332fa824dc0SYingwei Zheng } 333fa824dc0SYingwei Zheng 334fa824dc0SYingwei Zheng FPClassTest ConstantFPRange::classify() const { 335fa824dc0SYingwei Zheng uint32_t Mask = fcNone; 336fa824dc0SYingwei Zheng if (MayBeSNaN) 337fa824dc0SYingwei Zheng Mask |= fcSNan; 338fa824dc0SYingwei Zheng if (MayBeQNaN) 339fa824dc0SYingwei Zheng Mask |= fcQNan; 340fa824dc0SYingwei Zheng if (!isNaNOnly()) { 341fa824dc0SYingwei Zheng FPClassTest LowerMask = Lower.classify(); 342fa824dc0SYingwei Zheng FPClassTest UpperMask = Upper.classify(); 343fa824dc0SYingwei Zheng assert(LowerMask <= UpperMask && "Range is nan-only."); 3444db10561SYingwei Zheng // Set all bits from log2(LowerMask) to log2(UpperMask). 3454db10561SYingwei Zheng Mask |= (UpperMask << 1) - LowerMask; 346fa824dc0SYingwei Zheng } 347fa824dc0SYingwei Zheng return static_cast<FPClassTest>(Mask); 348fa824dc0SYingwei Zheng } 349fa824dc0SYingwei Zheng 350fa824dc0SYingwei Zheng void ConstantFPRange::print(raw_ostream &OS) const { 351fa824dc0SYingwei Zheng if (isFullSet()) 352fa824dc0SYingwei Zheng OS << "full-set"; 353fa824dc0SYingwei Zheng else if (isEmptySet()) 354fa824dc0SYingwei Zheng OS << "empty-set"; 355fa824dc0SYingwei Zheng else { 356fa824dc0SYingwei Zheng bool NaNOnly = isNaNOnly(); 357fa824dc0SYingwei Zheng if (!NaNOnly) 358fa824dc0SYingwei Zheng OS << '[' << Lower << ", " << Upper << ']'; 359fa824dc0SYingwei Zheng 360fa824dc0SYingwei Zheng if (MayBeSNaN || MayBeQNaN) { 361fa824dc0SYingwei Zheng if (!NaNOnly) 362fa824dc0SYingwei Zheng OS << " with "; 363fa824dc0SYingwei Zheng if (MayBeSNaN && MayBeQNaN) 364fa824dc0SYingwei Zheng OS << "NaN"; 365fa824dc0SYingwei Zheng else if (MayBeSNaN) 366fa824dc0SYingwei Zheng OS << "SNaN"; 367fa824dc0SYingwei Zheng else if (MayBeQNaN) 368fa824dc0SYingwei Zheng OS << "QNaN"; 369fa824dc0SYingwei Zheng } 370fa824dc0SYingwei Zheng } 371fa824dc0SYingwei Zheng } 372fa824dc0SYingwei Zheng 373fa824dc0SYingwei Zheng #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 374fa824dc0SYingwei Zheng LLVM_DUMP_METHOD void ConstantFPRange::dump() const { print(dbgs()); } 375fa824dc0SYingwei Zheng #endif 376fa824dc0SYingwei Zheng 377fa824dc0SYingwei Zheng ConstantFPRange 378fa824dc0SYingwei Zheng ConstantFPRange::intersectWith(const ConstantFPRange &CR) const { 379fa824dc0SYingwei Zheng assert(&getSemantics() == &CR.getSemantics() && 380fa824dc0SYingwei Zheng "Should only use the same semantics"); 381fa824dc0SYingwei Zheng APFloat NewLower = maxnum(Lower, CR.Lower); 382fa824dc0SYingwei Zheng APFloat NewUpper = minnum(Upper, CR.Upper); 383fa824dc0SYingwei Zheng canonicalizeRange(NewLower, NewUpper); 384fa824dc0SYingwei Zheng return ConstantFPRange(std::move(NewLower), std::move(NewUpper), 385fa824dc0SYingwei Zheng MayBeQNaN & CR.MayBeQNaN, MayBeSNaN & CR.MayBeSNaN); 386fa824dc0SYingwei Zheng } 387fa824dc0SYingwei Zheng 388fa824dc0SYingwei Zheng ConstantFPRange ConstantFPRange::unionWith(const ConstantFPRange &CR) const { 389fa824dc0SYingwei Zheng assert(&getSemantics() == &CR.getSemantics() && 390fa824dc0SYingwei Zheng "Should only use the same semantics"); 391fa824dc0SYingwei Zheng return ConstantFPRange(minnum(Lower, CR.Lower), maxnum(Upper, CR.Upper), 392fa824dc0SYingwei Zheng MayBeQNaN | CR.MayBeQNaN, MayBeSNaN | CR.MayBeSNaN); 393fa824dc0SYingwei Zheng } 394