xref: /freebsd/contrib/llvm-project/llvm/include/llvm/IR/ConstantFPRange.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- ConstantFPRange.h - Represent a range for floating-point -*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Represent a range of possible values that may occur when the program is run
10 // for a floating-point value. This keeps track of a lower and upper bound for
11 // the constant.
12 //
13 // Range = [Lower, Upper] U (MayBeQNaN ? QNaN : {}) U (MayBeSNaN ? SNaN : {})
14 // Specifically, [inf, -inf] represents an empty set.
15 // Note:
16 // 1. Bounds are inclusive.
17 // 2. -0 is considered to be less than 0. That is, range [0, 0] doesn't contain
18 // -0.
19 // 3. Currently wrapping ranges are not supported.
20 //
21 //===----------------------------------------------------------------------===//
22 
23 #ifndef LLVM_IR_CONSTANTFPRANGE_H
24 #define LLVM_IR_CONSTANTFPRANGE_H
25 
26 #include "llvm/ADT/APFloat.h"
27 #include "llvm/IR/Instructions.h"
28 #include "llvm/Support/Compiler.h"
29 #include <optional>
30 
31 namespace llvm {
32 
33 class raw_ostream;
34 struct KnownFPClass;
35 
36 /// This class represents a range of floating-point values.
37 class [[nodiscard]] ConstantFPRange {
38   APFloat Lower, Upper;
39   bool MayBeQNaN : 1;
40   bool MayBeSNaN : 1;
41 
42   /// Create empty constant range with same semantics.
getEmpty()43   ConstantFPRange getEmpty() const {
44     return ConstantFPRange(getSemantics(), /*IsFullSet=*/false);
45   }
46 
47   /// Create full constant range with same semantics.
getFull()48   ConstantFPRange getFull() const {
49     return ConstantFPRange(getSemantics(), /*IsFullSet=*/true);
50   }
51 
52   void makeEmpty();
53   void makeFull();
54 
55   /// Initialize a full or empty set for the specified semantics.
56   LLVM_ABI explicit ConstantFPRange(const fltSemantics &Sem, bool IsFullSet);
57 
58 public:
59   /// Initialize a range to hold the single specified value.
60   LLVM_ABI explicit ConstantFPRange(const APFloat &Value);
61 
62   /// Initialize a range of values explicitly.
63   /// Note: If \p LowerVal is greater than \p UpperVal, please use the canonical
64   /// form [Inf, -Inf].
65   LLVM_ABI ConstantFPRange(APFloat LowerVal, APFloat UpperVal, bool MayBeQNaN,
66                            bool MayBeSNaN);
67 
68   /// Create empty constant range with the given semantics.
getEmpty(const fltSemantics & Sem)69   static ConstantFPRange getEmpty(const fltSemantics &Sem) {
70     return ConstantFPRange(Sem, /*IsFullSet=*/false);
71   }
72 
73   /// Create full constant range with the given semantics.
getFull(const fltSemantics & Sem)74   static ConstantFPRange getFull(const fltSemantics &Sem) {
75     return ConstantFPRange(Sem, /*IsFullSet=*/true);
76   }
77 
78   /// Helper for (-inf, inf) to represent all finite values.
79   LLVM_ABI static ConstantFPRange getFinite(const fltSemantics &Sem);
80 
81   /// Helper for [-inf, inf] to represent all non-NaN values.
82   LLVM_ABI static ConstantFPRange getNonNaN(const fltSemantics &Sem);
83 
84   /// Create a range which doesn't contain NaNs.
getNonNaN(APFloat LowerVal,APFloat UpperVal)85   static ConstantFPRange getNonNaN(APFloat LowerVal, APFloat UpperVal) {
86     return ConstantFPRange(std::move(LowerVal), std::move(UpperVal),
87                            /*MayBeQNaN=*/false, /*MayBeSNaN=*/false);
88   }
89 
90   /// Create a range which may contain NaNs.
getMayBeNaN(APFloat LowerVal,APFloat UpperVal)91   static ConstantFPRange getMayBeNaN(APFloat LowerVal, APFloat UpperVal) {
92     return ConstantFPRange(std::move(LowerVal), std::move(UpperVal),
93                            /*MayBeQNaN=*/true, /*MayBeSNaN=*/true);
94   }
95 
96   /// Create a range which only contains NaNs.
97   LLVM_ABI static ConstantFPRange getNaNOnly(const fltSemantics &Sem,
98                                              bool MayBeQNaN, bool MayBeSNaN);
99 
100   /// Produce the smallest range such that all values that may satisfy the given
101   /// predicate with any value contained within Other is contained in the
102   /// returned range.  Formally, this returns a superset of
103   /// 'union over all y in Other . { x : fcmp op x y is true }'.  If the exact
104   /// answer is not representable as a ConstantFPRange, the return value will be
105   /// a proper superset of the above.
106   ///
107   /// Example: Pred = ole and Other = float [2, 5] returns Result = [-inf, 5]
108   LLVM_ABI static ConstantFPRange
109   makeAllowedFCmpRegion(FCmpInst::Predicate Pred, const ConstantFPRange &Other);
110 
111   /// Produce the largest range such that all values in the returned range
112   /// satisfy the given predicate with all values contained within Other.
113   /// Formally, this returns a subset of
114   /// 'intersection over all y in Other . { x : fcmp op x y is true }'.  If the
115   /// exact answer is not representable as a ConstantFPRange, the return value
116   /// will be a proper subset of the above.
117   ///
118   /// Example: Pred = ole and Other = float [2, 5] returns [-inf, 2]
119   LLVM_ABI static ConstantFPRange
120   makeSatisfyingFCmpRegion(FCmpInst::Predicate Pred,
121                            const ConstantFPRange &Other);
122 
123   /// Produce the exact range such that all values in the returned range satisfy
124   /// the given predicate with any value contained within Other. Formally, this
125   /// returns { x : fcmp op x Other is true }.
126   ///
127   /// Example: Pred = olt and Other = float 3 returns [-inf, 3)
128   /// If the exact answer is not representable as a ConstantFPRange, returns
129   /// std::nullopt.
130   LLVM_ABI static std::optional<ConstantFPRange>
131   makeExactFCmpRegion(FCmpInst::Predicate Pred, const APFloat &Other);
132 
133   /// Does the predicate \p Pred hold between ranges this and \p Other?
134   /// NOTE: false does not mean that inverse predicate holds!
135   LLVM_ABI bool fcmp(FCmpInst::Predicate Pred,
136                      const ConstantFPRange &Other) const;
137 
138   /// Return the lower value for this range.
getLower()139   const APFloat &getLower() const { return Lower; }
140 
141   /// Return the upper value for this range.
getUpper()142   const APFloat &getUpper() const { return Upper; }
143 
containsNaN()144   bool containsNaN() const { return MayBeQNaN || MayBeSNaN; }
containsQNaN()145   bool containsQNaN() const { return MayBeQNaN; }
containsSNaN()146   bool containsSNaN() const { return MayBeSNaN; }
147   LLVM_ABI bool isNaNOnly() const;
148 
149   /// Get the semantics of this ConstantFPRange.
getSemantics()150   const fltSemantics &getSemantics() const { return Lower.getSemantics(); }
151 
152   /// Return true if this set contains all of the elements possible
153   /// for this data-type.
154   LLVM_ABI bool isFullSet() const;
155 
156   /// Return true if this set contains no members.
157   LLVM_ABI bool isEmptySet() const;
158 
159   /// Return true if the specified value is in the set.
160   LLVM_ABI bool contains(const APFloat &Val) const;
161 
162   /// Return true if the other range is a subset of this one.
163   LLVM_ABI bool contains(const ConstantFPRange &CR) const;
164 
165   /// If this set contains a single element, return it, otherwise return null.
166   /// If \p ExcludesNaN is true, return the non-NaN single element.
167   LLVM_ABI const APFloat *getSingleElement(bool ExcludesNaN = false) const;
168 
169   /// Return true if this set contains exactly one member.
170   /// If \p ExcludesNaN is true, return true if this set contains exactly one
171   /// non-NaN member.
172   bool isSingleElement(bool ExcludesNaN = false) const {
173     return getSingleElement(ExcludesNaN) != nullptr;
174   }
175 
176   /// Return true if the sign bit of all values in this range is 1.
177   /// Return false if the sign bit of all values in this range is 0.
178   /// Otherwise, return std::nullopt.
179   LLVM_ABI std::optional<bool> getSignBit() const;
180 
181   /// Return true if this range is equal to another range.
182   LLVM_ABI bool operator==(const ConstantFPRange &CR) const;
183   /// Return true if this range is not equal to another range.
184   bool operator!=(const ConstantFPRange &CR) const { return !operator==(CR); }
185 
186   /// Return the FPClassTest which will return true for the value.
187   LLVM_ABI FPClassTest classify() const;
188 
189   /// Print out the bounds to a stream.
190   LLVM_ABI void print(raw_ostream &OS) const;
191 
192   /// Allow printing from a debugger easily.
193   LLVM_ABI void dump() const;
194 
195   /// Return the range that results from the intersection of this range with
196   /// another range.
197   LLVM_ABI ConstantFPRange intersectWith(const ConstantFPRange &CR) const;
198 
199   /// Return the smallest range that results from the union of this range
200   /// with another range.  The resultant range is guaranteed to include the
201   /// elements of both sets, but may contain more.
202   LLVM_ABI ConstantFPRange unionWith(const ConstantFPRange &CR) const;
203 };
204 
205 inline raw_ostream &operator<<(raw_ostream &OS, const ConstantFPRange &CR) {
206   CR.print(OS);
207   return OS;
208 }
209 
210 } // end namespace llvm
211 
212 #endif // LLVM_IR_CONSTANTFPRANGE_H
213