Index: clang/lib/Headers/__clang_hip_cmath.h =================================================================== --- clang/lib/Headers/__clang_hip_cmath.h +++ clang/lib/Headers/__clang_hip_cmath.h @@ -22,7 +22,7 @@ #endif #include #include -#endif // __HIPCC_RTC__ +#endif // !defined(__HIPCC_RTC__) #pragma push_macro("__DEVICE__") #define __DEVICE__ static __device__ inline __attribute__((always_inline)) @@ -36,6 +36,9 @@ __DEVICE__ float fma(float __x, float __y, float __z) { return ::fmaf(__x, __y, __z); } +#if !defined(__HIPCC_RTC__) +// The value returned by fpclassify is platform dependent, therefore it is not +// supported by hipRTC. __DEVICE__ int fpclassify(float __x) { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x); @@ -44,6 +47,8 @@ return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x); } +#endif // !defined(__HIPCC_RTC__) + __DEVICE__ float frexp(float __arg, int *__exp) { return ::frexpf(__arg, __exp); } @@ -209,11 +214,115 @@ template struct __hip_enable_if { typedef __T type; }; +namespace __hip { +template struct is_integral { + enum { value = 0 }; +}; +template <> struct is_integral { + enum { value = 1 }; +}; +template <> struct is_integral { + enum { value = 1 }; +}; +template <> struct is_integral { + enum { value = 1 }; +}; +template <> struct is_integral { + enum { value = 1 }; +}; +template <> struct is_integral { + enum { value = 1 }; +}; +template <> struct is_integral { + enum { value = 1 }; +}; +template <> struct is_integral { + enum { value = 1 }; +}; +template <> struct is_integral { + enum { value = 1 }; +}; +template <> struct is_integral { + enum { value = 1 }; +}; +template <> struct is_integral { + enum { value = 1 }; +}; +template <> struct is_integral { + enum { value = 1 }; +}; +template <> struct is_integral { + enum { value = 1 }; +}; +template <> struct is_integral { + enum { value = 1 }; +}; + +template struct is_arithmetic { + enum { value = 0 }; +}; +template <> struct is_arithmetic { + enum { value = 1 }; +}; +template <> struct is_arithmetic { + enum { value = 1 }; +}; +template <> struct is_arithmetic { + enum { value = 1 }; +}; +template <> struct is_arithmetic { + enum { value = 1 }; +}; +template <> struct is_arithmetic { + enum { value = 1 }; +}; +template <> struct is_arithmetic { + enum { value = 1 }; +}; +template <> struct is_arithmetic { + enum { value = 1 }; +}; +template <> struct is_arithmetic { + enum { value = 1 }; +}; +template <> struct is_arithmetic { + enum { value = 1 }; +}; +template <> struct is_arithmetic { + enum { value = 1 }; +}; +template <> struct is_arithmetic { + enum { value = 1 }; +}; +template <> struct is_arithmetic { + enum { value = 1 }; +}; +template <> struct is_arithmetic { + enum { value = 1 }; +}; +template <> struct is_arithmetic { + enum { value = 1 }; +}; +template <> struct is_arithmetic { + enum { value = 1 }; +}; +template <> struct is_arithmetic<_Float16> { + enum { value = 1 }; +}; + +struct true_type { + static const __constant__ bool value = true; +}; +struct false_type { + static const __constant__ bool value = false; +}; + +template struct is_same : public false_type {}; +template struct is_same<__T, __T> : public true_type {}; + // decltype is only available in C++11 and above. #if __cplusplus >= 201103L // __hip_promote -namespace __hip { - template struct __numeric_type { static void __test(...); static _Float16 __test(_Float16); @@ -229,8 +338,8 @@ // No support for long double, use double instead. static double __test(long double); - typedef decltype(__test(std::declval<_Tp>())) type; - static const bool value = !std::is_same::value; + typedef decltype(__test(_Tp{})) type; + static const bool value = !is_same::value; }; template <> struct __numeric_type { static const bool value = true; }; @@ -273,18 +382,17 @@ template class __promote : public __promote_imp<_A1, _A2, _A3> {}; - +#endif } // namespace __hip -#endif //__cplusplus >= 201103L // __HIP_OVERLOAD1 is used to resolve function calls with integer argument to // avoid compilation error due to ambibuity. e.g. floor(5) is resolved with // floor(double). #define __HIP_OVERLOAD1(__retty, __fn) \ template \ - __DEVICE__ typename __hip_enable_if::is_integer, \ - __retty>::type \ - __fn(__T __x) { \ + __DEVICE__ \ + typename __hip_enable_if<__hip::is_integral<__T>::value, __retty>::type \ + __fn(__T __x) { \ return ::__fn((double)__x); \ } @@ -295,8 +403,7 @@ #define __HIP_OVERLOAD2(__retty, __fn) \ template \ __DEVICE__ typename __hip_enable_if< \ - std::numeric_limits<__T1>::is_specialized && \ - std::numeric_limits<__T2>::is_specialized, \ + __hip::is_arithmetic<__T1>::value && __hip::is_arithmetic<__T2>::value, \ typename __hip::__promote<__T1, __T2>::type>::type \ __fn(__T1 __x, __T2 __y) { \ typedef typename __hip::__promote<__T1, __T2>::type __result_type; \ @@ -305,11 +412,10 @@ #else #define __HIP_OVERLOAD2(__retty, __fn) \ template \ - __DEVICE__ \ - typename __hip_enable_if::is_specialized && \ - std::numeric_limits<__T2>::is_specialized, \ - __retty>::type \ - __fn(__T1 __x, __T2 __y) { \ + __DEVICE__ typename __hip_enable_if<__hip::is_arithmetic<__T1>::value && \ + __hip::is_arithmetic<__T2>::value, \ + __retty>::type \ + __fn(__T1 __x, __T2 __y) { \ return __fn((double)__x, (double)__y); \ } #endif @@ -337,7 +443,9 @@ __HIP_OVERLOAD2(double, fmax) __HIP_OVERLOAD2(double, fmin) __HIP_OVERLOAD2(double, fmod) +#if !defined(__HIPCC_RTC__) __HIP_OVERLOAD1(int, fpclassify) +#endif // !defined(__HIPCC_RTC__) __HIP_OVERLOAD2(double, hypot) __HIP_OVERLOAD1(int, ilogb) __HIP_OVERLOAD1(bool, isfinite) @@ -383,9 +491,8 @@ #if __cplusplus >= 201103L template __DEVICE__ typename __hip_enable_if< - std::numeric_limits<__T1>::is_specialized && - std::numeric_limits<__T2>::is_specialized && - std::numeric_limits<__T3>::is_specialized, + __hip::is_arithmetic<__T1>::value && __hip::is_arithmetic<__T2>::value && + __hip::is_arithmetic<__T3>::value, typename __hip::__promote<__T1, __T2, __T3>::type>::type fma(__T1 __x, __T2 __y, __T3 __z) { typedef typename __hip::__promote<__T1, __T2, __T3>::type __result_type; @@ -393,33 +500,32 @@ } #else template -__DEVICE__ - typename __hip_enable_if::is_specialized && - std::numeric_limits<__T2>::is_specialized && - std::numeric_limits<__T3>::is_specialized, - double>::type - fma(__T1 __x, __T2 __y, __T3 __z) { +__DEVICE__ typename __hip_enable_if<__hip::is_arithmetic<__T1>::value && + __hip::is_arithmetic<__T2>::value && + __hip::is_arithmetic<__T3>::value, + double>::type +fma(__T1 __x, __T2 __y, __T3 __z) { return ::fma((double)__x, (double)__y, (double)__z); } #endif template __DEVICE__ - typename __hip_enable_if::is_integer, double>::type + typename __hip_enable_if<__hip::is_integral<__T>::value, double>::type frexp(__T __x, int *__exp) { return ::frexp((double)__x, __exp); } template __DEVICE__ - typename __hip_enable_if::is_integer, double>::type + typename __hip_enable_if<__hip::is_integral<__T>::value, double>::type ldexp(__T __x, int __exp) { return ::ldexp((double)__x, __exp); } template __DEVICE__ - typename __hip_enable_if::is_integer, double>::type + typename __hip_enable_if<__hip::is_integral<__T>::value, double>::type modf(__T __x, double *__exp) { return ::modf((double)__x, __exp); } @@ -427,8 +533,8 @@ #if __cplusplus >= 201103L template __DEVICE__ - typename __hip_enable_if::is_specialized && - std::numeric_limits<__T2>::is_specialized, + typename __hip_enable_if<__hip::is_arithmetic<__T1>::value && + __hip::is_arithmetic<__T2>::value, typename __hip::__promote<__T1, __T2>::type>::type remquo(__T1 __x, __T2 __y, int *__quo) { typedef typename __hip::__promote<__T1, __T2>::type __result_type; @@ -436,25 +542,24 @@ } #else template -__DEVICE__ - typename __hip_enable_if::is_specialized && - std::numeric_limits<__T2>::is_specialized, - double>::type - remquo(__T1 __x, __T2 __y, int *__quo) { +__DEVICE__ typename __hip_enable_if<__hip::is_arithmetic<__T1>::value && + __hip::is_arithmetic<__T2>::value, + double>::type +remquo(__T1 __x, __T2 __y, int *__quo) { return ::remquo((double)__x, (double)__y, __quo); } #endif template __DEVICE__ - typename __hip_enable_if::is_integer, double>::type + typename __hip_enable_if<__hip::is_integral<__T>::value, double>::type scalbln(__T __x, long int __exp) { return ::scalbln((double)__x, __exp); } template __DEVICE__ - typename __hip_enable_if::is_integer, double>::type + typename __hip_enable_if<__hip::is_integral<__T>::value, double>::type scalbn(__T __x, int __exp) { return ::scalbn((double)__x, __exp); } @@ -469,6 +574,7 @@ #endif // defined(__cplusplus) // Define these overloads inside the namespace our standard library uses. +#if !defined(__HIPCC_RTC__) #ifdef _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD #else @@ -624,8 +730,10 @@ #endif } // namespace std #endif +#endif // !defined(__HIPCC_RTC__) // Define device-side math functions from on MSVC. +#if !defined(__HIPCC_RTC__) #if defined(_MSC_VER) // Before VS2019, `` is also included in `` and other headers. @@ -659,6 +767,7 @@ } #endif // defined(__cplusplus) #endif // defined(_MSC_VER) +#endif // !defined(__HIPCC_RTC__) #pragma pop_macro("__DEVICE__") Index: clang/lib/Headers/__clang_hip_runtime_wrapper.h =================================================================== --- clang/lib/Headers/__clang_hip_runtime_wrapper.h +++ clang/lib/Headers/__clang_hip_runtime_wrapper.h @@ -72,10 +72,12 @@ #include <__clang_hip_libdevice_declares.h> #include <__clang_hip_math.h> -#if !defined(__HIPCC_RTC__) #if !_OPENMP || __HIP_ENABLE_CUDA_WRAPPER_FOR_OPENMP__ +#if !defined(__HIPCC_RTC__) #include <__clang_cuda_math_forward_declares.h> +#endif // __HIPCC_RTC__ #include <__clang_hip_cmath.h> +#if !defined(__HIPCC_RTC__) #include <__clang_cuda_complex_builtins.h> #include Index: clang/test/Headers/hip-header.hip =================================================================== --- clang/test/Headers/hip-header.hip +++ clang/test/Headers/hip-header.hip @@ -21,7 +21,21 @@ } // CHECK-LABEL: define{{.*}} i64 @_Z11test_size_tv -// CHEC: ret i64 8 +// CHECK: ret i64 8 __device__ size_t test_size_t() { return sizeof(size_t); } + +// Check there is no ambiguity when calling overloaded math functions. + +// CHECK-LABEL: define{{.*}}@_Z10test_floorv +// CHECK: call {{.*}}double @__ocml_floor_f64(double +__device__ float test_floor() { + return floor(5); +} + +// CHECK-LABEL: define{{.*}}@_Z8test_maxv +// CHECK: call {{.*}}double @__ocml_fmax_f64(double {{.*}}, double +__device__ float test_max() { + return max(5, 6.0); +}