brintos

brintos / llvm-project-archived public Read only

0
0
Text · 21.4 KiB · e8f0e78 Raw
630 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9/// \file10/// Defines the implementation for the fixed point number interface.11//12//===----------------------------------------------------------------------===//13 14#include "llvm/ADT/APFixedPoint.h"15#include "llvm/ADT/APFloat.h"16 17#include <cmath>18 19namespace llvm {20 21void FixedPointSemantics::print(llvm::raw_ostream &OS) const {22  OS << "width=" << getWidth() << ", ";23  if (isValidLegacySema())24    OS << "scale=" << getScale() << ", ";25  OS << "msb=" << getMsbWeight() << ", ";26  OS << "lsb=" << getLsbWeight() << ", ";27  OS << "IsSigned=" << IsSigned << ", ";28  OS << "HasUnsignedPadding=" << HasUnsignedPadding << ", ";29  OS << "IsSaturated=" << IsSaturated;30}31 32uint32_t FixedPointSemantics::toOpaqueInt() const {33  return llvm::bit_cast<uint32_t>(*this);34}35 36FixedPointSemantics FixedPointSemantics::getFromOpaqueInt(uint32_t I) {37  FixedPointSemantics F(0, 0, false, false, false);38  std::memcpy(&F, &I, sizeof(F));39  return F;40}41 42APFixedPoint APFixedPoint::convert(const FixedPointSemantics &DstSema,43                                   bool *Overflow) const {44  APSInt NewVal = Val;45  int RelativeUpscale = getLsbWeight() - DstSema.getLsbWeight();46  if (Overflow)47    *Overflow = false;48 49  if (RelativeUpscale > 0)50    NewVal = NewVal.extend(NewVal.getBitWidth() + RelativeUpscale);51  NewVal = NewVal.relativeShl(RelativeUpscale);52 53  auto Mask = APInt::getBitsSetFrom(54      NewVal.getBitWidth(),55      std::min(DstSema.getIntegralBits() - DstSema.getLsbWeight(),56               NewVal.getBitWidth()));57  APInt Masked(NewVal & Mask);58 59  // Change in the bits above the sign60  if (!(Masked == Mask || Masked == 0)) {61    // Found overflow in the bits above the sign62    if (DstSema.isSaturated())63      NewVal = NewVal.isNegative() ? Mask : ~Mask;64    else if (Overflow)65      *Overflow = true;66  }67 68  // If the dst semantics are unsigned, but our value is signed and negative, we69  // clamp to zero.70  if (!DstSema.isSigned() && NewVal.isSigned() && NewVal.isNegative()) {71    // Found negative overflow for unsigned result72    if (DstSema.isSaturated())73      NewVal = 0;74    else if (Overflow)75      *Overflow = true;76  }77 78  NewVal = NewVal.extOrTrunc(DstSema.getWidth());79  NewVal.setIsSigned(DstSema.isSigned());80  return APFixedPoint(NewVal, DstSema);81}82 83int APFixedPoint::compare(const APFixedPoint &Other) const {84  APSInt ThisVal = getValue();85  APSInt OtherVal = Other.getValue();86  bool ThisSigned = Val.isSigned();87  bool OtherSigned = OtherVal.isSigned();88 89  int CommonLsb = std::min(getLsbWeight(), Other.getLsbWeight());90  int CommonMsb = std::max(getMsbWeight(), Other.getMsbWeight());91  unsigned CommonWidth = CommonMsb - CommonLsb + 1;92 93  ThisVal = ThisVal.extOrTrunc(CommonWidth);94  OtherVal = OtherVal.extOrTrunc(CommonWidth);95 96  ThisVal = ThisVal.shl(getLsbWeight() - CommonLsb);97  OtherVal = OtherVal.shl(Other.getLsbWeight() - CommonLsb);98 99  if (ThisSigned && OtherSigned) {100    if (ThisVal.sgt(OtherVal))101      return 1;102    else if (ThisVal.slt(OtherVal))103      return -1;104  } else if (!ThisSigned && !OtherSigned) {105    if (ThisVal.ugt(OtherVal))106      return 1;107    else if (ThisVal.ult(OtherVal))108      return -1;109  } else if (ThisSigned && !OtherSigned) {110    if (ThisVal.isSignBitSet())111      return -1;112    else if (ThisVal.ugt(OtherVal))113      return 1;114    else if (ThisVal.ult(OtherVal))115      return -1;116  } else {117    // !ThisSigned && OtherSigned118    if (OtherVal.isSignBitSet())119      return 1;120    else if (ThisVal.ugt(OtherVal))121      return 1;122    else if (ThisVal.ult(OtherVal))123      return -1;124  }125 126  return 0;127}128 129APFixedPoint APFixedPoint::getMax(const FixedPointSemantics &Sema) {130  bool IsUnsigned = !Sema.isSigned();131  auto Val = APSInt::getMaxValue(Sema.getWidth(), IsUnsigned);132  if (IsUnsigned && Sema.hasUnsignedPadding())133    Val = Val.lshr(1);134  return APFixedPoint(Val, Sema);135}136 137APFixedPoint APFixedPoint::getMin(const FixedPointSemantics &Sema) {138  auto Val = APSInt::getMinValue(Sema.getWidth(), !Sema.isSigned());139  return APFixedPoint(Val, Sema);140}141 142APFixedPoint APFixedPoint::getEpsilon(const FixedPointSemantics &Sema) {143  APSInt Val(Sema.getWidth(), !Sema.isSigned());144  Val.setBit(/*BitPosition=*/0);145  return APFixedPoint(Val, Sema);146}147 148bool FixedPointSemantics::fitsInFloatSemantics(149    const fltSemantics &FloatSema) const {150  // A fixed point semantic fits in a floating point semantic if the maximum151  // and minimum values as integers of the fixed point semantic can fit in the152  // floating point semantic.153 154  // If these values do not fit, then a floating point rescaling of the true155  // maximum/minimum value will not fit either, so the floating point semantic156  // cannot be used to perform such a rescaling.157 158  APSInt MaxInt = APFixedPoint::getMax(*this).getValue();159  APFloat F(FloatSema);160  APFloat::opStatus Status = F.convertFromAPInt(MaxInt, MaxInt.isSigned(),161                                                APFloat::rmNearestTiesToAway);162  if ((Status & APFloat::opOverflow) || !isSigned())163    return !(Status & APFloat::opOverflow);164 165  APSInt MinInt = APFixedPoint::getMin(*this).getValue();166  Status = F.convertFromAPInt(MinInt, MinInt.isSigned(),167                              APFloat::rmNearestTiesToAway);168  return !(Status & APFloat::opOverflow);169}170 171FixedPointSemantics FixedPointSemantics::getCommonSemantics(172    const FixedPointSemantics &Other) const {173  int CommonLsb = std::min(getLsbWeight(), Other.getLsbWeight());174  int CommonMSb = std::max(getMsbWeight() - hasSignOrPaddingBit(),175                           Other.getMsbWeight() - Other.hasSignOrPaddingBit());176  unsigned CommonWidth = CommonMSb - CommonLsb + 1;177 178  bool ResultIsSigned = isSigned() || Other.isSigned();179  bool ResultIsSaturated = isSaturated() || Other.isSaturated();180  bool ResultHasUnsignedPadding = false;181  if (!ResultIsSigned) {182    // Both are unsigned.183    ResultHasUnsignedPadding = hasUnsignedPadding() &&184                               Other.hasUnsignedPadding() && !ResultIsSaturated;185  }186 187  // If the result is signed, add an extra bit for the sign. Otherwise, if it is188  // unsigned and has unsigned padding, we only need to add the extra padding189  // bit back if we are not saturating.190  if (ResultIsSigned || ResultHasUnsignedPadding)191    CommonWidth++;192 193  return FixedPointSemantics(CommonWidth, Lsb{CommonLsb}, ResultIsSigned,194                             ResultIsSaturated, ResultHasUnsignedPadding);195}196 197APFixedPoint APFixedPoint::add(const APFixedPoint &Other,198                               bool *Overflow) const {199  auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics());200  APFixedPoint ConvertedThis = convert(CommonFXSema);201  APFixedPoint ConvertedOther = Other.convert(CommonFXSema);202  APSInt ThisVal = ConvertedThis.getValue();203  APSInt OtherVal = ConvertedOther.getValue();204  bool Overflowed = false;205 206  APSInt Result;207  if (CommonFXSema.isSaturated()) {208    Result = CommonFXSema.isSigned() ? ThisVal.sadd_sat(OtherVal)209                                     : ThisVal.uadd_sat(OtherVal);210  } else {211    Result = ThisVal.isSigned() ? ThisVal.sadd_ov(OtherVal, Overflowed)212                                : ThisVal.uadd_ov(OtherVal, Overflowed);213  }214 215  if (Overflow)216    *Overflow = Overflowed;217 218  return APFixedPoint(Result, CommonFXSema);219}220 221APFixedPoint APFixedPoint::sub(const APFixedPoint &Other,222                               bool *Overflow) const {223  auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics());224  APFixedPoint ConvertedThis = convert(CommonFXSema);225  APFixedPoint ConvertedOther = Other.convert(CommonFXSema);226  APSInt ThisVal = ConvertedThis.getValue();227  APSInt OtherVal = ConvertedOther.getValue();228  bool Overflowed = false;229 230  APSInt Result;231  if (CommonFXSema.isSaturated()) {232    Result = CommonFXSema.isSigned() ? ThisVal.ssub_sat(OtherVal)233                                     : ThisVal.usub_sat(OtherVal);234  } else {235    Result = ThisVal.isSigned() ? ThisVal.ssub_ov(OtherVal, Overflowed)236                                : ThisVal.usub_ov(OtherVal, Overflowed);237  }238 239  if (Overflow)240    *Overflow = Overflowed;241 242  return APFixedPoint(Result, CommonFXSema);243}244 245APFixedPoint APFixedPoint::mul(const APFixedPoint &Other,246                               bool *Overflow) const {247  auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics());248  APFixedPoint ConvertedThis = convert(CommonFXSema);249  APFixedPoint ConvertedOther = Other.convert(CommonFXSema);250  APSInt ThisVal = ConvertedThis.getValue();251  APSInt OtherVal = ConvertedOther.getValue();252  bool Overflowed = false;253 254  // Widen the LHS and RHS so we can perform a full multiplication.255  unsigned Wide = CommonFXSema.getWidth() * 2;256  if (CommonFXSema.isSigned()) {257    ThisVal = ThisVal.sext(Wide);258    OtherVal = OtherVal.sext(Wide);259  } else {260    ThisVal = ThisVal.zext(Wide);261    OtherVal = OtherVal.zext(Wide);262  }263 264  // Perform the full multiplication and downscale to get the same scale.265  //266  // Note that the right shifts here perform an implicit downwards rounding.267  // This rounding could discard bits that would technically place the result268  // outside the representable range. We interpret the spec as allowing us to269  // perform the rounding step first, avoiding the overflow case that would270  // arise.271  APSInt Result;272  if (CommonFXSema.isSigned())273    Result = ThisVal.smul_ov(OtherVal, Overflowed)274                 .relativeAShl(CommonFXSema.getLsbWeight());275  else276    Result = ThisVal.umul_ov(OtherVal, Overflowed)277                 .relativeLShl(CommonFXSema.getLsbWeight());278  assert(!Overflowed && "Full multiplication cannot overflow!");279  Result.setIsSigned(CommonFXSema.isSigned());280 281  // If our result lies outside of the representative range of the common282  // semantic, we either have overflow or saturation.283  APSInt Max = APFixedPoint::getMax(CommonFXSema).getValue()284                                                 .extOrTrunc(Wide);285  APSInt Min = APFixedPoint::getMin(CommonFXSema).getValue()286                                                 .extOrTrunc(Wide);287  if (CommonFXSema.isSaturated()) {288    if (Result < Min)289      Result = Min;290    else if (Result > Max)291      Result = Max;292  } else {293    Overflowed = Result < Min || Result > Max;294  }295 296  if (Overflow)297    *Overflow = Overflowed;298 299  return APFixedPoint(Result.sextOrTrunc(CommonFXSema.getWidth()),300                      CommonFXSema);301}302 303APFixedPoint APFixedPoint::div(const APFixedPoint &Other,304                               bool *Overflow) const {305  auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics());306  APFixedPoint ConvertedThis = convert(CommonFXSema);307  APFixedPoint ConvertedOther = Other.convert(CommonFXSema);308  APSInt ThisVal = ConvertedThis.getValue();309  APSInt OtherVal = ConvertedOther.getValue();310  bool Overflowed = false;311 312  // Widen the LHS and RHS so we can perform a full division.313  // Also make sure that there will be enough space for the shift below to not314  // overflow315  unsigned Wide =316      CommonFXSema.getWidth() * 2 + std::max(-CommonFXSema.getMsbWeight(), 0);317  if (CommonFXSema.isSigned()) {318    ThisVal = ThisVal.sext(Wide);319    OtherVal = OtherVal.sext(Wide);320  } else {321    ThisVal = ThisVal.zext(Wide);322    OtherVal = OtherVal.zext(Wide);323  }324 325  // Upscale to compensate for the loss of precision from division, and326  // perform the full division.327  if (CommonFXSema.getLsbWeight() < 0)328    ThisVal = ThisVal.shl(-CommonFXSema.getLsbWeight());329  else if (CommonFXSema.getLsbWeight() > 0)330    OtherVal = OtherVal.shl(CommonFXSema.getLsbWeight());331  APSInt Result;332  if (CommonFXSema.isSigned()) {333    APInt Rem;334    APInt::sdivrem(ThisVal, OtherVal, Result, Rem);335    // If the quotient is negative and the remainder is nonzero, round336    // towards negative infinity by subtracting epsilon from the result.337    if (ThisVal.isNegative() != OtherVal.isNegative() && !Rem.isZero())338      Result = Result - 1;339  } else {340    Result = ThisVal.udiv(OtherVal);341  }342  Result.setIsSigned(CommonFXSema.isSigned());343 344  // If our result lies outside of the representative range of the common345  // semantic, we either have overflow or saturation.346  APSInt Max = APFixedPoint::getMax(CommonFXSema).getValue()347                                                 .extOrTrunc(Wide);348  APSInt Min = APFixedPoint::getMin(CommonFXSema).getValue()349                                                 .extOrTrunc(Wide);350  if (CommonFXSema.isSaturated()) {351    if (Result < Min)352      Result = Min;353    else if (Result > Max)354      Result = Max;355  } else {356    Overflowed = Result < Min || Result > Max;357  }358 359  if (Overflow)360    *Overflow = Overflowed;361 362  return APFixedPoint(Result.sextOrTrunc(CommonFXSema.getWidth()),363                      CommonFXSema);364}365 366APFixedPoint APFixedPoint::shl(unsigned Amt, bool *Overflow) const {367  APSInt ThisVal = Val;368  bool Overflowed = false;369 370  // Widen the LHS.371  unsigned Wide = Sema.getWidth() * 2;372  if (Sema.isSigned())373    ThisVal = ThisVal.sext(Wide);374  else375    ThisVal = ThisVal.zext(Wide);376 377  // Clamp the shift amount at the original width, and perform the shift.378  Amt = std::min(Amt, ThisVal.getBitWidth());379  APSInt Result = ThisVal << Amt;380  Result.setIsSigned(Sema.isSigned());381 382  // If our result lies outside of the representative range of the383  // semantic, we either have overflow or saturation.384  APSInt Max = APFixedPoint::getMax(Sema).getValue().extOrTrunc(Wide);385  APSInt Min = APFixedPoint::getMin(Sema).getValue().extOrTrunc(Wide);386  if (Sema.isSaturated()) {387    if (Result < Min)388      Result = Min;389    else if (Result > Max)390      Result = Max;391  } else {392    Overflowed = Result < Min || Result > Max;393  }394 395  if (Overflow)396    *Overflow = Overflowed;397 398  return APFixedPoint(Result.sextOrTrunc(Sema.getWidth()), Sema);399}400 401void APFixedPoint::toString(SmallVectorImpl<char> &Str) const {402  APSInt Val = getValue();403  int Lsb = getLsbWeight();404  int OrigWidth = getWidth();405 406  if (Lsb >= 0) {407    APSInt IntPart = Val;408    IntPart = IntPart.extend(IntPart.getBitWidth() + Lsb);409    IntPart <<= Lsb;410    IntPart.toString(Str, /*Radix=*/10);411    Str.push_back('.');412    Str.push_back('0');413    return;414  }415 416  if (Val.isSigned() && Val.isNegative()) {417    Val = -Val;418    Val.setIsUnsigned(true);419    Str.push_back('-');420  }421 422  int Scale = -getLsbWeight();423  APSInt IntPart = (OrigWidth > Scale) ? (Val >> Scale) : APSInt::get(0);424 425  // Add 4 digits to hold the value after multiplying 10 (the radix)426  unsigned Width = std::max(OrigWidth, Scale) + 4;427  APInt FractPart = Val.zextOrTrunc(Scale).zext(Width);428  APInt FractPartMask = APInt::getAllOnes(Scale).zext(Width);429  APInt RadixInt = APInt(Width, 10);430 431  IntPart.toString(Str, /*Radix=*/10);432  Str.push_back('.');433  do {434    (FractPart * RadixInt)435        .lshr(Scale)436        .toString(Str, /*Radix=*/10, Val.isSigned());437    FractPart = (FractPart * RadixInt) & FractPartMask;438  } while (FractPart != 0);439}440 441void APFixedPoint::print(raw_ostream &OS) const {442  OS << "APFixedPoint(" << toString() << ", {";443  Sema.print(OS);444  OS << "})";445}446 447#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)448LLVM_DUMP_METHOD void APFixedPoint::dump() const { print(llvm::errs()); }449#endif450 451APFixedPoint APFixedPoint::negate(bool *Overflow) const {452  if (!isSaturated()) {453    if (Overflow)454      *Overflow =455          (!isSigned() && Val != 0) || (isSigned() && Val.isMinSignedValue());456    return APFixedPoint(-Val, Sema);457  }458 459  // We never overflow for saturation460  if (Overflow)461    *Overflow = false;462 463  if (isSigned())464    return Val.isMinSignedValue() ? getMax(Sema) : APFixedPoint(-Val, Sema);465  else466    return APFixedPoint(Sema);467}468 469APSInt APFixedPoint::convertToInt(unsigned DstWidth, bool DstSign,470                                  bool *Overflow) const {471  APSInt Result = getIntPart();472  unsigned SrcWidth = getWidth();473 474  APSInt DstMin = APSInt::getMinValue(DstWidth, !DstSign);475  APSInt DstMax = APSInt::getMaxValue(DstWidth, !DstSign);476 477  if (SrcWidth < DstWidth) {478    Result = Result.extend(DstWidth);479  } else if (SrcWidth > DstWidth) {480    DstMin = DstMin.extend(SrcWidth);481    DstMax = DstMax.extend(SrcWidth);482  }483 484  if (Overflow) {485    if (Result.isSigned() && !DstSign) {486      *Overflow = Result.isNegative() || Result.ugt(DstMax);487    } else if (Result.isUnsigned() && DstSign) {488      *Overflow = Result.ugt(DstMax);489    } else {490      *Overflow = Result < DstMin || Result > DstMax;491    }492  }493 494  Result.setIsSigned(DstSign);495  return Result.extOrTrunc(DstWidth);496}497 498const fltSemantics *APFixedPoint::promoteFloatSemantics(const fltSemantics *S) {499  if (S == &APFloat::BFloat())500    return &APFloat::IEEEdouble();501  else if (S == &APFloat::IEEEhalf())502    return &APFloat::IEEEsingle();503  else if (S == &APFloat::IEEEsingle())504    return &APFloat::IEEEdouble();505  else if (S == &APFloat::IEEEdouble())506    return &APFloat::IEEEquad();507  llvm_unreachable("Could not promote float type!");508}509 510APFloat APFixedPoint::convertToFloat(const fltSemantics &FloatSema) const {511  // For some operations, rounding mode has an effect on the result, while512  // other operations are lossless and should never result in rounding.513  // To signify which these operations are, we define two rounding modes here.514  APFloat::roundingMode RM = APFloat::rmNearestTiesToEven;515  APFloat::roundingMode LosslessRM = APFloat::rmTowardZero;516 517  // Make sure that we are operating in a type that works with this fixed-point518  // semantic.519  const fltSemantics *OpSema = &FloatSema;520  while (!Sema.fitsInFloatSemantics(*OpSema))521    OpSema = promoteFloatSemantics(OpSema);522 523  // Convert the fixed point value bits as an integer. If the floating point524  // value does not have the required precision, we will round according to the525  // given mode.526  APFloat Flt(*OpSema);527  APFloat::opStatus S = Flt.convertFromAPInt(Val, Sema.isSigned(), RM);528 529  // If we cared about checking for precision loss, we could look at this530  // status.531  (void)S;532 533  // Scale down the integer value in the float to match the correct scaling534  // factor.535  APFloat ScaleFactor(std::pow(2, Sema.getLsbWeight()));536  bool Ignored;537  ScaleFactor.convert(*OpSema, LosslessRM, &Ignored);538  Flt.multiply(ScaleFactor, LosslessRM);539 540  if (OpSema != &FloatSema)541    Flt.convert(FloatSema, RM, &Ignored);542 543  return Flt;544}545 546APFixedPoint APFixedPoint::getFromIntValue(const APSInt &Value,547                                           const FixedPointSemantics &DstFXSema,548                                           bool *Overflow) {549  FixedPointSemantics IntFXSema = FixedPointSemantics::GetIntegerSemantics(550      Value.getBitWidth(), Value.isSigned());551  return APFixedPoint(Value, IntFXSema).convert(DstFXSema, Overflow);552}553 554APFixedPoint555APFixedPoint::getFromFloatValue(const APFloat &Value,556                                const FixedPointSemantics &DstFXSema,557                                bool *Overflow) {558  // For some operations, rounding mode has an effect on the result, while559  // other operations are lossless and should never result in rounding.560  // To signify which these operations are, we define two rounding modes here,561  // even though they are the same mode.562  APFloat::roundingMode RM = APFloat::rmTowardZero;563  APFloat::roundingMode LosslessRM = APFloat::rmTowardZero;564 565  const fltSemantics &FloatSema = Value.getSemantics();566 567  if (Value.isNaN()) {568    // Handle NaN immediately.569    if (Overflow)570      *Overflow = true;571    return APFixedPoint(DstFXSema);572  }573 574  // Make sure that we are operating in a type that works with this fixed-point575  // semantic.576  const fltSemantics *OpSema = &FloatSema;577  while (!DstFXSema.fitsInFloatSemantics(*OpSema))578    OpSema = promoteFloatSemantics(OpSema);579 580  APFloat Val = Value;581 582  bool Ignored;583  if (&FloatSema != OpSema)584    Val.convert(*OpSema, LosslessRM, &Ignored);585 586  // Scale up the float so that the 'fractional' part of the mantissa ends up in587  // the integer range instead. Rounding mode is irrelevant here.588  // It is fine if this overflows to infinity even for saturating types,589  // since we will use floating point comparisons to check for saturation.590  APFloat ScaleFactor(std::pow(2, -DstFXSema.getLsbWeight()));591  ScaleFactor.convert(*OpSema, LosslessRM, &Ignored);592  Val.multiply(ScaleFactor, LosslessRM);593 594  // Convert to the integral representation of the value. This rounding mode595  // is significant.596  APSInt Res(DstFXSema.getWidth(), !DstFXSema.isSigned());597  Val.convertToInteger(Res, RM, &Ignored);598 599  // Round the integral value and scale back. This makes the600  // overflow calculations below work properly. If we do not round here,601  // we risk checking for overflow with a value that is outside the602  // representable range of the fixed-point semantic even though no overflow603  // would occur had we rounded first.604  ScaleFactor = APFloat(std::pow(2, DstFXSema.getLsbWeight()));605  ScaleFactor.convert(*OpSema, LosslessRM, &Ignored);606  Val.roundToIntegral(RM);607  Val.multiply(ScaleFactor, LosslessRM);608 609  // Check for overflow/saturation by checking if the floating point value610  // is outside the range representable by the fixed-point value.611  APFloat FloatMax = getMax(DstFXSema).convertToFloat(*OpSema);612  APFloat FloatMin = getMin(DstFXSema).convertToFloat(*OpSema);613  bool Overflowed = false;614  if (DstFXSema.isSaturated()) {615    if (Val > FloatMax)616      Res = getMax(DstFXSema).getValue();617    else if (Val < FloatMin)618      Res = getMin(DstFXSema).getValue();619  } else {620    Overflowed = Val > FloatMax || Val < FloatMin;621  }622 623  if (Overflow)624    *Overflow = Overflowed;625 626  return APFixedPoint(Res, DstFXSema);627}628 629} // namespace llvm630