xref: /llvm-project/llvm/lib/IR/ConstantFPRange.cpp (revision a3a253d3c7780977077dd46493917b1949c0166d)
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