diff options
| author | vitalyisaev <[email protected]> | 2023-06-29 10:00:50 +0300 | 
|---|---|---|
| committer | vitalyisaev <[email protected]> | 2023-06-29 10:00:50 +0300 | 
| commit | 6ffe9e53658409f212834330e13564e4952558f6 (patch) | |
| tree | 85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/llvm16/lib/Support/APFixedPoint.cpp | |
| parent | 726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff) | |
YQ Connector: support managed ClickHouse
Со стороны dqrun можно обратиться к инстансу коннектора, который работает на streaming стенде, и извлечь данные из облачного CH.
Diffstat (limited to 'contrib/libs/llvm16/lib/Support/APFixedPoint.cpp')
| -rw-r--r-- | contrib/libs/llvm16/lib/Support/APFixedPoint.cpp | 605 | 
1 files changed, 605 insertions, 0 deletions
diff --git a/contrib/libs/llvm16/lib/Support/APFixedPoint.cpp b/contrib/libs/llvm16/lib/Support/APFixedPoint.cpp new file mode 100644 index 00000000000..3eea01bc980 --- /dev/null +++ b/contrib/libs/llvm16/lib/Support/APFixedPoint.cpp @@ -0,0 +1,605 @@ +//===- APFixedPoint.cpp - Fixed point constant handling ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +/// \file +/// Defines the implementation for the fixed point number interface. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/APFixedPoint.h" +#include "llvm/ADT/APFloat.h" + +#include <cmath> + +namespace llvm { + +void FixedPointSemantics::print(llvm::raw_ostream &OS) const { +  OS << "width=" << getWidth() << ", "; +  if (isValidLegacySema()) +    OS << "scale=" << getScale() << ", "; +  OS << "msb=" << getMsbWeight() << ", "; +  OS << "lsb=" << getLsbWeight() << ", "; +  OS << "IsSigned=" << IsSigned << ", "; +  OS << "HasUnsignedPadding=" << HasUnsignedPadding << ", "; +  OS << "IsSaturated=" << IsSaturated; +} + +APFixedPoint APFixedPoint::convert(const FixedPointSemantics &DstSema, +                                   bool *Overflow) const { +  APSInt NewVal = Val; +  int RelativeUpscale = getLsbWeight() - DstSema.getLsbWeight(); +  if (Overflow) +    *Overflow = false; + +  if (RelativeUpscale > 0) +    NewVal = NewVal.extend(NewVal.getBitWidth() + RelativeUpscale); +  NewVal = NewVal.relativeShl(RelativeUpscale); + +  auto Mask = APInt::getBitsSetFrom( +      NewVal.getBitWidth(), +      std::min(DstSema.getIntegralBits() - DstSema.getLsbWeight(), +               NewVal.getBitWidth())); +  APInt Masked(NewVal & Mask); + +  // Change in the bits above the sign +  if (!(Masked == Mask || Masked == 0)) { +    // Found overflow in the bits above the sign +    if (DstSema.isSaturated()) +      NewVal = NewVal.isNegative() ? Mask : ~Mask; +    else if (Overflow) +      *Overflow = true; +  } + +  // If the dst semantics are unsigned, but our value is signed and negative, we +  // clamp to zero. +  if (!DstSema.isSigned() && NewVal.isSigned() && NewVal.isNegative()) { +    // Found negative overflow for unsigned result +    if (DstSema.isSaturated()) +      NewVal = 0; +    else if (Overflow) +      *Overflow = true; +  } + +  NewVal = NewVal.extOrTrunc(DstSema.getWidth()); +  NewVal.setIsSigned(DstSema.isSigned()); +  return APFixedPoint(NewVal, DstSema); +} + +int APFixedPoint::compare(const APFixedPoint &Other) const { +  APSInt ThisVal = getValue(); +  APSInt OtherVal = Other.getValue(); +  bool ThisSigned = Val.isSigned(); +  bool OtherSigned = OtherVal.isSigned(); + +  int CommonLsb = std::min(getLsbWeight(), Other.getLsbWeight()); +  int CommonMsb = std::max(getMsbWeight(), Other.getMsbWeight()); +  unsigned CommonWidth = CommonMsb - CommonLsb + 1; + +  ThisVal = ThisVal.extOrTrunc(CommonWidth); +  OtherVal = OtherVal.extOrTrunc(CommonWidth); + +  ThisVal = ThisVal.shl(getLsbWeight() - CommonLsb); +  OtherVal = OtherVal.shl(Other.getLsbWeight() - CommonLsb); + +  if (ThisSigned && OtherSigned) { +    if (ThisVal.sgt(OtherVal)) +      return 1; +    else if (ThisVal.slt(OtherVal)) +      return -1; +  } else if (!ThisSigned && !OtherSigned) { +    if (ThisVal.ugt(OtherVal)) +      return 1; +    else if (ThisVal.ult(OtherVal)) +      return -1; +  } else if (ThisSigned && !OtherSigned) { +    if (ThisVal.isSignBitSet()) +      return -1; +    else if (ThisVal.ugt(OtherVal)) +      return 1; +    else if (ThisVal.ult(OtherVal)) +      return -1; +  } else { +    // !ThisSigned && OtherSigned +    if (OtherVal.isSignBitSet()) +      return 1; +    else if (ThisVal.ugt(OtherVal)) +      return 1; +    else if (ThisVal.ult(OtherVal)) +      return -1; +  } + +  return 0; +} + +APFixedPoint APFixedPoint::getMax(const FixedPointSemantics &Sema) { +  bool IsUnsigned = !Sema.isSigned(); +  auto Val = APSInt::getMaxValue(Sema.getWidth(), IsUnsigned); +  if (IsUnsigned && Sema.hasUnsignedPadding()) +    Val = Val.lshr(1); +  return APFixedPoint(Val, Sema); +} + +APFixedPoint APFixedPoint::getMin(const FixedPointSemantics &Sema) { +  auto Val = APSInt::getMinValue(Sema.getWidth(), !Sema.isSigned()); +  return APFixedPoint(Val, Sema); +} + +bool FixedPointSemantics::fitsInFloatSemantics( +    const fltSemantics &FloatSema) const { +  // A fixed point semantic fits in a floating point semantic if the maximum +  // and minimum values as integers of the fixed point semantic can fit in the +  // floating point semantic. + +  // If these values do not fit, then a floating point rescaling of the true +  // maximum/minimum value will not fit either, so the floating point semantic +  // cannot be used to perform such a rescaling. + +  APSInt MaxInt = APFixedPoint::getMax(*this).getValue(); +  APFloat F(FloatSema); +  APFloat::opStatus Status = F.convertFromAPInt(MaxInt, MaxInt.isSigned(), +                                                APFloat::rmNearestTiesToAway); +  if ((Status & APFloat::opOverflow) || !isSigned()) +    return !(Status & APFloat::opOverflow); + +  APSInt MinInt = APFixedPoint::getMin(*this).getValue(); +  Status = F.convertFromAPInt(MinInt, MinInt.isSigned(), +                              APFloat::rmNearestTiesToAway); +  return !(Status & APFloat::opOverflow); +} + +FixedPointSemantics FixedPointSemantics::getCommonSemantics( +    const FixedPointSemantics &Other) const { +  int CommonLsb = std::min(getLsbWeight(), Other.getLsbWeight()); +  int CommonMSb = std::max(getMsbWeight() - hasSignOrPaddingBit(), +                           Other.getMsbWeight() - Other.hasSignOrPaddingBit()); +  unsigned CommonWidth = CommonMSb - CommonLsb + 1; + +  bool ResultIsSigned = isSigned() || Other.isSigned(); +  bool ResultIsSaturated = isSaturated() || Other.isSaturated(); +  bool ResultHasUnsignedPadding = false; +  if (!ResultIsSigned) { +    // Both are unsigned. +    ResultHasUnsignedPadding = hasUnsignedPadding() && +                               Other.hasUnsignedPadding() && !ResultIsSaturated; +  } + +  // If the result is signed, add an extra bit for the sign. Otherwise, if it is +  // unsigned and has unsigned padding, we only need to add the extra padding +  // bit back if we are not saturating. +  if (ResultIsSigned || ResultHasUnsignedPadding) +    CommonWidth++; + +  return FixedPointSemantics(CommonWidth, Lsb{CommonLsb}, ResultIsSigned, +                             ResultIsSaturated, ResultHasUnsignedPadding); +} + +APFixedPoint APFixedPoint::add(const APFixedPoint &Other, +                               bool *Overflow) const { +  auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics()); +  APFixedPoint ConvertedThis = convert(CommonFXSema); +  APFixedPoint ConvertedOther = Other.convert(CommonFXSema); +  APSInt ThisVal = ConvertedThis.getValue(); +  APSInt OtherVal = ConvertedOther.getValue(); +  bool Overflowed = false; + +  APSInt Result; +  if (CommonFXSema.isSaturated()) { +    Result = CommonFXSema.isSigned() ? ThisVal.sadd_sat(OtherVal) +                                     : ThisVal.uadd_sat(OtherVal); +  } else { +    Result = ThisVal.isSigned() ? ThisVal.sadd_ov(OtherVal, Overflowed) +                                : ThisVal.uadd_ov(OtherVal, Overflowed); +  } + +  if (Overflow) +    *Overflow = Overflowed; + +  return APFixedPoint(Result, CommonFXSema); +} + +APFixedPoint APFixedPoint::sub(const APFixedPoint &Other, +                               bool *Overflow) const { +  auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics()); +  APFixedPoint ConvertedThis = convert(CommonFXSema); +  APFixedPoint ConvertedOther = Other.convert(CommonFXSema); +  APSInt ThisVal = ConvertedThis.getValue(); +  APSInt OtherVal = ConvertedOther.getValue(); +  bool Overflowed = false; + +  APSInt Result; +  if (CommonFXSema.isSaturated()) { +    Result = CommonFXSema.isSigned() ? ThisVal.ssub_sat(OtherVal) +                                     : ThisVal.usub_sat(OtherVal); +  } else { +    Result = ThisVal.isSigned() ? ThisVal.ssub_ov(OtherVal, Overflowed) +                                : ThisVal.usub_ov(OtherVal, Overflowed); +  } + +  if (Overflow) +    *Overflow = Overflowed; + +  return APFixedPoint(Result, CommonFXSema); +} + +APFixedPoint APFixedPoint::mul(const APFixedPoint &Other, +                               bool *Overflow) const { +  auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics()); +  APFixedPoint ConvertedThis = convert(CommonFXSema); +  APFixedPoint ConvertedOther = Other.convert(CommonFXSema); +  APSInt ThisVal = ConvertedThis.getValue(); +  APSInt OtherVal = ConvertedOther.getValue(); +  bool Overflowed = false; + +  // Widen the LHS and RHS so we can perform a full multiplication. +  unsigned Wide = CommonFXSema.getWidth() * 2; +  if (CommonFXSema.isSigned()) { +    ThisVal = ThisVal.sext(Wide); +    OtherVal = OtherVal.sext(Wide); +  } else { +    ThisVal = ThisVal.zext(Wide); +    OtherVal = OtherVal.zext(Wide); +  } + +  // Perform the full multiplication and downscale to get the same scale. +  // +  // Note that the right shifts here perform an implicit downwards rounding. +  // This rounding could discard bits that would technically place the result +  // outside the representable range. We interpret the spec as allowing us to +  // perform the rounding step first, avoiding the overflow case that would +  // arise. +  APSInt Result; +  if (CommonFXSema.isSigned()) +    Result = ThisVal.smul_ov(OtherVal, Overflowed) +                 .relativeAShl(CommonFXSema.getLsbWeight()); +  else +    Result = ThisVal.umul_ov(OtherVal, Overflowed) +                 .relativeLShl(CommonFXSema.getLsbWeight()); +  assert(!Overflowed && "Full multiplication cannot overflow!"); +  Result.setIsSigned(CommonFXSema.isSigned()); + +  // If our result lies outside of the representative range of the common +  // semantic, we either have overflow or saturation. +  APSInt Max = APFixedPoint::getMax(CommonFXSema).getValue() +                                                 .extOrTrunc(Wide); +  APSInt Min = APFixedPoint::getMin(CommonFXSema).getValue() +                                                 .extOrTrunc(Wide); +  if (CommonFXSema.isSaturated()) { +    if (Result < Min) +      Result = Min; +    else if (Result > Max) +      Result = Max; +  } else +    Overflowed = Result < Min || Result > Max; + +  if (Overflow) +    *Overflow = Overflowed; + +  return APFixedPoint(Result.sextOrTrunc(CommonFXSema.getWidth()), +                      CommonFXSema); +} + +APFixedPoint APFixedPoint::div(const APFixedPoint &Other, +                               bool *Overflow) const { +  auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics()); +  APFixedPoint ConvertedThis = convert(CommonFXSema); +  APFixedPoint ConvertedOther = Other.convert(CommonFXSema); +  APSInt ThisVal = ConvertedThis.getValue(); +  APSInt OtherVal = ConvertedOther.getValue(); +  bool Overflowed = false; + +  // Widen the LHS and RHS so we can perform a full division. +  // Also make sure that there will be enough space for the shift below to not +  // overflow +  unsigned Wide = +      CommonFXSema.getWidth() * 2 + std::max(-CommonFXSema.getMsbWeight(), 0); +  if (CommonFXSema.isSigned()) { +    ThisVal = ThisVal.sext(Wide); +    OtherVal = OtherVal.sext(Wide); +  } else { +    ThisVal = ThisVal.zext(Wide); +    OtherVal = OtherVal.zext(Wide); +  } + +  // Upscale to compensate for the loss of precision from division, and +  // perform the full division. +  if (CommonFXSema.getLsbWeight() < 0) +    ThisVal = ThisVal.shl(-CommonFXSema.getLsbWeight()); +  else if (CommonFXSema.getLsbWeight() > 0) +    OtherVal = OtherVal.shl(CommonFXSema.getLsbWeight()); +  APSInt Result; +  if (CommonFXSema.isSigned()) { +    APInt Rem; +    APInt::sdivrem(ThisVal, OtherVal, Result, Rem); +    // If the quotient is negative and the remainder is nonzero, round +    // towards negative infinity by subtracting epsilon from the result. +    if (ThisVal.isNegative() != OtherVal.isNegative() && !Rem.isZero()) +      Result = Result - 1; +  } else +    Result = ThisVal.udiv(OtherVal); +  Result.setIsSigned(CommonFXSema.isSigned()); + +  // If our result lies outside of the representative range of the common +  // semantic, we either have overflow or saturation. +  APSInt Max = APFixedPoint::getMax(CommonFXSema).getValue() +                                                 .extOrTrunc(Wide); +  APSInt Min = APFixedPoint::getMin(CommonFXSema).getValue() +                                                 .extOrTrunc(Wide); +  if (CommonFXSema.isSaturated()) { +    if (Result < Min) +      Result = Min; +    else if (Result > Max) +      Result = Max; +  } else +    Overflowed = Result < Min || Result > Max; + +  if (Overflow) +    *Overflow = Overflowed; + +  return APFixedPoint(Result.sextOrTrunc(CommonFXSema.getWidth()), +                      CommonFXSema); +} + +APFixedPoint APFixedPoint::shl(unsigned Amt, bool *Overflow) const { +  APSInt ThisVal = Val; +  bool Overflowed = false; + +  // Widen the LHS. +  unsigned Wide = Sema.getWidth() * 2; +  if (Sema.isSigned()) +    ThisVal = ThisVal.sext(Wide); +  else +    ThisVal = ThisVal.zext(Wide); + +  // Clamp the shift amount at the original width, and perform the shift. +  Amt = std::min(Amt, ThisVal.getBitWidth()); +  APSInt Result = ThisVal << Amt; +  Result.setIsSigned(Sema.isSigned()); + +  // If our result lies outside of the representative range of the +  // semantic, we either have overflow or saturation. +  APSInt Max = APFixedPoint::getMax(Sema).getValue().extOrTrunc(Wide); +  APSInt Min = APFixedPoint::getMin(Sema).getValue().extOrTrunc(Wide); +  if (Sema.isSaturated()) { +    if (Result < Min) +      Result = Min; +    else if (Result > Max) +      Result = Max; +  } else +    Overflowed = Result < Min || Result > Max; + +  if (Overflow) +    *Overflow = Overflowed; + +  return APFixedPoint(Result.sextOrTrunc(Sema.getWidth()), Sema); +} + +void APFixedPoint::toString(SmallVectorImpl<char> &Str) const { +  APSInt Val = getValue(); +  int Lsb = getLsbWeight(); +  int OrigWidth = getWidth(); + +  if (Lsb >= 0) { +    APSInt IntPart = Val; +    IntPart = IntPart.extend(IntPart.getBitWidth() + Lsb); +    IntPart <<= Lsb; +    IntPart.toString(Str, /*Radix=*/10); +    Str.push_back('.'); +    Str.push_back('0'); +    return; +  } + +  if (Val.isSigned() && Val.isNegative()) { +    Val = -Val; +    Val.setIsUnsigned(true); +    Str.push_back('-'); +  } + +  int Scale = -getLsbWeight(); +  APSInt IntPart = (OrigWidth > Scale) ? (Val >> Scale) : APSInt::get(0); + +  // Add 4 digits to hold the value after multiplying 10 (the radix) +  unsigned Width = std::max(OrigWidth, Scale) + 4; +  APInt FractPart = Val.zextOrTrunc(Scale).zext(Width); +  APInt FractPartMask = APInt::getAllOnes(Scale).zext(Width); +  APInt RadixInt = APInt(Width, 10); + +  IntPart.toString(Str, /*Radix=*/10); +  Str.push_back('.'); +  do { +    (FractPart * RadixInt) +        .lshr(Scale) +        .toString(Str, /*Radix=*/10, Val.isSigned()); +    FractPart = (FractPart * RadixInt) & FractPartMask; +  } while (FractPart != 0); +} + +void APFixedPoint::print(raw_ostream &OS) const { +  OS << "APFixedPoint(" << toString() << ", {"; +  Sema.print(OS); +  OS << "})"; +} +LLVM_DUMP_METHOD void APFixedPoint::dump() const { print(llvm::errs()); } + +APFixedPoint APFixedPoint::negate(bool *Overflow) const { +  if (!isSaturated()) { +    if (Overflow) +      *Overflow = +          (!isSigned() && Val != 0) || (isSigned() && Val.isMinSignedValue()); +    return APFixedPoint(-Val, Sema); +  } + +  // We never overflow for saturation +  if (Overflow) +    *Overflow = false; + +  if (isSigned()) +    return Val.isMinSignedValue() ? getMax(Sema) : APFixedPoint(-Val, Sema); +  else +    return APFixedPoint(Sema); +} + +APSInt APFixedPoint::convertToInt(unsigned DstWidth, bool DstSign, +                                  bool *Overflow) const { +  APSInt Result = getIntPart(); +  unsigned SrcWidth = getWidth(); + +  APSInt DstMin = APSInt::getMinValue(DstWidth, !DstSign); +  APSInt DstMax = APSInt::getMaxValue(DstWidth, !DstSign); + +  if (SrcWidth < DstWidth) { +    Result = Result.extend(DstWidth); +  } else if (SrcWidth > DstWidth) { +    DstMin = DstMin.extend(SrcWidth); +    DstMax = DstMax.extend(SrcWidth); +  } + +  if (Overflow) { +    if (Result.isSigned() && !DstSign) { +      *Overflow = Result.isNegative() || Result.ugt(DstMax); +    } else if (Result.isUnsigned() && DstSign) { +      *Overflow = Result.ugt(DstMax); +    } else { +      *Overflow = Result < DstMin || Result > DstMax; +    } +  } + +  Result.setIsSigned(DstSign); +  return Result.extOrTrunc(DstWidth); +} + +const fltSemantics *APFixedPoint::promoteFloatSemantics(const fltSemantics *S) { +  if (S == &APFloat::BFloat()) +    return &APFloat::IEEEdouble(); +  else if (S == &APFloat::IEEEhalf()) +    return &APFloat::IEEEsingle(); +  else if (S == &APFloat::IEEEsingle()) +    return &APFloat::IEEEdouble(); +  else if (S == &APFloat::IEEEdouble()) +    return &APFloat::IEEEquad(); +  llvm_unreachable("Could not promote float type!"); +} + +APFloat APFixedPoint::convertToFloat(const fltSemantics &FloatSema) const { +  // For some operations, rounding mode has an effect on the result, while +  // other operations are lossless and should never result in rounding. +  // To signify which these operations are, we define two rounding modes here. +  APFloat::roundingMode RM = APFloat::rmNearestTiesToEven; +  APFloat::roundingMode LosslessRM = APFloat::rmTowardZero; + +  // Make sure that we are operating in a type that works with this fixed-point +  // semantic. +  const fltSemantics *OpSema = &FloatSema; +  while (!Sema.fitsInFloatSemantics(*OpSema)) +    OpSema = promoteFloatSemantics(OpSema); + +  // Convert the fixed point value bits as an integer. If the floating point +  // value does not have the required precision, we will round according to the +  // given mode. +  APFloat Flt(*OpSema); +  APFloat::opStatus S = Flt.convertFromAPInt(Val, Sema.isSigned(), RM); + +  // If we cared about checking for precision loss, we could look at this +  // status. +  (void)S; + +  // Scale down the integer value in the float to match the correct scaling +  // factor. +  APFloat ScaleFactor(std::pow(2, Sema.getLsbWeight())); +  bool Ignored; +  ScaleFactor.convert(*OpSema, LosslessRM, &Ignored); +  Flt.multiply(ScaleFactor, LosslessRM); + +  if (OpSema != &FloatSema) +    Flt.convert(FloatSema, RM, &Ignored); + +  return Flt; +} + +APFixedPoint APFixedPoint::getFromIntValue(const APSInt &Value, +                                           const FixedPointSemantics &DstFXSema, +                                           bool *Overflow) { +  FixedPointSemantics IntFXSema = FixedPointSemantics::GetIntegerSemantics( +      Value.getBitWidth(), Value.isSigned()); +  return APFixedPoint(Value, IntFXSema).convert(DstFXSema, Overflow); +} + +APFixedPoint +APFixedPoint::getFromFloatValue(const APFloat &Value, +                                const FixedPointSemantics &DstFXSema, +                                bool *Overflow) { +  // For some operations, rounding mode has an effect on the result, while +  // other operations are lossless and should never result in rounding. +  // To signify which these operations are, we define two rounding modes here, +  // even though they are the same mode. +  APFloat::roundingMode RM = APFloat::rmTowardZero; +  APFloat::roundingMode LosslessRM = APFloat::rmTowardZero; + +  const fltSemantics &FloatSema = Value.getSemantics(); + +  if (Value.isNaN()) { +    // Handle NaN immediately. +    if (Overflow) +      *Overflow = true; +    return APFixedPoint(DstFXSema); +  } + +  // Make sure that we are operating in a type that works with this fixed-point +  // semantic. +  const fltSemantics *OpSema = &FloatSema; +  while (!DstFXSema.fitsInFloatSemantics(*OpSema)) +    OpSema = promoteFloatSemantics(OpSema); + +  APFloat Val = Value; + +  bool Ignored; +  if (&FloatSema != OpSema) +    Val.convert(*OpSema, LosslessRM, &Ignored); + +  // Scale up the float so that the 'fractional' part of the mantissa ends up in +  // the integer range instead. Rounding mode is irrelevant here. +  // It is fine if this overflows to infinity even for saturating types, +  // since we will use floating point comparisons to check for saturation. +  APFloat ScaleFactor(std::pow(2, -DstFXSema.getLsbWeight())); +  ScaleFactor.convert(*OpSema, LosslessRM, &Ignored); +  Val.multiply(ScaleFactor, LosslessRM); + +  // Convert to the integral representation of the value. This rounding mode +  // is significant. +  APSInt Res(DstFXSema.getWidth(), !DstFXSema.isSigned()); +  Val.convertToInteger(Res, RM, &Ignored); + +  // Round the integral value and scale back. This makes the +  // overflow calculations below work properly. If we do not round here, +  // we risk checking for overflow with a value that is outside the +  // representable range of the fixed-point semantic even though no overflow +  // would occur had we rounded first. +  ScaleFactor = APFloat(std::pow(2, DstFXSema.getLsbWeight())); +  ScaleFactor.convert(*OpSema, LosslessRM, &Ignored); +  Val.roundToIntegral(RM); +  Val.multiply(ScaleFactor, LosslessRM); + +  // Check for overflow/saturation by checking if the floating point value +  // is outside the range representable by the fixed-point value. +  APFloat FloatMax = getMax(DstFXSema).convertToFloat(*OpSema); +  APFloat FloatMin = getMin(DstFXSema).convertToFloat(*OpSema); +  bool Overflowed = false; +  if (DstFXSema.isSaturated()) { +    if (Val > FloatMax) +      Res = getMax(DstFXSema).getValue(); +    else if (Val < FloatMin) +      Res = getMin(DstFXSema).getValue(); +  } else +    Overflowed = Val > FloatMax || Val < FloatMin; + +  if (Overflow) +    *Overflow = Overflowed; + +  return APFixedPoint(Res, DstFXSema); +} + +} // namespace llvm  | 
