blob: 75558dbd34ae2a5566f71eec12e78c14f8b87f79 [file] [edit]
//===----------------------------------------------------------------------===//
//
// 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 __CLC_I2F
#ifdef __CLC_GEN_S
#if __CLC_GENSIZE_SRC == 8
#define __CLC_SRC_MAX SCHAR_MAX
#elif __CLC_GENSIZE_SRC == 16
#define __CLC_SRC_MAX SHRT_MAX
#elif __CLC_GENSIZE_SRC == 32
#define __CLC_SRC_MAX INT_MAX
#elif __CLC_GENSIZE_SRC == 64
#define __CLC_SRC_MAX LONG_MAX
#endif
#else // __CLC_GEN_S
#if __CLC_GENSIZE_SRC == 8
#define __CLC_SRC_MAX UCHAR_MAX
#elif __CLC_GENSIZE_SRC == 16
#define __CLC_SRC_MAX USHRT_MAX
#elif __CLC_GENSIZE_SRC == 32
#define __CLC_SRC_MAX UINT_MAX
#elif __CLC_GENSIZE_SRC == 64
#define __CLC_SRC_MAX ULONG_MAX
#endif
#endif // __CLC_GEN_S
#endif // __CLC_I2F
// Default conversion
// All conversions are in accordance with the OpenCL specification,
// which cites the C99 conversion rules.
//
// Conversions from integer to floating-point, and floating-point to
// floating-point through casting is done with the default rounding
// mode. While C99 allows dynamically changing the rounding mode
// during runtime, it is not a supported feature in OpenCL according
// to Section 7.1 - Rounding Modes in the OpenCL 1.2 specification.
//
// Therefore, we can assume for optimization purposes that the
// rounding mode is fixed to round-to-nearest-even. Platform target
// authors should ensure that the rounding-control registers remain
// in this state, and that this invariant holds.
//
// Also note, even though the OpenCL specification isn't entirely
// clear on this matter, we implement all rounding mode combinations
// even for integer-to-integer conversions. When such a conversion
// is used, the rounding mode is ignored.
#ifdef __CLC_SCALAR
_CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __CLC_FUNCTION(__CLC_GENTYPE_SRC x) {
return (__CLC_GENTYPE)x;
}
#else // __CLC_SCALAR
_CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __CLC_FUNCTION(__CLC_GENTYPE_SRC x) {
return __builtin_convertvector(x, __CLC_GENTYPE);
}
#endif // __CLC_SCALAR
// Rounding mode conversion
_CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __CLC_XCONCAT(__CLC_FUNCTION,
_rte)(__CLC_GENTYPE_SRC x) {
return __CLC_FUNCTION(x);
}
_CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __CLC_XCONCAT(__CLC_FUNCTION,
_rtz)(__CLC_GENTYPE_SRC x) {
__CLC_GENTYPE r = __CLC_FUNCTION(x);
#ifdef __CLC_I2F
__CLC_GENTYPE_SRC y =
__CLC_XCONCAT(__CLC_XCONCAT(__clc_convert_, __CLC_GENTYPE_SRC), _sat)(r);
__CLC_GENTYPE_SRC_U abs_x = __clc_abs(x);
__CLC_GENTYPE_SRC_U abs_y = __clc_abs(y);
#else
__CLC_GENTYPE_SRC y = __CLC_XCONCAT(__clc_convert_, __CLC_GENTYPE_SRC)(r);
__CLC_GENTYPE_SRC abs_x = __clc_fabs(x);
__CLC_GENTYPE_SRC abs_y = __clc_fabs(y);
#endif
__CLC_S_GENTYPE c = __CLC_CONVERT_S_GENTYPE(abs_y > abs_x);
#if defined(__CLC_I2F) && (__CLC_GENSIZE_SRC >= __CLC_FPSIZE)
c = c || __CLC_CONVERT_S_GENTYPE((__CLC_GENTYPE_SRC)__CLC_SRC_MAX == x);
#endif
__CLC_GENTYPE sel = __clc_select(
r, __clc_nextafter(r, __clc_sign(r) * (__CLC_GENTYPE)-INFINITY), c);
#if defined(__CLC_I2F) && (__CLC_FPSIZE == 16) && (__CLC_GENSIZE_SRC >= 16)
#if defined(__CLC_GEN_S) && (__CLC_GENSIZE_SRC == 16)
// short is 16 bits signed, so the maximum value rounded to zero is
// 0x1.ffcp+14 (0x1p+15 == 32768 > 0x7fff == 32767)
half dst_max = 0x1.ffcp+14h;
#else
half dst_max = 0x1.ffcp+15h;
#endif // defined(__CLC_GEN_S) && (__CLC_GENSIZE_SRC == 16)
half dst_min = -0x1.ffcp+15h;
sel = __clc_clamp(sel, (__CLC_GENTYPE)dst_min, (__CLC_GENTYPE)dst_max);
#endif // defined(__CLC_I2F) && (__CLC_FPSIZE == 16) && (__CLC_GENSIZE_SRC >=
// 16)
return sel;
}
_CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __CLC_XCONCAT(__CLC_FUNCTION,
_rtp)(__CLC_GENTYPE_SRC x) {
__CLC_GENTYPE r = __CLC_FUNCTION(x);
#ifdef __CLC_I2F
__CLC_GENTYPE_SRC y =
__CLC_XCONCAT(__CLC_XCONCAT(__clc_convert_, __CLC_GENTYPE_SRC), _sat)(r);
#else
__CLC_GENTYPE_SRC y = __CLC_XCONCAT(__clc_convert_, __CLC_GENTYPE_SRC)(r);
#endif
__CLC_GENTYPE sel =
__clc_select(r, __clc_nextafter(r, (__CLC_GENTYPE)INFINITY),
__CLC_CONVERT_S_GENTYPE(y < x));
#if defined(__CLC_I2F) && (__CLC_FPSIZE == 16) && (__CLC_GENSIZE_SRC >= 16)
half dst_min = -0x1.ffcp+15h;
sel = __clc_max(sel, (__CLC_GENTYPE)dst_min);
#endif
return sel;
}
_CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __CLC_XCONCAT(__CLC_FUNCTION,
_rtn)(__CLC_GENTYPE_SRC x) {
__CLC_GENTYPE r = __CLC_FUNCTION(x);
#ifdef __CLC_I2F
__CLC_GENTYPE_SRC y =
__CLC_XCONCAT(__CLC_XCONCAT(__clc_convert_, __CLC_GENTYPE_SRC), _sat)(r);
#else
__CLC_GENTYPE_SRC y = __CLC_XCONCAT(__clc_convert_, __CLC_GENTYPE_SRC)(r);
#endif
__CLC_S_GENTYPE c = __CLC_CONVERT_S_GENTYPE(y > x);
#if defined(__CLC_I2F) && (__CLC_GENSIZE_SRC >= __CLC_FPSIZE)
c = c || __CLC_CONVERT_S_GENTYPE((__CLC_GENTYPE_SRC)__CLC_SRC_MAX == x);
#endif
__CLC_GENTYPE sel =
__clc_select(r, __clc_nextafter(r, (__CLC_GENTYPE)-INFINITY), c);
#if defined(__CLC_I2F) && (__CLC_FPSIZE == 16) && (__CLC_GENSIZE_SRC >= 16)
#if defined(__CLC_GEN_S) && (__CLC_GENSIZE_SRC == 16)
// short is 16 bits signed, so the maximum value rounded to negative infinity
// is 0x1.ffcp+14 (0x1p+15 == 32768 > 0x7fff == 32767)
half dst_max = 0x1.ffcp+14h;
#else
half dst_max = 0x1.ffcp+15h;
#endif // defined(__CLC_GEN_S) && (__CLC_GENSIZE_SRC == 16)
sel = __clc_min(sel, (__CLC_GENTYPE)dst_max);
#endif // defined(__CLC_I2F) && (__CLC_FPSIZE == 16) &&
// (__CLC_GENSIZE_SRC >= 16)
return sel;
}
#undef __CLC_SRC_MAX