forked from OSchip/llvm-project
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:
parent
27886c6c1e
commit
518cda42b9
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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])));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 :
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue