[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