diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h index 52ed183c78ae..c6fa5ad674f6 100644 --- a/llvm/include/llvm/ADT/APFloat.h +++ b/llvm/include/llvm/ADT/APFloat.h @@ -870,13 +870,13 @@ public: /// Factory for NaN values. /// /// \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. static APFloat getNaN(const fltSemantics &Sem, bool Negative = false, - unsigned type = 0) { - if (type) { - APInt fill(64, type); - return getQNaN(Sem, Negative, &fill); + uint64_t payload = 0) { + if (payload) { + APInt intPayload(64, payload); + return getQNaN(Sem, Negative, &intPayload); } else { return getQNaN(Sem, Negative, nullptr); } diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h index 52fc4da62b63..afc93cd61d47 100644 --- a/llvm/include/llvm/IR/Constants.h +++ b/llvm/include/llvm/IR/Constants.h @@ -290,7 +290,11 @@ public: static Constant *get(Type* Ty, StringRef Str); 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 *getInfinity(Type *Ty, bool Negative = false); diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index aa1d6c909b37..22ffc811511c 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -719,9 +719,9 @@ Constant *ConstantFP::get(Type *Ty, StringRef Str) { 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()); - APFloat NaN = APFloat::getNaN(Semantics, Negative, Type); + APFloat NaN = APFloat::getNaN(Semantics, Negative, Payload); Constant *C = get(Ty->getContext(), NaN); if (VectorType *VTy = dyn_cast(Ty)) @@ -730,6 +730,28 @@ Constant *ConstantFP::getNaN(Type *Ty, bool Negative, unsigned Type) { 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(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(Ty)) + return ConstantVector::getSplat(VTy->getNumElements(), C); + + return C; +} + Constant *ConstantFP::getNegativeZero(Type *Ty) { const fltSemantics &Semantics = *TypeToFloatSemantics(Ty->getScalarType()); APFloat NegZero = APFloat::getZero(Semantics, /*Negative=*/true); diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp index b739e857849d..64053a811a35 100644 --- a/llvm/unittests/ADT/APFloatTest.cpp +++ b/llvm/unittests/ADT/APFloatTest.cpp @@ -1070,33 +1070,49 @@ TEST(APFloatTest, toInteger) { EXPECT_EQ(APSInt::getMaxValue(5, false), result); } -static APInt nanbits(const fltSemantics &Sem, - bool SNaN, bool Negative, uint64_t fill) { - APInt apfill(64, fill); +static APInt nanbitsFromAPInt(const fltSemantics &Sem, bool SNaN, bool Negative, + uint64_t payload) { + APInt appayload(64, payload); if (SNaN) - return APFloat::getSNaN(Sem, Negative, &apfill).bitcastToAPInt(); + return APFloat::getSNaN(Sem, Negative, &appayload).bitcastToAPInt(); else - return APFloat::getQNaN(Sem, Negative, &apfill).bitcastToAPInt(); + return APFloat::getQNaN(Sem, Negative, &appayload).bitcastToAPInt(); } TEST(APFloatTest, makeNaN) { - ASSERT_EQ(0x7fc00000, nanbits(APFloat::IEEEsingle(), false, false, 0)); - ASSERT_EQ(0xffc00000, nanbits(APFloat::IEEEsingle(), false, true, 0)); - ASSERT_EQ(0x7fc0ae72, nanbits(APFloat::IEEEsingle(), false, false, 0xae72)); - ASSERT_EQ(0x7fffae72, nanbits(APFloat::IEEEsingle(), false, false, 0xffffae72)); - ASSERT_EQ(0x7fa00000, nanbits(APFloat::IEEEsingle(), true, false, 0)); - ASSERT_EQ(0xffa00000, nanbits(APFloat::IEEEsingle(), true, true, 0)); - ASSERT_EQ(0x7f80ae72, nanbits(APFloat::IEEEsingle(), true, false, 0xae72)); - ASSERT_EQ(0x7fbfae72, nanbits(APFloat::IEEEsingle(), true, false, 0xffffae72)); + const struct { + uint64_t expected; + const fltSemantics &semantics; + bool SNaN; + bool Negative; + uint64_t payload; + } tests[] = { + /* 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)); - ASSERT_EQ(0xfff8000000000000ULL, nanbits(APFloat::IEEEdouble(), false, true, 0)); - 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)); + for (const auto &t : tests) { + ASSERT_EQ(t.expected, nanbitsFromAPInt(t.semantics, t.SNaN, t.Negative, t.payload)); + } } #ifdef GTEST_HAS_DEATH_TEST