[clang] [libc] Fix linking of AMDGPU device runtime control constants for math (PR #65676)

Joseph Huber via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 2 09:22:39 PDT 2023


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

>From d11fae15878622eb2eb452aedf616e01b577e102 Mon Sep 17 00:00:00 2001
From: Joseph Huber <jhuber6 at vols.utk.edu>
Date: Thu, 7 Sep 2023 16:08:30 -0500
Subject: [PATCH 1/2] [libc] Fix linking of AMDGPU device runtime control
 constants for math

Summary:
Currently, `libc` temporarily provides math by linking against existing
vendor implementations. To use the AMDGPU DeviceRTL we need to define a
handful of control constants that alter behaviour for architecture
specific things. Previously these were marked `extern const` because
they must be present when we link-in the vendor bitcode library.
However, this causes linker errors if more than one math function was
used.

This patch fixes the issue by marking these functions as used and inline
on top of being external. This means that they are linkable, but it
gives us `linkonce_odr` semantics. The downside is that these globals
won't be optimized out, but it allows us to perform constant propagation
on them unlike using `weak`.
---
 libc/src/math/gpu/vendor/amdgpu/platform.h | 94 ++++++++++++----------
 1 file changed, 53 insertions(+), 41 deletions(-)

diff --git a/libc/src/math/gpu/vendor/amdgpu/platform.h b/libc/src/math/gpu/vendor/amdgpu/platform.h
index 6ec47c24a93a2d7..8e2c23743127f48 100644
--- a/libc/src/math/gpu/vendor/amdgpu/platform.h
+++ b/libc/src/math/gpu/vendor/amdgpu/platform.h
@@ -9,6 +9,8 @@
 #ifndef LLVM_LIBC_SRC_MATH_GPU_AMDGPU_PLATFORM_H
 #define LLVM_LIBC_SRC_MATH_GPU_AMDGPU_PLATFORM_H
 
+#include "src/__support/macros/attributes.h"
+
 #include <stdint.h>
 
 namespace __llvm_libc {
@@ -19,96 +21,106 @@ namespace __llvm_libc {
 extern "C" {
 
 // Disable unsafe math optimizations in the implementation.
-extern const uint8_t __oclc_unsafe_math_opt = 0;
+extern const LIBC_INLINE uint8_t __oclc_unsafe_math_opt = 0;
 
 // Disable denormalization at zero optimizations in the implementation.
-extern const uint8_t __oclc_daz_opt = 0;
+extern const LIBC_INLINE uint8_t __oclc_daz_opt = 0;
 
 // Disable rounding optimizations for 32-bit square roots.
-extern const uint8_t __oclc_correctly_rounded_sqrt32 = 1;
+extern const LIBC_INLINE uint8_t __oclc_correctly_rounded_sqrt32 = 1;
 
 // Disable finite math optimizations.
-extern const uint8_t __oclc_finite_only_opt = 0;
+extern const LIBC_INLINE uint8_t __oclc_finite_only_opt = 0;
 
 #if defined(__gfx700__)
-extern const uint32_t __oclc_ISA_version = 7000;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 7000;
 #elif defined(__gfx701__)
-extern const uint32_t __oclc_ISA_version = 7001;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 7001;
 #elif defined(__gfx702__)
-extern const uint32_t __oclc_ISA_version = 7002;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 7002;
 #elif defined(__gfx703__)
-extern const uint32_t __oclc_ISA_version = 7003;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 7003;
 #elif defined(__gfx704__)
-extern const uint32_t __oclc_ISA_version = 7004;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 7004;
 #elif defined(__gfx705__)
-extern const uint32_t __oclc_ISA_version = 7005;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 7005;
 #elif defined(__gfx801__)
-extern const uint32_t __oclc_ISA_version = 8001;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 8001;
 #elif defined(__gfx802__)
-extern const uint32_t __oclc_ISA_version = 8002;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 8002;
 #elif defined(__gfx803__)
-extern const uint32_t __oclc_ISA_version = 8003;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 8003;
 #elif defined(__gfx805__)
-extern const uint32_t __oclc_ISA_version = 8005;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 8005;
 #elif defined(__gfx810__)
-extern const uint32_t __oclc_ISA_version = 8100;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 8100;
 #elif defined(__gfx900__)
-extern const uint32_t __oclc_ISA_version = 9000;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 9000;
 #elif defined(__gfx902__)
-extern const uint32_t __oclc_ISA_version = 9002;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 9002;
 #elif defined(__gfx904__)
-extern const uint32_t __oclc_ISA_version = 9004;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 9004;
 #elif defined(__gfx906__)
-extern const uint32_t __oclc_ISA_version = 9006;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 9006;
 #elif defined(__gfx908__)
-extern const uint32_t __oclc_ISA_version = 9008;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 9008;
 #elif defined(__gfx909__)
-extern const uint32_t __oclc_ISA_version = 9009;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 9009;
 #elif defined(__gfx90a__)
-extern const uint32_t __oclc_ISA_version = 9010;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 9010;
 #elif defined(__gfx90c__)
-extern const uint32_t __oclc_ISA_version = 9012;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 9012;
 #elif defined(__gfx940__)
-extern const uint32_t __oclc_ISA_version = 9400;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 9400;
 #elif defined(__gfx1010__)
-extern const uint32_t __oclc_ISA_version = 10100;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10100;
 #elif defined(__gfx1011__)
-extern const uint32_t __oclc_ISA_version = 10101;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10101;
 #elif defined(__gfx1012__)
-extern const uint32_t __oclc_ISA_version = 10102;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10102;
 #elif defined(__gfx1013__)
-extern const uint32_t __oclc_ISA_version = 10103;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10103;
 #elif defined(__gfx1030__)
-extern const uint32_t __oclc_ISA_version = 10300;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10300;
 #elif defined(__gfx1031__)
-extern const uint32_t __oclc_ISA_version = 10301;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10301;
 #elif defined(__gfx1032__)
-extern const uint32_t __oclc_ISA_version = 10302;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10302;
 #elif defined(__gfx1033__)
-extern const uint32_t __oclc_ISA_version = 10303;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10303;
 #elif defined(__gfx1034__)
-extern const uint32_t __oclc_ISA_version = 10304;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10304;
 #elif defined(__gfx1035__)
-extern const uint32_t __oclc_ISA_version = 10305;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10305;
 #elif defined(__gfx1036__)
-extern const uint32_t __oclc_ISA_version = 10306;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10306;
 #elif defined(__gfx1100__)
-extern const uint32_t __oclc_ISA_version = 11000;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 11000;
 #elif defined(__gfx1101__)
-extern const uint32_t __oclc_ISA_version = 11001;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 11001;
 #elif defined(__gfx1102__)
-extern const uint32_t __oclc_ISA_version = 11002;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 11002;
 #elif defined(__gfx1103__)
-extern const uint32_t __oclc_ISA_version = 11003;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 11003;
 #elif defined(__gfx1150__)
-extern const uint32_t __oclc_ISA_version = 11500;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 11500;
 #elif defined(__gfx1151__)
-extern const uint32_t __oclc_ISA_version = 11501;
+extern const LIBC_INLINE uint32_t __oclc_ISA_version = 11501;
 #else
 #error "Unknown AMDGPU architecture"
 #endif
 }
 
+// These aliases cause clang to emit the control constants with ODR linkage.
+// This allows us to link against the symbols without preventing them from being
+// optimized out or causing symbol collisions.
+[[gnu::alias("__oclc_unsafe_math_opt")]] const uint8_t __oclc_unsafe_math_opt__;
+[[gnu::alias("__oclc_daz_opt")]] const uint8_t __oclc_daz_opt__;
+[[gnu::alias("__oclc_correctly_rounded_sqrt32")]] const uint8_t
+    __oclc_correctly_rounded_sqrt32__;
+[[gnu::alias("__oclc_finite_only_opt")]] const uint8_t __oclc_finite_only_opt__;
+[[gnu::alias("__oclc_ISA_version")]] const uint32_t __oclc_ISA_version__;
+
 } // namespace __llvm_libc
 
 #endif // LLVM_LIBC_SRC_MATH_GPU_AMDGPU_PLATFORM_H

>From 7d03d3fd67e597bad19e546b589bc146d1bd06e0 Mon Sep 17 00:00:00 2001
From: Joseph Huber <jhuber6 at vols.utk.edu>
Date: Thu, 14 Sep 2023 10:02:05 -0500
Subject: [PATCH 2/2] LIBC_INLINE -> LIBC_INLINE_VAR

---
 libc/src/math/gpu/vendor/amdgpu/platform.h | 82 +++++++++++-----------
 1 file changed, 41 insertions(+), 41 deletions(-)

diff --git a/libc/src/math/gpu/vendor/amdgpu/platform.h b/libc/src/math/gpu/vendor/amdgpu/platform.h
index 8e2c23743127f48..16e8611ec703ad6 100644
--- a/libc/src/math/gpu/vendor/amdgpu/platform.h
+++ b/libc/src/math/gpu/vendor/amdgpu/platform.h
@@ -21,91 +21,91 @@ namespace __llvm_libc {
 extern "C" {
 
 // Disable unsafe math optimizations in the implementation.
-extern const LIBC_INLINE uint8_t __oclc_unsafe_math_opt = 0;
+extern const LIBC_INLINE_VAR uint8_t __oclc_unsafe_math_opt = 0;
 
 // Disable denormalization at zero optimizations in the implementation.
-extern const LIBC_INLINE uint8_t __oclc_daz_opt = 0;
+extern const LIBC_INLINE_VAR uint8_t __oclc_daz_opt = 0;
 
 // Disable rounding optimizations for 32-bit square roots.
-extern const LIBC_INLINE uint8_t __oclc_correctly_rounded_sqrt32 = 1;
+extern const LIBC_INLINE_VAR uint8_t __oclc_correctly_rounded_sqrt32 = 1;
 
 // Disable finite math optimizations.
-extern const LIBC_INLINE uint8_t __oclc_finite_only_opt = 0;
+extern const LIBC_INLINE_VAR uint8_t __oclc_finite_only_opt = 0;
 
 #if defined(__gfx700__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 7000;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 7000;
 #elif defined(__gfx701__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 7001;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 7001;
 #elif defined(__gfx702__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 7002;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 7002;
 #elif defined(__gfx703__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 7003;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 7003;
 #elif defined(__gfx704__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 7004;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 7004;
 #elif defined(__gfx705__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 7005;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 7005;
 #elif defined(__gfx801__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 8001;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 8001;
 #elif defined(__gfx802__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 8002;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 8002;
 #elif defined(__gfx803__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 8003;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 8003;
 #elif defined(__gfx805__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 8005;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 8005;
 #elif defined(__gfx810__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 8100;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 8100;
 #elif defined(__gfx900__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 9000;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 9000;
 #elif defined(__gfx902__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 9002;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 9002;
 #elif defined(__gfx904__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 9004;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 9004;
 #elif defined(__gfx906__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 9006;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 9006;
 #elif defined(__gfx908__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 9008;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 9008;
 #elif defined(__gfx909__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 9009;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 9009;
 #elif defined(__gfx90a__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 9010;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 9010;
 #elif defined(__gfx90c__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 9012;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 9012;
 #elif defined(__gfx940__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 9400;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 9400;
 #elif defined(__gfx1010__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10100;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 10100;
 #elif defined(__gfx1011__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10101;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 10101;
 #elif defined(__gfx1012__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10102;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 10102;
 #elif defined(__gfx1013__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10103;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 10103;
 #elif defined(__gfx1030__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10300;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 10300;
 #elif defined(__gfx1031__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10301;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 10301;
 #elif defined(__gfx1032__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10302;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 10302;
 #elif defined(__gfx1033__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10303;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 10303;
 #elif defined(__gfx1034__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10304;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 10304;
 #elif defined(__gfx1035__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10305;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 10305;
 #elif defined(__gfx1036__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 10306;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 10306;
 #elif defined(__gfx1100__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 11000;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 11000;
 #elif defined(__gfx1101__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 11001;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 11001;
 #elif defined(__gfx1102__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 11002;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 11002;
 #elif defined(__gfx1103__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 11003;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 11003;
 #elif defined(__gfx1150__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 11500;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 11500;
 #elif defined(__gfx1151__)
-extern const LIBC_INLINE uint32_t __oclc_ISA_version = 11501;
+extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 11501;
 #else
 #error "Unknown AMDGPU architecture"
 #endif



More information about the cfe-commits mailing list