constexpr variables are compile time constants and implicitly const, therefore they are safe to emit on both device and host side. Besides, in many cases they are intended for both device and host, therefore it makes sense to emit them on both device and host sides if necessary. In most cases constexpr variables are used as rvalue and the variables themselves do not need to be emitted. However if their address is taken, then they need to be emitted. For C++14, clang is able to handle that since clang emits them with available_externally linkage together with the initializer. However for C++17, the constexpr static data member of a class or template class become inline variables implicitly. Therefore they become definitions with linkonce_odr or weak_odr linkages. As such, they can not have available_externally linkage. This patch fixes that by adding implicit constant attribute to file scope constexpr variables and constexpr static data members in device compilation. Differential Revision: https://reviews.llvm.org/D79237
44 lines
1.4 KiB
Plaintext
44 lines
1.4 KiB
Plaintext
// RUN: %clang_cc1 -std=c++14 %s -emit-llvm -o - -triple nvptx \
|
|
// RUN: -fcuda-is-device | FileCheck --check-prefixes=CXX14 %s
|
|
// RUN: %clang_cc1 -std=c++17 %s -emit-llvm -o - -triple nvptx \
|
|
// RUN: -fcuda-is-device | FileCheck --check-prefixes=CXX17 %s
|
|
|
|
#include "Inputs/cuda.h"
|
|
|
|
// COM: @_ZL1a = internal {{.*}}constant i32 7
|
|
constexpr int a = 7;
|
|
__constant__ const int &use_a = a;
|
|
|
|
namespace B {
|
|
// COM: @_ZN1BL1bE = internal {{.*}}constant i32 9
|
|
constexpr int b = 9;
|
|
}
|
|
__constant__ const int &use_B_b = B::b;
|
|
|
|
struct Q {
|
|
// CXX14: @_ZN1Q2k2E = {{.*}}externally_initialized constant i32 6
|
|
// CXX17: @_ZN1Q2k2E = internal {{.*}}constant i32 6
|
|
// CXX14: @_ZN1Q2k1E = available_externally {{.*}}constant i32 5
|
|
// CXX17: @_ZN1Q2k1E = linkonce_odr {{.*}}constant i32 5
|
|
static constexpr int k1 = 5;
|
|
static constexpr int k2 = 6;
|
|
};
|
|
constexpr int Q::k2;
|
|
|
|
__constant__ const int &use_Q_k1 = Q::k1;
|
|
__constant__ const int &use_Q_k2 = Q::k2;
|
|
|
|
template<typename T> struct X {
|
|
// CXX14: @_ZN1XIiE1aE = available_externally {{.*}}constant i32 123
|
|
// CXX17: @_ZN1XIiE1aE = linkonce_odr {{.*}}constant i32 123
|
|
static constexpr int a = 123;
|
|
};
|
|
__constant__ const int &use_X_a = X<int>::a;
|
|
|
|
template <typename T, T a, T b> struct A {
|
|
// CXX14: @_ZN1AIiLi1ELi2EE1xE = available_externally {{.*}}constant i32 2
|
|
// CXX17: @_ZN1AIiLi1ELi2EE1xE = linkonce_odr {{.*}}constant i32 2
|
|
constexpr static T x = a * b;
|
|
};
|
|
__constant__ const int &y = A<int, 1, 2>::x;
|