mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
Add half precision floating point support (float16) to APFloat,
patch by Peter Johnson! (PR5195) llvm-svn: 84239
This commit is contained in:
parent
87bcf3b242
commit
5d2b384837
@ -125,6 +125,7 @@ namespace llvm {
|
||||
public:
|
||||
|
||||
/* We support the following floating point semantics. */
|
||||
static const fltSemantics IEEEhalf;
|
||||
static const fltSemantics IEEEsingle;
|
||||
static const fltSemantics IEEEdouble;
|
||||
static const fltSemantics IEEEquad;
|
||||
@ -321,12 +322,14 @@ namespace llvm {
|
||||
opStatus roundSignificandWithExponent(const integerPart *, unsigned int,
|
||||
int, roundingMode);
|
||||
|
||||
APInt convertHalfAPFloatToAPInt() const;
|
||||
APInt convertFloatAPFloatToAPInt() const;
|
||||
APInt convertDoubleAPFloatToAPInt() const;
|
||||
APInt convertQuadrupleAPFloatToAPInt() const;
|
||||
APInt convertF80LongDoubleAPFloatToAPInt() const;
|
||||
APInt convertPPCDoubleDoubleAPFloatToAPInt() const;
|
||||
void initFromAPInt(const APInt& api, bool isIEEE = false);
|
||||
void initFromHalfAPInt(const APInt& api);
|
||||
void initFromFloatAPInt(const APInt& api);
|
||||
void initFromDoubleAPInt(const APInt& api);
|
||||
void initFromQuadrupleAPInt(const APInt &api);
|
||||
|
@ -48,6 +48,7 @@ namespace llvm {
|
||||
unsigned int arithmeticOK;
|
||||
};
|
||||
|
||||
const fltSemantics APFloat::IEEEhalf = { 15, -14, 11, true };
|
||||
const fltSemantics APFloat::IEEEsingle = { 127, -126, 24, true };
|
||||
const fltSemantics APFloat::IEEEdouble = { 1023, -1022, 53, true };
|
||||
const fltSemantics APFloat::IEEEquad = { 16383, -16382, 113, true };
|
||||
@ -2812,6 +2813,35 @@ APFloat::convertFloatAPFloatToAPInt() const
|
||||
(mysignificand & 0x7fffff)));
|
||||
}
|
||||
|
||||
APInt
|
||||
APFloat::convertHalfAPFloatToAPInt() const
|
||||
{
|
||||
assert(semantics == (const llvm::fltSemantics*)&IEEEhalf);
|
||||
assert (partCount()==1);
|
||||
|
||||
uint32_t myexponent, mysignificand;
|
||||
|
||||
if (category==fcNormal) {
|
||||
myexponent = exponent+15; //bias
|
||||
mysignificand = (uint32_t)*significandParts();
|
||||
if (myexponent == 1 && !(mysignificand & 0x400))
|
||||
myexponent = 0; // denormal
|
||||
} else if (category==fcZero) {
|
||||
myexponent = 0;
|
||||
mysignificand = 0;
|
||||
} else if (category==fcInfinity) {
|
||||
myexponent = 0xff;
|
||||
mysignificand = 0;
|
||||
} else {
|
||||
assert(category == fcNaN && "Unknown category!");
|
||||
myexponent = 0xff;
|
||||
mysignificand = (uint32_t)*significandParts();
|
||||
}
|
||||
|
||||
return APInt(16, (((sign&1) << 15) | ((myexponent&0x1f) << 10) |
|
||||
(mysignificand & 0x3ff)));
|
||||
}
|
||||
|
||||
// This function creates an APInt that is just a bit map of the floating
|
||||
// point constant as it would appear in memory. It is not a conversion,
|
||||
// and treating the result as a normal integer is unlikely to be useful.
|
||||
@ -2819,6 +2849,9 @@ APFloat::convertFloatAPFloatToAPInt() const
|
||||
APInt
|
||||
APFloat::bitcastToAPInt() const
|
||||
{
|
||||
if (semantics == (const llvm::fltSemantics*)&IEEEhalf)
|
||||
return convertHalfAPFloatToAPInt();
|
||||
|
||||
if (semantics == (const llvm::fltSemantics*)&IEEEsingle)
|
||||
return convertFloatAPFloatToAPInt();
|
||||
|
||||
@ -3051,6 +3084,39 @@ APFloat::initFromFloatAPInt(const APInt & api)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
APFloat::initFromHalfAPInt(const APInt & api)
|
||||
{
|
||||
assert(api.getBitWidth()==16);
|
||||
uint32_t i = (uint32_t)*api.getRawData();
|
||||
uint32_t myexponent = (i >> 15) & 0x1f;
|
||||
uint32_t mysignificand = i & 0x3ff;
|
||||
|
||||
initialize(&APFloat::IEEEhalf);
|
||||
assert(partCount()==1);
|
||||
|
||||
sign = i >> 15;
|
||||
if (myexponent==0 && mysignificand==0) {
|
||||
// exponent, significand meaningless
|
||||
category = fcZero;
|
||||
} else if (myexponent==0x1f && mysignificand==0) {
|
||||
// exponent, significand meaningless
|
||||
category = fcInfinity;
|
||||
} else if (myexponent==0x1f && mysignificand!=0) {
|
||||
// sign, exponent, significand meaningless
|
||||
category = fcNaN;
|
||||
*significandParts() = mysignificand;
|
||||
} else {
|
||||
category = fcNormal;
|
||||
exponent = myexponent - 15; //bias
|
||||
*significandParts() = mysignificand;
|
||||
if (myexponent==0) // denormal
|
||||
exponent = -14;
|
||||
else
|
||||
*significandParts() |= 0x400; // integer bit
|
||||
}
|
||||
}
|
||||
|
||||
/// Treat api as containing the bits of a floating point number. Currently
|
||||
/// we infer the floating point type from the size of the APInt. The
|
||||
/// isIEEE argument distinguishes between PPC128 and IEEE128 (not meaningful
|
||||
@ -3058,7 +3124,9 @@ APFloat::initFromFloatAPInt(const APInt & api)
|
||||
void
|
||||
APFloat::initFromAPInt(const APInt& api, bool isIEEE)
|
||||
{
|
||||
if (api.getBitWidth() == 32)
|
||||
if (api.getBitWidth() == 16)
|
||||
return initFromHalfAPInt(api);
|
||||
else if (api.getBitWidth() == 32)
|
||||
return initFromFloatAPInt(api);
|
||||
else if (api.getBitWidth()==64)
|
||||
return initFromDoubleAPInt(api);
|
||||
|
Loading…
Reference in New Issue
Block a user