[Core] Grab-bag of improvements for Scalar.

Remove Scalar::Cast.

It was noted on the list that this method is unused. So, this patch
removes it.

Fix Scalar::Promote for most integer types

This fixes promotion of most integer types (128- and 256-bit types are
handled in a subsequent patch) to floating-point types. Previously
promotion was done bitwise, where value preservation is correct.

Fix Scalar::Promote for 128- and 256-bit integer types

This patch fixes the behavior of Scalar::Promote when trying to
perform a binary operation involving a 128- or 256-bit integer type
and a floating-point type. Now, the integer is cast to the floating
point type for the operation.

Patch by Tom Tromey!

Differential Revision:  https://reviews.llvm.org/D44907

llvm-svn: 328985
This commit is contained in:
Davide Italiano 2018-04-02 16:50:54 +00:00
parent f4e7e5210c
commit 49d802862d
3 changed files with 166 additions and 332 deletions

View File

@ -50,13 +50,13 @@ public:
e_ulong,
e_slonglong,
e_ulonglong,
e_sint128,
e_uint128,
e_sint256,
e_uint256,
e_float,
e_double,
e_long_double,
e_uint128,
e_sint128,
e_uint256,
e_sint256
e_long_double
};
//------------------------------------------------------------------
@ -165,8 +165,6 @@ public:
bool Promote(Scalar::Type type);
bool Cast(Scalar::Type type);
bool MakeSigned();
bool MakeUnsigned();

View File

@ -491,20 +491,24 @@ bool Scalar::Promote(Scalar::Type type) {
break;
case e_float:
m_float = llvm::APFloat(m_integer.bitsToFloat());
m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
m_float.convertFromAPInt(m_integer, true,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
m_float = llvm::APFloat(m_integer.bitsToDouble());
m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
m_float.convertFromAPInt(m_integer, true,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
if (m_ieee_quad)
m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
else
m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
: llvm::APFloat::x87DoubleExtended());
m_float.convertFromAPInt(m_integer, true,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@ -551,20 +555,24 @@ bool Scalar::Promote(Scalar::Type type) {
break;
case e_float:
m_float = llvm::APFloat(m_integer.bitsToFloat());
m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
m_float.convertFromAPInt(m_integer, false,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
m_float = llvm::APFloat(m_integer.bitsToDouble());
m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
m_float.convertFromAPInt(m_integer, false,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
if (m_ieee_quad)
m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
else
m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
: llvm::APFloat::x87DoubleExtended());
m_float.convertFromAPInt(m_integer, false,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@ -607,20 +615,24 @@ bool Scalar::Promote(Scalar::Type type) {
break;
case e_float:
m_float = llvm::APFloat(m_integer.bitsToFloat());
m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
m_float.convertFromAPInt(m_integer, true,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
m_float = llvm::APFloat(m_integer.bitsToDouble());
m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
m_float.convertFromAPInt(m_integer, true,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
if (m_ieee_quad)
m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
else
m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
: llvm::APFloat::x87DoubleExtended());
m_float.convertFromAPInt(m_integer, true,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@ -659,20 +671,24 @@ bool Scalar::Promote(Scalar::Type type) {
break;
case e_float:
m_float = llvm::APFloat(m_integer.bitsToFloat());
m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
m_float.convertFromAPInt(m_integer, false,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
m_float = llvm::APFloat(m_integer.bitsToDouble());
m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
m_float.convertFromAPInt(m_integer, false,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
if (m_ieee_quad)
m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
else
m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
: llvm::APFloat::x87DoubleExtended());
m_float.convertFromAPInt(m_integer, false,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@ -707,20 +723,24 @@ bool Scalar::Promote(Scalar::Type type) {
break;
case e_float:
m_float = llvm::APFloat(m_integer.bitsToFloat());
m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
m_float.convertFromAPInt(m_integer, true,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
m_float = llvm::APFloat(m_integer.bitsToDouble());
m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
m_float.convertFromAPInt(m_integer, true,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
if (m_ieee_quad)
m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
else
m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
: llvm::APFloat::x87DoubleExtended());
m_float.convertFromAPInt(m_integer, true,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@ -751,20 +771,24 @@ bool Scalar::Promote(Scalar::Type type) {
break;
case e_float:
m_float = llvm::APFloat(m_integer.bitsToFloat());
m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
m_float.convertFromAPInt(m_integer, false,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
m_float = llvm::APFloat(m_integer.bitsToDouble());
m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
m_float.convertFromAPInt(m_integer, false,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
if (m_ieee_quad)
m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
else
m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
: llvm::APFloat::x87DoubleExtended());
m_float.convertFromAPInt(m_integer, false,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@ -795,20 +819,24 @@ bool Scalar::Promote(Scalar::Type type) {
break;
case e_float:
m_float = llvm::APFloat(m_integer.bitsToFloat());
m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
m_float.convertFromAPInt(m_integer, true,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
m_float = llvm::APFloat(m_integer.bitsToDouble());
m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
m_float.convertFromAPInt(m_integer, true,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
if (m_ieee_quad)
m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
else
m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
: llvm::APFloat::x87DoubleExtended());
m_float.convertFromAPInt(m_integer, true,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@ -835,20 +863,24 @@ bool Scalar::Promote(Scalar::Type type) {
break;
case e_float:
m_float = llvm::APFloat(m_integer.bitsToFloat());
m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
m_float.convertFromAPInt(m_integer, false,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
m_float = llvm::APFloat(m_integer.bitsToDouble());
m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
m_float.convertFromAPInt(m_integer, false,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
if (m_ieee_quad)
m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
else
m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
: llvm::APFloat::x87DoubleExtended());
m_float.convertFromAPInt(m_integer, false,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@ -875,20 +907,24 @@ bool Scalar::Promote(Scalar::Type type) {
break;
case e_float:
m_float = llvm::APFloat(m_integer.bitsToFloat());
m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
m_float.convertFromAPInt(m_integer, true,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
m_float = llvm::APFloat(m_integer.bitsToDouble());
m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
m_float.convertFromAPInt(m_integer, true,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
if (m_ieee_quad)
m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
else
m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
: llvm::APFloat::x87DoubleExtended());
m_float.convertFromAPInt(m_integer, true,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@ -911,20 +947,24 @@ bool Scalar::Promote(Scalar::Type type) {
success = true;
break;
case e_float:
m_float = llvm::APFloat(m_integer.bitsToFloat());
m_float = llvm::APFloat(llvm::APFloat::IEEEsingle());
m_float.convertFromAPInt(m_integer, false,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_double:
m_float = llvm::APFloat(m_integer.bitsToDouble());
m_float = llvm::APFloat(llvm::APFloat::IEEEdouble());
m_float.convertFromAPInt(m_integer, false,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case e_long_double:
if (m_ieee_quad)
m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
else
m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
m_float = llvm::APFloat(m_ieee_quad ? llvm::APFloat::IEEEquad()
: llvm::APFloat::x87DoubleExtended());
m_float.convertFromAPInt(m_integer, false,
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
}
@ -948,20 +988,19 @@ bool Scalar::Promote(Scalar::Type type) {
success = true;
break;
case e_double:
m_float = llvm::APFloat((float_t)m_float.convertToFloat());
m_float = llvm::APFloat((double_t)m_float.convertToFloat());
success = true;
break;
case e_long_double:
if (m_ieee_quad)
m_float =
llvm::APFloat(llvm::APFloat::IEEEquad(), m_float.bitcastToAPInt());
else
m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(),
m_float.bitcastToAPInt());
case e_long_double: {
bool ignore;
m_float.convert(m_ieee_quad ? llvm::APFloat::IEEEquad()
: llvm::APFloat::x87DoubleExtended(),
llvm::APFloat::rmNearestTiesToEven, &ignore);
success = true;
break;
}
}
break;
case e_double:
@ -982,16 +1021,15 @@ bool Scalar::Promote(Scalar::Type type) {
case e_double:
success = true;
break;
case e_long_double:
if (m_ieee_quad)
m_float =
llvm::APFloat(llvm::APFloat::IEEEquad(), m_float.bitcastToAPInt());
else
m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(),
m_float.bitcastToAPInt());
case e_long_double: {
bool ignore;
m_float.convert(m_ieee_quad ? llvm::APFloat::IEEEquad()
: llvm::APFloat::x87DoubleExtended(),
llvm::APFloat::rmNearestTiesToEven, &ignore);
success = true;
break;
}
}
break;
case e_long_double:
@ -1088,253 +1126,6 @@ Scalar::Type Scalar::GetValueTypeForFloatWithByteSize(size_t byte_size) {
return e_void;
}
bool Scalar::Cast(Scalar::Type type) {
bool success = false;
switch (m_type) {
case e_void:
break;
case e_sint:
case e_uint:
case e_slong:
case e_ulong:
case e_slonglong:
case e_ulonglong:
case e_sint128:
case e_uint128:
case e_sint256:
case e_uint256:
switch (type) {
case e_void:
break;
case e_sint:
m_integer = m_integer.sextOrTrunc(sizeof(sint_t) * 8);
success = true;
break;
case e_uint:
m_integer = m_integer.zextOrTrunc(sizeof(sint_t) * 8);
success = true;
break;
case e_slong:
m_integer = m_integer.sextOrTrunc(sizeof(slong_t) * 8);
success = true;
break;
case e_ulong:
m_integer = m_integer.zextOrTrunc(sizeof(slong_t) * 8);
success = true;
break;
case e_slonglong:
m_integer = m_integer.sextOrTrunc(sizeof(slonglong_t) * 8);
success = true;
break;
case e_ulonglong:
m_integer = m_integer.zextOrTrunc(sizeof(slonglong_t) * 8);
success = true;
break;
case e_sint128:
m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128);
success = true;
break;
case e_uint128:
m_integer = m_integer.zextOrTrunc(BITWIDTH_INT128);
success = true;
break;
case e_sint256:
m_integer = m_integer.sextOrTrunc(BITWIDTH_INT256);
success = true;
break;
case e_uint256:
m_integer = m_integer.zextOrTrunc(BITWIDTH_INT256);
success = true;
break;
case e_float:
m_float = llvm::APFloat(m_integer.bitsToFloat());
success = true;
break;
case e_double:
m_float = llvm::APFloat(m_integer.bitsToDouble());
success = true;
break;
case e_long_double:
if (m_ieee_quad)
m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer);
else
m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer);
success = true;
break;
}
break;
case e_float:
switch (type) {
case e_void:
break;
case e_sint:
case e_uint:
case e_slong:
case e_ulong:
case e_slonglong:
case e_ulonglong:
case e_sint128:
case e_uint128:
case e_sint256:
case e_uint256:
m_integer = m_float.bitcastToAPInt();
success = true;
break;
case e_float:
m_float = llvm::APFloat(m_float.convertToFloat());
success = true;
break;
case e_double:
m_float = llvm::APFloat(m_float.convertToFloat());
success = true;
break;
case e_long_double:
if (m_ieee_quad)
m_float =
llvm::APFloat(llvm::APFloat::IEEEquad(), m_float.bitcastToAPInt());
else
m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(),
m_float.bitcastToAPInt());
success = true;
break;
}
break;
case e_double:
switch (type) {
case e_void:
break;
case e_sint:
case e_uint:
case e_slong:
case e_ulong:
case e_slonglong:
case e_ulonglong:
case e_sint128:
case e_uint128:
case e_sint256:
case e_uint256:
m_integer = m_float.bitcastToAPInt();
success = true;
break;
case e_float:
m_float = llvm::APFloat(m_float.convertToDouble());
success = true;
break;
case e_double:
m_float = llvm::APFloat(m_float.convertToDouble());
success = true;
break;
case e_long_double:
if (m_ieee_quad)
m_float =
llvm::APFloat(llvm::APFloat::IEEEquad(), m_float.bitcastToAPInt());
else
m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(),
m_float.bitcastToAPInt());
success = true;
break;
}
break;
case e_long_double:
switch (type) {
case e_void:
break;
case e_sint:
m_integer = m_float.bitcastToAPInt();
m_integer = m_integer.sextOrTrunc(sizeof(sint_t) * 8);
success = true;
break;
case e_uint:
m_integer = m_float.bitcastToAPInt();
m_integer = m_integer.zextOrTrunc(sizeof(sint_t) * 8);
success = true;
break;
case e_slong:
m_integer = m_float.bitcastToAPInt();
m_integer = m_integer.sextOrTrunc(sizeof(slong_t) * 8);
success = true;
break;
case e_ulong:
m_integer = m_float.bitcastToAPInt();
m_integer = m_integer.zextOrTrunc(sizeof(slong_t) * 8);
success = true;
break;
case e_slonglong:
m_integer = m_float.bitcastToAPInt();
m_integer = m_integer.sextOrTrunc(sizeof(slonglong_t) * 8);
success = true;
break;
case e_ulonglong:
m_integer = m_float.bitcastToAPInt();
m_integer = m_integer.zextOrTrunc(sizeof(slonglong_t) * 8);
success = true;
break;
case e_sint128:
m_integer = m_float.bitcastToAPInt();
m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128);
success = true;
break;
case e_uint128:
m_integer = m_float.bitcastToAPInt();
m_integer = m_integer.zextOrTrunc(BITWIDTH_INT128);
success = true;
break;
case e_sint256:
m_integer = m_float.bitcastToAPInt();
m_integer = m_integer.sextOrTrunc(BITWIDTH_INT256);
success = true;
break;
case e_uint256:
m_integer = m_float.bitcastToAPInt();
m_integer = m_integer.zextOrTrunc(BITWIDTH_INT256);
success = true;
break;
case e_float:
m_float = llvm::APFloat(m_float.convertToFloat());
success = true;
break;
case e_double:
m_float = llvm::APFloat(m_float.convertToFloat());
success = true;
break;
case e_long_double:
success = true;
break;
}
break;
}
if (success)
m_type = type;
return success;
}
bool Scalar::MakeSigned() {
bool success = false;
@ -1819,7 +1610,7 @@ float Scalar::Float(float fail_value) const {
case e_uint128:
case e_sint256:
case e_uint256:
return m_integer.bitsToFloat();
return llvm::APIntOps::RoundAPIntToFloat(m_integer);
case e_float:
return m_float.convertToFloat();
case e_double:
@ -1845,7 +1636,7 @@ double Scalar::Double(double fail_value) const {
case e_uint128:
case e_sint256:
case e_uint256:
return m_integer.bitsToDouble();
return llvm::APIntOps::RoundAPIntToDouble(m_integer);
case e_float:
return (double_t)m_float.convertToFloat();
case e_double:
@ -1871,7 +1662,7 @@ long double Scalar::LongDouble(long double fail_value) const {
case e_uint128:
case e_sint256:
case e_uint256:
return (long_double_t)m_integer.bitsToDouble();
return (long_double_t)llvm::APIntOps::RoundAPIntToDouble(m_integer);
case e_float:
return (long_double_t)m_float.convertToFloat();
case e_double:

View File

@ -73,6 +73,12 @@ TEST(ScalarTest, CastOperations) {
ASSERT_EQ((unsigned long)a, a_scalar.ULong());
ASSERT_EQ((signed long long)a, a_scalar.SLongLong());
ASSERT_EQ((unsigned long long)a, a_scalar.ULongLong());
int a2 = 23;
Scalar a2_scalar(a2);
ASSERT_EQ((float)a2, a2_scalar.Float());
ASSERT_EQ((double)a2, a2_scalar.Double());
ASSERT_EQ((long double)a2, a2_scalar.LongDouble());
}
TEST(ScalarTest, ExtractBitfield) {
@ -140,3 +146,42 @@ TEST(ScalarTest, Division) {
EXPECT_TRUE(r.IsValid());
EXPECT_EQ(r, Scalar(2.5));
}
TEST(ScalarTest, Promotion) {
static Scalar::Type int_types[] = {
Scalar::e_sint, Scalar::e_uint, Scalar::e_slong,
Scalar::e_ulong, Scalar::e_slonglong, Scalar::e_ulonglong,
Scalar::e_sint128, Scalar::e_uint128, Scalar::e_sint256,
Scalar::e_uint256,
Scalar::e_void // sentinel
};
static Scalar::Type float_types[] = {
Scalar::e_float, Scalar::e_double, Scalar::e_long_double,
Scalar::e_void // sentinel
};
for (int i = 0; int_types[i] != Scalar::e_void; ++i) {
for (int j = 0; float_types[j] != Scalar::e_void; ++j) {
Scalar lhs(2);
EXPECT_TRUE(lhs.Promote(int_types[i])) << "int promotion #" << i;
Scalar rhs(0.5f);
EXPECT_TRUE(rhs.Promote(float_types[j])) << "float promotion #" << j;
Scalar x(2.5f);
EXPECT_TRUE(x.Promote(float_types[j]));
EXPECT_EQ(lhs + rhs, x);
}
}
for (int i = 0; float_types[i] != Scalar::e_void; ++i) {
for (int j = 0; float_types[j] != Scalar::e_void; ++j) {
Scalar lhs(2);
EXPECT_TRUE(lhs.Promote(float_types[i])) << "float promotion #" << i;
Scalar rhs(0.5f);
EXPECT_TRUE(rhs.Promote(float_types[j])) << "float promotion #" << j;
Scalar x(2.5f);
EXPECT_TRUE(x.Promote(float_types[j]));
EXPECT_EQ(lhs + rhs, x);
}
}
}