//===----------------------------------------------------------------------===// // // 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