Skip to content

Commit 12da97e

Browse files
committed
[OpenMP][AMDGCN] Initial math headers support
With this patch, OpenMP on AMDGCN will use the math functions provided by ROCm ocml library. Linking device code to the ocml will be done in the next patch. Reviewed By: JonChesterfield, jdoerfert, scchan Differential Revision: https://reviews.llvm.org/D104904
1 parent 8d0f96f commit 12da97e

File tree

11 files changed

+276
-92
lines changed

11 files changed

+276
-92
lines changed

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1256,7 +1256,8 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
12561256
// If we are offloading to a target via OpenMP we need to include the
12571257
// openmp_wrappers folder which contains alternative system headers.
12581258
if (JA.isDeviceOffloading(Action::OFK_OpenMP) &&
1259-
getToolChain().getTriple().isNVPTX()){
1259+
(getToolChain().getTriple().isNVPTX() ||
1260+
getToolChain().getTriple().isAMDGCN())) {
12601261
if (!Args.hasArg(options::OPT_nobuiltininc)) {
12611262
// Add openmp_wrappers/* to our system include path. This lets us wrap
12621263
// standard library headers.

clang/lib/Headers/__clang_hip_cmath.h

Lines changed: 110 additions & 78 deletions
Large diffs are not rendered by default.

clang/lib/Headers/__clang_hip_math.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#ifndef __CLANG_HIP_MATH_H__
1010
#define __CLANG_HIP_MATH_H__
1111

12-
#if !defined(__HIP__)
12+
#if !defined(__HIP__) && !defined(__OPENMP_AMDGCN__)
1313
#error "This file is for HIP and OpenMP AMDGCN device compilation only."
1414
#endif
1515

@@ -19,18 +19,27 @@
1919
#endif
2020
#include <limits.h>
2121
#include <stdint.h>
22-
#endif // __HIPCC_RTC__
22+
#endif // !defined(__HIPCC_RTC__)
2323

2424
#pragma push_macro("__DEVICE__")
25+
26+
#ifdef __OPENMP_AMDGCN__
27+
#define __DEVICE__ static inline __attribute__((always_inline, nothrow))
28+
#else
2529
#define __DEVICE__ static __device__ inline __attribute__((always_inline))
30+
#endif
2631

2732
// A few functions return bool type starting only in C++11.
2833
#pragma push_macro("__RETURN_TYPE")
34+
#ifdef __OPENMP_AMDGCN__
35+
#define __RETURN_TYPE int
36+
#else
2937
#if defined(__cplusplus)
3038
#define __RETURN_TYPE bool
3139
#else
3240
#define __RETURN_TYPE int
3341
#endif
42+
#endif // __OPENMP_AMDGCN__
3443

3544
#if defined (__cplusplus) && __cplusplus < 201103L
3645
// emulate static_assert on type sizes
@@ -1262,15 +1271,15 @@ float min(float __x, float __y) { return fminf(__x, __y); }
12621271
__DEVICE__
12631272
double min(double __x, double __y) { return fmin(__x, __y); }
12641273

1265-
#if !defined(__HIPCC_RTC__)
1274+
#if !defined(__HIPCC_RTC__) && !defined(__OPENMP_AMDGCN__)
12661275
__host__ inline static int min(int __arg1, int __arg2) {
12671276
return std::min(__arg1, __arg2);
12681277
}
12691278

12701279
__host__ inline static int max(int __arg1, int __arg2) {
12711280
return std::max(__arg1, __arg2);
12721281
}
1273-
#endif // __HIPCC_RTC__
1282+
#endif // !defined(__HIPCC_RTC__) && !defined(__OPENMP_AMDGCN__)
12741283
#endif
12751284

12761285
#pragma pop_macro("__DEVICE__")

clang/lib/Headers/openmp_wrappers/__clang_openmp_device_functions.h

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@
1414
#error "This file is for OpenMP compilation only."
1515
#endif
1616

17-
#pragma omp begin declare variant match( \
18-
device = {arch(nvptx, nvptx64)}, implementation = {extension(match_any)})
19-
2017
#ifdef __cplusplus
2118
extern "C" {
2219
#endif
2320

21+
#pragma omp begin declare variant match( \
22+
device = {arch(nvptx, nvptx64)}, implementation = {extension(match_any)})
23+
2424
#define __CUDA__
2525
#define __OPENMP_NVPTX__
2626

@@ -33,12 +33,32 @@ extern "C" {
3333
#undef __OPENMP_NVPTX__
3434
#undef __CUDA__
3535

36-
#ifdef __cplusplus
37-
} // extern "C"
36+
#pragma omp end declare variant
37+
38+
#pragma omp begin declare variant match(device = {arch(amdgcn)})
39+
40+
// Import types which will be used by __clang_hip_libdevice_declares.h
41+
#ifndef __cplusplus
42+
#include <stdbool.h>
43+
#include <stdint.h>
3844
#endif
3945

46+
#define __OPENMP_AMDGCN__
47+
#pragma push_macro("__device__")
48+
#define __device__
49+
50+
/// Include declarations for libdevice functions.
51+
#include <__clang_hip_libdevice_declares.h>
52+
53+
#pragma pop_macro("__device__")
54+
#undef __OPENMP_AMDGCN__
55+
4056
#pragma omp end declare variant
4157

58+
#ifdef __cplusplus
59+
} // extern "C"
60+
#endif
61+
4262
// Ensure we make `_ZdlPv`, aka. `operator delete(void*)` available without the
4363
// need to `include <new>` in C++ mode.
4464
#ifdef __cplusplus

clang/lib/Headers/openmp_wrappers/cmath

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,58 @@ __DEVICE__ float tgamma(float __x) { return ::tgammaf(__x); }
7575

7676
#pragma omp end declare variant
7777

78+
#ifdef __AMDGCN__
79+
#pragma omp begin declare variant match(device = {arch(amdgcn)})
80+
81+
#pragma push_macro("__constant__")
82+
#define __constant__ __attribute__((constant))
83+
#define __OPENMP_AMDGCN__
84+
85+
#include <__clang_hip_cmath.h>
86+
87+
#pragma pop_macro("__constant__")
88+
#undef __OPENMP_AMDGCN__
89+
90+
// Define overloads otherwise which are absent
91+
#define __DEVICE__ static constexpr __attribute__((always_inline, nothrow))
92+
93+
__DEVICE__ float acos(float __x) { return ::acosf(__x); }
94+
__DEVICE__ float acosh(float __x) { return ::acoshf(__x); }
95+
__DEVICE__ float asin(float __x) { return ::asinf(__x); }
96+
__DEVICE__ float asinh(float __x) { return ::asinhf(__x); }
97+
__DEVICE__ float atan(float __x) { return ::atanf(__x); }
98+
__DEVICE__ float atan2(float __x, float __y) { return ::atan2f(__x, __y); }
99+
__DEVICE__ float atanh(float __x) { return ::atanhf(__x); }
100+
__DEVICE__ float cbrt(float __x) { return ::cbrtf(__x); }
101+
__DEVICE__ float cosh(float __x) { return ::coshf(__x); }
102+
__DEVICE__ float erf(float __x) { return ::erff(__x); }
103+
__DEVICE__ float erfc(float __x) { return ::erfcf(__x); }
104+
__DEVICE__ float exp2(float __x) { return ::exp2f(__x); }
105+
__DEVICE__ float expm1(float __x) { return ::expm1f(__x); }
106+
__DEVICE__ float fdim(float __x, float __y) { return ::fdimf(__x, __y); }
107+
__DEVICE__ float hypot(float __x, float __y) { return ::hypotf(__x, __y); }
108+
__DEVICE__ int ilogb(float __x) { return ::ilogbf(__x); }
109+
__DEVICE__ float ldexp(float __arg, int __exp) {
110+
return ::ldexpf(__arg, __exp);
111+
}
112+
__DEVICE__ float lgamma(float __x) { return ::lgammaf(__x); }
113+
__DEVICE__ float log1p(float __x) { return ::log1pf(__x); }
114+
__DEVICE__ float logb(float __x) { return ::logbf(__x); }
115+
__DEVICE__ float nextafter(float __x, float __y) {
116+
return ::nextafterf(__x, __y);
117+
}
118+
__DEVICE__ float remainder(float __x, float __y) {
119+
return ::remainderf(__x, __y);
120+
}
121+
__DEVICE__ float scalbn(float __x, int __y) { return ::scalbnf(__x, __y); }
122+
__DEVICE__ float sinh(float __x) { return ::sinhf(__x); }
123+
__DEVICE__ float tan(float __x) { return ::tanf(__x); }
124+
__DEVICE__ float tanh(float __x) { return ::tanhf(__x); }
125+
__DEVICE__ float tgamma(float __x) { return ::tgammaf(__x); }
126+
127+
#undef __DEVICE__
128+
129+
#pragma omp end declare variant
130+
#endif // __AMDGCN__
131+
78132
#endif

clang/lib/Headers/openmp_wrappers/math.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,12 @@
4848

4949
#pragma omp end declare variant
5050

51+
#pragma omp begin declare variant match(device = {arch(amdgcn)})
52+
53+
#define __OPENMP_AMDGCN__
54+
#include <__clang_hip_math.h>
55+
#undef __OPENMP_AMDGCN__
56+
57+
#pragma omp end declare variant
58+
5159
#endif
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#pragma once
2+
3+
namespace std {
4+
template<class T> constexpr const T& min(const T& a, const T& b);
5+
template<class T> constexpr const T& max(const T& a, const T& b);
6+
}

clang/test/Headers/Inputs/include/cstdlib

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@ float abs(float __x) { return fabs(__x); }
2727
double abs(double __x) { return fabs(__x); }
2828

2929
}
30+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#pragma once
2+
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// RUN: %clang_cc1 -internal-isystem %S/Inputs/include -x c -fopenmp -triple x86_64-unknown-unknown -fopenmp-targets=amdgcn-amd-amdhsa -emit-llvm-bc %s -o %t-host.bc
2+
// RUN: %clang_cc1 -internal-isystem %S/../../lib/Headers/openmp_wrappers -include __clang_openmp_device_functions.h -internal-isystem %S/../../lib/Headers/openmp_wrappers -internal-isystem %S/Inputs/include -x c -fopenmp -triple amdgcn-amd-amdhsa -aux-triple x86_64-unknown-unknown -fopenmp-targets=amdgcn-amd-amdhsa -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-host.bc -o - | FileCheck %s --check-prefixes=CHECK-C,CHECK
3+
// RUN: %clang_cc1 -internal-isystem %S/Inputs/include -x c++ -fopenmp -triple x86_64-unknown-unknown -fopenmp-targets=amdgcn-amd-amdhsa -emit-llvm-bc %s -o %t-host.bc
4+
// RUN: %clang_cc1 -internal-isystem %S/../../lib/Headers/openmp_wrappers -include __clang_openmp_device_functions.h -internal-isystem %S/../../lib/Headers/openmp_wrappers -internal-isystem %S/Inputs/include -x c++ -fopenmp -triple amdgcn-amd-amdhsa -aux-triple x86_64-unknown-unknown -fopenmp-targets=amdgcn-amd-amdhsa -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-host.bc -o - | FileCheck %s --check-prefixes=CHECK-CPP,CHECK
5+
6+
#ifdef __cplusplus
7+
#include <cmath>
8+
#else
9+
#include <math.h>
10+
#endif
11+
12+
void test_math_f64(double x) {
13+
// CHECK-LABEL: define {{.*}}test_math_f64
14+
#pragma omp target
15+
{
16+
// CHECK: call double @__ocml_sin_f64
17+
double l1 = sin(x);
18+
// CHECK: call double @__ocml_cos_f64
19+
double l2 = cos(x);
20+
// CHECK: call double @__ocml_fabs_f64
21+
double l3 = fabs(x);
22+
}
23+
}
24+
25+
void test_math_f32(float x) {
26+
// CHECK-LABEL: define {{.*}}test_math_f32
27+
#pragma omp target
28+
{
29+
// CHECK-C: call double @__ocml_sin_f64
30+
// CHECK-CPP: call float @__ocml_sin_f32
31+
float l1 = sin(x);
32+
// CHECK-C: call double @__ocml_cos_f64
33+
// CHECK-CPP: call float @__ocml_cos_f32
34+
float l2 = cos(x);
35+
// CHECK-C: call double @__ocml_fabs_f64
36+
// CHECK-CPP: call float @__ocml_fabs_f32
37+
float l3 = fabs(x);
38+
}
39+
}
40+
void test_math_f32_suffix(float x) {
41+
// CHECK-LABEL: define {{.*}}test_math_f32_suffix
42+
#pragma omp target
43+
{
44+
// CHECK: call float @__ocml_sin_f32
45+
float l1 = sinf(x);
46+
// CHECK: call float @__ocml_cos_f32
47+
float l2 = cosf(x);
48+
// CHECK: call float @__ocml_fabs_f32
49+
float l3 = fabsf(x);
50+
}
51+
}

clang/test/Headers/openmp_device_math_isnan.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@
2121
double math(float f, double d) {
2222
double r = 0;
2323
// INT_RETURN: call i32 @__nv_isnanf(float
24-
// AMD_INT_RETURN: call i32 @_{{.*}}isnanf(float
24+
// AMD_INT_RETURN: call i32 @__ocml_isnan_f32(float
2525
// BOOL_RETURN: call i32 @__nv_isnanf(float
26-
// AMD_BOOL_RETURN: call zeroext i1 @_{{.*}}isnanf(float
26+
// AMD_BOOL_RETURN: call i32 @__ocml_isnan_f32(float
2727
r += std::isnan(f);
2828
// INT_RETURN: call i32 @__nv_isnand(double
29-
// AMD_INT_RETURN: call i32 @_{{.*}}isnand(double
29+
// AMD_INT_RETURN: call i32 @__ocml_isnan_f64(double
3030
// BOOL_RETURN: call i32 @__nv_isnand(double
31-
// AMD_BOOL_RETURN: call zeroext i1 @_{{.*}}isnand(double
31+
// AMD_BOOL_RETURN: call i32 @__ocml_isnan_f64(double
3232
r += std::isnan(d);
3333
return r;
3434
}

0 commit comments

Comments
 (0)