From bb35299560c023fec1dd96529da643c545f6237f Mon Sep 17 00:00:00 2001 From: Alex Voicu Date: Sat, 18 Nov 2017 01:16:31 +0000 Subject: [PATCH] This actually (tries) to do the right thing all the way, by using memcpy for bitcasting, and not rely on undefined behaviour of a different flavour as a substitute for the original undefined behaviour. Note that the compiler will (should) optimise down to the same emitted code, since this is a pattern it understands. --- hipamd/src/device_functions.cpp | 71 +++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 13 deletions(-) diff --git a/hipamd/src/device_functions.cpp b/hipamd/src/device_functions.cpp index a66cc1e9fb..63425bc9f4 100644 --- a/hipamd/src/device_functions.cpp +++ b/hipamd/src/device_functions.cpp @@ -43,11 +43,21 @@ __device__ float __double2float_rz(double x) __device__ int __double2hiint(double x) { - return reinterpret_cast(x)[1]; + static_assert(sizeof(double) == 2 * sizeof(int), ""); + + int tmp[2]; + __builtin_memcpy(tmp, &x, sizeof(tmp)); + + return tmp[1]; } __device__ int __double2loint(double x) { - return reinterpret_cast(x)[0]; + static_assert(sizeof(double) == 2 * sizeof(int), ""); + + int tmp[2]; + __builtin_memcpy(tmp, &x, sizeof(tmp)); + + return tmp[0]; } @@ -122,7 +132,12 @@ __device__ unsigned long long int __double2ull_rz(double x) __device__ long long int __double_as_longlong(double x) { - return reinterpret_cast(x); + static_assert(sizeof(long long) == sizeof(double), ""); + + long long tmp; + __builtin_memcpy(&tmp, &x, sizeof(tmp)); + + return tmp; } __device__ int __float2int_rd(float x) @@ -195,17 +210,32 @@ __device__ unsigned long long int __float2ull_rz(float x) __device__ int __float_as_int(float x) { - return reinterpret_cast(x); + static_assert(sizeof(int) == sizeof(float), ""); + + int tmp; + __builtin_memcpy(&tmp, &x, sizeof(tmp)); + + return tmp; } __device__ unsigned int __float_as_uint(float x) { - return reinterpret_cast(x); + static_assert(sizeof(unsigned int) == sizeof(float), ""); + + unsigned int tmp; + __builtin_memcpy(&tmp, &x, sizeof(tmp)); + + return tmp; } -__device__ double __hiloint2double(int hi, int lo) -{ // TODO: this matches the original in not considering endianness, is that - // correct though? - int tmp[] = {lo, hi}; - return reinterpret_cast(tmp); +__device__ double __hiloint2double(int32_t hi, int32_t lo) +{ + static_assert(sizeof(double) == sizeof(uint64_t), ""); + + uint64_t tmp0 = + (static_cast(hi) << 32ull) | static_cast(lo); + double tmp1; + __builtin_memcpy(&tmp1, &tmp0, sizeof(tmp0)); + + return tmp1; } __device__ double __int2double_rn(int x) { @@ -231,7 +261,12 @@ __device__ float __int2float_rz(int x) __device__ float __int_as_float(int x) { - return reinterpret_cast(x); + static_assert(sizeof(float) == sizeof(int), ""); + + float tmp; + __builtin_memcpy(&tmp, &x, sizeof(tmp)); + + return tmp; } __device__ double __ll2double_rd(long long int x) @@ -270,7 +305,12 @@ __device__ float __ll2float_rz(long long int x) __device__ double __longlong_as_double(long long int x) { - return reinterpret_cast(x); + static_assert(sizeof(double) == sizeof(long long), ""); + + double tmp; + __builtin_memcpy(&tmp, &x, sizeof(tmp)); + + return x; } __device__ double __uint2double_rn(int x) @@ -297,7 +337,12 @@ __device__ float __uint2float_rz(unsigned int x) __device__ float __uint_as_float(unsigned int x) { - return reinterpret_cast(x); + static_assert(sizeof(float) == sizeof(unsigned int), ""); + + float tmp; + __builtin_memcpy(&tmp, &x, sizeof(tmp)); + + return tmp; } __device__ double __ull2double_rd(unsigned long long int x)