diff options
author | Tobias Grosser <grosser@fim.uni-passau.de> | 2012-05-24 15:59:06 +0000 |
---|---|---|
committer | Tobias Grosser <grosser@fim.uni-passau.de> | 2012-05-24 15:59:06 +0000 |
commit | 057beb8d4fe8d5dad98ad80a49a649730c3a3eb0 (patch) | |
tree | 48e33d7c92b9abb8e79b152d07fef085fcc9b061 | |
parent | 91bf23e6b7b9b4a00ebc73d4136a3b985581002a (diff) | |
download | external_llvm-057beb8d4fe8d5dad98ad80a49a649730c3a3eb0.zip external_llvm-057beb8d4fe8d5dad98ad80a49a649730c3a3eb0.tar.gz external_llvm-057beb8d4fe8d5dad98ad80a49a649730c3a3eb0.tar.bz2 |
Add half support to LLVM (for OpenCL)
Submitted by: Anton Lokhmotov <Anton.Lokhmotov@arm.com>
Approved by: o Anton Korobeynikov
o Micah Villmow
o David Neto
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@157393 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | docs/BitCodeFormat.html | 12 | ||||
-rw-r--r-- | docs/LangRef.html | 8 | ||||
-rw-r--r-- | lib/AsmParser/LLLexer.cpp | 6 | ||||
-rw-r--r-- | lib/VMCore/AsmWriter.cpp | 25 | ||||
-rw-r--r-- | test/Assembler/half-constprop.ll | 17 | ||||
-rw-r--r-- | test/Assembler/half-conv.ll | 13 | ||||
-rw-r--r-- | test/Assembler/half.ll | 8 |
7 files changed, 76 insertions, 13 deletions
diff --git a/docs/BitCodeFormat.html b/docs/BitCodeFormat.html index a8777ee..30145de 100644 --- a/docs/BitCodeFormat.html +++ b/docs/BitCodeFormat.html @@ -1145,6 +1145,18 @@ type table. </div> <!-- _______________________________________________________________________ --> +<h4><a name="TYPE_CODE_HALF">TYPE_CODE_HALF Record</a></h4> + +<div> + +<p><tt>[HALF]</tt></p> + +<p>The <tt>HALF</tt> record (code 10) adds a <tt>half</tt> (16-bit +floating point) type to the type table. +</p> +</div> + +<!-- _______________________________________________________________________ --> <h4><a name="TYPE_CODE_FLOAT">TYPE_CODE_FLOAT Record</a></h4> <div> diff --git a/docs/LangRef.html b/docs/LangRef.html index 8f7a17c..a781992 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -2289,8 +2289,9 @@ in signal handlers).</p> by <tt>0xM</tt> followed by 32 hexadecimal digits. The IEEE 128-bit format is represented by <tt>0xL</tt> followed by 32 hexadecimal digits; no currently supported target uses this format. Long doubles will only work if - they match the long double format on your target. All hexadecimal formats - are big-endian (sign bit at the left).</p> + they match the long double format on your target. The IEEE 16-bit format + (half precision) is represented by <tt>0xH</tt> followed by 4 hexadecimal + digits. All hexadecimal formats are big-endian (sign bit at the left).</p> <p>There are no constants of type x86mmx.</p> </div> @@ -7947,7 +7948,8 @@ LLVM</a>.</p> <div> -<p>Half precision floating point is a storage-only format. This means that it is +<p>For most target platforms, half precision floating point is a storage-only + format. This means that it is a dense encoding (in memory) but does not support computation in the format.</p> diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index 8818168..e718069 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -673,11 +673,12 @@ lltok::Kind LLLexer::LexIdentifier() { /// HexFP80Constant 0xK[0-9A-Fa-f]+ /// HexFP128Constant 0xL[0-9A-Fa-f]+ /// HexPPC128Constant 0xM[0-9A-Fa-f]+ +/// HexHalfConstant 0xH[0-9A-Fa-f]+ lltok::Kind LLLexer::Lex0x() { CurPtr = TokStart + 2; char Kind; - if (CurPtr[0] >= 'K' && CurPtr[0] <= 'M') { + if (CurPtr[0] >= 'K' && CurPtr[0] <= 'M' || CurPtr[0] == 'H') { Kind = *CurPtr++; } else { Kind = 'J'; @@ -718,6 +719,9 @@ lltok::Kind LLLexer::Lex0x() { HexToIntPair(TokStart+3, CurPtr, Pair); APFloatVal = APFloat(APInt(128, Pair)); return lltok::APFloat; + case 'H': + APFloatVal = APFloat(APInt(16,HexIntToVal(TokStart+3, CurPtr))); + return lltok::APFloat; } } diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 7b39efb..4a7fde1 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -708,8 +708,7 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, } if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) { - if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEhalf || - &CFP->getValueAPF().getSemantics() == &APFloat::IEEEsingle || + if (&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 @@ -759,16 +758,20 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, return; } - // Some form of long double. These appear as a magic letter identifying - // the type, then a fixed number of hex digits. + // Either half, or some form of long double. + // These appear as a magic letter identifying the type, then a + // fixed number of hex digits. Out << "0x"; + // Bit position, in the current word, of the next nibble to print. + int shiftcount; + if (&CFP->getValueAPF().getSemantics() == &APFloat::x87DoubleExtended) { Out << 'K'; // api needed to prevent premature destruction APInt api = CFP->getValueAPF().bitcastToAPInt(); const uint64_t* p = api.getRawData(); uint64_t word = p[1]; - int shiftcount=12; + shiftcount = 12; int width = api.getBitWidth(); for (int j=0; j<width; j+=4, shiftcount-=4) { unsigned int nibble = (word>>shiftcount) & 15; @@ -784,17 +787,21 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, } } return; - } else if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEquad) + } else if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEquad) { + shiftcount = 60; Out << 'L'; - else if (&CFP->getValueAPF().getSemantics() == &APFloat::PPCDoubleDouble) + } else if (&CFP->getValueAPF().getSemantics() == &APFloat::PPCDoubleDouble) { + shiftcount = 60; Out << 'M'; - else + } else if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEhalf) { + shiftcount = 12; + Out << 'H'; + } else llvm_unreachable("Unsupported floating point type"); // api needed to prevent premature destruction APInt api = CFP->getValueAPF().bitcastToAPInt(); const uint64_t* p = api.getRawData(); uint64_t word = *p; - int shiftcount=60; int width = api.getBitWidth(); for (int j=0; j<width; j+=4, shiftcount-=4) { unsigned int nibble = (word>>shiftcount) & 15; diff --git a/test/Assembler/half-constprop.ll b/test/Assembler/half-constprop.ll new file mode 100644 index 0000000..03ccdda --- /dev/null +++ b/test/Assembler/half-constprop.ll @@ -0,0 +1,17 @@ +; RUN: llvm-as < %s | opt -O3 | llvm-dis | FileCheck %s +; Testing half constant propagation. + +define half @abc() nounwind { +entry: + %a = alloca half, align 2 + %b = alloca half, align 2 + %.compoundliteral = alloca float, align 4 + store half 0xH4200, half* %a, align 2 + store half 0xH4B9A, half* %b, align 2 + %tmp = load half* %a, align 2 + %tmp1 = load half* %b, align 2 + %add = fadd half %tmp, %tmp1 +; CHECK: 0xH4C8D + ret half %add +} + diff --git a/test/Assembler/half-conv.ll b/test/Assembler/half-conv.ll new file mode 100644 index 0000000..bf9ae57 --- /dev/null +++ b/test/Assembler/half-conv.ll @@ -0,0 +1,13 @@ +; RUN: llvm-as < %s | opt -O3 | llvm-dis | FileCheck %s +; Testing half to float conversion. + +define float @abc() nounwind { +entry: + %a = alloca half, align 2 + %.compoundliteral = alloca float, align 4 + store half 0xH4C8D, half* %a, align 2 + %tmp = load half* %a, align 2 + %conv = fpext half %tmp to float +; CHECK: 0x4032340000000000 + ret float %conv +} diff --git a/test/Assembler/half.ll b/test/Assembler/half.ll new file mode 100644 index 0000000..63ad392 --- /dev/null +++ b/test/Assembler/half.ll @@ -0,0 +1,8 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s +; Basic smoke test for half type. + +; CHECK: define half @halftest +define half @halftest(half %A0) { +; CHECK: ret half %A0 + ret half %A0 +} |