summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/ADT/APFloat.h14
-rw-r--r--llvm/lib/IR/AsmWriter.cpp45
-rw-r--r--llvm/lib/Support/APFloat.cpp31
-rw-r--r--llvm/unittests/ADT/APFloatTest.cpp21
4 files changed, 74 insertions, 37 deletions
diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h
index e7e5036e693..bef6efde1f0 100644
--- a/llvm/include/llvm/ADT/APFloat.h
+++ b/llvm/include/llvm/ADT/APFloat.h
@@ -397,6 +397,12 @@ public:
/// consider inserting before falling back to scientific
/// notation. 0 means to always use scientific notation.
///
+ /// \param TruncateZero Indicate whether to remove the trailing zero in
+ /// fraction part or not. Also setting this parameter to false forcing
+ /// producing of output more similar to default printf behavior.
+ /// Specifically the lower e is used as exponent delimiter and exponent
+ /// always contains no less than two digits.
+ ///
/// Number Precision MaxPadding Result
/// ------ --------- ---------- ------
/// 1.01E+4 5 2 10100
@@ -406,7 +412,7 @@ public:
/// 1.01E-2 4 2 0.0101
/// 1.01E-2 4 1 1.01E-2
void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision = 0,
- unsigned FormatMaxPadding = 3) const;
+ unsigned FormatMaxPadding = 3, bool TruncateZero = true) const;
/// If this value has an exact multiplicative inverse, store it in inv and
/// return true.
@@ -649,7 +655,7 @@ public:
bool isInteger() const;
void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision,
- unsigned FormatMaxPadding) const;
+ unsigned FormatMaxPadding, bool TruncateZero = true) const;
bool getExactInverse(APFloat *inv) const;
@@ -1144,9 +1150,9 @@ public:
APFloat &operator=(APFloat &&RHS) = default;
void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision = 0,
- unsigned FormatMaxPadding = 3) const {
+ unsigned FormatMaxPadding = 3, bool TruncateZero = true) const {
APFLOAT_DISPATCH_ON_SEMANTICS(
- toString(Str, FormatPrecision, FormatMaxPadding));
+ toString(Str, FormatPrecision, FormatMaxPadding, TruncateZero));
}
void print(raw_ostream &) const;
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index d0b77e7218b..27f6e366876 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -1103,35 +1103,34 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
}
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
- if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEsingle() ||
- &CFP->getValueAPF().getSemantics() == &APFloat::IEEEdouble()) {
+ const APFloat &APF = CFP->getValueAPF();
+ if (&APF.getSemantics() == &APFloat::IEEEsingle() ||
+ &APF.getSemantics() == &APFloat::IEEEdouble()) {
// We would like to output the FP constant value in exponential notation,
// but we cannot do this if doing so will lose precision. Check here to
// make sure that we only output it in exponential format if we can parse
// the value back and get the same value.
//
bool ignored;
- bool isDouble = &CFP->getValueAPF().getSemantics()==&APFloat::IEEEdouble();
- bool isInf = CFP->getValueAPF().isInfinity();
- bool isNaN = CFP->getValueAPF().isNaN();
+ bool isDouble = &APF.getSemantics() == &APFloat::IEEEdouble();
+ bool isInf = APF.isInfinity();
+ bool isNaN = APF.isNaN();
if (!isInf && !isNaN) {
- double Val = isDouble ? CFP->getValueAPF().convertToDouble() :
- CFP->getValueAPF().convertToFloat();
+ double Val = isDouble ? APF.convertToDouble() : APF.convertToFloat();
SmallString<128> StrVal;
- raw_svector_ostream(StrVal) << Val;
-
+ APF.toString(StrVal, 6, 0, false);
// Check to make sure that the stringized number is not some string like
// "Inf" or NaN, that atof will accept, but the lexer will not. Check
// that the string matches the "[-+]?[0-9]" regex.
//
- if ((StrVal[0] >= '0' && StrVal[0] <= '9') ||
- ((StrVal[0] == '-' || StrVal[0] == '+') &&
- (StrVal[1] >= '0' && StrVal[1] <= '9'))) {
- // Reparse stringized version!
- if (APFloat(APFloat::IEEEdouble(), StrVal).convertToDouble() == Val) {
- Out << StrVal;
- return;
- }
+ assert((StrVal[0] >= '0' && StrVal[0] <= '9') ||
+ ((StrVal[0] == '-' || StrVal[0] == '+') &&
+ (StrVal[1] >= '0' && StrVal[1] <= '9')) &&
+ "[-+]?[0-9] regex does not match!");
+ // Reparse stringized version!
+ if (APFloat(APFloat::IEEEdouble(), StrVal).convertToDouble() == Val) {
+ Out << StrVal;
+ return;
}
}
// Otherwise we could not reparse it to exactly the same value, so we must
@@ -1140,7 +1139,7 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
// x86, so we must not use these types.
static_assert(sizeof(double) == sizeof(uint64_t),
"assuming that double is 64 bits!");
- APFloat apf = CFP->getValueAPF();
+ APFloat apf = APF;
// Floats are represented in ASCII IR as double, convert.
if (!isDouble)
apf.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven,
@@ -1153,27 +1152,27 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
// These appear as a magic letter identifying the type, then a
// fixed number of hex digits.
Out << "0x";
- APInt API = CFP->getValueAPF().bitcastToAPInt();
- if (&CFP->getValueAPF().getSemantics() == &APFloat::x87DoubleExtended()) {
+ APInt API = APF.bitcastToAPInt();
+ if (&APF.getSemantics() == &APFloat::x87DoubleExtended()) {
Out << 'K';
Out << format_hex_no_prefix(API.getHiBits(16).getZExtValue(), 4,
/*Upper=*/true);
Out << format_hex_no_prefix(API.getLoBits(64).getZExtValue(), 16,
/*Upper=*/true);
return;
- } else if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEquad()) {
+ } else if (&APF.getSemantics() == &APFloat::IEEEquad()) {
Out << 'L';
Out << format_hex_no_prefix(API.getLoBits(64).getZExtValue(), 16,
/*Upper=*/true);
Out << format_hex_no_prefix(API.getHiBits(64).getZExtValue(), 16,
/*Upper=*/true);
- } else if (&CFP->getValueAPF().getSemantics() == &APFloat::PPCDoubleDouble()) {
+ } else if (&APF.getSemantics() == &APFloat::PPCDoubleDouble()) {
Out << 'M';
Out << format_hex_no_prefix(API.getLoBits(64).getZExtValue(), 16,
/*Upper=*/true);
Out << format_hex_no_prefix(API.getHiBits(64).getZExtValue(), 16,
/*Upper=*/true);
- } else if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEhalf()) {
+ } else if (&APF.getSemantics() == &APFloat::IEEEhalf()) {
Out << 'H';
Out << format_hex_no_prefix(API.getZExtValue(), 4,
/*Upper=*/true);
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index c4c892f0352..e1e2c22e1df 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -3393,7 +3393,7 @@ namespace {
}
void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision,
- unsigned FormatMaxPadding) const {
+ unsigned FormatMaxPadding, bool TruncateZero) const {
switch (category) {
case fcInfinity:
if (isNegative())
@@ -3407,9 +3407,16 @@ void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision,
if (isNegative())
Str.push_back('-');
- if (!FormatMaxPadding)
- append(Str, "0.0E+0");
- else
+ if (!FormatMaxPadding) {
+ if (TruncateZero)
+ append(Str, "0.0E+0");
+ else {
+ append(Str, "0.0");
+ if (FormatPrecision > 1)
+ Str.append(FormatPrecision - 1, '0');
+ append(Str, "e+00");
+ }
+ } else
Str.push_back('0');
return;
@@ -3543,12 +3550,16 @@ void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision,
Str.push_back(buffer[NDigits-1]);
Str.push_back('.');
- if (NDigits == 1)
+ if (NDigits == 1 && TruncateZero)
Str.push_back('0');
else
for (unsigned I = 1; I != NDigits; ++I)
Str.push_back(buffer[NDigits-1-I]);
- Str.push_back('E');
+ // Fill with zeros up to FormatPrecision.
+ if (!TruncateZero && FormatPrecision > NDigits - 1)
+ Str.append(FormatPrecision - NDigits + 1, '0');
+ // For !TruncateZero we use lower 'e'.
+ Str.push_back(TruncateZero ? 'E' : 'e');
Str.push_back(exp >= 0 ? '+' : '-');
if (exp < 0) exp = -exp;
@@ -3557,6 +3568,9 @@ void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision,
expbuf.push_back((char) ('0' + (exp % 10)));
exp /= 10;
} while (exp);
+ // Exponent always at least two digits if we do not truncate zeros.
+ if (!TruncateZero && expbuf.size() < 2)
+ expbuf.push_back('0');
for (unsigned I = 0, E = expbuf.size(); I != E; ++I)
Str.push_back(expbuf[E-1-I]);
return;
@@ -4362,10 +4376,11 @@ bool DoubleAPFloat::isInteger() const {
void DoubleAPFloat::toString(SmallVectorImpl<char> &Str,
unsigned FormatPrecision,
- unsigned FormatMaxPadding) const {
+ unsigned FormatMaxPadding,
+ bool TruncateZero) const {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
APFloat(semPPCDoubleDoubleLegacy, bitcastToAPInt())
- .toString(Str, FormatPrecision, FormatMaxPadding);
+ .toString(Str, FormatPrecision, FormatMaxPadding, TruncateZero);
}
bool DoubleAPFloat::getExactInverse(APFloat *inv) const {
diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp
index 378c48d7e0a..338f2b8a5a6 100644
--- a/llvm/unittests/ADT/APFloatTest.cpp
+++ b/llvm/unittests/ADT/APFloatTest.cpp
@@ -27,10 +27,11 @@ static double convertToDoubleFromString(const char *Str) {
return F.convertToDouble();
}
-static std::string convertToString(double d, unsigned Prec, unsigned Pad) {
+static std::string convertToString(double d, unsigned Prec, unsigned Pad,
+ bool Tr = true) {
llvm::SmallVector<char, 100> Buffer;
llvm::APFloat F(d);
- F.toString(Buffer, Prec, Pad);
+ F.toString(Buffer, Prec, Pad, Tr);
return std::string(Buffer.data(), Buffer.size());
}
@@ -949,6 +950,22 @@ TEST(APFloatTest, toString) {
ASSERT_EQ("873.18340000000001", convertToString(873.1834, 0, 1));
ASSERT_EQ("8.7318340000000001E+2", convertToString(873.1834, 0, 0));
ASSERT_EQ("1.7976931348623157E+308", convertToString(1.7976931348623157E+308, 0, 0));
+ ASSERT_EQ("10", convertToString(10.0, 6, 3, false));
+ ASSERT_EQ("1.000000e+01", convertToString(10.0, 6, 0, false));
+ ASSERT_EQ("10100", convertToString(1.01E+4, 5, 2, false));
+ ASSERT_EQ("1.0100e+04", convertToString(1.01E+4, 4, 2, false));
+ ASSERT_EQ("1.01000e+04", convertToString(1.01E+4, 5, 1, false));
+ ASSERT_EQ("0.0101", convertToString(1.01E-2, 5, 2, false));
+ ASSERT_EQ("0.0101", convertToString(1.01E-2, 4, 2, false));
+ ASSERT_EQ("1.01000e-02", convertToString(1.01E-2, 5, 1, false));
+ ASSERT_EQ("0.78539816339744828",
+ convertToString(0.78539816339744830961, 0, 3, false));
+ ASSERT_EQ("4.94065645841246540e-324",
+ convertToString(4.9406564584124654e-324, 0, 3, false));
+ ASSERT_EQ("873.18340000000001", convertToString(873.1834, 0, 1, false));
+ ASSERT_EQ("8.73183400000000010e+02", convertToString(873.1834, 0, 0, false));
+ ASSERT_EQ("1.79769313486231570e+308",
+ convertToString(1.7976931348623157E+308, 0, 0, false));
}
TEST(APFloatTest, toInteger) {
OpenPOWER on IntegriCloud