blob: c0a517a927433879ebd7c58fae0df3fba9336727 [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
//
//===----------------------------------------------------------------------===//
// 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