Skip to content

Commit

Permalink
[NFC][LLVM][AsmWriter] Extract logic to write out ConstantFP from Wri…
Browse files Browse the repository at this point in the history
…teConstantInternal.

This makes is easier to extend the code to support vector types.
  • Loading branch information
paulwalker-arm committed Feb 13, 2024
1 parent 485ebbf commit 4f13f35
Showing 1 changed file with 94 additions and 88 deletions.
182 changes: 94 additions & 88 deletions llvm/lib/IR/AsmWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1406,6 +1406,99 @@ static void WriteOptimizationInfo(raw_ostream &Out, const User *U) {
}
}

static void WriteAPFloatInternal(raw_ostream &Out, const APFloat &APF) {
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 = &APF.getSemantics() == &APFloat::IEEEdouble();
bool isInf = APF.isInfinity();
bool isNaN = APF.isNaN();

if (!isInf && !isNaN) {
double Val = APF.convertToDouble();
SmallString<128> StrVal;
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.
//
assert((isDigit(StrVal[0]) ||
((StrVal[0] == '-' || StrVal[0] == '+') && isDigit(StrVal[1]))) &&
"[-+]?[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
// output the string in hexadecimal format! Note that loading and storing
// floating point types changes the bits of NaNs on some hosts, notably
// x86, so we must not use these types.
static_assert(sizeof(double) == sizeof(uint64_t),
"assuming that double is 64 bits!");
APFloat apf = APF;

// Floats are represented in ASCII IR as double, convert.
// FIXME: We should allow 32-bit hex float and remove this.
if (!isDouble) {
// A signaling NaN is quieted on conversion, so we need to recreate the
// expected value after convert (quiet bit of the payload is clear).
bool IsSNAN = apf.isSignaling();
apf.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven,
&ignored);
if (IsSNAN) {
APInt Payload = apf.bitcastToAPInt();
apf =
APFloat::getSNaN(APFloat::IEEEdouble(), apf.isNegative(), &Payload);
}
}

Out << format_hex(apf.bitcastToAPInt().getZExtValue(), 0, /*Upper=*/true);
return;
}

// Either half, bfloat or some form of long double.
// These appear as a magic letter identifying the type, then a
// fixed number of hex digits.
Out << "0x";
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);
} 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 (&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 (&APF.getSemantics() == &APFloat::IEEEhalf()) {
Out << 'H';
Out << format_hex_no_prefix(API.getZExtValue(), 4,
/*Upper=*/true);
} else if (&APF.getSemantics() == &APFloat::BFloat()) {
Out << 'R';
Out << format_hex_no_prefix(API.getZExtValue(), 4,
/*Upper=*/true);
} else
llvm_unreachable("Unsupported floating point type");
}

static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
AsmWriterContext &WriterCtx) {
if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
Expand All @@ -1418,94 +1511,7 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
}

if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
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 = &APF.getSemantics() == &APFloat::IEEEdouble();
bool isInf = APF.isInfinity();
bool isNaN = APF.isNaN();
if (!isInf && !isNaN) {
double Val = APF.convertToDouble();
SmallString<128> StrVal;
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.
//
assert((isDigit(StrVal[0]) || ((StrVal[0] == '-' || StrVal[0] == '+') &&
isDigit(StrVal[1]))) &&
"[-+]?[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
// output the string in hexadecimal format! Note that loading and storing
// floating point types changes the bits of NaNs on some hosts, notably
// x86, so we must not use these types.
static_assert(sizeof(double) == sizeof(uint64_t),
"assuming that double is 64 bits!");
APFloat apf = APF;
// Floats are represented in ASCII IR as double, convert.
// FIXME: We should allow 32-bit hex float and remove this.
if (!isDouble) {
// A signaling NaN is quieted on conversion, so we need to recreate the
// expected value after convert (quiet bit of the payload is clear).
bool IsSNAN = apf.isSignaling();
apf.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven,
&ignored);
if (IsSNAN) {
APInt Payload = apf.bitcastToAPInt();
apf = APFloat::getSNaN(APFloat::IEEEdouble(), apf.isNegative(),
&Payload);
}
}
Out << format_hex(apf.bitcastToAPInt().getZExtValue(), 0, /*Upper=*/true);
return;
}

// Either half, bfloat or some form of long double.
// These appear as a magic letter identifying the type, then a
// fixed number of hex digits.
Out << "0x";
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 (&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 (&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 (&APF.getSemantics() == &APFloat::IEEEhalf()) {
Out << 'H';
Out << format_hex_no_prefix(API.getZExtValue(), 4,
/*Upper=*/true);
} else if (&APF.getSemantics() == &APFloat::BFloat()) {
Out << 'R';
Out << format_hex_no_prefix(API.getZExtValue(), 4,
/*Upper=*/true);
} else
llvm_unreachable("Unsupported floating point type");
WriteAPFloatInternal(Out, CFP->getValueAPF());
return;
}

Expand Down

0 comments on commit 4f13f35

Please sign in to comment.