LLVM 22.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
147 return FixedPointSemantics(0, 1, false, false, false);
148 }
149
150 static unsigned getHashValue(const FixedPointSemantics &Val) {
151 return hash_value(Val);
152 }
153
154 static bool isEqual(const char &LHS, const char &RHS) { return LHS == RHS; }
155};
156
157/// The APFixedPoint class works similarly to APInt/APSInt in that it is a
158/// functional replacement for a scaled integer. It supports a wide range of
159/// semantics including the one used by fixed point types proposed in ISO/IEC
160/// JTC1 SC22 WG14 N1169. The class carries the value and semantics of
161/// a fixed point, and provides different operations that would normally be
162/// performed on fixed point types.
164public:
165 APFixedPoint(const APInt &Val, const FixedPointSemantics &Sema)
166 : Val(Val, !Sema.isSigned()), Sema(Sema) {
167 assert(Val.getBitWidth() == Sema.getWidth() &&
168 "The value should have a bit width that matches the Sema width");
169 }
170
172 : APFixedPoint(APInt(Sema.getWidth(), Val, Sema.isSigned(),
173 /*implicitTrunc=*/true),
174 Sema) {}
175
176 // Zero initialization.
178
179 APSInt getValue() const { return APSInt(Val, !Sema.isSigned()); }
180 inline unsigned getWidth() const { return Sema.getWidth(); }
181 inline unsigned getScale() const { return Sema.getScale(); }
182 int getLsbWeight() const { return Sema.getLsbWeight(); }
183 int getMsbWeight() const { return Sema.getMsbWeight(); }
184 inline bool isSaturated() const { return Sema.isSaturated(); }
185 inline bool isSigned() const { return Sema.isSigned(); }
186 inline bool hasPadding() const { return Sema.hasUnsignedPadding(); }
187 FixedPointSemantics getSemantics() const { return Sema; }
188
189 bool getBoolValue() const { return Val.getBoolValue(); }
190
191 // Convert this number to match the semantics provided. If the overflow
192 // parameter is provided, set this value to true or false to indicate if this
193 // operation results in an overflow.
195 bool *Overflow = nullptr) const;
196
197 // Perform binary operations on a fixed point type. The resulting fixed point
198 // value will be in the common, full precision semantics that can represent
199 // the precision and ranges of both input values. See convert() for an
200 // explanation of the Overflow parameter.
202 bool *Overflow = nullptr) const;
204 bool *Overflow = nullptr) const;
206 bool *Overflow = nullptr) const;
208 bool *Overflow = nullptr) const;
209
210 // Perform shift operations on a fixed point type. Unlike the other binary
211 // operations, the resulting fixed point value will be in the original
212 // semantic.
213 LLVM_ABI APFixedPoint shl(unsigned Amt, bool *Overflow = nullptr) const;
214 APFixedPoint shr(unsigned Amt, bool *Overflow = nullptr) const {
215 // Right shift cannot overflow.
216 if (Overflow)
217 *Overflow = false;
218 return APFixedPoint(Val >> Amt, Sema);
219 }
220
221 /// Perform a unary negation (-X) on this fixed point type, taking into
222 /// account saturation if applicable.
223 LLVM_ABI APFixedPoint negate(bool *Overflow = nullptr) const;
224
225 /// Return the integral part of this fixed point number, rounded towards
226 /// zero. (-2.5k -> -2)
228 if (getMsbWeight() < 0)
229 return APSInt(APInt::getZero(getWidth()), Val.isUnsigned());
230 APSInt ExtVal =
231 (getLsbWeight() > 0) ? Val.extend(getWidth() + getLsbWeight()) : Val;
232 if (Val < 0 && Val != -Val) // Cover the case when we have the min val
233 return -((-ExtVal).relativeShl(getLsbWeight()));
234 return ExtVal.relativeShl(getLsbWeight());
235 }
236
237 /// Return the integral part of this fixed point number, rounded towards
238 /// zero. The value is stored into an APSInt with the provided width and sign.
239 /// If the overflow parameter is provided, and the integral value is not able
240 /// to be fully stored in the provided width and sign, the overflow parameter
241 /// is set to true.
242 LLVM_ABI APSInt convertToInt(unsigned DstWidth, bool DstSign,
243 bool *Overflow = nullptr) const;
244
245 /// Convert this fixed point number to a floating point value with the
246 /// provided semantics.
247 LLVM_ABI APFloat convertToFloat(const fltSemantics &FloatSema) const;
248
249 LLVM_ABI void toString(SmallVectorImpl<char> &Str) const;
250 std::string toString() const {
252 toString(S);
253 return std::string(S);
254 }
255
256 LLVM_ABI void print(raw_ostream &) const;
257
258#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
259 LLVM_DUMP_METHOD void dump() const;
260#endif
261
262 // If LHS > RHS, return 1. If LHS == RHS, return 0. If LHS < RHS, return -1.
263 LLVM_ABI int compare(const APFixedPoint &Other) const;
264 bool operator==(const APFixedPoint &Other) const {
265 return compare(Other) == 0;
266 }
267 bool operator!=(const APFixedPoint &Other) const {
268 return compare(Other) != 0;
269 }
270 bool operator>(const APFixedPoint &Other) const { return compare(Other) > 0; }
271 bool operator<(const APFixedPoint &Other) const { return compare(Other) < 0; }
272 bool operator>=(const APFixedPoint &Other) const {
273 return compare(Other) >= 0;
274 }
275 bool operator<=(const APFixedPoint &Other) const {
276 return compare(Other) <= 0;
277 }
278
282
283 /// Given a floating point semantic, return the next floating point semantic
284 /// with a larger exponent and larger or equal mantissa.
285 LLVM_ABI static const fltSemantics *
287
288 /// Create an APFixedPoint with a value equal to that of the provided integer,
289 /// and in the same semantics as the provided target semantics. If the value
290 /// is not able to fit in the specified fixed point semantics, and the
291 /// overflow parameter is provided, it is set to true.
293 getFromIntValue(const APSInt &Value, const FixedPointSemantics &DstFXSema,
294 bool *Overflow = nullptr);
295
296 /// Create an APFixedPoint with a value equal to that of the provided
297 /// floating point value, in the provided target semantics. If the value is
298 /// not able to fit in the specified fixed point semantics and the overflow
299 /// parameter is specified, it is set to true.
300 /// For NaN, the Overflow flag is always set. For +inf and -inf, if the
301 /// semantic is saturating, the value saturates. Otherwise, the Overflow flag
302 /// is set.
304 getFromFloatValue(const APFloat &Value, const FixedPointSemantics &DstFXSema,
305 bool *Overflow = nullptr);
306
307private:
308 APSInt Val;
310};
311
313 OS << FX.toString();
314 return OS;
315}
316
318 return hash_combine(Val.getSemantics(), Val.getValue());
319}
320
321template <> struct DenseMapInfo<APFixedPoint> {
325
329
330 static unsigned getHashValue(const APFixedPoint &Val) {
331 return hash_value(Val);
332 }
333
334 static bool isEqual(const APFixedPoint &LHS, const APFixedPoint &RHS) {
335 return LHS.getSemantics() == RHS.getSemantics() &&
336 LHS.getValue() == RHS.getValue();
337 }
338};
339
340} // namespace llvm
341
342#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:638
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:200
An arbitrary precision integer that knows its signedness.
Definition APSInt.h:24
APSInt relativeShl(unsigned Amt) const
Definition APSInt.h:218
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:76
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:174
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:198
@ 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:591
static unsigned getHashValue(const APFixedPoint &Val)
static APFixedPoint getTombstoneKey()
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)
static FixedPointSemantics getTombstoneKey()
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.