Skip to content

Commit 8b44945

Browse files
Revert "[APFloat] Properly implement DoubleAPFloat::convertToSignExtendedInteger"
This reverts commit 052c38b. I'm getting: llvm/lib/Support/APFloat.cpp:5627:29: error: use of undeclared identifier 'Parts' 5627 | assert(DstPartsCount <= Parts.size() && "Integer too big"); | ^ 1 error generated.
1 parent 2344f82 commit 8b44945

File tree

3 files changed

+51
-540
lines changed

3 files changed

+51
-540
lines changed

llvm/include/llvm/ADT/APFloat.h

Lines changed: 22 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -609,10 +609,29 @@ class IEEEFloat final {
609609
/// return true.
610610
LLVM_ABI bool getExactInverse(APFloat *inv) const;
611611

612+
// If this is an exact power of two, return the exponent while ignoring the
613+
// sign bit. If it's not an exact power of 2, return INT_MIN
612614
LLVM_ABI LLVM_READONLY int getExactLog2Abs() const;
613615

616+
// If this is an exact power of two, return the exponent. If it's not an exact
617+
// power of 2, return INT_MIN
618+
LLVM_READONLY
619+
int getExactLog2() const {
620+
return isNegative() ? INT_MIN : getExactLog2Abs();
621+
}
622+
623+
/// Returns the exponent of the internal representation of the APFloat.
624+
///
625+
/// Because the radix of APFloat is 2, this is equivalent to floor(log2(x)).
626+
/// For special APFloat values, this returns special error codes:
627+
///
628+
/// NaN -> \c IEK_NaN
629+
/// 0 -> \c IEK_Zero
630+
/// Inf -> \c IEK_Inf
631+
///
614632
LLVM_ABI friend int ilogb(const IEEEFloat &Arg);
615633

634+
/// Returns: X * 2^Exp for integral exponents.
616635
LLVM_ABI friend IEEEFloat scalbn(IEEEFloat X, int Exp, roundingMode);
617636

618637
LLVM_ABI friend IEEEFloat frexp(const IEEEFloat &X, int &Exp, roundingMode);
@@ -787,17 +806,7 @@ class IEEEFloat final {
787806
};
788807

789808
LLVM_ABI hash_code hash_value(const IEEEFloat &Arg);
790-
/// Returns the exponent of the internal representation of the APFloat.
791-
///
792-
/// Because the radix of APFloat is 2, this is equivalent to floor(log2(x)).
793-
/// For special APFloat values, this returns special error codes:
794-
///
795-
/// NaN -> \c IEK_NaN
796-
/// 0 -> \c IEK_Zero
797-
/// Inf -> \c IEK_Inf
798-
///
799809
LLVM_ABI int ilogb(const IEEEFloat &Arg);
800-
/// Returns: X * 2^Exp for integral exponents.
801810
LLVM_ABI IEEEFloat scalbn(IEEEFloat X, int Exp, roundingMode);
802811
LLVM_ABI IEEEFloat frexp(const IEEEFloat &Val, int &Exp, roundingMode RM);
803812

@@ -815,9 +824,6 @@ class DoubleAPFloat final {
815824

816825
opStatus addWithSpecial(const DoubleAPFloat &LHS, const DoubleAPFloat &RHS,
817826
DoubleAPFloat &Out, roundingMode RM);
818-
opStatus convertToSignExtendedInteger(MutableArrayRef<integerPart> Input,
819-
unsigned int Width, bool IsSigned,
820-
roundingMode RM, bool *IsExact) const;
821827

822828
public:
823829
LLVM_ABI DoubleAPFloat(const fltSemantics &S);
@@ -898,9 +904,9 @@ class DoubleAPFloat final {
898904

899905
LLVM_ABI bool getExactInverse(APFloat *inv) const;
900906

907+
LLVM_ABI LLVM_READONLY int getExactLog2() const;
901908
LLVM_ABI LLVM_READONLY int getExactLog2Abs() const;
902909

903-
LLVM_ABI friend int ilogb(const DoubleAPFloat &X);
904910
LLVM_ABI friend DoubleAPFloat scalbn(const DoubleAPFloat &X, int Exp,
905911
roundingMode);
906912
LLVM_ABI friend DoubleAPFloat frexp(const DoubleAPFloat &X, int &Exp,
@@ -1339,23 +1345,12 @@ class APFloat : public APFloatBase {
13391345

13401346
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM,
13411347
bool *losesInfo);
1342-
// Convert a floating point number to an integer according to the
1343-
// rounding mode. We provide deterministic values in case of an invalid
1344-
// operation exception, namely zero for NaNs and the minimal or maximal value
1345-
// respectively for underflow or overflow.
1346-
// The *IsExact output tells whether the result is exact, in the sense that
1347-
// converting it back to the original floating point type produces the
1348-
// original value. This is almost equivalent to result==opOK, except for
1349-
// negative zeroes.
13501348
opStatus convertToInteger(MutableArrayRef<integerPart> Input,
13511349
unsigned int Width, bool IsSigned, roundingMode RM,
13521350
bool *IsExact) const {
13531351
APFLOAT_DISPATCH_ON_SEMANTICS(
13541352
convertToInteger(Input, Width, IsSigned, RM, IsExact));
13551353
}
1356-
// Same as convertToInteger(integerPart*, ...), except the result is returned
1357-
// in an APSInt, whose initial bit-width and signed-ness are used to determine
1358-
// the precision of the conversion.
13591354
LLVM_ABI opStatus convertToInteger(APSInt &Result, roundingMode RM,
13601355
bool *IsExact) const;
13611356
opStatus convertFromAPInt(const APInt &Input, bool IsSigned,
@@ -1514,28 +1509,18 @@ class APFloat : public APFloatBase {
15141509
APFLOAT_DISPATCH_ON_SEMANTICS(getExactInverse(inv));
15151510
}
15161511

1517-
// If this is an exact power of two, return the exponent while ignoring the
1518-
// sign bit. If it's not an exact power of 2, return INT_MIN
15191512
LLVM_READONLY
15201513
int getExactLog2Abs() const {
15211514
APFLOAT_DISPATCH_ON_SEMANTICS(getExactLog2Abs());
15221515
}
15231516

1524-
// If this is an exact power of two, return the exponent. If it's not an exact
1525-
// power of 2, return INT_MIN
15261517
LLVM_READONLY
15271518
int getExactLog2() const {
1528-
return isNegative() ? INT_MIN : getExactLog2Abs();
1519+
APFLOAT_DISPATCH_ON_SEMANTICS(getExactLog2());
15291520
}
15301521

15311522
LLVM_ABI friend hash_code hash_value(const APFloat &Arg);
1532-
friend int ilogb(const APFloat &Arg) {
1533-
if (APFloat::usesLayout<detail::IEEEFloat>(Arg.getSemantics()))
1534-
return ilogb(Arg.getIEEE());
1535-
if (APFloat::usesLayout<detail::DoubleAPFloat>(Arg.getSemantics()))
1536-
return ilogb(Arg.getIEEE());
1537-
llvm_unreachable("Unexpected semantics");
1538-
}
1523+
friend int ilogb(const APFloat &Arg) { return ilogb(Arg.getIEEE()); }
15391524
friend APFloat scalbn(APFloat X, int Exp, roundingMode RM);
15401525
friend APFloat frexp(const APFloat &X, int &Exp, roundingMode RM);
15411526
friend IEEEFloat;

llvm/lib/Support/APFloat.cpp

Lines changed: 14 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -5519,127 +5519,13 @@ APFloat::opStatus DoubleAPFloat::next(bool nextDown) {
55195519
return opOK;
55205520
}
55215521

5522-
APFloat::opStatus DoubleAPFloat::convertToSignExtendedInteger(
5523-
MutableArrayRef<integerPart> Input, unsigned int Width, bool IsSigned,
5524-
roundingMode RM, bool *IsExact) const {
5525-
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
5526-
5527-
// If Hi is not finite, or Lo is zero, the value is entirely represented
5528-
// by Hi. Delegate to the simpler single-APFloat conversion.
5529-
if (!getFirst().isFiniteNonZero() || getSecond().isZero())
5530-
return getFirst().convertToInteger(Input, Width, IsSigned, RM, IsExact);
5531-
5532-
// First, round the full double-double value to an integral value. This
5533-
// simplifies the rest of the function, as we no longer need to consider
5534-
// fractional parts.
5535-
*IsExact = false;
5536-
DoubleAPFloat Integral = *this;
5537-
const opStatus RoundStatus = Integral.roundToIntegral(RM);
5538-
if (RoundStatus == opInvalidOp)
5539-
return RoundStatus;
5540-
const APFloat &IntegralHi = Integral.getFirst();
5541-
const APFloat &IntegralLo = Integral.getSecond();
5542-
5543-
// If rounding results in either component being zero, the sum is trivial.
5544-
// Delegate to the simpler single-APFloat conversion.
5545-
bool HiIsExact;
5546-
if (IntegralHi.isZero() || IntegralLo.isZero()) {
5547-
const opStatus HiStatus =
5548-
IntegralHi.convertToInteger(Input, Width, IsSigned, RM, &HiIsExact);
5549-
// The conversion from an integer-valued float to an APInt may fail if the
5550-
// result would be out of range. Regardless, taking this path is only
5551-
// possible if rounding occured during the initial `roundToIntegral`.
5552-
return HiStatus == opOK ? opInexact : HiStatus;
5553-
}
5554-
5555-
// A negative number cannot be represented by an unsigned integer.
5556-
// Since a double-double is canonical, if Hi is negative, the sum is negative.
5557-
if (!IsSigned && IntegralHi.isNegative())
5558-
return opInvalidOp;
5559-
5560-
// Handle the special boundary case where |Hi| is exactly the power of two
5561-
// that marks the edge of the integer's range (e.g., 2^63 for int64_t). In
5562-
// this situation, Hi itself won't fit, but the sum Hi + Lo might.
5563-
// `PositiveOverflowWidth` is the bit number for this boundary (N-1 for
5564-
// signed, N for unsigned).
5565-
bool LoIsExact;
5566-
const int HiExactLog2 = IntegralHi.getExactLog2Abs();
5567-
const unsigned PositiveOverflowWidth = IsSigned ? Width - 1 : Width;
5568-
if (HiExactLog2 >= 0 &&
5569-
static_cast<unsigned>(HiExactLog2) == PositiveOverflowWidth) {
5570-
// If Hi and Lo have the same sign, |Hi + Lo| > |Hi|, so the sum is
5571-
// guaranteed to overflow. E.g., for uint128_t, (2^128, 1) overflows.
5572-
if (IntegralHi.isNegative() == IntegralLo.isNegative())
5573-
return opInvalidOp;
5574-
5575-
// If the signs differ, the sum will fit. We can compute the result using
5576-
// properties of two's complement arithmetic without a wide intermediate
5577-
// integer. E.g., for uint128_t, (2^128, -1) should be 2^128 - 1.
5578-
[[maybe_unused]] opStatus LoStatus = IntegralLo.convertToInteger(
5579-
Input, Width, /*IsSigned=*/true, RM, &LoIsExact);
5580-
assert(LoStatus == opOK && "Unexpected failure");
5581-
5582-
// Adjust the bit pattern of Lo to account for Hi's value:
5583-
// - For unsigned (Hi=2^Width): `2^Width + Lo` in `Width`-bit
5584-
// arithmetic is equivalent to just `Lo`. The conversion of `Lo` above
5585-
// already produced the correct final bit pattern.
5586-
// - For signed (Hi=2^(Width-1)): The sum `2^(Width-1) + Lo` (where Lo<0)
5587-
// can be computed by taking the two's complement pattern for `Lo` and
5588-
// clearing the sign bit.
5589-
if (IsSigned && !IntegralHi.isNegative())
5590-
APInt::tcClearBit(Input.data(), PositiveOverflowWidth);
5591-
*IsExact = RoundStatus == opOK;
5592-
return RoundStatus;
5593-
}
5594-
5595-
// General case: Hi is not a power-of-two boundary, so we know it fits.
5596-
// Since we already rounded the full value, we now just need to convert the
5597-
// components to integers. The rounding mode should not matter.
5598-
[[maybe_unused]] opStatus HiStatus = IntegralHi.convertToInteger(
5599-
Input, Width, IsSigned, rmTowardZero, &HiIsExact);
5600-
assert(HiStatus == opOK && "Unexpected failure");
5601-
5602-
// Convert Lo into a temporary integer of the same width.
5603-
APSInt LoResult{Width, /*isUnsigned=*/!IsSigned};
5604-
[[maybe_unused]] opStatus LoStatus =
5605-
IntegralLo.convertToInteger(LoResult, rmTowardZero, &LoIsExact);
5606-
assert(LoStatus == opOK && "Unexpected failure");
5607-
5608-
// Add Lo to Hi. This addition is guaranteed not to overflow because of the
5609-
// double-double canonicalization rule (`|Lo| <= ulp(Hi)/2`). The only case
5610-
// where the sum could cross the integer type's boundary is when Hi is a
5611-
// power of two, which is handled by the special case block above.
5612-
APInt::tcAdd(Input.data(), LoResult.getRawData(), /*carry=*/0, Input.size());
5613-
5614-
*IsExact = RoundStatus == opOK;
5615-
return RoundStatus;
5616-
}
5617-
56185522
APFloat::opStatus
56195523
DoubleAPFloat::convertToInteger(MutableArrayRef<integerPart> Input,
56205524
unsigned int Width, bool IsSigned,
56215525
roundingMode RM, bool *IsExact) const {
5622-
opStatus FS =
5623-
convertToSignExtendedInteger(Input, Width, IsSigned, RM, IsExact);
5624-
5625-
if (FS == opInvalidOp) {
5626-
const unsigned DstPartsCount = partCountForBits(Width);
5627-
assert(DstPartsCount <= Parts.size() && "Integer too big");
5628-
5629-
unsigned Bits;
5630-
if (getCategory() == fcNaN)
5631-
Bits = 0;
5632-
else if (isNegative())
5633-
Bits = IsSigned;
5634-
else
5635-
Bits = Width - IsSigned;
5636-
5637-
tcSetLeastSignificantBits(Input.data(), DstPartsCount, Bits);
5638-
if (isNegative() && IsSigned)
5639-
APInt::tcShiftLeft(Input.data(), DstPartsCount, Width - 1);
5640-
}
5641-
5642-
return FS;
5526+
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
5527+
return APFloat(semPPCDoubleDoubleLegacy, bitcastToAPInt())
5528+
.convertToInteger(Input, Width, IsSigned, RM, IsExact);
56435529
}
56445530

56455531
APFloat::opStatus DoubleAPFloat::convertFromAPInt(const APInt &Input,
@@ -5740,31 +5626,14 @@ bool DoubleAPFloat::getExactInverse(APFloat *inv) const {
57405626
return Ret;
57415627
}
57425628

5629+
int DoubleAPFloat::getExactLog2() const {
5630+
// TODO: Implement me
5631+
return INT_MIN;
5632+
}
5633+
57435634
int DoubleAPFloat::getExactLog2Abs() const {
5744-
// In order for Hi + Lo to be a power of two, the following must be true:
5745-
// 1. Hi must be a power of two.
5746-
// 2. Lo must be zero.
5747-
if (getSecond().isNonZero())
5748-
return INT_MIN;
5749-
return getFirst().getExactLog2Abs();
5750-
}
5751-
5752-
int ilogb(const DoubleAPFloat& Arg) {
5753-
const APFloat& Hi = Arg.getFirst();
5754-
const APFloat& Lo = Arg.getSecond();
5755-
int IlogbResult = ilogb(Hi);
5756-
// Zero and non-finite values can delegate to ilogb(Hi).
5757-
if (Arg.getCategory() != fcNormal)
5758-
return IlogbResult;
5759-
// If Lo can't change the binade, we can delegate to ilogb(Hi).
5760-
if (Lo.isZero() ||
5761-
Hi.isNegative() == Lo.isNegative())
5762-
return IlogbResult;
5763-
if (Hi.getExactLog2Abs() == INT_MIN)
5764-
return IlogbResult;
5765-
// Numbers of the form 2^a - 2^b or -2^a + 2^b are almost powers of two but
5766-
// get nudged out of the binade by the low component.
5767-
return IlogbResult - 1;
5635+
// TODO: Implement me
5636+
return INT_MIN;
57685637
}
57695638

57705639
DoubleAPFloat scalbn(const DoubleAPFloat &Arg, int Exp,
@@ -5880,6 +5749,10 @@ void APFloat::Profile(FoldingSetNodeID &NID) const {
58805749
NID.Add(bitcastToAPInt());
58815750
}
58825751

5752+
/* Same as convertToInteger(integerPart*, ...), except the result is returned in
5753+
an APSInt, whose initial bit-width and signed-ness are used to determine the
5754+
precision of the conversion.
5755+
*/
58835756
APFloat::opStatus APFloat::convertToInteger(APSInt &result,
58845757
roundingMode rounding_mode,
58855758
bool *isExact) const {

0 commit comments

Comments
 (0)