LLVM 23.0.0git
APFixedPoint.h
Go to the documentation of this file.
1//===- APFixedPoint.h - Fixed point constant handling -----------*- 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/// \file
10/// Defines the fixed point number interface.
11/// This is a class for abstracting various operations performed on fixed point
12/// types.
13///
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_ADT_APFIXEDPOINT_H
17#define LLVM_ADT_APFIXEDPOINT_H
18
19#include "llvm/ADT/APSInt.h"
20#include "llvm/ADT/Hashing.h"
24
25namespace llvm {
26
27class APFloat;
28struct fltSemantics;
29
30/// The fixed point semantics work similarly to fltSemantics. The width
31/// specifies the whole bit width of the underlying scaled integer (with padding
32/// if any). The scale represents the number of fractional bits in this type.
33/// When HasUnsignedPadding is true and this type is unsigned, the first bit
34/// in the value this represents is treated as padding.
36public:
37 static constexpr unsigned WidthBitWidth = 16;
38 static constexpr unsigned LsbWeightBitWidth = 13;
39 /// Used to differentiate between constructors with Width and Lsb from the
40 /// default Width and scale
41 struct Lsb {
43 };
44 FixedPointSemantics(unsigned Width, unsigned Scale, bool IsSigned,
45 bool IsSaturated, bool HasUnsignedPadding)
46 : FixedPointSemantics(Width, Lsb{-static_cast<int>(Scale)}, IsSigned,
47 IsSaturated, HasUnsignedPadding) {}
48 FixedPointSemantics(unsigned Width, Lsb Weight, bool IsSigned,
49 bool IsSaturated, bool HasUnsignedPadding)
50 : Width(Width), LsbWeight(Weight.LsbWeight), IsSigned(IsSigned),
51 IsSaturated(IsSaturated), HasUnsignedPadding(HasUnsignedPadding) {
53 assert(!(IsSigned && HasUnsignedPadding) &&
54 "Cannot have unsigned padding on a signed type.");
55 }
56
57 /// Check if the Semantic follow the requirements of an older more limited
58 /// version of this class
59 bool isValidLegacySema() const {
60 return LsbWeight <= 0 && static_cast<int>(Width) >= -LsbWeight;
61 }
62 unsigned getWidth() const { return Width; }
63 unsigned getScale() const { assert(isValidLegacySema()); return -LsbWeight; }
64 int getLsbWeight() const { return LsbWeight; }
65 int getMsbWeight() const {
66 return LsbWeight + Width - 1 /*Both lsb and msb are both part of width*/;
67 }
68 bool isSigned() const { return IsSigned; }
69 bool isSaturated() const { return IsSaturated; }
70 bool hasUnsignedPadding() const { return HasUnsignedPadding; }
71
72 void setSaturated(bool Saturated) { IsSaturated = Saturated; }
73
74 /// return true if the first bit doesn't have a strictly positive weight
75 bool hasSignOrPaddingBit() const { return IsSigned || HasUnsignedPadding; }
76
77 /// Return the number of integral bits represented by these semantics. These
78 /// are separate from the fractional bits and do not include the sign or
79 /// padding bit.
80 unsigned getIntegralBits() const {
81 return std::max(getMsbWeight() + 1 - hasSignOrPaddingBit(), 0);
82 }
83
84 /// Return the FixedPointSemantics that allows for calculating the full
85 /// precision semantic that can precisely represent the precision and ranges
86 /// of both input values. This does not compute the resulting semantics for a
87 /// given binary operation.
90
91 /// Print semantics for debug purposes
92 LLVM_ABI void print(llvm::raw_ostream &OS) const;
93
94 /// Returns true if this fixed-point semantic with its value bits interpreted
95 /// as an integer can fit in the given floating point semantic without
96 /// overflowing to infinity.
97 /// For example, a signed 8-bit fixed-point semantic has a maximum and
98 /// minimum integer representation of 127 and -128, respectively. If both of
99 /// these values can be represented (possibly inexactly) in the floating
100 /// point semantic without overflowing, this returns true.
101 LLVM_ABI bool fitsInFloatSemantics(const fltSemantics &FloatSema) const;
102
103 /// Return the FixedPointSemantics for an integer type.
105 bool IsSigned) {
106 return FixedPointSemantics(Width, /*Scale=*/0, IsSigned,
107 /*IsSaturated=*/false,
108 /*HasUnsignedPadding=*/false);
109 }
110
112 return Width == Other.Width && LsbWeight == Other.LsbWeight &&
113 IsSigned == Other.IsSigned && IsSaturated == Other.IsSaturated &&
114 HasUnsignedPadding == Other.HasUnsignedPadding;
115 }
116 bool operator!=(FixedPointSemantics Other) const { return !(*this == Other); }
117
118 /// Convert the semantics to a 32-bit unsigned integer.
119 /// The result is dependent on the host endianness and not stable across LLVM
120 /// versions. See getFromOpaqueInt() to convert it back to a
121 /// FixedPointSemantics object.
123 /// Create a FixedPointSemantics object from an integer created via
124 /// toOpaqueInt().
126
127private:
128 unsigned Width : WidthBitWidth;
129 signed int LsbWeight : LsbWeightBitWidth;
130 unsigned IsSigned : 1;
131 unsigned IsSaturated : 1;
132 unsigned HasUnsignedPadding : 1;
133};
134
135static_assert(sizeof(FixedPointSemantics) == 4, "");
136
138 return hash_value(bit_cast<uint32_t>(Val));
139}
140
143 return FixedPointSemantics(0, 0, false, false, false);
144 }
145
146 static unsigned getHashValue(const FixedPointSemantics &Val) {
147 return hash_value(Val);
148 }
149
150 static bool isEqual(const char &LHS, const char &RHS) { return LHS == RHS; }
151};
152
153/// The APFixedPoint class works similarly to APInt/APSInt in that it is a
154/// functional replacement for a scaled integer. It supports a wide range of
155/// semantics including the one used by fixed point types proposed in ISO/IEC
156/// JTC1 SC22 WG14 N1169. The class carries the value and semantics of
157/// a fixed point, and provides different operations that would normally be
158/// performed on fixed point types.
160public:
161 APFixedPoint(const APInt &Val, const FixedPointSemantics &Sema)
162 : Val(Val, !Sema.isSigned()), Sema(Sema) {
163 assert(Val.getBitWidth() == Sema.getWidth() &&
164 "The value should have a bit width that matches the Sema width");
165 }
166
168 : APFixedPoint(APInt(Sema.getWidth(), Val, Sema.isSigned(),
169 /*implicitTrunc=*/true),
170 Sema) {}
171
172 // Zero initialization.
174
175 APSInt getValue() const { return APSInt(Val, !Sema.isSigned()); }
176 inline unsigned getWidth() const { return Sema.getWidth(); }
177 inline unsigned getScale() const { return Sema.getScale(); }
178 int getLsbWeight() const { return Sema.getLsbWeight(); }
179 int getMsbWeight() const { return Sema.getMsbWeight(); }
180 inline bool isSaturated() const { return Sema.isSaturated(); }
181 inline bool isSigned() const { return Sema.isSigned(); }
182 inline bool hasPadding() const { return Sema.hasUnsignedPadding(); }
183 FixedPointSemantics getSemantics() const { return Sema; }
184
185 bool getBoolValue() const { return Val.getBoolValue(); }
186
187 // Convert this number to match the semantics provided. If the overflow
188 // parameter is provided, set this value to true or false to indicate if this
189 // operation results in an overflow.
191 bool *Overflow = nullptr) const;
192
193 // Perform binary operations on a fixed point type. The resulting fixed point
194 // value will be in the common, full precision semantics that can represent
195 // the precision and ranges of both input values. See convert() for an
196 // explanation of the Overflow parameter.
198 bool *Overflow = nullptr) const;
200 bool *Overflow = nullptr) const;
202 bool *Overflow = nullptr) const;
204 bool *Overflow = nullptr) const;
205
206 // Perform shift operations on a fixed point type. Unlike the other binary
207 // operations, the resulting fixed point value will be in the original
208 // semantic.
209 LLVM_ABI APFixedPoint shl(unsigned Amt, bool *Overflow = nullptr) const;
210 APFixedPoint shr(unsigned Amt, bool *Overflow = nullptr) const {
211 // Right shift cannot overflow.
212 if (Overflow)
213 *Overflow = false;
214 return APFixedPoint(Val >> Amt, Sema);
215 }
216
217 /// Perform a unary negation (-X) on this fixed point type, taking into
218 /// account saturation if applicable.
219 LLVM_ABI APFixedPoint negate(bool *Overflow = nullptr) const;
220
221 /// Return the integral part of this fixed point number, rounded towards
222 /// zero. (-2.5k -> -2)
224 if (getMsbWeight() < 0)
225 return APSInt(APInt::getZero(getWidth()), Val.isUnsigned());
226 APSInt ExtVal =
227 (getLsbWeight() > 0) ? Val.extend(getWidth() + getLsbWeight()) : Val;
228 if (Val < 0 && Val != -Val) // Cover the case when we have the min val
229 return -((-ExtVal).relativeShl(getLsbWeight()));
230 return ExtVal.relativeShl(getLsbWeight());
231 }
232
233 /// Return the integral part of this fixed point number, rounded towards
234 /// zero. The value is stored into an APSInt with the provided width and sign.
235 /// If the overflow parameter is provided, and the integral value is not able
236 /// to be fully stored in the provided width and sign, the overflow parameter
237 /// is set to true.
238 LLVM_ABI APSInt convertToInt(unsigned DstWidth, bool DstSign,
239 bool *Overflow = nullptr) const;
240
241 /// Convert this fixed point number to a floating point value with the
242 /// provided semantics.
243 LLVM_ABI APFloat convertToFloat(const fltSemantics &FloatSema) const;
244
245 LLVM_ABI void toString(SmallVectorImpl<char> &Str) const;
246 std::string toString() const {
248 toString(S);
249 return std::string(S);
250 }
251
252 LLVM_ABI void print(raw_ostream &) const;
253
254#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
255 LLVM_DUMP_METHOD void dump() const;
256#endif
257
258 // If LHS > RHS, return 1. If LHS == RHS, return 0. If LHS < RHS, return -1.
259 LLVM_ABI int compare(const APFixedPoint &Other) const;
260 bool operator==(const APFixedPoint &Other) const {
261 return compare(Other) == 0;
262 }
263 bool operator!=(const APFixedPoint &Other) const {
264 return compare(Other) != 0;
265 }
266 bool operator>(const APFixedPoint &Other) const { return compare(Other) > 0; }
267 bool operator<(const APFixedPoint &Other) const { return compare(Other) < 0; }
268 bool operator>=(const APFixedPoint &Other) const {
269 return compare(Other) >= 0;
270 }
271 bool operator<=(const APFixedPoint &Other) const {
272 return compare(Other) <= 0;
273 }
274
278
279 /// Given a floating point semantic, return the next floating point semantic
280 /// with a larger exponent and larger or equal mantissa.
281 LLVM_ABI static const fltSemantics *
283
284 /// Create an APFixedPoint with a value equal to that of the provided integer,
285 /// and in the same semantics as the provided target semantics. If the value
286 /// is not able to fit in the specified fixed point semantics, and the
287 /// overflow parameter is provided, it is set to true.
289 getFromIntValue(const APSInt &Value, const FixedPointSemantics &DstFXSema,
290 bool *Overflow = nullptr);
291
292 /// Create an APFixedPoint with a value equal to that of the provided
293 /// floating point value, in the provided target semantics. If the value is
294 /// not able to fit in the specified fixed point semantics and the overflow
295 /// parameter is specified, it is set to true.
296 /// For NaN, the Overflow flag is always set. For +inf and -inf, if the
297 /// semantic is saturating, the value saturates. Otherwise, the Overflow flag
298 /// is set.
300 getFromFloatValue(const APFloat &Value, const FixedPointSemantics &DstFXSema,
301 bool *Overflow = nullptr);
302
303private:
304 APSInt Val;
306};
307
309 OS << FX.toString();
310 return OS;
311}
312
314 return hash_combine(Val.getSemantics(), Val.getValue());
315}
316
317template <> struct DenseMapInfo<APFixedPoint> {
321
322 static unsigned getHashValue(const APFixedPoint &Val) {
323 return hash_value(Val);
324 }
325
326 static bool isEqual(const APFixedPoint &LHS, const APFixedPoint &RHS) {
327 return LHS.getSemantics() == RHS.getSemantics() &&
328 LHS.getValue() == RHS.getValue();
329 }
330};
331
332} // namespace llvm
333
334#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:661
This file defines the SmallString class.
Value * RHS
Value * LHS
The APFixedPoint class works similarly to APInt/APSInt in that it is a functional replacement for a s...
LLVM_ABI APFixedPoint convert(const FixedPointSemantics &DstSema, bool *Overflow=nullptr) const
LLVM_ABI void toString(SmallVectorImpl< char > &Str) const
APFixedPoint(const APInt &Val, const FixedPointSemantics &Sema)
static LLVM_ABI APFixedPoint getMin(const FixedPointSemantics &Sema)
bool operator==(const APFixedPoint &Other) const
bool operator!=(const APFixedPoint &Other) const
int getLsbWeight() const
FixedPointSemantics getSemantics() const
LLVM_ABI int compare(const APFixedPoint &Other) const
bool operator<(const APFixedPoint &Other) const
LLVM_ABI APSInt convertToInt(unsigned DstWidth, bool DstSign, bool *Overflow=nullptr) const
Return the integral part of this fixed point number, rounded towards zero.
APFixedPoint shr(unsigned Amt, bool *Overflow=nullptr) const
static LLVM_ABI APFixedPoint getFromFloatValue(const APFloat &Value, const FixedPointSemantics &DstFXSema, bool *Overflow=nullptr)
Create an APFixedPoint with a value equal to that of the provided floating point value,...
APFixedPoint(const FixedPointSemantics &Sema)
LLVM_ABI APFixedPoint sub(const APFixedPoint &Other, bool *Overflow=nullptr) const
LLVM_ABI APFloat convertToFloat(const fltSemantics &FloatSema) const
Convert this fixed point number to a floating point value with the provided semantics.
APFixedPoint(uint64_t Val, const FixedPointSemantics &Sema)
LLVM_DUMP_METHOD void dump() const
static LLVM_ABI APFixedPoint getFromIntValue(const APSInt &Value, const FixedPointSemantics &DstFXSema, bool *Overflow=nullptr)
Create an APFixedPoint with a value equal to that of the provided integer, and in the same semantics ...
unsigned getScale() const
std::string toString() const
LLVM_ABI void print(raw_ostream &) const
APSInt getValue() const
unsigned getWidth() const
bool isSigned() const
bool operator>=(const APFixedPoint &Other) const
bool hasPadding() const
LLVM_ABI APFixedPoint negate(bool *Overflow=nullptr) const
Perform a unary negation (-X) on this fixed point type, taking into account saturation if applicable.
LLVM_ABI APFixedPoint shl(unsigned Amt, bool *Overflow=nullptr) const
bool operator<=(const APFixedPoint &Other) const
bool operator>(const APFixedPoint &Other) const
bool isSaturated() const
static LLVM_ABI APFixedPoint getEpsilon(const FixedPointSemantics &Sema)
static LLVM_ABI const fltSemantics * promoteFloatSemantics(const fltSemantics *S)
Given a floating point semantic, return the next floating point semantic with a larger exponent and l...
LLVM_ABI APFixedPoint div(const APFixedPoint &Other, bool *Overflow=nullptr) const
LLVM_ABI APFixedPoint mul(const APFixedPoint &Other, bool *Overflow=nullptr) const
APSInt getIntPart() const
Return the integral part of this fixed point number, rounded towards zero.
LLVM_ABI APFixedPoint add(const APFixedPoint &Other, bool *Overflow=nullptr) const
bool getBoolValue() const
int getMsbWeight() const
static LLVM_ABI APFixedPoint getMax(const FixedPointSemantics &Sema)
Class for arbitrary precision integers.
Definition APInt.h:78
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Definition APInt.h:201
An arbitrary precision integer that knows its signedness.
Definition APSInt.h:24
APSInt relativeShl(unsigned Amt) const
Definition APSInt.h:216
APSInt extend(uint32_t width) const
Definition APSInt.h:113
The fixed point semantics work similarly to fltSemantics.
static LLVM_ABI FixedPointSemantics getFromOpaqueInt(uint32_t)
Create a FixedPointSemantics object from an integer created via toOpaqueInt().
static constexpr unsigned WidthBitWidth
unsigned getWidth() const
void setSaturated(bool Saturated)
bool hasUnsignedPadding() const
static constexpr unsigned LsbWeightBitWidth
unsigned getScale() const
unsigned getIntegralBits() const
Return the number of integral bits represented by these semantics.
LLVM_ABI FixedPointSemantics getCommonSemantics(const FixedPointSemantics &Other) const
Return the FixedPointSemantics that allows for calculating the full precision semantic that can preci...
bool operator!=(FixedPointSemantics Other) const
bool operator==(FixedPointSemantics Other) const
LLVM_ABI void print(llvm::raw_ostream &OS) const
Print semantics for debug purposes.
LLVM_ABI bool fitsInFloatSemantics(const fltSemantics &FloatSema) const
Returns true if this fixed-point semantic with its value bits interpreted as an integer can fit in th...
bool hasSignOrPaddingBit() const
return true if the first bit doesn't have a strictly positive weight
FixedPointSemantics(unsigned Width, Lsb Weight, bool IsSigned, bool IsSaturated, bool HasUnsignedPadding)
LLVM_ABI uint32_t toOpaqueInt() const
Convert the semantics to a 32-bit unsigned integer.
FixedPointSemantics(unsigned Width, unsigned Scale, bool IsSigned, bool IsSaturated, bool HasUnsignedPadding)
bool isValidLegacySema() const
Check if the Semantic follow the requirements of an older more limited version of this class.
static FixedPointSemantics GetIntegerSemantics(unsigned Width, bool IsSigned)
Return the FixedPointSemantics for an integer type.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
LLVM Value Representation.
Definition Value.h:75
An opaque object representing a hash code.
Definition Hashing.h:78
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
This is an optimization pass for GlobalISel generic memory operations.
hash_code hash_value(const FixedPointSemantics &Val)
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:165
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:189
@ Other
Any other memory.
Definition ModRef.h:68
To bit_cast(const From &from) noexcept
Definition bit.h:90
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
Definition Hashing.h:325
static unsigned getHashValue(const APFixedPoint &Val)
static bool isEqual(const APFixedPoint &LHS, const APFixedPoint &RHS)
static APFixedPoint getEmptyKey()
static FixedPointSemantics getEmptyKey()
static bool isEqual(const char &LHS, const char &RHS)
static unsigned getHashValue(const FixedPointSemantics &Val)
An information struct used to provide DenseMap with the various necessary components for a given valu...
Used to differentiate between constructors with Width and Lsb from the default Width and scale.