[libc] Add support for FMA in the GPU utilities This adds the generic FMA utilities for the GPU. We implement these through the builtins which map to the FMA instructions in the ISA. These may not have strict compliance with other assumptions in the the `libc` such as rounding modes. I've included the relevant information on how the GPU vendors map the behaviour. This should help make it easier to implement some future generic versions. Depends on D152486 Reviewed By: lntue Differential Revision: https://reviews.llvm.org/D152923
diff --git a/libc/config/gpu/entrypoints.txt b/libc/config/gpu/entrypoints.txt index deabf54..567f6d3 100644 --- a/libc/config/gpu/entrypoints.txt +++ b/libc/config/gpu/entrypoints.txt
@@ -83,6 +83,8 @@ set(TARGET_LIBM_ENTRYPOINTS # math.h entrypoints + libc.src.math.fma + libc.src.math.fmaf libc.src.math.sin libc.src.math.round libc.src.math.roundf
diff --git a/libc/src/__support/FPUtil/FMA.h b/libc/src/__support/FPUtil/FMA.h index 79a465a..178d34f 100644 --- a/libc/src/__support/FPUtil/FMA.h +++ b/libc/src/__support/FPUtil/FMA.h
@@ -20,6 +20,8 @@ #include "aarch64/FMA.h" #elif defined(LIBC_TARGET_ARCH_IS_RISCV64) #include "riscv64/FMA.h" +#elif defined(LIBC_TARGET_ARCH_IS_GPU) +#include "gpu/FMA.h" #endif #else
diff --git a/libc/src/__support/FPUtil/gpu/FMA.h b/libc/src/__support/FPUtil/gpu/FMA.h new file mode 100644 index 0000000..7b458db --- /dev/null +++ b/libc/src/__support/FPUtil/gpu/FMA.h
@@ -0,0 +1,33 @@ +//===-- GPU implementations of the fma function -----------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_SUPPORT_FPUTIL_GPU_FMA_H +#define LLVM_LIBC_SRC_SUPPORT_FPUTIL_GPU_FMA_H + +// These intrinsics map to the FMA instrunctions in the target ISA for the GPU. +// The default rounding mode generated from these will be to the nearest even. +static_assert(__has_builtin(__builtin_fma), "FMA builtins must be defined"); +static_assert(__has_builtin(__builtin_fmaf), "FMA builtins must be defined"); + +namespace __llvm_libc { +namespace fputil { + +template <typename T> +LIBC_INLINE cpp::enable_if_t<cpp::is_same_v<T, float>, T> fma(T x, T y, T z) { + __builtin_fmaf(x, y, z); +} + +template <typename T> +LIBC_INLINE cpp::enable_if_t<cpp::is_same_v<T, double>, T> fma(T x, T y, T z) { + __builtin_fma(x, y, z); +} + +} // namespace fputil +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_GPU_FMA_H
diff --git a/libc/src/__support/macros/properties/cpu_features.h b/libc/src/__support/macros/properties/cpu_features.h index fda1ef1..086b216 100644 --- a/libc/src/__support/macros/properties/cpu_features.h +++ b/libc/src/__support/macros/properties/cpu_features.h
@@ -37,7 +37,7 @@ #endif #if defined(__ARM_FEATURE_FMA) || (defined(__AVX2__) && defined(__FMA__)) || \ - defined(__LIBC_RISCV_USE_FMA) + defined(__NVPTX__) || defined(__AMDGPU__) || defined(__LIBC_RISCV_USE_FMA) #define LIBC_TARGET_CPU_HAS_FMA #endif