aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2011-12-17 00:04:22 +0000
committerDan Gohman <gohman@apple.com>2011-12-17 00:04:22 +0000
commitce16339930a2b03e53b4e6399ef59c092a7f2cfa (patch)
tree8265888014a73aa5764f99d7b6bb0553066f78bc
parent2e1b0c0cd9fab8f1841e1039cf39dcceeba70f73 (diff)
downloadexternal_llvm-ce16339930a2b03e53b4e6399ef59c092a7f2cfa.zip
external_llvm-ce16339930a2b03e53b4e6399ef59c092a7f2cfa.tar.gz
external_llvm-ce16339930a2b03e53b4e6399ef59c092a7f2cfa.tar.bz2
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). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146786 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--docs/LangRef.html10
-rw-r--r--include/llvm-c/Core.h3
-rw-r--r--include/llvm/Bitcode/LLVMBitCodes.h2
-rw-r--r--include/llvm/Type.h36
-rw-r--r--lib/AsmParser/LLLexer.cpp3
-rw-r--r--lib/AsmParser/LLParser.cpp15
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp7
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp3
-rw-r--r--lib/Transforms/InstCombine/InstCombineCasts.cpp3
-rw-r--r--lib/Transforms/InstCombine/InstCombineCompares.cpp4
-rw-r--r--lib/VMCore/AsmWriter.cpp43
-rw-r--r--lib/VMCore/ConstantFold.cpp3
-rw-r--r--lib/VMCore/Constants.cpp27
-rw-r--r--lib/VMCore/Core.cpp8
-rw-r--r--lib/VMCore/LLVMContextImpl.cpp1
-rw-r--r--lib/VMCore/LLVMContextImpl.h2
-rw-r--r--lib/VMCore/Type.cpp10
-rw-r--r--test/Feature/float.ll1
18 files changed, 124 insertions, 57 deletions
diff --git a/docs/LangRef.html b/docs/LangRef.html
index 90308a4..58ebbc3 100644
--- a/docs/LangRef.html
+++ b/docs/LangRef.html
@@ -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
diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h
index 3ffaddd..ed7d469 100644
--- a/include/llvm-c/Core.h
+++ b/include/llvm-c/Core.h
@@ -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);
diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h
index 48d1695..0b65145 100644
--- a/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/include/llvm/Bitcode/LLVMBitCodes.h
@@ -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]
diff --git a/include/llvm/Type.h b/include/llvm/Type.h
index a571b4d..4b5f434 100644
--- a/include/llvm/Type.h
+++ b/include/llvm/Type.h
@@ -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);
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp
index 1b6b11a..d93108f 100644
--- a/lib/AsmParser/LLLexer.cpp
+++ b/lib/AsmParser/LLLexer.cpp
@@ -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;
}
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index 4678269..bccca4f 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -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);
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index d584015..b86d6e0 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -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])));
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index d980163..f890786 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -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
diff --git a/lib/Transforms/InstCombine/InstCombineCasts.cpp b/lib/Transforms/InstCombine/InstCombineCasts.cpp
index 46e4acd..49a498f 100644
--- a/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -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;
diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 144b92b..4427f4b 100644
--- a/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -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;
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp
index 4fb5fd3..3da4774 100644
--- a/lib/VMCore/AsmWriter.cpp
+++ b/lib/VMCore/AsmWriter.cpp
@@ -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;
-
- // 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;
+ 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;
+ }
}
}
// 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);
diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp
index d1a9e7a..4d7a857 100644
--- a/lib/VMCore/ConstantFold.cpp
+++ b/lib/VMCore/ConstantFold.cpp
@@ -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 :
diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp
index a148912..f17f9a2 100644
--- a/lib/VMCore/Constants.cpp
+++ b/lib/VMCore/Constants.cpp
@@ -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;
}
diff --git a/lib/VMCore/Core.cpp b/lib/VMCore/Core.cpp
index a505e4b..612d5fa 100644
--- a/lib/VMCore/Core.cpp
+++ b/lib/VMCore/Core.cpp
@@ -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());
}
diff --git a/lib/VMCore/LLVMContextImpl.cpp b/lib/VMCore/LLVMContextImpl.cpp
index 504b372..252b340 100644
--- a/lib/VMCore/LLVMContextImpl.cpp
+++ b/lib/VMCore/LLVMContextImpl.cpp
@@ -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),
diff --git a/lib/VMCore/LLVMContextImpl.h b/lib/VMCore/LLVMContextImpl.h
index a3f68fe..30f9d46 100644
--- a/lib/VMCore/LLVMContextImpl.h
+++ b/lib/VMCore/LLVMContextImpl.h
@@ -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;
diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp
index 469defd..f4fad66 100644
--- a/lib/VMCore/Type.cpp
+++ b/lib/VMCore/Type.cpp
@@ -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);
}
diff --git a/test/Feature/float.ll b/test/Feature/float.ll
index 6c6c5dd..b875afe 100644
--- a/test/Feature/float.ll
+++ b/test/Feature/float.ll
@@ -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