APFixedPoint.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. //===- APFixedPoint.cpp - 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 implementation for the fixed point number interface.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/ADT/APFixedPoint.h"
  14. #include "llvm/ADT/APFloat.h"
  15. namespace llvm {
  16. APFixedPoint APFixedPoint::convert(const FixedPointSemantics &DstSema,
  17. bool *Overflow) const {
  18. APSInt NewVal = Val;
  19. unsigned DstWidth = DstSema.getWidth();
  20. unsigned DstScale = DstSema.getScale();
  21. bool Upscaling = DstScale > getScale();
  22. if (Overflow)
  23. *Overflow = false;
  24. if (Upscaling) {
  25. NewVal = NewVal.extend(NewVal.getBitWidth() + DstScale - getScale());
  26. NewVal <<= (DstScale - getScale());
  27. } else {
  28. NewVal >>= (getScale() - DstScale);
  29. }
  30. auto Mask = APInt::getBitsSetFrom(
  31. NewVal.getBitWidth(),
  32. std::min(DstScale + DstSema.getIntegralBits(), NewVal.getBitWidth()));
  33. APInt Masked(NewVal & Mask);
  34. // Change in the bits above the sign
  35. if (!(Masked == Mask || Masked == 0)) {
  36. // Found overflow in the bits above the sign
  37. if (DstSema.isSaturated())
  38. NewVal = NewVal.isNegative() ? Mask : ~Mask;
  39. else if (Overflow)
  40. *Overflow = true;
  41. }
  42. // If the dst semantics are unsigned, but our value is signed and negative, we
  43. // clamp to zero.
  44. if (!DstSema.isSigned() && NewVal.isSigned() && NewVal.isNegative()) {
  45. // Found negative overflow for unsigned result
  46. if (DstSema.isSaturated())
  47. NewVal = 0;
  48. else if (Overflow)
  49. *Overflow = true;
  50. }
  51. NewVal = NewVal.extOrTrunc(DstWidth);
  52. NewVal.setIsSigned(DstSema.isSigned());
  53. return APFixedPoint(NewVal, DstSema);
  54. }
  55. int APFixedPoint::compare(const APFixedPoint &Other) const {
  56. APSInt ThisVal = getValue();
  57. APSInt OtherVal = Other.getValue();
  58. bool ThisSigned = Val.isSigned();
  59. bool OtherSigned = OtherVal.isSigned();
  60. unsigned OtherScale = Other.getScale();
  61. unsigned OtherWidth = OtherVal.getBitWidth();
  62. unsigned CommonWidth = std::max(Val.getBitWidth(), OtherWidth);
  63. // Prevent overflow in the event the widths are the same but the scales differ
  64. CommonWidth += getScale() >= OtherScale ? getScale() - OtherScale
  65. : OtherScale - getScale();
  66. ThisVal = ThisVal.extOrTrunc(CommonWidth);
  67. OtherVal = OtherVal.extOrTrunc(CommonWidth);
  68. unsigned CommonScale = std::max(getScale(), OtherScale);
  69. ThisVal = ThisVal.shl(CommonScale - getScale());
  70. OtherVal = OtherVal.shl(CommonScale - OtherScale);
  71. if (ThisSigned && OtherSigned) {
  72. if (ThisVal.sgt(OtherVal))
  73. return 1;
  74. else if (ThisVal.slt(OtherVal))
  75. return -1;
  76. } else if (!ThisSigned && !OtherSigned) {
  77. if (ThisVal.ugt(OtherVal))
  78. return 1;
  79. else if (ThisVal.ult(OtherVal))
  80. return -1;
  81. } else if (ThisSigned && !OtherSigned) {
  82. if (ThisVal.isSignBitSet())
  83. return -1;
  84. else if (ThisVal.ugt(OtherVal))
  85. return 1;
  86. else if (ThisVal.ult(OtherVal))
  87. return -1;
  88. } else {
  89. // !ThisSigned && OtherSigned
  90. if (OtherVal.isSignBitSet())
  91. return 1;
  92. else if (ThisVal.ugt(OtherVal))
  93. return 1;
  94. else if (ThisVal.ult(OtherVal))
  95. return -1;
  96. }
  97. return 0;
  98. }
  99. APFixedPoint APFixedPoint::getMax(const FixedPointSemantics &Sema) {
  100. bool IsUnsigned = !Sema.isSigned();
  101. auto Val = APSInt::getMaxValue(Sema.getWidth(), IsUnsigned);
  102. if (IsUnsigned && Sema.hasUnsignedPadding())
  103. Val = Val.lshr(1);
  104. return APFixedPoint(Val, Sema);
  105. }
  106. APFixedPoint APFixedPoint::getMin(const FixedPointSemantics &Sema) {
  107. auto Val = APSInt::getMinValue(Sema.getWidth(), !Sema.isSigned());
  108. return APFixedPoint(Val, Sema);
  109. }
  110. bool FixedPointSemantics::fitsInFloatSemantics(
  111. const fltSemantics &FloatSema) const {
  112. // A fixed point semantic fits in a floating point semantic if the maximum
  113. // and minimum values as integers of the fixed point semantic can fit in the
  114. // floating point semantic.
  115. // If these values do not fit, then a floating point rescaling of the true
  116. // maximum/minimum value will not fit either, so the floating point semantic
  117. // cannot be used to perform such a rescaling.
  118. APSInt MaxInt = APFixedPoint::getMax(*this).getValue();
  119. APFloat F(FloatSema);
  120. APFloat::opStatus Status = F.convertFromAPInt(MaxInt, MaxInt.isSigned(),
  121. APFloat::rmNearestTiesToAway);
  122. if ((Status & APFloat::opOverflow) || !isSigned())
  123. return !(Status & APFloat::opOverflow);
  124. APSInt MinInt = APFixedPoint::getMin(*this).getValue();
  125. Status = F.convertFromAPInt(MinInt, MinInt.isSigned(),
  126. APFloat::rmNearestTiesToAway);
  127. return !(Status & APFloat::opOverflow);
  128. }
  129. FixedPointSemantics FixedPointSemantics::getCommonSemantics(
  130. const FixedPointSemantics &Other) const {
  131. unsigned CommonScale = std::max(getScale(), Other.getScale());
  132. unsigned CommonWidth =
  133. std::max(getIntegralBits(), Other.getIntegralBits()) + CommonScale;
  134. bool ResultIsSigned = isSigned() || Other.isSigned();
  135. bool ResultIsSaturated = isSaturated() || Other.isSaturated();
  136. bool ResultHasUnsignedPadding = false;
  137. if (!ResultIsSigned) {
  138. // Both are unsigned.
  139. ResultHasUnsignedPadding = hasUnsignedPadding() &&
  140. Other.hasUnsignedPadding() && !ResultIsSaturated;
  141. }
  142. // If the result is signed, add an extra bit for the sign. Otherwise, if it is
  143. // unsigned and has unsigned padding, we only need to add the extra padding
  144. // bit back if we are not saturating.
  145. if (ResultIsSigned || ResultHasUnsignedPadding)
  146. CommonWidth++;
  147. return FixedPointSemantics(CommonWidth, CommonScale, ResultIsSigned,
  148. ResultIsSaturated, ResultHasUnsignedPadding);
  149. }
  150. APFixedPoint APFixedPoint::add(const APFixedPoint &Other,
  151. bool *Overflow) const {
  152. auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics());
  153. APFixedPoint ConvertedThis = convert(CommonFXSema);
  154. APFixedPoint ConvertedOther = Other.convert(CommonFXSema);
  155. APSInt ThisVal = ConvertedThis.getValue();
  156. APSInt OtherVal = ConvertedOther.getValue();
  157. bool Overflowed = false;
  158. APSInt Result;
  159. if (CommonFXSema.isSaturated()) {
  160. Result = CommonFXSema.isSigned() ? ThisVal.sadd_sat(OtherVal)
  161. : ThisVal.uadd_sat(OtherVal);
  162. } else {
  163. Result = ThisVal.isSigned() ? ThisVal.sadd_ov(OtherVal, Overflowed)
  164. : ThisVal.uadd_ov(OtherVal, Overflowed);
  165. }
  166. if (Overflow)
  167. *Overflow = Overflowed;
  168. return APFixedPoint(Result, CommonFXSema);
  169. }
  170. APFixedPoint APFixedPoint::sub(const APFixedPoint &Other,
  171. bool *Overflow) const {
  172. auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics());
  173. APFixedPoint ConvertedThis = convert(CommonFXSema);
  174. APFixedPoint ConvertedOther = Other.convert(CommonFXSema);
  175. APSInt ThisVal = ConvertedThis.getValue();
  176. APSInt OtherVal = ConvertedOther.getValue();
  177. bool Overflowed = false;
  178. APSInt Result;
  179. if (CommonFXSema.isSaturated()) {
  180. Result = CommonFXSema.isSigned() ? ThisVal.ssub_sat(OtherVal)
  181. : ThisVal.usub_sat(OtherVal);
  182. } else {
  183. Result = ThisVal.isSigned() ? ThisVal.ssub_ov(OtherVal, Overflowed)
  184. : ThisVal.usub_ov(OtherVal, Overflowed);
  185. }
  186. if (Overflow)
  187. *Overflow = Overflowed;
  188. return APFixedPoint(Result, CommonFXSema);
  189. }
  190. APFixedPoint APFixedPoint::mul(const APFixedPoint &Other,
  191. bool *Overflow) const {
  192. auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics());
  193. APFixedPoint ConvertedThis = convert(CommonFXSema);
  194. APFixedPoint ConvertedOther = Other.convert(CommonFXSema);
  195. APSInt ThisVal = ConvertedThis.getValue();
  196. APSInt OtherVal = ConvertedOther.getValue();
  197. bool Overflowed = false;
  198. // Widen the LHS and RHS so we can perform a full multiplication.
  199. unsigned Wide = CommonFXSema.getWidth() * 2;
  200. if (CommonFXSema.isSigned()) {
  201. ThisVal = ThisVal.sextOrSelf(Wide);
  202. OtherVal = OtherVal.sextOrSelf(Wide);
  203. } else {
  204. ThisVal = ThisVal.zextOrSelf(Wide);
  205. OtherVal = OtherVal.zextOrSelf(Wide);
  206. }
  207. // Perform the full multiplication and downscale to get the same scale.
  208. //
  209. // Note that the right shifts here perform an implicit downwards rounding.
  210. // This rounding could discard bits that would technically place the result
  211. // outside the representable range. We interpret the spec as allowing us to
  212. // perform the rounding step first, avoiding the overflow case that would
  213. // arise.
  214. APSInt Result;
  215. if (CommonFXSema.isSigned())
  216. Result = ThisVal.smul_ov(OtherVal, Overflowed)
  217. .ashr(CommonFXSema.getScale());
  218. else
  219. Result = ThisVal.umul_ov(OtherVal, Overflowed)
  220. .lshr(CommonFXSema.getScale());
  221. assert(!Overflowed && "Full multiplication cannot overflow!");
  222. Result.setIsSigned(CommonFXSema.isSigned());
  223. // If our result lies outside of the representative range of the common
  224. // semantic, we either have overflow or saturation.
  225. APSInt Max = APFixedPoint::getMax(CommonFXSema).getValue()
  226. .extOrTrunc(Wide);
  227. APSInt Min = APFixedPoint::getMin(CommonFXSema).getValue()
  228. .extOrTrunc(Wide);
  229. if (CommonFXSema.isSaturated()) {
  230. if (Result < Min)
  231. Result = Min;
  232. else if (Result > Max)
  233. Result = Max;
  234. } else
  235. Overflowed = Result < Min || Result > Max;
  236. if (Overflow)
  237. *Overflow = Overflowed;
  238. return APFixedPoint(Result.sextOrTrunc(CommonFXSema.getWidth()),
  239. CommonFXSema);
  240. }
  241. APFixedPoint APFixedPoint::div(const APFixedPoint &Other,
  242. bool *Overflow) const {
  243. auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics());
  244. APFixedPoint ConvertedThis = convert(CommonFXSema);
  245. APFixedPoint ConvertedOther = Other.convert(CommonFXSema);
  246. APSInt ThisVal = ConvertedThis.getValue();
  247. APSInt OtherVal = ConvertedOther.getValue();
  248. bool Overflowed = false;
  249. // Widen the LHS and RHS so we can perform a full division.
  250. unsigned Wide = CommonFXSema.getWidth() * 2;
  251. if (CommonFXSema.isSigned()) {
  252. ThisVal = ThisVal.sextOrSelf(Wide);
  253. OtherVal = OtherVal.sextOrSelf(Wide);
  254. } else {
  255. ThisVal = ThisVal.zextOrSelf(Wide);
  256. OtherVal = OtherVal.zextOrSelf(Wide);
  257. }
  258. // Upscale to compensate for the loss of precision from division, and
  259. // perform the full division.
  260. ThisVal = ThisVal.shl(CommonFXSema.getScale());
  261. APSInt Result;
  262. if (CommonFXSema.isSigned()) {
  263. APInt Rem;
  264. APInt::sdivrem(ThisVal, OtherVal, Result, Rem);
  265. // If the quotient is negative and the remainder is nonzero, round
  266. // towards negative infinity by subtracting epsilon from the result.
  267. if (ThisVal.isNegative() != OtherVal.isNegative() && !Rem.isZero())
  268. Result = Result - 1;
  269. } else
  270. Result = ThisVal.udiv(OtherVal);
  271. Result.setIsSigned(CommonFXSema.isSigned());
  272. // If our result lies outside of the representative range of the common
  273. // semantic, we either have overflow or saturation.
  274. APSInt Max = APFixedPoint::getMax(CommonFXSema).getValue()
  275. .extOrTrunc(Wide);
  276. APSInt Min = APFixedPoint::getMin(CommonFXSema).getValue()
  277. .extOrTrunc(Wide);
  278. if (CommonFXSema.isSaturated()) {
  279. if (Result < Min)
  280. Result = Min;
  281. else if (Result > Max)
  282. Result = Max;
  283. } else
  284. Overflowed = Result < Min || Result > Max;
  285. if (Overflow)
  286. *Overflow = Overflowed;
  287. return APFixedPoint(Result.sextOrTrunc(CommonFXSema.getWidth()),
  288. CommonFXSema);
  289. }
  290. APFixedPoint APFixedPoint::shl(unsigned Amt, bool *Overflow) const {
  291. APSInt ThisVal = Val;
  292. bool Overflowed = false;
  293. // Widen the LHS.
  294. unsigned Wide = Sema.getWidth() * 2;
  295. if (Sema.isSigned())
  296. ThisVal = ThisVal.sextOrSelf(Wide);
  297. else
  298. ThisVal = ThisVal.zextOrSelf(Wide);
  299. // Clamp the shift amount at the original width, and perform the shift.
  300. Amt = std::min(Amt, ThisVal.getBitWidth());
  301. APSInt Result = ThisVal << Amt;
  302. Result.setIsSigned(Sema.isSigned());
  303. // If our result lies outside of the representative range of the
  304. // semantic, we either have overflow or saturation.
  305. APSInt Max = APFixedPoint::getMax(Sema).getValue().extOrTrunc(Wide);
  306. APSInt Min = APFixedPoint::getMin(Sema).getValue().extOrTrunc(Wide);
  307. if (Sema.isSaturated()) {
  308. if (Result < Min)
  309. Result = Min;
  310. else if (Result > Max)
  311. Result = Max;
  312. } else
  313. Overflowed = Result < Min || Result > Max;
  314. if (Overflow)
  315. *Overflow = Overflowed;
  316. return APFixedPoint(Result.sextOrTrunc(Sema.getWidth()), Sema);
  317. }
  318. void APFixedPoint::toString(SmallVectorImpl<char> &Str) const {
  319. APSInt Val = getValue();
  320. unsigned Scale = getScale();
  321. if (Val.isSigned() && Val.isNegative() && Val != -Val) {
  322. Val = -Val;
  323. Str.push_back('-');
  324. }
  325. APSInt IntPart = Val >> Scale;
  326. // Add 4 digits to hold the value after multiplying 10 (the radix)
  327. unsigned Width = Val.getBitWidth() + 4;
  328. APInt FractPart = Val.zextOrTrunc(Scale).zext(Width);
  329. APInt FractPartMask = APInt::getAllOnes(Scale).zext(Width);
  330. APInt RadixInt = APInt(Width, 10);
  331. IntPart.toString(Str, /*Radix=*/10);
  332. Str.push_back('.');
  333. do {
  334. (FractPart * RadixInt)
  335. .lshr(Scale)
  336. .toString(Str, /*Radix=*/10, Val.isSigned());
  337. FractPart = (FractPart * RadixInt) & FractPartMask;
  338. } while (FractPart != 0);
  339. }
  340. APFixedPoint APFixedPoint::negate(bool *Overflow) const {
  341. if (!isSaturated()) {
  342. if (Overflow)
  343. *Overflow =
  344. (!isSigned() && Val != 0) || (isSigned() && Val.isMinSignedValue());
  345. return APFixedPoint(-Val, Sema);
  346. }
  347. // We never overflow for saturation
  348. if (Overflow)
  349. *Overflow = false;
  350. if (isSigned())
  351. return Val.isMinSignedValue() ? getMax(Sema) : APFixedPoint(-Val, Sema);
  352. else
  353. return APFixedPoint(Sema);
  354. }
  355. APSInt APFixedPoint::convertToInt(unsigned DstWidth, bool DstSign,
  356. bool *Overflow) const {
  357. APSInt Result = getIntPart();
  358. unsigned SrcWidth = getWidth();
  359. APSInt DstMin = APSInt::getMinValue(DstWidth, !DstSign);
  360. APSInt DstMax = APSInt::getMaxValue(DstWidth, !DstSign);
  361. if (SrcWidth < DstWidth) {
  362. Result = Result.extend(DstWidth);
  363. } else if (SrcWidth > DstWidth) {
  364. DstMin = DstMin.extend(SrcWidth);
  365. DstMax = DstMax.extend(SrcWidth);
  366. }
  367. if (Overflow) {
  368. if (Result.isSigned() && !DstSign) {
  369. *Overflow = Result.isNegative() || Result.ugt(DstMax);
  370. } else if (Result.isUnsigned() && DstSign) {
  371. *Overflow = Result.ugt(DstMax);
  372. } else {
  373. *Overflow = Result < DstMin || Result > DstMax;
  374. }
  375. }
  376. Result.setIsSigned(DstSign);
  377. return Result.extOrTrunc(DstWidth);
  378. }
  379. const fltSemantics *APFixedPoint::promoteFloatSemantics(const fltSemantics *S) {
  380. if (S == &APFloat::BFloat())
  381. return &APFloat::IEEEdouble();
  382. else if (S == &APFloat::IEEEhalf())
  383. return &APFloat::IEEEsingle();
  384. else if (S == &APFloat::IEEEsingle())
  385. return &APFloat::IEEEdouble();
  386. else if (S == &APFloat::IEEEdouble())
  387. return &APFloat::IEEEquad();
  388. llvm_unreachable("Could not promote float type!");
  389. }
  390. APFloat APFixedPoint::convertToFloat(const fltSemantics &FloatSema) const {
  391. // For some operations, rounding mode has an effect on the result, while
  392. // other operations are lossless and should never result in rounding.
  393. // To signify which these operations are, we define two rounding modes here.
  394. APFloat::roundingMode RM = APFloat::rmNearestTiesToEven;
  395. APFloat::roundingMode LosslessRM = APFloat::rmTowardZero;
  396. // Make sure that we are operating in a type that works with this fixed-point
  397. // semantic.
  398. const fltSemantics *OpSema = &FloatSema;
  399. while (!Sema.fitsInFloatSemantics(*OpSema))
  400. OpSema = promoteFloatSemantics(OpSema);
  401. // Convert the fixed point value bits as an integer. If the floating point
  402. // value does not have the required precision, we will round according to the
  403. // given mode.
  404. APFloat Flt(*OpSema);
  405. APFloat::opStatus S = Flt.convertFromAPInt(Val, Sema.isSigned(), RM);
  406. // If we cared about checking for precision loss, we could look at this
  407. // status.
  408. (void)S;
  409. // Scale down the integer value in the float to match the correct scaling
  410. // factor.
  411. APFloat ScaleFactor(std::pow(2, -(int)Sema.getScale()));
  412. bool Ignored;
  413. ScaleFactor.convert(*OpSema, LosslessRM, &Ignored);
  414. Flt.multiply(ScaleFactor, LosslessRM);
  415. if (OpSema != &FloatSema)
  416. Flt.convert(FloatSema, RM, &Ignored);
  417. return Flt;
  418. }
  419. APFixedPoint APFixedPoint::getFromIntValue(const APSInt &Value,
  420. const FixedPointSemantics &DstFXSema,
  421. bool *Overflow) {
  422. FixedPointSemantics IntFXSema = FixedPointSemantics::GetIntegerSemantics(
  423. Value.getBitWidth(), Value.isSigned());
  424. return APFixedPoint(Value, IntFXSema).convert(DstFXSema, Overflow);
  425. }
  426. APFixedPoint
  427. APFixedPoint::getFromFloatValue(const APFloat &Value,
  428. const FixedPointSemantics &DstFXSema,
  429. bool *Overflow) {
  430. // For some operations, rounding mode has an effect on the result, while
  431. // other operations are lossless and should never result in rounding.
  432. // To signify which these operations are, we define two rounding modes here,
  433. // even though they are the same mode.
  434. APFloat::roundingMode RM = APFloat::rmTowardZero;
  435. APFloat::roundingMode LosslessRM = APFloat::rmTowardZero;
  436. const fltSemantics &FloatSema = Value.getSemantics();
  437. if (Value.isNaN()) {
  438. // Handle NaN immediately.
  439. if (Overflow)
  440. *Overflow = true;
  441. return APFixedPoint(DstFXSema);
  442. }
  443. // Make sure that we are operating in a type that works with this fixed-point
  444. // semantic.
  445. const fltSemantics *OpSema = &FloatSema;
  446. while (!DstFXSema.fitsInFloatSemantics(*OpSema))
  447. OpSema = promoteFloatSemantics(OpSema);
  448. APFloat Val = Value;
  449. bool Ignored;
  450. if (&FloatSema != OpSema)
  451. Val.convert(*OpSema, LosslessRM, &Ignored);
  452. // Scale up the float so that the 'fractional' part of the mantissa ends up in
  453. // the integer range instead. Rounding mode is irrelevant here.
  454. // It is fine if this overflows to infinity even for saturating types,
  455. // since we will use floating point comparisons to check for saturation.
  456. APFloat ScaleFactor(std::pow(2, DstFXSema.getScale()));
  457. ScaleFactor.convert(*OpSema, LosslessRM, &Ignored);
  458. Val.multiply(ScaleFactor, LosslessRM);
  459. // Convert to the integral representation of the value. This rounding mode
  460. // is significant.
  461. APSInt Res(DstFXSema.getWidth(), !DstFXSema.isSigned());
  462. Val.convertToInteger(Res, RM, &Ignored);
  463. // Round the integral value and scale back. This makes the
  464. // overflow calculations below work properly. If we do not round here,
  465. // we risk checking for overflow with a value that is outside the
  466. // representable range of the fixed-point semantic even though no overflow
  467. // would occur had we rounded first.
  468. ScaleFactor = APFloat(std::pow(2, -(int)DstFXSema.getScale()));
  469. ScaleFactor.convert(*OpSema, LosslessRM, &Ignored);
  470. Val.roundToIntegral(RM);
  471. Val.multiply(ScaleFactor, LosslessRM);
  472. // Check for overflow/saturation by checking if the floating point value
  473. // is outside the range representable by the fixed-point value.
  474. APFloat FloatMax = getMax(DstFXSema).convertToFloat(*OpSema);
  475. APFloat FloatMin = getMin(DstFXSema).convertToFloat(*OpSema);
  476. bool Overflowed = false;
  477. if (DstFXSema.isSaturated()) {
  478. if (Val > FloatMax)
  479. Res = getMax(DstFXSema).getValue();
  480. else if (Val < FloatMin)
  481. Res = getMin(DstFXSema).getValue();
  482. } else
  483. Overflowed = Val > FloatMax || Val < FloatMin;
  484. if (Overflow)
  485. *Overflow = Overflowed;
  486. return APFixedPoint(Res, DstFXSema);
  487. }
  488. } // namespace llvm