mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-12 17:32:19 +00:00
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
This commit is contained in:
parent
91bf23e6b7
commit
057beb8d4f
@ -1144,6 +1144,18 @@ type table.
|
||||
</p>
|
||||
</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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
17
test/Assembler/half-constprop.ll
Normal file
17
test/Assembler/half-constprop.ll
Normal file
@ -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
|
||||
}
|
||||
|
13
test/Assembler/half-conv.ll
Normal file
13
test/Assembler/half-conv.ll
Normal file
@ -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
|
||||
}
|
8
test/Assembler/half.ll
Normal file
8
test/Assembler/half.ll
Normal file
@ -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
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user