The powers that be have decided that LLVM IR should now support 16-bit

"half precision" floating-point with a first-class type.

This patch adds basic IR support (but not codegen support).

llvm-svn: 146786
This commit is contained in:
Dan Gohman 2011-12-17 00:04:22 +00:00
parent 27886c6c1e
commit 518cda42b9
18 changed files with 123 additions and 56 deletions

View File

@ -1709,7 +1709,7 @@ in signal handlers).</p>
</tr>
<tr>
<td><a href="#t_floating">floating point</a></td>
<td><tt>float, double, x86_fp80, fp128, ppc_fp128</tt></td>
<td><tt>half, float, double, x86_fp80, fp128, ppc_fp128</tt></td>
</tr>
<tr>
<td><a name="t_firstclass">first class</a></td>
@ -1809,6 +1809,7 @@ in signal handlers).</p>
<table>
<tbody>
<tr><th>Type</th><th>Description</th></tr>
<tr><td><tt>half</tt></td><td>16-bit floating point value</td></tr>
<tr><td><tt>float</tt></td><td>32-bit floating point value</td></tr>
<tr><td><tt>double</tt></td><td>64-bit floating point value</td></tr>
<tr><td><tt>fp128</tt></td><td>128-bit floating point value (112-bit mantissa)</td></tr>
@ -2268,10 +2269,11 @@ in signal handlers).</p>
represented in their IEEE hexadecimal format so that assembly and disassembly
do not cause any bits to change in the constants.</p>
<p>When using the hexadecimal form, constants of types float and double are
<p>When using the hexadecimal form, constants of types half, float, and double are
represented using the 16-digit form shown above (which matches the IEEE754
representation for double); float values must, however, be exactly
representable as IEE754 single precision. Hexadecimal format is always used
representation for double); half and float values must, however, be exactly
representable as IEE754 half and single precision, respectively.
Hexadecimal format is always used
for long double, and there are three forms of long double. The 80-bit format
used by x86 is represented as <tt>0xK</tt> followed by 20 hexadecimal digits.
The 128-bit format used by PowerPC (two adjacent doubles) is represented

View File

@ -203,6 +203,7 @@ typedef enum {
typedef enum {
LLVMVoidTypeKind, /**< type with no size */
LLVMHalfTypeKind, /**< 16 bit floating point type */
LLVMFloatTypeKind, /**< 32 bit floating point type */
LLVMDoubleTypeKind, /**< 64 bit floating point type */
LLVMX86_FP80TypeKind, /**< 80 bit floating point type (X87) */
@ -382,12 +383,14 @@ LLVMTypeRef LLVMIntType(unsigned NumBits);
unsigned LLVMGetIntTypeWidth(LLVMTypeRef IntegerTy);
/* Operations on real types */
LLVMTypeRef LLVMHalfTypeInContext(LLVMContextRef C);
LLVMTypeRef LLVMFloatTypeInContext(LLVMContextRef C);
LLVMTypeRef LLVMDoubleTypeInContext(LLVMContextRef C);
LLVMTypeRef LLVMX86FP80TypeInContext(LLVMContextRef C);
LLVMTypeRef LLVMFP128TypeInContext(LLVMContextRef C);
LLVMTypeRef LLVMPPCFP128TypeInContext(LLVMContextRef C);
LLVMTypeRef LLVMHalfType(void);
LLVMTypeRef LLVMFloatType(void);
LLVMTypeRef LLVMDoubleType(void);
LLVMTypeRef LLVMX86FP80Type(void);

View File

@ -94,7 +94,7 @@ namespace bitc {
TYPE_CODE_FUNCTION_OLD = 9, // FUNCTION: [vararg, attrid, retty,
// paramty x N]
// Code #10 is unused.
TYPE_CODE_HALF = 10, // HALF
TYPE_CODE_ARRAY = 11, // ARRAY: [numelts, eltty]
TYPE_CODE_VECTOR = 12, // VECTOR: [numelts, eltty]

View File

@ -47,23 +47,24 @@ public:
enum TypeID {
// PrimitiveTypes - make sure LastPrimitiveTyID stays up to date.
VoidTyID = 0, ///< 0: type with no size
FloatTyID, ///< 1: 32-bit floating point type
DoubleTyID, ///< 2: 64-bit floating point type
X86_FP80TyID, ///< 3: 80-bit floating point type (X87)
FP128TyID, ///< 4: 128-bit floating point type (112-bit mantissa)
PPC_FP128TyID, ///< 5: 128-bit floating point type (two 64-bits, PowerPC)
LabelTyID, ///< 6: Labels
MetadataTyID, ///< 7: Metadata
X86_MMXTyID, ///< 8: MMX vectors (64 bits, X86 specific)
HalfTyID, ///< 1: 32-bit floating point type
FloatTyID, ///< 2: 32-bit floating point type
DoubleTyID, ///< 3: 64-bit floating point type
X86_FP80TyID, ///< 4: 80-bit floating point type (X87)
FP128TyID, ///< 5: 128-bit floating point type (112-bit mantissa)
PPC_FP128TyID, ///< 6: 128-bit floating point type (two 64-bits, PowerPC)
LabelTyID, ///< 7: Labels
MetadataTyID, ///< 8: Metadata
X86_MMXTyID, ///< 9: MMX vectors (64 bits, X86 specific)
// Derived types... see DerivedTypes.h file.
// Make sure FirstDerivedTyID stays up to date!
IntegerTyID, ///< 9: Arbitrary bit width integers
FunctionTyID, ///< 10: Functions
StructTyID, ///< 11: Structures
ArrayTyID, ///< 12: Arrays
PointerTyID, ///< 13: Pointers
VectorTyID, ///< 14: SIMD 'packed' format, or other vector type
IntegerTyID, ///< 10: Arbitrary bit width integers
FunctionTyID, ///< 11: Functions
StructTyID, ///< 12: Structures
ArrayTyID, ///< 13: Arrays
PointerTyID, ///< 14: Pointers
VectorTyID, ///< 15: SIMD 'packed' format, or other vector type
NumTypeIDs, // Must remain as last defined ID
LastPrimitiveTyID = X86_MMXTyID,
@ -121,6 +122,9 @@ public:
/// isVoidTy - Return true if this is 'void'.
bool isVoidTy() const { return ID == VoidTyID; }
/// isHalfTy - Return true if this is 'half', a 16-bit IEEE fp type.
bool isHalfTy() const { return ID == HalfTyID; }
/// isFloatTy - Return true if this is 'float', a 32-bit IEEE fp type.
bool isFloatTy() const { return ID == FloatTyID; }
@ -139,7 +143,7 @@ public:
/// isFloatingPointTy - Return true if this is one of the five floating point
/// types
bool isFloatingPointTy() const {
return ID == FloatTyID || ID == DoubleTyID ||
return ID == HalfTyID || ID == FloatTyID || ID == DoubleTyID ||
ID == X86_FP80TyID || ID == FP128TyID || ID == PPC_FP128TyID;
}
@ -310,6 +314,7 @@ public:
//
static Type *getVoidTy(LLVMContext &C);
static Type *getLabelTy(LLVMContext &C);
static Type *getHalfTy(LLVMContext &C);
static Type *getFloatTy(LLVMContext &C);
static Type *getDoubleTy(LLVMContext &C);
static Type *getMetadataTy(LLVMContext &C);
@ -328,6 +333,7 @@ public:
// Convenience methods for getting pointer types with one of the above builtin
// types as pointee.
//
static PointerType *getHalfPtrTy(LLVMContext &C, unsigned AS = 0);
static PointerType *getFloatPtrTy(LLVMContext &C, unsigned AS = 0);
static PointerType *getDoublePtrTy(LLVMContext &C, unsigned AS = 0);
static PointerType *getX86_FP80PtrTy(LLVMContext &C, unsigned AS = 0);

View File

@ -574,6 +574,7 @@ lltok::Kind LLLexer::LexIdentifier() {
if (Len == strlen(STR) && !memcmp(StartChar, STR, strlen(STR))) { \
TyVal = LLVMTY; return lltok::Type; }
TYPEKEYWORD("void", Type::getVoidTy(Context));
TYPEKEYWORD("half", Type::getHalfTy(Context));
TYPEKEYWORD("float", Type::getFloatTy(Context));
TYPEKEYWORD("double", Type::getDoubleTy(Context));
TYPEKEYWORD("x86_fp80", Type::getX86_FP80Ty(Context));
@ -693,7 +694,7 @@ lltok::Kind LLLexer::Lex0x() {
if (Kind == 'J') {
// HexFPConstant - Floating point constant represented in IEEE format as a
// hexadecimal number for when exponential notation is not precise enough.
// Float and double only.
// Half, Float, and double only.
APFloatVal = APFloat(BitsToDouble(HexIntToVal(TokStart+2, CurPtr)));
return lltok::APFloat;
}

View File

@ -2483,13 +2483,16 @@ bool LLParser::ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V,
!ConstantFP::isValueValidForType(Ty, ID.APFloatVal))
return Error(ID.Loc, "floating point constant invalid for type");
// The lexer has no type info, so builds all float and double FP constants
// as double. Fix this here. Long double does not need this.
if (&ID.APFloatVal.getSemantics() == &APFloat::IEEEdouble &&
Ty->isFloatTy()) {
// The lexer has no type info, so builds all half, float, and double FP
// constants as double. Fix this here. Long double does not need this.
if (&ID.APFloatVal.getSemantics() == &APFloat::IEEEdouble) {
bool Ignored;
ID.APFloatVal.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven,
&Ignored);
if (Ty->isHalfTy())
ID.APFloatVal.convert(APFloat::IEEEhalf, APFloat::rmNearestTiesToEven,
&Ignored);
else if (Ty->isFloatTy())
ID.APFloatVal.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven,
&Ignored);
}
V = ConstantFP::get(Context, ID.APFloatVal);

View File

@ -565,6 +565,9 @@ bool BitcodeReader::ParseTypeTableBody() {
case bitc::TYPE_CODE_VOID: // VOID
ResultTy = Type::getVoidTy(Context);
break;
case bitc::TYPE_CODE_HALF: // HALF
ResultTy = Type::getHalfTy(Context);
break;
case bitc::TYPE_CODE_FLOAT: // FLOAT
ResultTy = Type::getFloatTy(Context);
break;
@ -1032,7 +1035,9 @@ bool BitcodeReader::ParseConstants() {
case bitc::CST_CODE_FLOAT: { // FLOAT: [fpval]
if (Record.empty())
return Error("Invalid FLOAT record");
if (CurTy->isFloatTy())
if (CurTy->isHalfTy())
V = ConstantFP::get(Context, APFloat(APInt(16, (uint16_t)Record[0])));
else if (CurTy->isFloatTy())
V = ConstantFP::get(Context, APFloat(APInt(32, (uint32_t)Record[0])));
else if (CurTy->isDoubleTy())
V = ConstantFP::get(Context, APFloat(APInt(64, Record[0])));

View File

@ -266,6 +266,7 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) {
switch (T->getTypeID()) {
default: llvm_unreachable("Unknown type!");
case Type::VoidTyID: Code = bitc::TYPE_CODE_VOID; break;
case Type::HalfTyID: Code = bitc::TYPE_CODE_HALF; break;
case Type::FloatTyID: Code = bitc::TYPE_CODE_FLOAT; break;
case Type::DoubleTyID: Code = bitc::TYPE_CODE_DOUBLE; break;
case Type::X86_FP80TyID: Code = bitc::TYPE_CODE_X86_FP80; break;
@ -826,7 +827,7 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
} else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
Code = bitc::CST_CODE_FLOAT;
Type *Ty = CFP->getType();
if (Ty->isFloatTy() || Ty->isDoubleTy()) {
if (Ty->isHalfTy() || Ty->isFloatTy() || Ty->isDoubleTy()) {
Record.push_back(CFP->getValueAPF().bitcastToAPInt().getZExtValue());
} else if (Ty->isX86_FP80Ty()) {
// api needed to prevent premature destruction

View File

@ -1160,6 +1160,9 @@ static Value *LookThroughFPExtensions(Value *V) {
if (ConstantFP *CFP = dyn_cast<ConstantFP>(V)) {
if (CFP->getType() == Type::getPPC_FP128Ty(V->getContext()))
return V; // No constant folding of this.
// See if the value can be truncated to half and then reextended.
if (Value *V = FitsInFPType(CFP, APFloat::IEEEhalf))
return V;
// See if the value can be truncated to float and then reextended.
if (Value *V = FitsInFPType(CFP, APFloat::IEEEsingle))
return V;

View File

@ -2848,7 +2848,9 @@ Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) {
const fltSemantics *Sem;
// FIXME: This shouldn't be here.
if (LHSExt->getSrcTy()->isFloatTy())
if (LHSExt->getSrcTy()->isHalfTy())
Sem = &APFloat::IEEEhalf;
else if (LHSExt->getSrcTy()->isFloatTy())
Sem = &APFloat::IEEEsingle;
else if (LHSExt->getSrcTy()->isDoubleTy())
Sem = &APFloat::IEEEdouble;

View File

@ -189,6 +189,7 @@ void TypePrinting::incorporateTypes(const Module &M) {
void TypePrinting::print(Type *Ty, raw_ostream &OS) {
switch (Ty->getTypeID()) {
case Type::VoidTyID: OS << "void"; break;
case Type::HalfTyID: OS << "half"; break;
case Type::FloatTyID: OS << "float"; break;
case Type::DoubleTyID: OS << "double"; break;
case Type::X86_FP80TyID: OS << "x86_fp80"; break;
@ -708,31 +709,35 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
}
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEdouble ||
&CFP->getValueAPF().getSemantics() == &APFloat::IEEEsingle) {
if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEhalf ||
&CFP->getValueAPF().getSemantics() == &APFloat::IEEEsingle ||
&CFP->getValueAPF().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 isHalf = &CFP->getValueAPF().getSemantics()==&APFloat::IEEEhalf;
bool isDouble = &CFP->getValueAPF().getSemantics()==&APFloat::IEEEdouble;
double Val = isDouble ? CFP->getValueAPF().convertToDouble() :
CFP->getValueAPF().convertToFloat();
SmallString<128> StrVal;
raw_svector_ostream(StrVal) << Val;
if (!isHalf) {
double Val = isDouble ? CFP->getValueAPF().convertToDouble() :
CFP->getValueAPF().convertToFloat();
SmallString<128> StrVal;
raw_svector_ostream(StrVal) << Val;
// 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 (atof(StrVal.c_str()) == Val) {
Out << StrVal.str();
return;
// 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 (atof(StrVal.c_str()) == Val) {
Out << StrVal.str();
return;
}
}
}
// Otherwise we could not reparse it to exactly the same value, so we must
@ -743,7 +748,7 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
"assuming that double is 64 bits!");
char Buffer[40];
APFloat apf = CFP->getValueAPF();
// Floats are represented in ASCII IR as double, convert.
// Halves and floats are represented in ASCII IR as double, convert.
if (!isDouble)
apf.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven,
&ignored);

View File

@ -571,7 +571,8 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
if (ConstantFP *FPC = dyn_cast<ConstantFP>(V)) {
bool ignored;
APFloat Val = FPC->getValueAPF();
Val.convert(DestTy->isFloatTy() ? APFloat::IEEEsingle :
Val.convert(DestTy->isHalfTy() ? APFloat::IEEEhalf :
DestTy->isFloatTy() ? APFloat::IEEEsingle :
DestTy->isDoubleTy() ? APFloat::IEEEdouble :
DestTy->isX86_FP80Ty() ? APFloat::x87DoubleExtended :
DestTy->isFP128Ty() ? APFloat::IEEEquad :

View File

@ -84,6 +84,9 @@ Constant *Constant::getNullValue(Type *Ty) {
switch (Ty->getTypeID()) {
case Type::IntegerTyID:
return ConstantInt::get(Ty, 0);
case Type::HalfTyID:
return ConstantFP::get(Ty->getContext(),
APFloat::getZero(APFloat::IEEEhalf));
case Type::FloatTyID:
return ConstantFP::get(Ty->getContext(),
APFloat::getZero(APFloat::IEEEsingle));
@ -468,6 +471,8 @@ ConstantInt* ConstantInt::get(IntegerType* Ty, StringRef Str,
//===----------------------------------------------------------------------===//
static const fltSemantics *TypeToFloatSemantics(Type *Ty) {
if (Ty->isHalfTy())
return &APFloat::IEEEhalf;
if (Ty->isFloatTy())
return &APFloat::IEEEsingle;
if (Ty->isDoubleTy())
@ -550,7 +555,9 @@ ConstantFP* ConstantFP::get(LLVMContext &Context, const APFloat& V) {
if (!Slot) {
Type *Ty;
if (&V.getSemantics() == &APFloat::IEEEsingle)
if (&V.getSemantics() == &APFloat::IEEEhalf)
Ty = Type::getHalfTy(Context);
else if (&V.getSemantics() == &APFloat::IEEEsingle)
Ty = Type::getFloatTy(Context);
else if (&V.getSemantics() == &APFloat::IEEEdouble)
Ty = Type::getDoubleTy(Context);
@ -939,6 +946,12 @@ bool ConstantFP::isValueValidForType(Type *Ty, const APFloat& Val) {
return false; // These can't be represented as floating point!
// FIXME rounding mode needs to be more flexible
case Type::HalfTyID: {
if (&Val2.getSemantics() == &APFloat::IEEEhalf)
return true;
Val2.convert(APFloat::IEEEhalf, APFloat::rmNearestTiesToEven, &losesInfo);
return !losesInfo;
}
case Type::FloatTyID: {
if (&Val2.getSemantics() == &APFloat::IEEEsingle)
return true;
@ -946,22 +959,26 @@ bool ConstantFP::isValueValidForType(Type *Ty, const APFloat& Val) {
return !losesInfo;
}
case Type::DoubleTyID: {
if (&Val2.getSemantics() == &APFloat::IEEEsingle ||
if (&Val2.getSemantics() == &APFloat::IEEEhalf ||
&Val2.getSemantics() == &APFloat::IEEEsingle ||
&Val2.getSemantics() == &APFloat::IEEEdouble)
return true;
Val2.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &losesInfo);
return !losesInfo;
}
case Type::X86_FP80TyID:
return &Val2.getSemantics() == &APFloat::IEEEsingle ||
return &Val2.getSemantics() == &APFloat::IEEEhalf ||
&Val2.getSemantics() == &APFloat::IEEEsingle ||
&Val2.getSemantics() == &APFloat::IEEEdouble ||
&Val2.getSemantics() == &APFloat::x87DoubleExtended;
case Type::FP128TyID:
return &Val2.getSemantics() == &APFloat::IEEEsingle ||
return &Val2.getSemantics() == &APFloat::IEEEhalf ||
&Val2.getSemantics() == &APFloat::IEEEsingle ||
&Val2.getSemantics() == &APFloat::IEEEdouble ||
&Val2.getSemantics() == &APFloat::IEEEquad;
case Type::PPC_FP128TyID:
return &Val2.getSemantics() == &APFloat::IEEEsingle ||
return &Val2.getSemantics() == &APFloat::IEEEhalf ||
&Val2.getSemantics() == &APFloat::IEEEsingle ||
&Val2.getSemantics() == &APFloat::IEEEdouble ||
&Val2.getSemantics() == &APFloat::PPCDoubleDouble;
}

View File

@ -136,6 +136,8 @@ LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty) {
assert(false && "Unhandled TypeID.");
case Type::VoidTyID:
return LLVMVoidTypeKind;
case Type::HalfTyID:
return LLVMHalfTypeKind;
case Type::FloatTyID:
return LLVMFloatTypeKind;
case Type::DoubleTyID:
@ -222,6 +224,9 @@ unsigned LLVMGetIntTypeWidth(LLVMTypeRef IntegerTy) {
/*--.. Operations on real types ............................................--*/
LLVMTypeRef LLVMHalfTypeInContext(LLVMContextRef C) {
return (LLVMTypeRef) Type::getHalfTy(*unwrap(C));
}
LLVMTypeRef LLVMFloatTypeInContext(LLVMContextRef C) {
return (LLVMTypeRef) Type::getFloatTy(*unwrap(C));
}
@ -241,6 +246,9 @@ LLVMTypeRef LLVMX86MMXTypeInContext(LLVMContextRef C) {
return (LLVMTypeRef) Type::getX86_MMXTy(*unwrap(C));
}
LLVMTypeRef LLVMHalfType(void) {
return LLVMHalfTypeInContext(LLVMGetGlobalContext());
}
LLVMTypeRef LLVMFloatType(void) {
return LLVMFloatTypeInContext(LLVMGetGlobalContext());
}

View File

@ -21,6 +21,7 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
: TheTrueVal(0), TheFalseVal(0),
VoidTy(C, Type::VoidTyID),
LabelTy(C, Type::LabelTyID),
HalfTy(C, Type::HalfTyID),
FloatTy(C, Type::FloatTyID),
DoubleTy(C, Type::DoubleTyID),
MetadataTy(C, Type::MetadataTyID),

View File

@ -169,7 +169,7 @@ public:
LeakDetectorImpl<Value> LLVMObjects;
// Basic type instances.
Type VoidTy, LabelTy, FloatTy, DoubleTy, MetadataTy;
Type VoidTy, LabelTy, HalfTy, FloatTy, DoubleTy, MetadataTy;
Type X86_FP80Ty, FP128Ty, PPC_FP128Ty, X86_MMXTy;
IntegerType Int1Ty, Int8Ty, Int16Ty, Int32Ty, Int64Ty;

View File

@ -25,6 +25,7 @@ using namespace llvm;
Type *Type::getPrimitiveType(LLVMContext &C, TypeID IDNumber) {
switch (IDNumber) {
case VoidTyID : return getVoidTy(C);
case HalfTyID : return getHalfTy(C);
case FloatTyID : return getFloatTy(C);
case DoubleTyID : return getDoubleTy(C);
case X86_FP80TyID : return getX86_FP80Ty(C);
@ -73,7 +74,7 @@ bool Type::isIntOrIntVectorTy() const {
/// isFPOrFPVectorTy - Return true if this is a FP type or a vector of FP types.
///
bool Type::isFPOrFPVectorTy() const {
if (ID == Type::FloatTyID || ID == Type::DoubleTyID ||
if (ID == Type::HalfTyID || ID == Type::FloatTyID || ID == Type::DoubleTyID ||
ID == Type::FP128TyID || ID == Type::X86_FP80TyID ||
ID == Type::PPC_FP128TyID)
return true;
@ -139,6 +140,7 @@ bool Type::isEmptyTy() const {
unsigned Type::getPrimitiveSizeInBits() const {
switch (getTypeID()) {
case Type::HalfTyID: return 16;
case Type::FloatTyID: return 32;
case Type::DoubleTyID: return 64;
case Type::X86_FP80TyID: return 80;
@ -165,6 +167,7 @@ int Type::getFPMantissaWidth() const {
if (const VectorType *VTy = dyn_cast<VectorType>(this))
return VTy->getElementType()->getFPMantissaWidth();
assert(isFloatingPointTy() && "Not a floating point type!");
if (ID == HalfTyID) return 11;
if (ID == FloatTyID) return 24;
if (ID == DoubleTyID) return 53;
if (ID == X86_FP80TyID) return 64;
@ -207,6 +210,7 @@ bool Type::isSizedDerivedType() const {
Type *Type::getVoidTy(LLVMContext &C) { return &C.pImpl->VoidTy; }
Type *Type::getLabelTy(LLVMContext &C) { return &C.pImpl->LabelTy; }
Type *Type::getHalfTy(LLVMContext &C) { return &C.pImpl->HalfTy; }
Type *Type::getFloatTy(LLVMContext &C) { return &C.pImpl->FloatTy; }
Type *Type::getDoubleTy(LLVMContext &C) { return &C.pImpl->DoubleTy; }
Type *Type::getMetadataTy(LLVMContext &C) { return &C.pImpl->MetadataTy; }
@ -225,6 +229,10 @@ IntegerType *Type::getIntNTy(LLVMContext &C, unsigned N) {
return IntegerType::get(C, N);
}
PointerType *Type::getHalfPtrTy(LLVMContext &C, unsigned AS) {
return getHalfTy(C)->getPointerTo(AS);
}
PointerType *Type::getFloatPtrTy(LLVMContext &C, unsigned AS) {
return getFloatTy(C)->getPointerTo(AS);
}

View File

@ -2,5 +2,6 @@
; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll
; RUN: diff %t1.ll %t2.ll
@H1 = global half 0x4010000000000000
@F1 = global float 0x4010000000000000
@D1 = global double 0x4010000000000000