diff options
author | David Majnemer <david.majnemer@gmail.com> | 2025-08-12 18:31:02 -0700 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2025-08-12 18:32:58 -0700 |
commit | acef1db3b2dbc59e4c8f5fa9c167917a2dd207b0 (patch) | |
tree | 97272fe0e8bbb5f4378c794970bc141fefbd5bcd /llvm/lib/Support/APFloat.cpp | |
parent | 331a5db9de0e17e4c54dfbd58ddc54a8111d3cba (diff) | |
download | llvm-acef1db3b2dbc59e4c8f5fa9c167917a2dd207b0.zip llvm-acef1db3b2dbc59e4c8f5fa9c167917a2dd207b0.tar.gz llvm-acef1db3b2dbc59e4c8f5fa9c167917a2dd207b0.tar.bz2 |
[APFloat] Remove some overly optimistic assertions
An earlier draft of DoubleAPFloat::convertToSignExtendedInteger had
arranged for overflow to be handled in a different way. However, these
assertions are now possible if Hi+Lo are out of range and Lo != 0.
A test has been added to defend against a regression.
Diffstat (limited to 'llvm/lib/Support/APFloat.cpp')
-rw-r--r-- | llvm/lib/Support/APFloat.cpp | 24 |
1 files changed, 13 insertions, 11 deletions
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp index 529d002..d2a417f 100644 --- a/llvm/lib/Support/APFloat.cpp +++ b/llvm/lib/Support/APFloat.cpp @@ -5536,7 +5536,7 @@ APFloat::opStatus DoubleAPFloat::convertToSignExtendedInteger( DoubleAPFloat Integral = *this; const opStatus RoundStatus = Integral.roundToIntegral(RM); if (RoundStatus == opInvalidOp) - return RoundStatus; + return opInvalidOp; const APFloat &IntegralHi = Integral.getFirst(); const APFloat &IntegralLo = Integral.getSecond(); @@ -5548,7 +5548,7 @@ APFloat::opStatus DoubleAPFloat::convertToSignExtendedInteger( IntegralHi.convertToInteger(Input, Width, IsSigned, RM, &HiIsExact); // The conversion from an integer-valued float to an APInt may fail if the // result would be out of range. Regardless, taking this path is only - // possible if rounding occured during the initial `roundToIntegral`. + // possible if rounding occurred during the initial `roundToIntegral`. return HiStatus == opOK ? opInexact : HiStatus; } @@ -5575,9 +5575,10 @@ APFloat::opStatus DoubleAPFloat::convertToSignExtendedInteger( // If the signs differ, the sum will fit. We can compute the result using // properties of two's complement arithmetic without a wide intermediate // integer. E.g., for uint128_t, (2^128, -1) should be 2^128 - 1. - [[maybe_unused]] opStatus LoStatus = IntegralLo.convertToInteger( + const opStatus LoStatus = IntegralLo.convertToInteger( Input, Width, /*IsSigned=*/true, RM, &LoIsExact); - assert(LoStatus == opOK && "Unexpected failure"); + if (LoStatus == opInvalidOp) + return opInvalidOp; // Adjust the bit pattern of Lo to account for Hi's value: // - For unsigned (Hi=2^Width): `2^Width + Lo` in `Width`-bit @@ -5592,18 +5593,19 @@ APFloat::opStatus DoubleAPFloat::convertToSignExtendedInteger( return RoundStatus; } - // General case: Hi is not a power-of-two boundary, so we know it fits. - // Since we already rounded the full value, we now just need to convert the - // components to integers. The rounding mode should not matter. - [[maybe_unused]] opStatus HiStatus = IntegralHi.convertToInteger( + // Convert Hi into an integer. This may not fit but that is OK: we know that + // Hi + Lo would not fit either in this situation. + const opStatus HiStatus = IntegralHi.convertToInteger( Input, Width, IsSigned, rmTowardZero, &HiIsExact); - assert(HiStatus == opOK && "Unexpected failure"); + if (HiStatus == opInvalidOp) + return HiStatus; // Convert Lo into a temporary integer of the same width. APSInt LoResult{Width, /*isUnsigned=*/!IsSigned}; - [[maybe_unused]] opStatus LoStatus = + const opStatus LoStatus = IntegralLo.convertToInteger(LoResult, rmTowardZero, &LoIsExact); - assert(LoStatus == opOK && "Unexpected failure"); + if (LoStatus == opInvalidOp) + return LoStatus; // Add Lo to Hi. This addition is guaranteed not to overflow because of the // double-double canonicalization rule (`|Lo| <= ulp(Hi)/2`). The only case |