From: Dan Gohman Date: Sat, 17 Dec 2011 00:04:22 +0000 (+0000) Subject: The powers that be have decided that LLVM IR should now support 16-bit X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=ce16339930a2b03e53b4e6399ef59c092a7f2cfa;p=oota-llvm.git 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 --- diff --git a/docs/LangRef.html b/docs/LangRef.html index 90308a45d22..58ebbc3f052 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -1709,7 +1709,7 @@ in signal handlers).

floating point - float, double, x86_fp80, fp128, ppc_fp128 + half, float, double, x86_fp80, fp128, ppc_fp128 first class @@ -1809,6 +1809,7 @@ in signal handlers).

+ @@ -2268,10 +2269,11 @@ in signal handlers).

represented in their IEEE hexadecimal format so that assembly and disassembly do not cause any bits to change in the constants.

-

When using the hexadecimal form, constants of types float and double are +

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 0xK 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 3ffaddd990f..ed7d46932c7 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 48d1695ecf7..0b651452535 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 a571b4dbe50..4b5f434057e 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 1b6b11a5d3e..d93108fc476 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 4678269a249..bccca4f7d5d 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 d584015ef85..b86d6e08833 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 d98016367d8..f8907862598 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(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 46e4acde7b5..49a498ff5f3 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(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 144b92b362e..4427f4be588 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 4fb5fd3cb74..3da4774451e 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(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 d1a9e7a70f9..4d7a857de5c 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(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 a1489123ca7..f17f9a26ca0 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 a505e4b4f5e..612d5fa2b91 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 504b37267f7..252b34033b2 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 a3f68fecbbf..30f9d469878 100644 --- a/lib/VMCore/LLVMContextImpl.h +++ b/lib/VMCore/LLVMContextImpl.h @@ -169,7 +169,7 @@ public: LeakDetectorImpl 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 469defdb85d..f4fad667a13 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(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 6c6c5dd5397..b875afe9804 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

TypeDescription
half16-bit floating point value
float32-bit floating point value
double64-bit floating point value
fp128128-bit floating point value (112-bit mantissa)