forked from OSchip/llvm-project
APFloat: allow 64-bit of payload
Summary: The APFloat and Constant APIs taking an APInt allow arbitrary payloads, and that's great. There's a convenience API which takes an unsigned, and that's silly because it then directly creates a 64-bit APInt. Just change it to 64-bits directly. At the same time, add ConstantFP NaN getters which match the APFloat ones (with getQNaN / getSNaN and APInt parameters). Improve the APFloat testing to set more payload bits. Reviewers: scanon, rjmccall Subscribers: jkorous, dexonsmith, kristina, llvm-commits Differential Revision: https://reviews.llvm.org/D55460 llvm-svn: 348791
This commit is contained in:
parent
ce2837f880
commit
69f6098e89
|
@ -870,13 +870,13 @@ public:
|
||||||
/// Factory for NaN values.
|
/// Factory for NaN values.
|
||||||
///
|
///
|
||||||
/// \param Negative - True iff the NaN generated should be negative.
|
/// \param Negative - True iff the NaN generated should be negative.
|
||||||
/// \param type - The unspecified fill bits for creating the NaN, 0 by
|
/// \param payload - The unspecified fill bits for creating the NaN, 0 by
|
||||||
/// default. The value is truncated as necessary.
|
/// default. The value is truncated as necessary.
|
||||||
static APFloat getNaN(const fltSemantics &Sem, bool Negative = false,
|
static APFloat getNaN(const fltSemantics &Sem, bool Negative = false,
|
||||||
unsigned type = 0) {
|
uint64_t payload = 0) {
|
||||||
if (type) {
|
if (payload) {
|
||||||
APInt fill(64, type);
|
APInt intPayload(64, payload);
|
||||||
return getQNaN(Sem, Negative, &fill);
|
return getQNaN(Sem, Negative, &intPayload);
|
||||||
} else {
|
} else {
|
||||||
return getQNaN(Sem, Negative, nullptr);
|
return getQNaN(Sem, Negative, nullptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -290,7 +290,11 @@ public:
|
||||||
|
|
||||||
static Constant *get(Type* Ty, StringRef Str);
|
static Constant *get(Type* Ty, StringRef Str);
|
||||||
static ConstantFP *get(LLVMContext &Context, const APFloat &V);
|
static ConstantFP *get(LLVMContext &Context, const APFloat &V);
|
||||||
static Constant *getNaN(Type *Ty, bool Negative = false, unsigned type = 0);
|
static Constant *getNaN(Type *Ty, bool Negative = false, uint64_t Payload = 0);
|
||||||
|
static Constant *getQNaN(Type *Ty, bool Negative = false,
|
||||||
|
APInt *Payload = nullptr);
|
||||||
|
static Constant *getSNaN(Type *Ty, bool Negative = false,
|
||||||
|
APInt *Payload = nullptr);
|
||||||
static Constant *getNegativeZero(Type *Ty);
|
static Constant *getNegativeZero(Type *Ty);
|
||||||
static Constant *getInfinity(Type *Ty, bool Negative = false);
|
static Constant *getInfinity(Type *Ty, bool Negative = false);
|
||||||
|
|
||||||
|
|
|
@ -719,9 +719,9 @@ Constant *ConstantFP::get(Type *Ty, StringRef Str) {
|
||||||
return C;
|
return C;
|
||||||
}
|
}
|
||||||
|
|
||||||
Constant *ConstantFP::getNaN(Type *Ty, bool Negative, unsigned Type) {
|
Constant *ConstantFP::getNaN(Type *Ty, bool Negative, uint64_t Payload) {
|
||||||
const fltSemantics &Semantics = *TypeToFloatSemantics(Ty->getScalarType());
|
const fltSemantics &Semantics = *TypeToFloatSemantics(Ty->getScalarType());
|
||||||
APFloat NaN = APFloat::getNaN(Semantics, Negative, Type);
|
APFloat NaN = APFloat::getNaN(Semantics, Negative, Payload);
|
||||||
Constant *C = get(Ty->getContext(), NaN);
|
Constant *C = get(Ty->getContext(), NaN);
|
||||||
|
|
||||||
if (VectorType *VTy = dyn_cast<VectorType>(Ty))
|
if (VectorType *VTy = dyn_cast<VectorType>(Ty))
|
||||||
|
@ -730,6 +730,28 @@ Constant *ConstantFP::getNaN(Type *Ty, bool Negative, unsigned Type) {
|
||||||
return C;
|
return C;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Constant *ConstantFP::getQNaN(Type *Ty, bool Negative, APInt *Payload) {
|
||||||
|
const fltSemantics &Semantics = *TypeToFloatSemantics(Ty->getScalarType());
|
||||||
|
APFloat NaN = APFloat::getQNaN(Semantics, Negative, Payload);
|
||||||
|
Constant *C = get(Ty->getContext(), NaN);
|
||||||
|
|
||||||
|
if (VectorType *VTy = dyn_cast<VectorType>(Ty))
|
||||||
|
return ConstantVector::getSplat(VTy->getNumElements(), C);
|
||||||
|
|
||||||
|
return C;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constant *ConstantFP::getSNaN(Type *Ty, bool Negative, APInt *Payload) {
|
||||||
|
const fltSemantics &Semantics = *TypeToFloatSemantics(Ty->getScalarType());
|
||||||
|
APFloat NaN = APFloat::getSNaN(Semantics, Negative, Payload);
|
||||||
|
Constant *C = get(Ty->getContext(), NaN);
|
||||||
|
|
||||||
|
if (VectorType *VTy = dyn_cast<VectorType>(Ty))
|
||||||
|
return ConstantVector::getSplat(VTy->getNumElements(), C);
|
||||||
|
|
||||||
|
return C;
|
||||||
|
}
|
||||||
|
|
||||||
Constant *ConstantFP::getNegativeZero(Type *Ty) {
|
Constant *ConstantFP::getNegativeZero(Type *Ty) {
|
||||||
const fltSemantics &Semantics = *TypeToFloatSemantics(Ty->getScalarType());
|
const fltSemantics &Semantics = *TypeToFloatSemantics(Ty->getScalarType());
|
||||||
APFloat NegZero = APFloat::getZero(Semantics, /*Negative=*/true);
|
APFloat NegZero = APFloat::getZero(Semantics, /*Negative=*/true);
|
||||||
|
|
|
@ -1070,33 +1070,49 @@ TEST(APFloatTest, toInteger) {
|
||||||
EXPECT_EQ(APSInt::getMaxValue(5, false), result);
|
EXPECT_EQ(APSInt::getMaxValue(5, false), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static APInt nanbits(const fltSemantics &Sem,
|
static APInt nanbitsFromAPInt(const fltSemantics &Sem, bool SNaN, bool Negative,
|
||||||
bool SNaN, bool Negative, uint64_t fill) {
|
uint64_t payload) {
|
||||||
APInt apfill(64, fill);
|
APInt appayload(64, payload);
|
||||||
if (SNaN)
|
if (SNaN)
|
||||||
return APFloat::getSNaN(Sem, Negative, &apfill).bitcastToAPInt();
|
return APFloat::getSNaN(Sem, Negative, &appayload).bitcastToAPInt();
|
||||||
else
|
else
|
||||||
return APFloat::getQNaN(Sem, Negative, &apfill).bitcastToAPInt();
|
return APFloat::getQNaN(Sem, Negative, &appayload).bitcastToAPInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(APFloatTest, makeNaN) {
|
TEST(APFloatTest, makeNaN) {
|
||||||
ASSERT_EQ(0x7fc00000, nanbits(APFloat::IEEEsingle(), false, false, 0));
|
const struct {
|
||||||
ASSERT_EQ(0xffc00000, nanbits(APFloat::IEEEsingle(), false, true, 0));
|
uint64_t expected;
|
||||||
ASSERT_EQ(0x7fc0ae72, nanbits(APFloat::IEEEsingle(), false, false, 0xae72));
|
const fltSemantics &semantics;
|
||||||
ASSERT_EQ(0x7fffae72, nanbits(APFloat::IEEEsingle(), false, false, 0xffffae72));
|
bool SNaN;
|
||||||
ASSERT_EQ(0x7fa00000, nanbits(APFloat::IEEEsingle(), true, false, 0));
|
bool Negative;
|
||||||
ASSERT_EQ(0xffa00000, nanbits(APFloat::IEEEsingle(), true, true, 0));
|
uint64_t payload;
|
||||||
ASSERT_EQ(0x7f80ae72, nanbits(APFloat::IEEEsingle(), true, false, 0xae72));
|
} tests[] = {
|
||||||
ASSERT_EQ(0x7fbfae72, nanbits(APFloat::IEEEsingle(), true, false, 0xffffae72));
|
/* expected semantics SNaN Neg payload */
|
||||||
|
{ 0x7fc00000ULL, APFloat::IEEEsingle(), false, false, 0x00000000ULL },
|
||||||
|
{ 0xffc00000ULL, APFloat::IEEEsingle(), false, true, 0x00000000ULL },
|
||||||
|
{ 0x7fc0ae72ULL, APFloat::IEEEsingle(), false, false, 0x0000ae72ULL },
|
||||||
|
{ 0x7fffae72ULL, APFloat::IEEEsingle(), false, false, 0xffffae72ULL },
|
||||||
|
{ 0x7fdaae72ULL, APFloat::IEEEsingle(), false, false, 0x00daae72ULL },
|
||||||
|
{ 0x7fa00000ULL, APFloat::IEEEsingle(), true, false, 0x00000000ULL },
|
||||||
|
{ 0xffa00000ULL, APFloat::IEEEsingle(), true, true, 0x00000000ULL },
|
||||||
|
{ 0x7f80ae72ULL, APFloat::IEEEsingle(), true, false, 0x0000ae72ULL },
|
||||||
|
{ 0x7fbfae72ULL, APFloat::IEEEsingle(), true, false, 0xffffae72ULL },
|
||||||
|
{ 0x7f9aae72ULL, APFloat::IEEEsingle(), true, false, 0x001aae72ULL },
|
||||||
|
{ 0x7ff8000000000000ULL, APFloat::IEEEdouble(), false, false, 0x0000000000000000ULL },
|
||||||
|
{ 0xfff8000000000000ULL, APFloat::IEEEdouble(), false, true, 0x0000000000000000ULL },
|
||||||
|
{ 0x7ff800000000ae72ULL, APFloat::IEEEdouble(), false, false, 0x000000000000ae72ULL },
|
||||||
|
{ 0x7fffffffffffae72ULL, APFloat::IEEEdouble(), false, false, 0xffffffffffffae72ULL },
|
||||||
|
{ 0x7ffdaaaaaaaaae72ULL, APFloat::IEEEdouble(), false, false, 0x000daaaaaaaaae72ULL },
|
||||||
|
{ 0x7ff4000000000000ULL, APFloat::IEEEdouble(), true, false, 0x0000000000000000ULL },
|
||||||
|
{ 0xfff4000000000000ULL, APFloat::IEEEdouble(), true, true, 0x0000000000000000ULL },
|
||||||
|
{ 0x7ff000000000ae72ULL, APFloat::IEEEdouble(), true, false, 0x000000000000ae72ULL },
|
||||||
|
{ 0x7ff7ffffffffae72ULL, APFloat::IEEEdouble(), true, false, 0xffffffffffffae72ULL },
|
||||||
|
{ 0x7ff1aaaaaaaaae72ULL, APFloat::IEEEdouble(), true, false, 0x0001aaaaaaaaae72ULL },
|
||||||
|
};
|
||||||
|
|
||||||
ASSERT_EQ(0x7ff8000000000000ULL, nanbits(APFloat::IEEEdouble(), false, false, 0));
|
for (const auto &t : tests) {
|
||||||
ASSERT_EQ(0xfff8000000000000ULL, nanbits(APFloat::IEEEdouble(), false, true, 0));
|
ASSERT_EQ(t.expected, nanbitsFromAPInt(t.semantics, t.SNaN, t.Negative, t.payload));
|
||||||
ASSERT_EQ(0x7ff800000000ae72ULL, nanbits(APFloat::IEEEdouble(), false, false, 0xae72));
|
}
|
||||||
ASSERT_EQ(0x7fffffffffffae72ULL, nanbits(APFloat::IEEEdouble(), false, false, 0xffffffffffffae72ULL));
|
|
||||||
ASSERT_EQ(0x7ff4000000000000ULL, nanbits(APFloat::IEEEdouble(), true, false, 0));
|
|
||||||
ASSERT_EQ(0xfff4000000000000ULL, nanbits(APFloat::IEEEdouble(), true, true, 0));
|
|
||||||
ASSERT_EQ(0x7ff000000000ae72ULL, nanbits(APFloat::IEEEdouble(), true, false, 0xae72));
|
|
||||||
ASSERT_EQ(0x7ff7ffffffffae72ULL, nanbits(APFloat::IEEEdouble(), true, false, 0xffffffffffffae72ULL));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GTEST_HAS_DEATH_TEST
|
#ifdef GTEST_HAS_DEATH_TEST
|
||||||
|
|
Loading…
Reference in New Issue