| //===----------------------------------------------------------------------===// |
| // |
| // 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| // Default conversion |
| |
| // All conversions are in accordance with the OpenCL specification, |
| // which cites the C99 conversion rules. |
| // |
| // 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. |
| |
| #define __CLC_GENSIZE_DST __CLC_GENSIZE |
| |
| _CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __CLC_FUNCTION(__CLC_S_GENTYPE_SRC x) { |
| #ifdef __CLC_SCALAR |
| return x; |
| #else |
| return __builtin_convertvector(x, __CLC_GENTYPE); |
| #endif |
| } |
| _CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __CLC_FUNCTION(__CLC_U_GENTYPE_SRC x) { |
| #ifdef __CLC_SCALAR |
| return x; |
| #else |
| return __builtin_convertvector(x, __CLC_GENTYPE); |
| #endif |
| } |
| |
| #ifdef __CLC_GEN_S |
| |
| #if __CLC_GENSIZE == 8 |
| #define __CLC_DST_MAX SCHAR_MAX |
| #define __CLC_DST_MIN SCHAR_MIN |
| #elif __CLC_GENSIZE == 16 |
| #define __CLC_DST_MAX SHRT_MAX |
| #define __CLC_DST_MIN SHRT_MIN |
| #elif __CLC_GENSIZE == 32 |
| #define __CLC_DST_MAX INT_MAX |
| #define __CLC_DST_MIN INT_MIN |
| #elif __CLC_GENSIZE == 64 |
| #define __CLC_DST_MAX LONG_MAX |
| #define __CLC_DST_MIN LONG_MIN |
| #endif |
| |
| #else // __CLC_GEN_S |
| |
| #if __CLC_GENSIZE == 8 |
| #define __CLC_DST_MAX UCHAR_MAX |
| #define __CLC_DST_MIN UCHAR_MIN |
| #elif __CLC_GENSIZE == 16 |
| #define __CLC_DST_MAX USHRT_MAX |
| #define __CLC_DST_MIN USHRT_MIN |
| #elif __CLC_GENSIZE == 32 |
| #define __CLC_DST_MAX UINT_MAX |
| #define __CLC_DST_MIN UINT_MIN |
| #elif __CLC_GENSIZE == 64 |
| #define __CLC_DST_MAX ULONG_MAX |
| #define __CLC_DST_MIN ULONG_MIN |
| #endif |
| |
| #endif // __CLC_GEN_S |
| |
| _CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __CLC_FUNCTION_SAT(__CLC_S_GENTYPE_SRC x) { |
| #if defined(__CLC_GEN_S) && (__CLC_GENSIZE_SRC == __CLC_GENSIZE_DST) |
| // Conversion between same types |
| return x; |
| #else |
| #if __CLC_GENSIZE_SRC == __CLC_GENSIZE_DST |
| x = __clc_max(x, (__CLC_S_SCALAR_TYPE_SRC)0); |
| #elif __CLC_GENSIZE_SRC > __CLC_GENSIZE_DST |
| x = __clc_clamp(x, (__CLC_S_SCALAR_TYPE_SRC)__CLC_DST_MIN, |
| (__CLC_S_SCALAR_TYPE_SRC)__CLC_DST_MAX); |
| #elif defined(__CLC_GEN_U) |
| // sizeof(src) < sizeof(dst) |
| x = __clc_max(x, (__CLC_S_SCALAR_TYPE_SRC)0); |
| #endif |
| return __CLC_FUNCTION(x); |
| #endif |
| } |
| |
| _CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __CLC_FUNCTION_SAT(__CLC_U_GENTYPE_SRC x) { |
| #if defined(__CLC_GEN_U) && (__CLC_GENSIZE_SRC == __CLC_GENSIZE_DST) |
| // Conversion between same types |
| return x; |
| #else |
| #if __CLC_GENSIZE_SRC >= __CLC_GENSIZE_DST |
| x = __clc_min(x, (__CLC_U_SCALAR_TYPE_SRC)__CLC_DST_MAX); |
| #endif |
| return __CLC_FUNCTION(x); |
| #endif |
| } |
| |
| #ifdef __CLC_SCALAR |
| #define __CLC_DEFINE_FUNCTION_ROUNDING_MODE_NONSAT_IMPL(TYPE_SRC, MODE) \ |
| _CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __CLC_XCONCAT(__CLC_FUNCTION, \ |
| MODE)(TYPE_SRC x) { \ |
| return x; \ |
| } |
| #else |
| #define __CLC_DEFINE_FUNCTION_ROUNDING_MODE_NONSAT_IMPL(TYPE_SRC, MODE) \ |
| _CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __CLC_XCONCAT(__CLC_FUNCTION, \ |
| MODE)(TYPE_SRC x) { \ |
| return __builtin_convertvector(x, __CLC_GENTYPE); \ |
| } |
| #endif |
| |
| #define __CLC_DEFINE_FUNCTION_ROUNDING_MODE_IMPL(TYPE_SRC, MODE) \ |
| __CLC_DEFINE_FUNCTION_ROUNDING_MODE_NONSAT_IMPL(TYPE_SRC, MODE) \ |
| _CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __CLC_XCONCAT(__CLC_FUNCTION_SAT, \ |
| MODE)(TYPE_SRC x) { \ |
| return __CLC_FUNCTION_SAT(x); \ |
| } |
| |
| #define __CLC_DEFINE_FUNCTION_ROUNDING_MODE(MODE) \ |
| __CLC_DEFINE_FUNCTION_ROUNDING_MODE_IMPL(__CLC_S_GENTYPE_SRC, MODE) \ |
| __CLC_DEFINE_FUNCTION_ROUNDING_MODE_IMPL(__CLC_U_GENTYPE_SRC, MODE) |
| |
| __CLC_DEFINE_FUNCTION_ROUNDING_MODE(_rte) |
| __CLC_DEFINE_FUNCTION_ROUNDING_MODE(_rtz) |
| __CLC_DEFINE_FUNCTION_ROUNDING_MODE(_rtp) |
| __CLC_DEFINE_FUNCTION_ROUNDING_MODE(_rtn) |
| |
| #undef __CLC_DEFINE_FUNCTION_ROUNDING_MODE_NONSAT_IMPL |
| #undef __CLC_DEFINE_FUNCTION_ROUNDING_MODE_IMPL |
| #undef __CLC_DEFINE_FUNCTION_ROUNDING_MODE |
| |
| #undef __CLC_DST_MAX |
| #undef __CLC_DST_MIN |
| |
| #undef __CLC_GENSIZE_DST |