[llvm] [OpenMP] Use __builtin_bit_cast instead of UB type punning (PR #122325)

Joseph Huber via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 9 11:59:24 PST 2025


https://github.com/jhuber6 updated https://github.com/llvm/llvm-project/pull/122325

>From 118a5a7fbe3af9a01600bbce2c06f42d862ae514 Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Thu, 9 Jan 2025 11:53:26 -0600
Subject: [PATCH] [OpenMP] Use __builtin_bit_cast instead of UB type punning

Summary:
Fixes type punning, moved out of shared utils because this isn't present
in GCC 7.4 and isn't used outside of the device runtime anyway.
---
 offload/DeviceRTL/include/DeviceUtils.h     |  5 ++++
 offload/DeviceRTL/include/Synchronization.h | 32 ++++++++++-----------
 offload/DeviceRTL/src/Mapping.cpp           |  8 +++---
 offload/include/Shared/Utils.h              |  5 ----
 4 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/offload/DeviceRTL/include/DeviceUtils.h b/offload/DeviceRTL/include/DeviceUtils.h
index fb00d6c7552557..fa66b973a4f5e7 100644
--- a/offload/DeviceRTL/include/DeviceUtils.h
+++ b/offload/DeviceRTL/include/DeviceUtils.h
@@ -60,6 +60,11 @@ struct remove_addrspace<T [[clang::address_space(N)]]> : type_identity<T> {};
 template <class T>
 using remove_addrspace_t = typename remove_addrspace<T>::type;
 
+template <typename To, typename From> inline To bitCast(From V) {
+  static_assert(sizeof(To) == sizeof(From), "Bad conversion");
+  return __builtin_bit_cast(To, V);
+}
+
 /// Return the value \p Var from thread Id \p SrcLane in the warp if the thread
 /// is identified by \p Mask.
 int32_t shuffle(uint64_t Mask, int32_t Var, int32_t SrcLane, int32_t Width);
diff --git a/offload/DeviceRTL/include/Synchronization.h b/offload/DeviceRTL/include/Synchronization.h
index ae065850d824c2..e1968675550d49 100644
--- a/offload/DeviceRTL/include/Synchronization.h
+++ b/offload/DeviceRTL/include/Synchronization.h
@@ -98,20 +98,20 @@ template <typename Ty, typename V = utils::remove_addrspace_t<Ty>>
 utils::enable_if_t<utils::is_same_v<V, float>, V>
 max(Ty *Address, V Val, atomic::OrderingTy Ordering) {
   if (Val >= 0)
-    return utils::convertViaPun<float>(
-        max((int32_t *)Address, utils::convertViaPun<int32_t>(Val), Ordering));
-  return utils::convertViaPun<float>(
-      min((uint32_t *)Address, utils::convertViaPun<uint32_t>(Val), Ordering));
+    return utils::bitCast<float>(
+        max((int32_t *)Address, utils::bitCast<int32_t>(Val), Ordering));
+  return utils::bitCast<float>(
+      min((uint32_t *)Address, utils::bitCast<uint32_t>(Val), Ordering));
 }
 
 template <typename Ty, typename V = utils::remove_addrspace_t<Ty>>
 utils::enable_if_t<utils::is_same_v<V, double>, V>
 max(Ty *Address, V Val, atomic::OrderingTy Ordering) {
   if (Val >= 0)
-    return utils::convertViaPun<double>(
-        max((int64_t *)Address, utils::convertViaPun<int64_t>(Val), Ordering));
-  return utils::convertViaPun<double>(
-      min((uint64_t *)Address, utils::convertViaPun<uint64_t>(Val), Ordering));
+    return utils::bitCast<double>(
+        max((int64_t *)Address, utils::bitCast<int64_t>(Val), Ordering));
+  return utils::bitCast<double>(
+      min((uint64_t *)Address, utils::bitCast<uint64_t>(Val), Ordering));
 }
 
 template <typename Ty, typename V = utils::remove_addrspace_t<Ty>>
@@ -126,10 +126,10 @@ template <typename Ty, typename V = utils::remove_addrspace_t<Ty>>
 utils::enable_if_t<utils::is_same_v<V, float>, V>
 min(Ty *Address, V Val, atomic::OrderingTy Ordering) {
   if (Val >= 0)
-    return utils::convertViaPun<float>(
-        min((int32_t *)Address, utils::convertViaPun<int32_t>(Val), Ordering));
-  return utils::convertViaPun<float>(
-      max((uint32_t *)Address, utils::convertViaPun<uint32_t>(Val), Ordering));
+    return utils::bitCast<float>(
+        min((int32_t *)Address, utils::bitCast<int32_t>(Val), Ordering));
+  return utils::bitCast<float>(
+      max((uint32_t *)Address, utils::bitCast<uint32_t>(Val), Ordering));
 }
 
 // TODO: Implement this with __atomic_fetch_max and remove the duplication.
@@ -138,10 +138,10 @@ utils::enable_if_t<utils::is_same_v<V, double>, V>
 min(Ty *Address, utils::remove_addrspace_t<Ty> Val,
     atomic::OrderingTy Ordering) {
   if (Val >= 0)
-    return utils::convertViaPun<double>(
-        min((int64_t *)Address, utils::convertViaPun<int64_t>(Val), Ordering));
-  return utils::convertViaPun<double>(
-      max((uint64_t *)Address, utils::convertViaPun<uint64_t>(Val), Ordering));
+    return utils::bitCast<double>(
+        min((int64_t *)Address, utils::bitCast<int64_t>(Val), Ordering));
+  return utils::bitCast<double>(
+      max((uint64_t *)Address, utils::bitCast<uint64_t>(Val), Ordering));
 }
 
 template <typename Ty, typename V = utils::remove_addrspace_t<Ty>>
diff --git a/offload/DeviceRTL/src/Mapping.cpp b/offload/DeviceRTL/src/Mapping.cpp
index 881bd12f034051..8583a539824c82 100644
--- a/offload/DeviceRTL/src/Mapping.cpp
+++ b/offload/DeviceRTL/src/Mapping.cpp
@@ -371,8 +371,8 @@ int ompx_shfl_down_sync_i(uint64_t mask, int var, unsigned delta, int width) {
 
 float ompx_shfl_down_sync_f(uint64_t mask, float var, unsigned delta,
                             int width) {
-  return utils::convertViaPun<float>(utils::shuffleDown(
-      mask, utils::convertViaPun<int32_t>(var), delta, width));
+  return utils::bitCast<float>(
+      utils::shuffleDown(mask, utils::bitCast<int32_t>(var), delta, width));
 }
 
 long ompx_shfl_down_sync_l(uint64_t mask, long var, unsigned delta, int width) {
@@ -381,8 +381,8 @@ long ompx_shfl_down_sync_l(uint64_t mask, long var, unsigned delta, int width) {
 
 double ompx_shfl_down_sync_d(uint64_t mask, double var, unsigned delta,
                              int width) {
-  return utils::convertViaPun<double>(utils::shuffleDown(
-      mask, utils::convertViaPun<int64_t>(var), delta, width));
+  return utils::bitCast<double>(
+      utils::shuffleDown(mask, utils::bitCast<int64_t>(var), delta, width));
 }
 }
 
diff --git a/offload/include/Shared/Utils.h b/offload/include/Shared/Utils.h
index 83a82678312c13..523e6bc505b81d 100644
--- a/offload/include/Shared/Utils.h
+++ b/offload/include/Shared/Utils.h
@@ -68,11 +68,6 @@ inline uint32_t popc(uint64_t V) {
   return __builtin_popcountl(V);
 }
 
-template <typename DstTy, typename SrcTy> inline DstTy convertViaPun(SrcTy V) {
-  static_assert(sizeof(DstTy) == sizeof(SrcTy), "Bad conversion");
-  return *((DstTy *)(&V));
-}
-
 } // namespace utils
 
 #endif // OMPTARGET_SHARED_UTILS_H



More information about the llvm-commits mailing list