[VENTUS][RISCV][libclc] Add more soft float function support

This commit is contained in:
zhoujing 2023-07-13 13:24:03 +08:00
parent d2c3e47f6a
commit 209306abc9
7 changed files with 586 additions and 190 deletions

View File

@ -26,78 +26,114 @@
#
# convert_<destTypen><_sat><_roundingMode>(<sourceTypen>)
types = ['char', 'uchar', 'short', 'ushort', 'int', 'uint', 'float']
int_types = ['char', 'uchar', 'short', 'ushort', 'int', 'uint']
unsigned_types = ['uchar', 'ushort', 'uint']
float_types = ['float']
vector_sizes = ['', '2', '3', '4', '8', '16']
half_sizes = [('2',''), ('4','2'), ('8','4'), ('16','8')]
types = [
"char",
"uchar",
"short",
"ushort",
"int",
"uint",
"long",
"ulong",
"float",
"double",
]
int_types = ["char", "uchar", "short", "ushort", "int", "uint", "long", "ulong"]
unsigned_types = ["uchar", "ushort", "uint", "ulong"]
float_types = ["float", "double"]
int64_types = ["long", "ulong"]
float64_types = ["double"]
vector_sizes = ["", "2", "3", "4", "8", "16"]
half_sizes = [("2", ""), ("4", "2"), ("8", "4"), ("16", "8")]
saturation = ['','_sat']
rounding_modes = ['_rtz','_rte','_rtp','_rtn']
float_prefix = {'float':'FLT_', 'double':'DBL_'}
float_suffix = {'float':'f'}
saturation = ["", "_sat"]
rounding_modes = ["_rtz", "_rte", "_rtp", "_rtn"]
float_prefix = {"float": "FLT_", "double": "DBL_"}
float_suffix = {"float": "f", "double": ""}
bool_type = {'char' : 'char',
'uchar' : 'char',
'short' : 'short',
'ushort': 'short',
'int' : 'int',
'uint' : 'int',
'float' : 'int'}
bool_type = {
"char": "char",
"uchar": "char",
"short": "short",
"ushort": "short",
"int": "int",
"uint": "int",
"long": "long",
"ulong": "long",
"float": "int",
"double": "long",
}
unsigned_type = {'char' : 'uchar',
'uchar' : 'uchar',
'short' : 'ushort',
'ushort': 'ushort',
'int' : 'uint',
'uint' : 'uint'}
unsigned_type = {
"char": "uchar",
"uchar": "uchar",
"short": "ushort",
"ushort": "ushort",
"int": "uint",
"uint": "uint",
"long": "ulong",
"ulong": "ulong",
}
sizeof_type = {'char' : 1, 'uchar' : 1,
'short' : 2, 'ushort' : 2,
'int' : 4, 'uint' : 4,
'float' : 4}
sizeof_type = {
"char": 1,
"uchar": 1,
"short": 2,
"ushort": 2,
"int": 4,
"uint": 4,
"long": 8,
"ulong": 8,
"float": 4,
"double": 8,
}
limit_max = {'char' : 'CHAR_MAX',
'uchar' : 'UCHAR_MAX',
'short' : 'SHRT_MAX',
'ushort': 'USHRT_MAX',
'int' : 'INT_MAX',
'uint' : 'UINT_MAX',
'long' : 'LONG_MAX',
'ulong' : 'ULONG_MAX'}
limit_max = {
"char": "CHAR_MAX",
"uchar": "UCHAR_MAX",
"short": "SHRT_MAX",
"ushort": "USHRT_MAX",
"int": "INT_MAX",
"uint": "UINT_MAX",
"long": "LONG_MAX",
"ulong": "ULONG_MAX",
}
limit_min = {
"char": "CHAR_MIN",
"uchar": "0",
"short": "SHRT_MIN",
"ushort": "0",
"int": "INT_MIN",
"uint": "0",
"long": "LONG_MIN",
"ulong": "0",
}
limit_min = {'char' : 'CHAR_MIN',
'uchar' : '0',
'short' : 'SHRT_MIN',
'ushort': '0',
'int' : 'INT_MIN',
'uint' : '0',
'long' : 'LONG_MIN',
'ulong' : '0'}
def conditional_guard(src, dst):
int64_count = 0
float64_count = 0
# if src in int64_types:
# int64_count = int64_count +1
# elif src in float64_types:
# float64_count = float64_count + 1
# if dst in int64_types:
# int64_count = int64_count +1
# elif dst in float64_types:
# float64_count = float64_count + 1
if float64_count > 0:
#In embedded profile, if cl_khr_fp64 is supported cles_khr_int64 has to be
print("#ifdef cl_khr_fp64")
return True
elif int64_count > 0:
print("#if defined cles_khr_int64 || !defined(__EMBEDDED_PROFILE__)")
return True
return False
int64_count = 0
float64_count = 0
if src in int64_types:
int64_count = int64_count + 1
elif src in float64_types:
float64_count = float64_count + 1
if dst in int64_types:
int64_count = int64_count + 1
elif dst in float64_types:
float64_count = float64_count + 1
if float64_count > 0:
# In embedded profile, if cl_khr_fp64 is supported cles_khr_int64 has to be
print("#ifdef cl_khr_fp64")
return True
elif int64_count > 0:
print("#if defined cles_khr_int64 || !defined(__EMBEDDED_PROFILE__)")
return True
return False
print("""/* !!!! AUTOGENERATED FILE generated by convert_type.py !!!!!
print(
"""/* !!!! AUTOGENERATED FILE generated by convert_type.py !!!!!
DON'T CHANGE THIS FILE. MAKE YOUR CHANGES TO convert_type.py AND RUN:
$ ./generate-conversion-type-cl.sh
@ -141,7 +177,8 @@ print("""/* !!!! AUTOGENERATED FILE generated by convert_type.py !!!!!
#pragma OPENCL EXTENSION cles_khr_int64 : enable
#endif
""")
"""
)
#
# Default Conversions
@ -170,45 +207,58 @@ print("""/* !!!! AUTOGENERATED FILE generated by convert_type.py !!!!!
# is used, the rounding mode is ignored.
#
def generate_default_conversion(src, dst, mode):
close_conditional = conditional_guard(src, dst)
# scalar conversions
print("""_CLC_DEF _CLC_OVERLOAD
def generate_default_conversion(src, dst, mode):
close_conditional = conditional_guard(src, dst)
# scalar conversions
print(
"""_CLC_DEF _CLC_OVERLOAD
{DST} convert_{DST}{M}({SRC} x)
{{
return ({DST})x;
}}
""".format(SRC=src, DST=dst, M=mode))
""".format(
SRC=src, DST=dst, M=mode
)
)
# vector conversions, done through decomposition to components
for size, half_size in half_sizes:
print("""_CLC_DEF _CLC_OVERLOAD
# vector conversions, done through decomposition to components
for size, half_size in half_sizes:
print(
"""_CLC_DEF _CLC_OVERLOAD
{DST}{N} convert_{DST}{N}{M}({SRC}{N} x)
{{
return ({DST}{N})(convert_{DST}{H}(x.lo), convert_{DST}{H}(x.hi));
}}
""".format(SRC=src, DST=dst, N=size, H=half_size, M=mode))
""".format(
SRC=src, DST=dst, N=size, H=half_size, M=mode
)
)
# 3-component vector conversions
print("""_CLC_DEF _CLC_OVERLOAD
# 3-component vector conversions
print(
"""_CLC_DEF _CLC_OVERLOAD
{DST}3 convert_{DST}3{M}({SRC}3 x)
{{
return ({DST}3)(convert_{DST}2(x.s01), convert_{DST}(x.s2));
}}""".format(SRC=src, DST=dst, M=mode))
}}""".format(
SRC=src, DST=dst, M=mode
)
)
if close_conditional:
print("#endif")
if close_conditional:
print("#endif")
for src in types:
for dst in types:
generate_default_conversion(src, dst, '')
for dst in types:
generate_default_conversion(src, dst, "")
for src in int_types:
for dst in int_types:
for mode in rounding_modes:
generate_default_conversion(src, dst, mode)
for dst in int_types:
for mode in rounding_modes:
generate_default_conversion(src, dst, mode)
#
# Saturated Conversions To Integers
@ -221,97 +271,127 @@ for src in int_types:
# conversions with saturation.
#
def generate_saturated_conversion(src, dst, size):
# Header
close_conditional = conditional_guard(src, dst)
print("""_CLC_DEF _CLC_OVERLOAD
# Header
close_conditional = conditional_guard(src, dst)
print(
"""_CLC_DEF _CLC_OVERLOAD
{DST}{N} convert_{DST}{N}_sat({SRC}{N} x)
{{""".format(DST=dst, SRC=src, N=size))
{{""".format(
DST=dst, SRC=src, N=size
)
)
# FIXME: This is a work around for lack of select function with
# signed third argument when the first two arguments are unsigned types.
# We cast to the signed type for sign-extension, then do a bitcast to
# the unsigned type.
if dst in unsigned_types:
bool_prefix = "as_{DST}{N}(convert_{BOOL}{N}".format(DST=dst, BOOL=bool_type[dst], N=size);
bool_suffix = ")"
else:
bool_prefix = "convert_{BOOL}{N}".format(BOOL=bool_type[dst], N=size);
bool_suffix = ""
# FIXME: This is a work around for lack of select function with
# signed third argument when the first two arguments are unsigned types.
# We cast to the signed type for sign-extension, then do a bitcast to
# the unsigned type.
if dst in unsigned_types:
bool_prefix = "as_{DST}{N}(convert_{BOOL}{N}".format(
DST=dst, BOOL=bool_type[dst], N=size
)
bool_suffix = ")"
else:
bool_prefix = "convert_{BOOL}{N}".format(BOOL=bool_type[dst], N=size)
bool_suffix = ""
# Body
if src == dst:
# Body
if src == dst:
# Conversion between same types
print(" return x;")
# Conversion between same types
print(" return x;")
elif src in float_types:
elif src in float_types:
# Conversion from float to int
print(""" {DST}{N} y = convert_{DST}{N}(x);
# Conversion from float to int
print(
""" {DST}{N} y = convert_{DST}{N}(x);
y = select(y, ({DST}{N}){DST_MIN}, {BP}(x < ({SRC}{N}){DST_MIN}){BS});
y = select(y, ({DST}{N}){DST_MAX}, {BP}(x > ({SRC}{N}){DST_MAX}){BS});
return y;""".format(SRC=src, DST=dst, N=size,
DST_MIN=limit_min[dst], DST_MAX=limit_max[dst],
BP=bool_prefix, BS=bool_suffix))
return y;""".format(
SRC=src,
DST=dst,
N=size,
DST_MIN=limit_min[dst],
DST_MAX=limit_max[dst],
BP=bool_prefix,
BS=bool_suffix,
)
)
else:
else:
# Integer to integer convesion with sizeof(src) == sizeof(dst)
if sizeof_type[src] == sizeof_type[dst]:
if src in unsigned_types:
print(" x = min(x, ({SRC}){DST_MAX});".format(SRC=src, DST_MAX=limit_max[dst]))
else:
print(" x = max(x, ({SRC})0);".format(SRC=src))
# Integer to integer convesion with sizeof(src) == sizeof(dst)
if sizeof_type[src] == sizeof_type[dst]:
if src in unsigned_types:
print(
" x = min(x, ({SRC}){DST_MAX});".format(
SRC=src, DST_MAX=limit_max[dst]
)
)
else:
print(" x = max(x, ({SRC})0);".format(SRC=src))
# Integer to integer conversion where sizeof(src) > sizeof(dst)
elif sizeof_type[src] > sizeof_type[dst]:
if src in unsigned_types:
print(" x = min(x, ({SRC}){DST_MAX});".format(SRC=src, DST_MAX=limit_max[dst]))
else:
print(" x = clamp(x, ({SRC}){DST_MIN}, ({SRC}){DST_MAX});"
.format(SRC=src, DST_MIN=limit_min[dst], DST_MAX=limit_max[dst]))
# Integer to integer conversion where sizeof(src) > sizeof(dst)
elif sizeof_type[src] > sizeof_type[dst]:
if src in unsigned_types:
print(
" x = min(x, ({SRC}){DST_MAX});".format(
SRC=src, DST_MAX=limit_max[dst]
)
)
else:
print(
" x = clamp(x, ({SRC}){DST_MIN}, ({SRC}){DST_MAX});".format(
SRC=src, DST_MIN=limit_min[dst], DST_MAX=limit_max[dst]
)
)
# Integer to integer conversion where sizeof(src) < sizeof(dst)
elif src not in unsigned_types and dst in unsigned_types:
print(" x = max(x, ({SRC})0);".format(SRC=src))
# Integer to integer conversion where sizeof(src) < sizeof(dst)
elif src not in unsigned_types and dst in unsigned_types:
print(" x = max(x, ({SRC})0);".format(SRC=src))
print(" return convert_{DST}{N}(x);".format(DST=dst, N=size))
print(" return convert_{DST}{N}(x);".format(DST=dst, N=size))
# Footer
print("}")
if close_conditional:
print("#endif")
# Footer
print("}")
if close_conditional:
print("#endif")
for src in types:
for dst in int_types:
for size in vector_sizes:
generate_saturated_conversion(src, dst, size)
for dst in int_types:
for size in vector_sizes:
generate_saturated_conversion(src, dst, size)
def generate_saturated_conversion_with_rounding(src, dst, size, mode):
# Header
close_conditional = conditional_guard(src, dst)
# Header
close_conditional = conditional_guard(src, dst)
# Body
print("""_CLC_DEF _CLC_OVERLOAD
# Body
print(
"""_CLC_DEF _CLC_OVERLOAD
{DST}{N} convert_{DST}{N}_sat{M}({SRC}{N} x)
{{
return convert_{DST}{N}_sat(x);
}}
""".format(DST=dst, SRC=src, N=size, M=mode))
""".format(
DST=dst, SRC=src, N=size, M=mode
)
)
# Footer
if close_conditional:
print("#endif")
# Footer
if close_conditional:
print("#endif")
for src in int_types:
for dst in int_types:
for size in vector_sizes:
for mode in rounding_modes:
generate_saturated_conversion_with_rounding(src, dst, size, mode)
for dst in int_types:
for size in vector_sizes:
for mode in rounding_modes:
generate_saturated_conversion_with_rounding(src, dst, size, mode)
#
# Conversions To/From Floating-Point With Rounding
@ -327,59 +407,81 @@ for src in int_types:
# Only conversions to integers can have saturation.
#
def generate_float_conversion(src, dst, size, mode, sat):
# Header
close_conditional = conditional_guard(src, dst)
print("""_CLC_DEF _CLC_OVERLOAD
# Header
close_conditional = conditional_guard(src, dst)
print(
"""_CLC_DEF _CLC_OVERLOAD
{DST}{N} convert_{DST}{N}{S}{M}({SRC}{N} x)
{{""".format(SRC=src, DST=dst, N=size, M=mode, S=sat))
{{""".format(
SRC=src, DST=dst, N=size, M=mode, S=sat
)
)
# Perform conversion
if dst in int_types:
if mode == '_rte':
print(" x = rint(x);");
elif mode == '_rtp':
print(" x = ceil(x);");
elif mode == '_rtn':
print(" x = floor(x);");
print(" return convert_{DST}{N}{S}(x);".format(DST=dst, N=size, S=sat))
elif mode == '_rte':
print(" return convert_{DST}{N}(x);".format(DST=dst, N=size))
else:
print(" {DST}{N} r = convert_{DST}{N}(x);".format(DST=dst, N=size))
print(" {SRC}{N} y = convert_{SRC}{N}(r);".format(SRC=src, N=size))
if mode == '_rtz':
if src in int_types:
print(" {USRC}{N} abs_x = abs(x);".format(USRC=unsigned_type[src], N=size))
print(" {USRC}{N} abs_y = abs(y);".format(USRC=unsigned_type[src], N=size))
else:
print(" {SRC}{N} abs_x = fabs(x);".format(SRC=src, N=size))
print(" {SRC}{N} abs_y = fabs(y);".format(SRC=src, N=size))
print(" return select(r, nextafter(r, sign(r) * ({DST}{N})-INFINITY), convert_{BOOL}{N}(abs_y > abs_x));"
.format(DST=dst, N=size, BOOL=bool_type[dst]))
if mode == '_rtp':
print(" return select(r, nextafter(r, ({DST}{N})INFINITY), convert_{BOOL}{N}(y < x));"
.format(DST=dst, N=size, BOOL=bool_type[dst]))
if mode == '_rtn':
print(" return select(r, nextafter(r, ({DST}{N})-INFINITY), convert_{BOOL}{N}(y > x));"
.format(DST=dst, N=size, BOOL=bool_type[dst]))
# Perform conversion
if dst in int_types:
if mode == "_rte":
print(" x = rint(x);")
elif mode == "_rtp":
print(" x = ceil(x);")
elif mode == "_rtn":
print(" x = floor(x);")
print(" return convert_{DST}{N}{S}(x);".format(DST=dst, N=size, S=sat))
elif mode == "_rte":
print(" return convert_{DST}{N}(x);".format(DST=dst, N=size))
else:
print(" {DST}{N} r = convert_{DST}{N}(x);".format(DST=dst, N=size))
print(" {SRC}{N} y = convert_{SRC}{N}(r);".format(SRC=src, N=size))
if mode == "_rtz":
if src in int_types:
print(
" {USRC}{N} abs_x = abs(x);".format(
USRC=unsigned_type[src], N=size
)
)
print(
" {USRC}{N} abs_y = abs(y);".format(
USRC=unsigned_type[src], N=size
)
)
else:
print(" {SRC}{N} abs_x = fabs(x);".format(SRC=src, N=size))
print(" {SRC}{N} abs_y = fabs(y);".format(SRC=src, N=size))
print(
" return select(r, nextafter(r, sign(r) * ({DST}{N})-INFINITY), convert_{BOOL}{N}(abs_y > abs_x));".format(
DST=dst, N=size, BOOL=bool_type[dst]
)
)
if mode == "_rtp":
print(
" return select(r, nextafter(r, ({DST}{N})INFINITY), convert_{BOOL}{N}(y < x));".format(
DST=dst, N=size, BOOL=bool_type[dst]
)
)
if mode == "_rtn":
print(
" return select(r, nextafter(r, ({DST}{N})-INFINITY), convert_{BOOL}{N}(y > x));".format(
DST=dst, N=size, BOOL=bool_type[dst]
)
)
# Footer
print("}")
if close_conditional:
print("#endif")
# Footer
print("}")
if close_conditional:
print("#endif")
for src in float_types:
for dst in int_types:
for size in vector_sizes:
for mode in rounding_modes:
for sat in saturation:
generate_float_conversion(src, dst, size, mode, sat)
for dst in int_types:
for size in vector_sizes:
for mode in rounding_modes:
for sat in saturation:
generate_float_conversion(src, dst, size, mode, sat)
for src in types:
for dst in float_types:
for size in vector_sizes:
for mode in rounding_modes:
generate_float_conversion(src, dst, size, mode, '')
for dst in float_types:
for size in vector_sizes:
for mode in rounding_modes:
generate_float_conversion(src, dst, size, mode, "")

View File

@ -16,6 +16,7 @@ compiler-rt/divdf3.cl
compiler-rt/extendsfdf2.cl
compiler-rt/fixdfdi.cl
compiler-rt/fixdfsi.cl
compiler-rt/fixsfdi.cl
compiler-rt/float-intrinsics.cl
compiler-rt/floatdidf.cl
compiler-rt/floatdisf.cl
@ -24,4 +25,8 @@ compiler-rt/subdef3.cl
compiler-rt/truncdfsf2.cl
compiler-rt/floatsidf.cl
compiler-rt/fma.cl
compiler-rt/floor.cl
compiler-rt/floor.cl
compiler-rt/floatunsidf.cl
compiler-rt/floatundisf.cl
compiler-rt/floatundidf.cl
compiler-rt/isfinite.cl

View File

@ -0,0 +1,74 @@
//===-- fixsfdi.c - Implement __fixsfdi -----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifdef cl_khr_fp64
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#include "types.h"
typedef si_int fixint_t;
typedef su_int fixuint_t;
static __inline fixint_t __fixint(fp_t a) {
const fixint_t fixint_max = (fixint_t)((~(fixuint_t)0) / 2);
const fixint_t fixint_min = -fixint_max - 1;
const rep_t aRep = toRep(a);
const rep_t aAbs =
aRep & ((1UL << (52 + ((sizeof(rep_t) * 8) - 52 - 1))) - 1U);
const fixint_t sign =
aRep & (1UL << (52 + ((sizeof(rep_t) * 8) - 52 - 1))) ? -1 : 1;
const int exponent =
(aAbs >> 52) - (((1 << ((sizeof(rep_t) * 8) - 52 - 1)) - 1) >> 1);
const rep_t significand = (aAbs & ((1UL << 52) - 1U)) | (1UL << 52);
if (exponent < 0)
return 0;
if ((unsigned)exponent >= sizeof(fixint_t) * 8)
return sign == 1 ? fixint_max : fixint_min;
if (exponent < 52)
return sign * (significand >> (52 - exponent));
else
return sign * ((fixint_t)significand << (exponent - 52));
}
si_int __fixdfsi(fp_t a) { return __fixint(a); }
du_int __fixuint(fp_t a) {
const rep_t aRep = toRep(a);
const rep_t aAbs =
aRep & ((1U << (23 + ((sizeof(rep_t) * 8) - 23 - 1))) - 1U);
const int sign =
aRep & (1U << (23 + ((sizeof(rep_t) * 8) - 23 - 1))) ? -1 : 1;
const int exponent =
(aAbs >> 23) - (((1 << ((sizeof(rep_t) * 8) - 23 - 1)) - 1) >> 1);
const rep_t significand = (aAbs & ((1U << 23) - 1U)) | (1U << 23);
if (sign == -1 || exponent < 0)
return 0;
if ((unsigned)exponent >= sizeof(fixuint_t) * 8)
return ~(fixuint_t)0;
if (exponent < 23)
return significand >> (23 - exponent);
else
return (fixuint_t)significand << (exponent - 23);
}
du_int __fixunssfdi(fp_t a) { return __fixuint(a); }
di_int __fixsfdi(fp_t a) { return __fixint(a); }
su_int __fixunsdfsi(fp_t a) { return __fixuint(a); }
du_int __fixunsdfdi(fp_t a) { return __fixuint(a); }
#endif

View File

@ -0,0 +1,56 @@
//===-- floatundidf.c - Implement __floatundidf ---------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Referenced from floatundidf.c, but implemented in OpenCL language
//
//===----------------------------------------------------------------------===//
#ifdef cl_khr_fp64
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#include "types.h"
double __floatundidf(du_int a) {
if (a == 0)
return 0.0;
const unsigned N = sizeof(du_int) * 8;
int sd = N - __builtin_clzll(a);
int e = sd - 1;
if (sd > 53) {
switch (sd) {
case 53 + 1:
a <<= 1;
break;
case 53 + 2:
break;
default:
a = (a >> (sd - (53 + 2))) |
((a & ((du_int)(-1) >> ((N + 53 + 2) - sd))) != 0);
};
a |= (a & 4) != 0;
++a;
a >>= 2;
if (a & ((du_int)1 << 53)) {
a >>= 1;
++e;
}
} else {
a <<= (53 - sd);
}
double_bits fb;
fb.u.s.high = ((su_int)(e + 1023) << 20) | ((su_int)(a >> 32) & 0x000FFFFF);
fb.u.s.low = (su_int)a;
return fb.f;
}
#endif

View File

@ -0,0 +1,67 @@
//===-- floatundisf.cl - Implement __floatundisf --------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Referenced from muldf3.c, but implemented in OpenCL language
//
//===----------------------------------------------------------------------===//
// Returns: convert a to a float, rounding toward even.
// Assumption: float is a IEEE 32 bit floating point type
// long is a 64 bit integral type
// seee eeee emmm mmmm mmmm mmmm mmmm mmmm
typedef union {
int u;
float f;
} float_bits;
float __floatundisf(long a) {
if (a == 0)
return 0.0F;
const unsigned N = sizeof(long) * 8;
int sd = N - __builtin_clzll(a); // number of significant digits
int e = sd - 1; // 8 exponent
if (sd > 24) {
// start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx
// finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR
// 12345678901234567890123456
// 1 = msb 1 bit
// P = bit FLT_MANT_DIG-1 bits to the right of 1
// Q = bit FLT_MANT_DIG bits to the right of 1
// R = "or" of all bits to the right of Q
switch (sd) {
case 24 + 1:
a <<= 1;
break;
case 24 + 2:
break;
default:
a = (a >> (sd - (24 + 2))) |
((a & ((long)(-1) >> ((N + 24+ 2) - sd))) != 0);
};
// finish:
a |= (a & 4) != 0; // Or P into R
++a; // round - this step may add a significant bit
a >>= 2; // dump Q and R
// a is now rounded to FLT_MANT_DIG or FLT_MANT_DIG+1 bits
if (a & ((long)1 << 24)) {
a >>= 1;
++e;
}
// a is now rounded to FLT_MANT_DIG bits
} else {
a <<= (24 - sd);
// a is now rounded to FLT_MANT_DIG bits
}
float_bits fb;
fb.u = ((e + 127) << 23) | // exponent
((unsigned)a & 0x007FFFFF); // mantissa
return fb.f;
}

View File

@ -0,0 +1,38 @@
//===-- lib/floatunsidf.c - uint -> double-precision conversion ---*- C -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Referenced from floatunsidf.c, but implemented in OpenCL language
//
//===----------------------------------------------------------------------===//
#ifdef cl_khr_fp64
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#include "types.h"
fp_t __floatunsidf(su_int a) {
const int aWidth = sizeof a * 8;
if (a == 0)
return fromRep(0);
const int exponent = (aWidth - 1) - __builtin_clz(a);
rep_t result;
const int shift = 52 - exponent;
result = (rep_t)a << shift ^ (1UL << 52);
result +=
(rep_t)(exponent + (((1 << ((sizeof(rep_t) * 8) - 52 - 1)) - 1) >> 1))
<< 52;
return fromRep(result);
}
#endif

View File

@ -0,0 +1,54 @@
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#ifdef cl_khr_fp64
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#include "types.h"
#define FP_NAN 0
#define FP_INFINITE 1
#define FP_ZERO 2
#define FP_SUBNORMAL 3
#define FP_NORMAL 4
union __double_repr { double __f; __uint64_t __i; };
#define __FLOAT_BITS(f) (((union __float_repr){ (float)(f) }).__i)
#define __DOUBLE_BITS(f) (((union __double_repr){ (double)(f) }).__i)
#define _fpclassify(x) ( \
sizeof(x) == sizeof(double) ? __fpclassify(x) : \
__fpclassifyl(x) )
#define _isinf(x) ( \
sizeof(x) == sizeof(double) ? (__DOUBLE_BITS(x) & (__uint64_t)-1>>1) == (__uint64_t)0x7ff<<52 : \
__fpclassifyl(x) == FP_INFINITE)
#define _isnan(x) ( \
sizeof(x) == sizeof(double) ? (__DOUBLE_BITS(x) & (__uint64_t)-1>>1) > (__uint64_t)0x7ff<<52 : \
__fpclassifyl(x) == FP_NAN)
#define _isnormal(x) ( \
sizeof(x) == sizeof(double) ? ((__DOUBLE_BITS(x)+((__uint64_t)1<<52)) & (__uint64_t)-1>>1) >= (__uint64_t)1<<53 : \
__fpclassifyl(x) == FP_NORMAL)
#define _isfinite(x) ( \
(__DOUBLE_BITS(x) & (__uint64_t)-1>>1) < (__uint64_t)0x7ff<<52)
// If there are other needs, we can define other
bool isfinite(double x) {
return _isfinite(x);
}
#endif