Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / lib / Support / APFixedPoint.cpp
blob3eea01bc98093ac16367c6fa3fda74c1cd0bb3a6
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.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/ADT/APFixedPoint.h"
15 #include "llvm/ADT/APFloat.h"
17 #include <cmath>
19 namespace llvm {
21 void 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;
32 APFixedPoint APFixedPoint::convert(const FixedPointSemantics &DstSema,
33 bool *Overflow) const {
34 APSInt NewVal = Val;
35 int RelativeUpscale = getLsbWeight() - DstSema.getLsbWeight();
36 if (Overflow)
37 *Overflow = false;
39 if (RelativeUpscale > 0)
40 NewVal = NewVal.extend(NewVal.getBitWidth() + RelativeUpscale);
41 NewVal = NewVal.relativeShl(RelativeUpscale);
43 auto Mask = APInt::getBitsSetFrom(
44 NewVal.getBitWidth(),
45 std::min(DstSema.getIntegralBits() - DstSema.getLsbWeight(),
46 NewVal.getBitWidth()));
47 APInt Masked(NewVal & Mask);
49 // Change in the bits above the sign
50 if (!(Masked == Mask || Masked == 0)) {
51 // Found overflow in the bits above the sign
52 if (DstSema.isSaturated())
53 NewVal = NewVal.isNegative() ? Mask : ~Mask;
54 else if (Overflow)
55 *Overflow = true;
58 // If the dst semantics are unsigned, but our value is signed and negative, we
59 // clamp to zero.
60 if (!DstSema.isSigned() && NewVal.isSigned() && NewVal.isNegative()) {
61 // Found negative overflow for unsigned result
62 if (DstSema.isSaturated())
63 NewVal = 0;
64 else if (Overflow)
65 *Overflow = true;
68 NewVal = NewVal.extOrTrunc(DstSema.getWidth());
69 NewVal.setIsSigned(DstSema.isSigned());
70 return APFixedPoint(NewVal, DstSema);
73 int APFixedPoint::compare(const APFixedPoint &Other) const {
74 APSInt ThisVal = getValue();
75 APSInt OtherVal = Other.getValue();
76 bool ThisSigned = Val.isSigned();
77 bool OtherSigned = OtherVal.isSigned();
79 int CommonLsb = std::min(getLsbWeight(), Other.getLsbWeight());
80 int CommonMsb = std::max(getMsbWeight(), Other.getMsbWeight());
81 unsigned CommonWidth = CommonMsb - CommonLsb + 1;
83 ThisVal = ThisVal.extOrTrunc(CommonWidth);
84 OtherVal = OtherVal.extOrTrunc(CommonWidth);
86 ThisVal = ThisVal.shl(getLsbWeight() - CommonLsb);
87 OtherVal = OtherVal.shl(Other.getLsbWeight() - CommonLsb);
89 if (ThisSigned && OtherSigned) {
90 if (ThisVal.sgt(OtherVal))
91 return 1;
92 else if (ThisVal.slt(OtherVal))
93 return -1;
94 } else if (!ThisSigned && !OtherSigned) {
95 if (ThisVal.ugt(OtherVal))
96 return 1;
97 else if (ThisVal.ult(OtherVal))
98 return -1;
99 } else if (ThisSigned && !OtherSigned) {
100 if (ThisVal.isSignBitSet())
101 return -1;
102 else if (ThisVal.ugt(OtherVal))
103 return 1;
104 else if (ThisVal.ult(OtherVal))
105 return -1;
106 } else {
107 // !ThisSigned && OtherSigned
108 if (OtherVal.isSignBitSet())
109 return 1;
110 else if (ThisVal.ugt(OtherVal))
111 return 1;
112 else if (ThisVal.ult(OtherVal))
113 return -1;
116 return 0;
119 APFixedPoint APFixedPoint::getMax(const FixedPointSemantics &Sema) {
120 bool IsUnsigned = !Sema.isSigned();
121 auto Val = APSInt::getMaxValue(Sema.getWidth(), IsUnsigned);
122 if (IsUnsigned && Sema.hasUnsignedPadding())
123 Val = Val.lshr(1);
124 return APFixedPoint(Val, Sema);
127 APFixedPoint APFixedPoint::getMin(const FixedPointSemantics &Sema) {
128 auto Val = APSInt::getMinValue(Sema.getWidth(), !Sema.isSigned());
129 return APFixedPoint(Val, Sema);
132 bool FixedPointSemantics::fitsInFloatSemantics(
133 const fltSemantics &FloatSema) const {
134 // A fixed point semantic fits in a floating point semantic if the maximum
135 // and minimum values as integers of the fixed point semantic can fit in the
136 // floating point semantic.
138 // If these values do not fit, then a floating point rescaling of the true
139 // maximum/minimum value will not fit either, so the floating point semantic
140 // cannot be used to perform such a rescaling.
142 APSInt MaxInt = APFixedPoint::getMax(*this).getValue();
143 APFloat F(FloatSema);
144 APFloat::opStatus Status = F.convertFromAPInt(MaxInt, MaxInt.isSigned(),
145 APFloat::rmNearestTiesToAway);
146 if ((Status & APFloat::opOverflow) || !isSigned())
147 return !(Status & APFloat::opOverflow);
149 APSInt MinInt = APFixedPoint::getMin(*this).getValue();
150 Status = F.convertFromAPInt(MinInt, MinInt.isSigned(),
151 APFloat::rmNearestTiesToAway);
152 return !(Status & APFloat::opOverflow);
155 FixedPointSemantics FixedPointSemantics::getCommonSemantics(
156 const FixedPointSemantics &Other) const {
157 int CommonLsb = std::min(getLsbWeight(), Other.getLsbWeight());
158 int CommonMSb = std::max(getMsbWeight() - hasSignOrPaddingBit(),
159 Other.getMsbWeight() - Other.hasSignOrPaddingBit());
160 unsigned CommonWidth = CommonMSb - CommonLsb + 1;
162 bool ResultIsSigned = isSigned() || Other.isSigned();
163 bool ResultIsSaturated = isSaturated() || Other.isSaturated();
164 bool ResultHasUnsignedPadding = false;
165 if (!ResultIsSigned) {
166 // Both are unsigned.
167 ResultHasUnsignedPadding = hasUnsignedPadding() &&
168 Other.hasUnsignedPadding() && !ResultIsSaturated;
171 // If the result is signed, add an extra bit for the sign. Otherwise, if it is
172 // unsigned and has unsigned padding, we only need to add the extra padding
173 // bit back if we are not saturating.
174 if (ResultIsSigned || ResultHasUnsignedPadding)
175 CommonWidth++;
177 return FixedPointSemantics(CommonWidth, Lsb{CommonLsb}, ResultIsSigned,
178 ResultIsSaturated, ResultHasUnsignedPadding);
181 APFixedPoint APFixedPoint::add(const APFixedPoint &Other,
182 bool *Overflow) const {
183 auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics());
184 APFixedPoint ConvertedThis = convert(CommonFXSema);
185 APFixedPoint ConvertedOther = Other.convert(CommonFXSema);
186 APSInt ThisVal = ConvertedThis.getValue();
187 APSInt OtherVal = ConvertedOther.getValue();
188 bool Overflowed = false;
190 APSInt Result;
191 if (CommonFXSema.isSaturated()) {
192 Result = CommonFXSema.isSigned() ? ThisVal.sadd_sat(OtherVal)
193 : ThisVal.uadd_sat(OtherVal);
194 } else {
195 Result = ThisVal.isSigned() ? ThisVal.sadd_ov(OtherVal, Overflowed)
196 : ThisVal.uadd_ov(OtherVal, Overflowed);
199 if (Overflow)
200 *Overflow = Overflowed;
202 return APFixedPoint(Result, CommonFXSema);
205 APFixedPoint APFixedPoint::sub(const APFixedPoint &Other,
206 bool *Overflow) const {
207 auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics());
208 APFixedPoint ConvertedThis = convert(CommonFXSema);
209 APFixedPoint ConvertedOther = Other.convert(CommonFXSema);
210 APSInt ThisVal = ConvertedThis.getValue();
211 APSInt OtherVal = ConvertedOther.getValue();
212 bool Overflowed = false;
214 APSInt Result;
215 if (CommonFXSema.isSaturated()) {
216 Result = CommonFXSema.isSigned() ? ThisVal.ssub_sat(OtherVal)
217 : ThisVal.usub_sat(OtherVal);
218 } else {
219 Result = ThisVal.isSigned() ? ThisVal.ssub_ov(OtherVal, Overflowed)
220 : ThisVal.usub_ov(OtherVal, Overflowed);
223 if (Overflow)
224 *Overflow = Overflowed;
226 return APFixedPoint(Result, CommonFXSema);
229 APFixedPoint APFixedPoint::mul(const APFixedPoint &Other,
230 bool *Overflow) const {
231 auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics());
232 APFixedPoint ConvertedThis = convert(CommonFXSema);
233 APFixedPoint ConvertedOther = Other.convert(CommonFXSema);
234 APSInt ThisVal = ConvertedThis.getValue();
235 APSInt OtherVal = ConvertedOther.getValue();
236 bool Overflowed = false;
238 // Widen the LHS and RHS so we can perform a full multiplication.
239 unsigned Wide = CommonFXSema.getWidth() * 2;
240 if (CommonFXSema.isSigned()) {
241 ThisVal = ThisVal.sext(Wide);
242 OtherVal = OtherVal.sext(Wide);
243 } else {
244 ThisVal = ThisVal.zext(Wide);
245 OtherVal = OtherVal.zext(Wide);
248 // Perform the full multiplication and downscale to get the same scale.
250 // Note that the right shifts here perform an implicit downwards rounding.
251 // This rounding could discard bits that would technically place the result
252 // outside the representable range. We interpret the spec as allowing us to
253 // perform the rounding step first, avoiding the overflow case that would
254 // arise.
255 APSInt Result;
256 if (CommonFXSema.isSigned())
257 Result = ThisVal.smul_ov(OtherVal, Overflowed)
258 .relativeAShl(CommonFXSema.getLsbWeight());
259 else
260 Result = ThisVal.umul_ov(OtherVal, Overflowed)
261 .relativeLShl(CommonFXSema.getLsbWeight());
262 assert(!Overflowed && "Full multiplication cannot overflow!");
263 Result.setIsSigned(CommonFXSema.isSigned());
265 // If our result lies outside of the representative range of the common
266 // semantic, we either have overflow or saturation.
267 APSInt Max = APFixedPoint::getMax(CommonFXSema).getValue()
268 .extOrTrunc(Wide);
269 APSInt Min = APFixedPoint::getMin(CommonFXSema).getValue()
270 .extOrTrunc(Wide);
271 if (CommonFXSema.isSaturated()) {
272 if (Result < Min)
273 Result = Min;
274 else if (Result > Max)
275 Result = Max;
276 } else
277 Overflowed = Result < Min || Result > Max;
279 if (Overflow)
280 *Overflow = Overflowed;
282 return APFixedPoint(Result.sextOrTrunc(CommonFXSema.getWidth()),
283 CommonFXSema);
286 APFixedPoint APFixedPoint::div(const APFixedPoint &Other,
287 bool *Overflow) const {
288 auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics());
289 APFixedPoint ConvertedThis = convert(CommonFXSema);
290 APFixedPoint ConvertedOther = Other.convert(CommonFXSema);
291 APSInt ThisVal = ConvertedThis.getValue();
292 APSInt OtherVal = ConvertedOther.getValue();
293 bool Overflowed = false;
295 // Widen the LHS and RHS so we can perform a full division.
296 // Also make sure that there will be enough space for the shift below to not
297 // overflow
298 unsigned Wide =
299 CommonFXSema.getWidth() * 2 + std::max(-CommonFXSema.getMsbWeight(), 0);
300 if (CommonFXSema.isSigned()) {
301 ThisVal = ThisVal.sext(Wide);
302 OtherVal = OtherVal.sext(Wide);
303 } else {
304 ThisVal = ThisVal.zext(Wide);
305 OtherVal = OtherVal.zext(Wide);
308 // Upscale to compensate for the loss of precision from division, and
309 // perform the full division.
310 if (CommonFXSema.getLsbWeight() < 0)
311 ThisVal = ThisVal.shl(-CommonFXSema.getLsbWeight());
312 else if (CommonFXSema.getLsbWeight() > 0)
313 OtherVal = OtherVal.shl(CommonFXSema.getLsbWeight());
314 APSInt Result;
315 if (CommonFXSema.isSigned()) {
316 APInt Rem;
317 APInt::sdivrem(ThisVal, OtherVal, Result, Rem);
318 // If the quotient is negative and the remainder is nonzero, round
319 // towards negative infinity by subtracting epsilon from the result.
320 if (ThisVal.isNegative() != OtherVal.isNegative() && !Rem.isZero())
321 Result = Result - 1;
322 } else
323 Result = ThisVal.udiv(OtherVal);
324 Result.setIsSigned(CommonFXSema.isSigned());
326 // If our result lies outside of the representative range of the common
327 // semantic, we either have overflow or saturation.
328 APSInt Max = APFixedPoint::getMax(CommonFXSema).getValue()
329 .extOrTrunc(Wide);
330 APSInt Min = APFixedPoint::getMin(CommonFXSema).getValue()
331 .extOrTrunc(Wide);
332 if (CommonFXSema.isSaturated()) {
333 if (Result < Min)
334 Result = Min;
335 else if (Result > Max)
336 Result = Max;
337 } else
338 Overflowed = Result < Min || Result > Max;
340 if (Overflow)
341 *Overflow = Overflowed;
343 return APFixedPoint(Result.sextOrTrunc(CommonFXSema.getWidth()),
344 CommonFXSema);
347 APFixedPoint APFixedPoint::shl(unsigned Amt, bool *Overflow) const {
348 APSInt ThisVal = Val;
349 bool Overflowed = false;
351 // Widen the LHS.
352 unsigned Wide = Sema.getWidth() * 2;
353 if (Sema.isSigned())
354 ThisVal = ThisVal.sext(Wide);
355 else
356 ThisVal = ThisVal.zext(Wide);
358 // Clamp the shift amount at the original width, and perform the shift.
359 Amt = std::min(Amt, ThisVal.getBitWidth());
360 APSInt Result = ThisVal << Amt;
361 Result.setIsSigned(Sema.isSigned());
363 // If our result lies outside of the representative range of the
364 // semantic, we either have overflow or saturation.
365 APSInt Max = APFixedPoint::getMax(Sema).getValue().extOrTrunc(Wide);
366 APSInt Min = APFixedPoint::getMin(Sema).getValue().extOrTrunc(Wide);
367 if (Sema.isSaturated()) {
368 if (Result < Min)
369 Result = Min;
370 else if (Result > Max)
371 Result = Max;
372 } else
373 Overflowed = Result < Min || Result > Max;
375 if (Overflow)
376 *Overflow = Overflowed;
378 return APFixedPoint(Result.sextOrTrunc(Sema.getWidth()), Sema);
381 void APFixedPoint::toString(SmallVectorImpl<char> &Str) const {
382 APSInt Val = getValue();
383 int Lsb = getLsbWeight();
384 int OrigWidth = getWidth();
386 if (Lsb >= 0) {
387 APSInt IntPart = Val;
388 IntPart = IntPart.extend(IntPart.getBitWidth() + Lsb);
389 IntPart <<= Lsb;
390 IntPart.toString(Str, /*Radix=*/10);
391 Str.push_back('.');
392 Str.push_back('0');
393 return;
396 if (Val.isSigned() && Val.isNegative()) {
397 Val = -Val;
398 Val.setIsUnsigned(true);
399 Str.push_back('-');
402 int Scale = -getLsbWeight();
403 APSInt IntPart = (OrigWidth > Scale) ? (Val >> Scale) : APSInt::get(0);
405 // Add 4 digits to hold the value after multiplying 10 (the radix)
406 unsigned Width = std::max(OrigWidth, Scale) + 4;
407 APInt FractPart = Val.zextOrTrunc(Scale).zext(Width);
408 APInt FractPartMask = APInt::getAllOnes(Scale).zext(Width);
409 APInt RadixInt = APInt(Width, 10);
411 IntPart.toString(Str, /*Radix=*/10);
412 Str.push_back('.');
413 do {
414 (FractPart * RadixInt)
415 .lshr(Scale)
416 .toString(Str, /*Radix=*/10, Val.isSigned());
417 FractPart = (FractPart * RadixInt) & FractPartMask;
418 } while (FractPart != 0);
421 void APFixedPoint::print(raw_ostream &OS) const {
422 OS << "APFixedPoint(" << toString() << ", {";
423 Sema.print(OS);
424 OS << "})";
426 LLVM_DUMP_METHOD void APFixedPoint::dump() const { print(llvm::errs()); }
428 APFixedPoint APFixedPoint::negate(bool *Overflow) const {
429 if (!isSaturated()) {
430 if (Overflow)
431 *Overflow =
432 (!isSigned() && Val != 0) || (isSigned() && Val.isMinSignedValue());
433 return APFixedPoint(-Val, Sema);
436 // We never overflow for saturation
437 if (Overflow)
438 *Overflow = false;
440 if (isSigned())
441 return Val.isMinSignedValue() ? getMax(Sema) : APFixedPoint(-Val, Sema);
442 else
443 return APFixedPoint(Sema);
446 APSInt APFixedPoint::convertToInt(unsigned DstWidth, bool DstSign,
447 bool *Overflow) const {
448 APSInt Result = getIntPart();
449 unsigned SrcWidth = getWidth();
451 APSInt DstMin = APSInt::getMinValue(DstWidth, !DstSign);
452 APSInt DstMax = APSInt::getMaxValue(DstWidth, !DstSign);
454 if (SrcWidth < DstWidth) {
455 Result = Result.extend(DstWidth);
456 } else if (SrcWidth > DstWidth) {
457 DstMin = DstMin.extend(SrcWidth);
458 DstMax = DstMax.extend(SrcWidth);
461 if (Overflow) {
462 if (Result.isSigned() && !DstSign) {
463 *Overflow = Result.isNegative() || Result.ugt(DstMax);
464 } else if (Result.isUnsigned() && DstSign) {
465 *Overflow = Result.ugt(DstMax);
466 } else {
467 *Overflow = Result < DstMin || Result > DstMax;
471 Result.setIsSigned(DstSign);
472 return Result.extOrTrunc(DstWidth);
475 const fltSemantics *APFixedPoint::promoteFloatSemantics(const fltSemantics *S) {
476 if (S == &APFloat::BFloat())
477 return &APFloat::IEEEdouble();
478 else if (S == &APFloat::IEEEhalf())
479 return &APFloat::IEEEsingle();
480 else if (S == &APFloat::IEEEsingle())
481 return &APFloat::IEEEdouble();
482 else if (S == &APFloat::IEEEdouble())
483 return &APFloat::IEEEquad();
484 llvm_unreachable("Could not promote float type!");
487 APFloat APFixedPoint::convertToFloat(const fltSemantics &FloatSema) const {
488 // For some operations, rounding mode has an effect on the result, while
489 // other operations are lossless and should never result in rounding.
490 // To signify which these operations are, we define two rounding modes here.
491 APFloat::roundingMode RM = APFloat::rmNearestTiesToEven;
492 APFloat::roundingMode LosslessRM = APFloat::rmTowardZero;
494 // Make sure that we are operating in a type that works with this fixed-point
495 // semantic.
496 const fltSemantics *OpSema = &FloatSema;
497 while (!Sema.fitsInFloatSemantics(*OpSema))
498 OpSema = promoteFloatSemantics(OpSema);
500 // Convert the fixed point value bits as an integer. If the floating point
501 // value does not have the required precision, we will round according to the
502 // given mode.
503 APFloat Flt(*OpSema);
504 APFloat::opStatus S = Flt.convertFromAPInt(Val, Sema.isSigned(), RM);
506 // If we cared about checking for precision loss, we could look at this
507 // status.
508 (void)S;
510 // Scale down the integer value in the float to match the correct scaling
511 // factor.
512 APFloat ScaleFactor(std::pow(2, Sema.getLsbWeight()));
513 bool Ignored;
514 ScaleFactor.convert(*OpSema, LosslessRM, &Ignored);
515 Flt.multiply(ScaleFactor, LosslessRM);
517 if (OpSema != &FloatSema)
518 Flt.convert(FloatSema, RM, &Ignored);
520 return Flt;
523 APFixedPoint APFixedPoint::getFromIntValue(const APSInt &Value,
524 const FixedPointSemantics &DstFXSema,
525 bool *Overflow) {
526 FixedPointSemantics IntFXSema = FixedPointSemantics::GetIntegerSemantics(
527 Value.getBitWidth(), Value.isSigned());
528 return APFixedPoint(Value, IntFXSema).convert(DstFXSema, Overflow);
531 APFixedPoint
532 APFixedPoint::getFromFloatValue(const APFloat &Value,
533 const FixedPointSemantics &DstFXSema,
534 bool *Overflow) {
535 // For some operations, rounding mode has an effect on the result, while
536 // other operations are lossless and should never result in rounding.
537 // To signify which these operations are, we define two rounding modes here,
538 // even though they are the same mode.
539 APFloat::roundingMode RM = APFloat::rmTowardZero;
540 APFloat::roundingMode LosslessRM = APFloat::rmTowardZero;
542 const fltSemantics &FloatSema = Value.getSemantics();
544 if (Value.isNaN()) {
545 // Handle NaN immediately.
546 if (Overflow)
547 *Overflow = true;
548 return APFixedPoint(DstFXSema);
551 // Make sure that we are operating in a type that works with this fixed-point
552 // semantic.
553 const fltSemantics *OpSema = &FloatSema;
554 while (!DstFXSema.fitsInFloatSemantics(*OpSema))
555 OpSema = promoteFloatSemantics(OpSema);
557 APFloat Val = Value;
559 bool Ignored;
560 if (&FloatSema != OpSema)
561 Val.convert(*OpSema, LosslessRM, &Ignored);
563 // Scale up the float so that the 'fractional' part of the mantissa ends up in
564 // the integer range instead. Rounding mode is irrelevant here.
565 // It is fine if this overflows to infinity even for saturating types,
566 // since we will use floating point comparisons to check for saturation.
567 APFloat ScaleFactor(std::pow(2, -DstFXSema.getLsbWeight()));
568 ScaleFactor.convert(*OpSema, LosslessRM, &Ignored);
569 Val.multiply(ScaleFactor, LosslessRM);
571 // Convert to the integral representation of the value. This rounding mode
572 // is significant.
573 APSInt Res(DstFXSema.getWidth(), !DstFXSema.isSigned());
574 Val.convertToInteger(Res, RM, &Ignored);
576 // Round the integral value and scale back. This makes the
577 // overflow calculations below work properly. If we do not round here,
578 // we risk checking for overflow with a value that is outside the
579 // representable range of the fixed-point semantic even though no overflow
580 // would occur had we rounded first.
581 ScaleFactor = APFloat(std::pow(2, DstFXSema.getLsbWeight()));
582 ScaleFactor.convert(*OpSema, LosslessRM, &Ignored);
583 Val.roundToIntegral(RM);
584 Val.multiply(ScaleFactor, LosslessRM);
586 // Check for overflow/saturation by checking if the floating point value
587 // is outside the range representable by the fixed-point value.
588 APFloat FloatMax = getMax(DstFXSema).convertToFloat(*OpSema);
589 APFloat FloatMin = getMin(DstFXSema).convertToFloat(*OpSema);
590 bool Overflowed = false;
591 if (DstFXSema.isSaturated()) {
592 if (Val > FloatMax)
593 Res = getMax(DstFXSema).getValue();
594 else if (Val < FloatMin)
595 Res = getMin(DstFXSema).getValue();
596 } else
597 Overflowed = Val > FloatMax || Val < FloatMin;
599 if (Overflow)
600 *Overflow = Overflowed;
602 return APFixedPoint(Res, DstFXSema);
605 } // namespace llvm