File indexing completed on 2026-05-10 08:43:02
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef LLVM_ADT_APFIXEDPOINT_H
0017 #define LLVM_ADT_APFIXEDPOINT_H
0018
0019 #include "llvm/ADT/APSInt.h"
0020 #include "llvm/ADT/Hashing.h"
0021 #include "llvm/ADT/SmallString.h"
0022 #include "llvm/Support/raw_ostream.h"
0023
0024 namespace llvm {
0025
0026 class APFloat;
0027 struct fltSemantics;
0028
0029
0030
0031
0032
0033
0034 class FixedPointSemantics {
0035 public:
0036 static constexpr unsigned WidthBitWidth = 16;
0037 static constexpr unsigned LsbWeightBitWidth = 13;
0038
0039
0040 struct Lsb {
0041 int LsbWeight;
0042 };
0043 FixedPointSemantics(unsigned Width, unsigned Scale, bool IsSigned,
0044 bool IsSaturated, bool HasUnsignedPadding)
0045 : FixedPointSemantics(Width, Lsb{-static_cast<int>(Scale)}, IsSigned,
0046 IsSaturated, HasUnsignedPadding) {}
0047 FixedPointSemantics(unsigned Width, Lsb Weight, bool IsSigned,
0048 bool IsSaturated, bool HasUnsignedPadding)
0049 : Width(Width), LsbWeight(Weight.LsbWeight), IsSigned(IsSigned),
0050 IsSaturated(IsSaturated), HasUnsignedPadding(HasUnsignedPadding) {
0051 assert(isUInt<WidthBitWidth>(Width) && isInt<LsbWeightBitWidth>(Weight.LsbWeight));
0052 assert(!(IsSigned && HasUnsignedPadding) &&
0053 "Cannot have unsigned padding on a signed type.");
0054 }
0055
0056
0057
0058 bool isValidLegacySema() const {
0059 return LsbWeight <= 0 && static_cast<int>(Width) >= -LsbWeight;
0060 }
0061 unsigned getWidth() const { return Width; }
0062 unsigned getScale() const { assert(isValidLegacySema()); return -LsbWeight; }
0063 int getLsbWeight() const { return LsbWeight; }
0064 int getMsbWeight() const {
0065 return LsbWeight + Width - 1 ;
0066 }
0067 bool isSigned() const { return IsSigned; }
0068 bool isSaturated() const { return IsSaturated; }
0069 bool hasUnsignedPadding() const { return HasUnsignedPadding; }
0070
0071 void setSaturated(bool Saturated) { IsSaturated = Saturated; }
0072
0073
0074 bool hasSignOrPaddingBit() const { return IsSigned || HasUnsignedPadding; }
0075
0076
0077
0078
0079 unsigned getIntegralBits() const {
0080 return std::max(getMsbWeight() + 1 - hasSignOrPaddingBit(), 0);
0081 }
0082
0083
0084
0085
0086
0087 FixedPointSemantics
0088 getCommonSemantics(const FixedPointSemantics &Other) const;
0089
0090
0091 void print(llvm::raw_ostream& OS) const;
0092
0093
0094
0095
0096
0097
0098
0099
0100 bool fitsInFloatSemantics(const fltSemantics &FloatSema) const;
0101
0102
0103 static FixedPointSemantics GetIntegerSemantics(unsigned Width,
0104 bool IsSigned) {
0105 return FixedPointSemantics(Width, 0, IsSigned,
0106 false,
0107 false);
0108 }
0109
0110 bool operator==(FixedPointSemantics Other) const {
0111 return Width == Other.Width && LsbWeight == Other.LsbWeight &&
0112 IsSigned == Other.IsSigned && IsSaturated == Other.IsSaturated &&
0113 HasUnsignedPadding == Other.HasUnsignedPadding;
0114 }
0115 bool operator!=(FixedPointSemantics Other) const { return !(*this == Other); }
0116
0117
0118
0119
0120
0121 uint32_t toOpaqueInt() const;
0122
0123
0124 static FixedPointSemantics getFromOpaqueInt(uint32_t);
0125
0126 private:
0127 unsigned Width : WidthBitWidth;
0128 signed int LsbWeight : LsbWeightBitWidth;
0129 unsigned IsSigned : 1;
0130 unsigned IsSaturated : 1;
0131 unsigned HasUnsignedPadding : 1;
0132 };
0133
0134 static_assert(sizeof(FixedPointSemantics) == 4, "");
0135
0136 inline hash_code hash_value(const FixedPointSemantics &Val) {
0137 return hash_value(bit_cast<uint32_t>(Val));
0138 }
0139
0140 template <> struct DenseMapInfo<FixedPointSemantics> {
0141 static inline FixedPointSemantics getEmptyKey() {
0142 return FixedPointSemantics(0, 0, false, false, false);
0143 }
0144
0145 static inline FixedPointSemantics getTombstoneKey() {
0146 return FixedPointSemantics(0, 1, false, false, false);
0147 }
0148
0149 static unsigned getHashValue(const FixedPointSemantics &Val) {
0150 return hash_value(Val);
0151 }
0152
0153 static bool isEqual(const char &LHS, const char &RHS) { return LHS == RHS; }
0154 };
0155
0156
0157
0158
0159
0160
0161
0162 class APFixedPoint {
0163 public:
0164 APFixedPoint(const APInt &Val, const FixedPointSemantics &Sema)
0165 : Val(Val, !Sema.isSigned()), Sema(Sema) {
0166 assert(Val.getBitWidth() == Sema.getWidth() &&
0167 "The value should have a bit width that matches the Sema width");
0168 }
0169
0170 APFixedPoint(uint64_t Val, const FixedPointSemantics &Sema)
0171 : APFixedPoint(APInt(Sema.getWidth(), Val, Sema.isSigned(),
0172 true),
0173 Sema) {}
0174
0175
0176 APFixedPoint(const FixedPointSemantics &Sema) : APFixedPoint(0, Sema) {}
0177
0178 APSInt getValue() const { return APSInt(Val, !Sema.isSigned()); }
0179 inline unsigned getWidth() const { return Sema.getWidth(); }
0180 inline unsigned getScale() const { return Sema.getScale(); }
0181 int getLsbWeight() const { return Sema.getLsbWeight(); }
0182 int getMsbWeight() const { return Sema.getMsbWeight(); }
0183 inline bool isSaturated() const { return Sema.isSaturated(); }
0184 inline bool isSigned() const { return Sema.isSigned(); }
0185 inline bool hasPadding() const { return Sema.hasUnsignedPadding(); }
0186 FixedPointSemantics getSemantics() const { return Sema; }
0187
0188 bool getBoolValue() const { return Val.getBoolValue(); }
0189
0190
0191
0192
0193 APFixedPoint convert(const FixedPointSemantics &DstSema,
0194 bool *Overflow = nullptr) const;
0195
0196
0197
0198
0199
0200 APFixedPoint add(const APFixedPoint &Other, bool *Overflow = nullptr) const;
0201 APFixedPoint sub(const APFixedPoint &Other, bool *Overflow = nullptr) const;
0202 APFixedPoint mul(const APFixedPoint &Other, bool *Overflow = nullptr) const;
0203 APFixedPoint div(const APFixedPoint &Other, bool *Overflow = nullptr) const;
0204
0205
0206
0207
0208 APFixedPoint shl(unsigned Amt, bool *Overflow = nullptr) const;
0209 APFixedPoint shr(unsigned Amt, bool *Overflow = nullptr) const {
0210
0211 if (Overflow)
0212 *Overflow = false;
0213 return APFixedPoint(Val >> Amt, Sema);
0214 }
0215
0216
0217
0218 APFixedPoint negate(bool *Overflow = nullptr) const;
0219
0220
0221
0222 APSInt getIntPart() const {
0223 if (getMsbWeight() < 0)
0224 return APSInt(APInt::getZero(getWidth()), Val.isUnsigned());
0225 APSInt ExtVal =
0226 (getLsbWeight() > 0) ? Val.extend(getWidth() + getLsbWeight()) : Val;
0227 if (Val < 0 && Val != -Val)
0228 return -((-ExtVal).relativeShl(getLsbWeight()));
0229 return ExtVal.relativeShl(getLsbWeight());
0230 }
0231
0232
0233
0234
0235
0236
0237 APSInt convertToInt(unsigned DstWidth, bool DstSign,
0238 bool *Overflow = nullptr) const;
0239
0240
0241
0242 APFloat convertToFloat(const fltSemantics &FloatSema) const;
0243
0244 void toString(SmallVectorImpl<char> &Str) const;
0245 std::string toString() const {
0246 SmallString<40> S;
0247 toString(S);
0248 return std::string(S);
0249 }
0250
0251 void print(raw_ostream &) const;
0252 void dump() const;
0253
0254
0255 int compare(const APFixedPoint &Other) const;
0256 bool operator==(const APFixedPoint &Other) const {
0257 return compare(Other) == 0;
0258 }
0259 bool operator!=(const APFixedPoint &Other) const {
0260 return compare(Other) != 0;
0261 }
0262 bool operator>(const APFixedPoint &Other) const { return compare(Other) > 0; }
0263 bool operator<(const APFixedPoint &Other) const { return compare(Other) < 0; }
0264 bool operator>=(const APFixedPoint &Other) const {
0265 return compare(Other) >= 0;
0266 }
0267 bool operator<=(const APFixedPoint &Other) const {
0268 return compare(Other) <= 0;
0269 }
0270
0271 static APFixedPoint getMax(const FixedPointSemantics &Sema);
0272 static APFixedPoint getMin(const FixedPointSemantics &Sema);
0273 static APFixedPoint getEpsilon(const FixedPointSemantics &Sema);
0274
0275
0276
0277 static const fltSemantics *promoteFloatSemantics(const fltSemantics *S);
0278
0279
0280
0281
0282
0283 static APFixedPoint getFromIntValue(const APSInt &Value,
0284 const FixedPointSemantics &DstFXSema,
0285 bool *Overflow = nullptr);
0286
0287
0288
0289
0290
0291
0292
0293
0294 static APFixedPoint getFromFloatValue(const APFloat &Value,
0295 const FixedPointSemantics &DstFXSema,
0296 bool *Overflow = nullptr);
0297
0298 private:
0299 APSInt Val;
0300 FixedPointSemantics Sema;
0301 };
0302
0303 inline raw_ostream &operator<<(raw_ostream &OS, const APFixedPoint &FX) {
0304 OS << FX.toString();
0305 return OS;
0306 }
0307
0308 inline hash_code hash_value(const APFixedPoint &Val) {
0309 return hash_combine(Val.getSemantics(), Val.getValue());
0310 }
0311
0312 template <> struct DenseMapInfo<APFixedPoint> {
0313 static inline APFixedPoint getEmptyKey() {
0314 return APFixedPoint(DenseMapInfo<FixedPointSemantics>::getEmptyKey());
0315 }
0316
0317 static inline APFixedPoint getTombstoneKey() {
0318 return APFixedPoint(DenseMapInfo<FixedPointSemantics>::getTombstoneKey());
0319 }
0320
0321 static unsigned getHashValue(const APFixedPoint &Val) {
0322 return hash_value(Val);
0323 }
0324
0325 static bool isEqual(const APFixedPoint &LHS, const APFixedPoint &RHS) {
0326 return LHS.getSemantics() == RHS.getSemantics() &&
0327 LHS.getValue() == RHS.getValue();
0328 }
0329 };
0330
0331 }
0332
0333 #endif