mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 15:06:09 +00:00

CUDA/HIP program may be compiled with -fopenmp. In this case, -fopenmp is only passed to host compilation to take advantages of multi-threads computation. CUDA/HIP and OpenMP both use Sema::DeviceCallGraph to store functions to be analyzed and remove them once they decide the function is sure to be emitted. CUDA/HIP and OpenMP have different functions to determine if a function is sure to be emitted. To check host/device correctly for CUDA/HIP when -fopenmp is enabled, there needs a unified logic to determine whether a function is to be emitted. The logic needs to be aware of both CUDA and OpenMP logic. Differential Revision: https://reviews.llvm.org/D67837 llvm-svn: 374263
75 lines
2.5 KiB
Plaintext
75 lines
2.5 KiB
Plaintext
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -isystem %S/Inputs %s
|
|
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -isystem %S/Inputs %s \
|
|
// RUN: -fcuda-is-device
|
|
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -isystem %S/Inputs \
|
|
// RUN: -fopenmp %s
|
|
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -isystem %S/Inputs \
|
|
// RUN: -fopenmp %s -fcuda-is-device
|
|
|
|
#include "Inputs/cuda.h"
|
|
|
|
// Declares one function and pulls it into namespace ns:
|
|
//
|
|
// __device__ int OverloadMe();
|
|
// namespace ns { using ::OverloadMe; }
|
|
//
|
|
// Clang cares that this is done in a system header.
|
|
#include <overload.h>
|
|
|
|
// Opaque type used to determine which overload we're invoking.
|
|
struct HostReturnTy {};
|
|
|
|
// These shouldn't become host+device because they already have attributes.
|
|
__host__ constexpr int HostOnly() { return 0; }
|
|
// expected-note@-1 0+ {{not viable}}
|
|
__device__ constexpr int DeviceOnly() { return 0; }
|
|
// expected-note@-1 0+ {{not viable}}
|
|
|
|
constexpr int HostDevice() { return 0; }
|
|
|
|
// This should be a host-only function, because there's a previous __device__
|
|
// overload in <overload.h>.
|
|
constexpr HostReturnTy OverloadMe() { return HostReturnTy(); }
|
|
|
|
namespace ns {
|
|
// The "using" statement in overload.h should prevent OverloadMe from being
|
|
// implicitly host+device.
|
|
constexpr HostReturnTy OverloadMe() { return HostReturnTy(); }
|
|
} // namespace ns
|
|
|
|
// This is an error, because NonSysHdrOverload was not defined in a system
|
|
// header.
|
|
__device__ int NonSysHdrOverload() { return 0; }
|
|
// expected-note@-1 {{conflicting __device__ function declared here}}
|
|
constexpr int NonSysHdrOverload() { return 0; }
|
|
// expected-error@-1 {{constexpr function 'NonSysHdrOverload' without __host__ or __device__ attributes}}
|
|
|
|
// Variadic device functions are not allowed, so this is just treated as
|
|
// host-only.
|
|
constexpr void Variadic(const char*, ...);
|
|
// expected-note@-1 {{call to __host__ function from __device__ function}}
|
|
|
|
__host__ void HostFn() {
|
|
HostOnly();
|
|
DeviceOnly(); // expected-error {{no matching function}}
|
|
HostReturnTy x = OverloadMe();
|
|
HostReturnTy y = ns::OverloadMe();
|
|
Variadic("abc", 42);
|
|
}
|
|
|
|
__device__ void DeviceFn() {
|
|
HostOnly(); // expected-error {{no matching function}}
|
|
DeviceOnly();
|
|
int x = OverloadMe();
|
|
int y = ns::OverloadMe();
|
|
Variadic("abc", 42); // expected-error {{no matching function}}
|
|
}
|
|
|
|
__host__ __device__ void HostDeviceFn() {
|
|
#ifdef __CUDA_ARCH__
|
|
int y = OverloadMe();
|
|
#else
|
|
constexpr HostReturnTy y = OverloadMe();
|
|
#endif
|
|
}
|