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