Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:57

0001 //===- ConstantFPRange.h - Represent a range for floating-point -*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // Represent a range of possible values that may occur when the program is run
0010 // for a floating-point value. This keeps track of a lower and upper bound for
0011 // the constant.
0012 //
0013 // Range = [Lower, Upper] U (MayBeQNaN ? QNaN : {}) U (MayBeSNaN ? SNaN : {})
0014 // Specifically, [inf, -inf] represents an empty set.
0015 // Note:
0016 // 1. Bounds are inclusive.
0017 // 2. -0 is considered to be less than 0. That is, range [0, 0] doesn't contain
0018 // -0.
0019 // 3. Currently wrapping ranges are not supported.
0020 //
0021 //===----------------------------------------------------------------------===//
0022 
0023 #ifndef LLVM_IR_CONSTANTFPRANGE_H
0024 #define LLVM_IR_CONSTANTFPRANGE_H
0025 
0026 #include "llvm/ADT/APFloat.h"
0027 #include "llvm/IR/Instructions.h"
0028 #include <optional>
0029 
0030 namespace llvm {
0031 
0032 class raw_ostream;
0033 struct KnownFPClass;
0034 
0035 /// This class represents a range of floating-point values.
0036 class [[nodiscard]] ConstantFPRange {
0037   APFloat Lower, Upper;
0038   bool MayBeQNaN : 1;
0039   bool MayBeSNaN : 1;
0040 
0041   /// Create empty constant range with same semantics.
0042   ConstantFPRange getEmpty() const {
0043     return ConstantFPRange(getSemantics(), /*IsFullSet=*/false);
0044   }
0045 
0046   /// Create full constant range with same semantics.
0047   ConstantFPRange getFull() const {
0048     return ConstantFPRange(getSemantics(), /*IsFullSet=*/true);
0049   }
0050 
0051   void makeEmpty();
0052   void makeFull();
0053 
0054   /// Initialize a full or empty set for the specified semantics.
0055   explicit ConstantFPRange(const fltSemantics &Sem, bool IsFullSet);
0056 
0057 public:
0058   /// Initialize a range to hold the single specified value.
0059   explicit ConstantFPRange(const APFloat &Value);
0060 
0061   /// Initialize a range of values explicitly.
0062   /// Note: If \p LowerVal is greater than \p UpperVal, please use the canonical
0063   /// form [Inf, -Inf].
0064   ConstantFPRange(APFloat LowerVal, APFloat UpperVal, bool MayBeQNaN,
0065                   bool MayBeSNaN);
0066 
0067   /// Create empty constant range with the given semantics.
0068   static ConstantFPRange getEmpty(const fltSemantics &Sem) {
0069     return ConstantFPRange(Sem, /*IsFullSet=*/false);
0070   }
0071 
0072   /// Create full constant range with the given semantics.
0073   static ConstantFPRange getFull(const fltSemantics &Sem) {
0074     return ConstantFPRange(Sem, /*IsFullSet=*/true);
0075   }
0076 
0077   /// Helper for (-inf, inf) to represent all finite values.
0078   static ConstantFPRange getFinite(const fltSemantics &Sem);
0079 
0080   /// Helper for [-inf, inf] to represent all non-NaN values.
0081   static ConstantFPRange getNonNaN(const fltSemantics &Sem);
0082 
0083   /// Create a range which doesn't contain NaNs.
0084   static ConstantFPRange getNonNaN(APFloat LowerVal, APFloat UpperVal) {
0085     return ConstantFPRange(std::move(LowerVal), std::move(UpperVal),
0086                            /*MayBeQNaN=*/false, /*MayBeSNaN=*/false);
0087   }
0088 
0089   /// Create a range which may contain NaNs.
0090   static ConstantFPRange getMayBeNaN(APFloat LowerVal, APFloat UpperVal) {
0091     return ConstantFPRange(std::move(LowerVal), std::move(UpperVal),
0092                            /*MayBeQNaN=*/true, /*MayBeSNaN=*/true);
0093   }
0094 
0095   /// Create a range which only contains NaNs.
0096   static ConstantFPRange getNaNOnly(const fltSemantics &Sem, bool MayBeQNaN,
0097                                     bool MayBeSNaN);
0098 
0099   /// Produce the smallest range such that all values that may satisfy the given
0100   /// predicate with any value contained within Other is contained in the
0101   /// returned range.  Formally, this returns a superset of
0102   /// 'union over all y in Other . { x : fcmp op x y is true }'.  If the exact
0103   /// answer is not representable as a ConstantFPRange, the return value will be
0104   /// a proper superset of the above.
0105   ///
0106   /// Example: Pred = ole and Other = float [2, 5] returns Result = [-inf, 5]
0107   static ConstantFPRange makeAllowedFCmpRegion(FCmpInst::Predicate Pred,
0108                                                const ConstantFPRange &Other);
0109 
0110   /// Produce the largest range such that all values in the returned range
0111   /// satisfy the given predicate with all values contained within Other.
0112   /// Formally, this returns a subset of
0113   /// 'intersection over all y in Other . { x : fcmp op x y is true }'.  If the
0114   /// exact answer is not representable as a ConstantFPRange, the return value
0115   /// will be a proper subset of the above.
0116   ///
0117   /// Example: Pred = ole and Other = float [2, 5] returns [-inf, 2]
0118   static ConstantFPRange makeSatisfyingFCmpRegion(FCmpInst::Predicate Pred,
0119                                                   const ConstantFPRange &Other);
0120 
0121   /// Produce the exact range such that all values in the returned range satisfy
0122   /// the given predicate with any value contained within Other. Formally, this
0123   /// returns { x : fcmp op x Other is true }.
0124   ///
0125   /// Example: Pred = olt and Other = float 3 returns [-inf, 3)
0126   /// If the exact answer is not representable as a ConstantFPRange, returns
0127   /// std::nullopt.
0128   static std::optional<ConstantFPRange>
0129   makeExactFCmpRegion(FCmpInst::Predicate Pred, const APFloat &Other);
0130 
0131   /// Does the predicate \p Pred hold between ranges this and \p Other?
0132   /// NOTE: false does not mean that inverse predicate holds!
0133   bool fcmp(FCmpInst::Predicate Pred, const ConstantFPRange &Other) const;
0134 
0135   /// Return the lower value for this range.
0136   const APFloat &getLower() const { return Lower; }
0137 
0138   /// Return the upper value for this range.
0139   const APFloat &getUpper() const { return Upper; }
0140 
0141   bool containsNaN() const { return MayBeQNaN || MayBeSNaN; }
0142   bool containsQNaN() const { return MayBeQNaN; }
0143   bool containsSNaN() const { return MayBeSNaN; }
0144   bool isNaNOnly() const;
0145 
0146   /// Get the semantics of this ConstantFPRange.
0147   const fltSemantics &getSemantics() const { return Lower.getSemantics(); }
0148 
0149   /// Return true if this set contains all of the elements possible
0150   /// for this data-type.
0151   bool isFullSet() const;
0152 
0153   /// Return true if this set contains no members.
0154   bool isEmptySet() const;
0155 
0156   /// Return true if the specified value is in the set.
0157   bool contains(const APFloat &Val) const;
0158 
0159   /// Return true if the other range is a subset of this one.
0160   bool contains(const ConstantFPRange &CR) const;
0161 
0162   /// If this set contains a single element, return it, otherwise return null.
0163   /// If \p ExcludesNaN is true, return the non-NaN single element.
0164   const APFloat *getSingleElement(bool ExcludesNaN = false) const;
0165 
0166   /// Return true if this set contains exactly one member.
0167   /// If \p ExcludesNaN is true, return true if this set contains exactly one
0168   /// non-NaN member.
0169   bool isSingleElement(bool ExcludesNaN = false) const {
0170     return getSingleElement(ExcludesNaN) != nullptr;
0171   }
0172 
0173   /// Return true if the sign bit of all values in this range is 1.
0174   /// Return false if the sign bit of all values in this range is 0.
0175   /// Otherwise, return std::nullopt.
0176   std::optional<bool> getSignBit() const;
0177 
0178   /// Return true if this range is equal to another range.
0179   bool operator==(const ConstantFPRange &CR) const;
0180   /// Return true if this range is not equal to another range.
0181   bool operator!=(const ConstantFPRange &CR) const { return !operator==(CR); }
0182 
0183   /// Return the FPClassTest which will return true for the value.
0184   FPClassTest classify() const;
0185 
0186   /// Print out the bounds to a stream.
0187   void print(raw_ostream &OS) const;
0188 
0189   /// Allow printing from a debugger easily.
0190   void dump() const;
0191 
0192   /// Return the range that results from the intersection of this range with
0193   /// another range.
0194   ConstantFPRange intersectWith(const ConstantFPRange &CR) const;
0195 
0196   /// Return the smallest range that results from the union of this range
0197   /// with another range.  The resultant range is guaranteed to include the
0198   /// elements of both sets, but may contain more.
0199   ConstantFPRange unionWith(const ConstantFPRange &CR) const;
0200 };
0201 
0202 inline raw_ostream &operator<<(raw_ostream &OS, const ConstantFPRange &CR) {
0203   CR.print(OS);
0204   return OS;
0205 }
0206 
0207 } // end namespace llvm
0208 
0209 #endif // LLVM_IR_CONSTANTFPRANGE_H