Skip to content

Commit 7208e8d

Browse files
yxsamliuzhang2amd
authored andcommitted
[CUDA][HIP] allow trivial ctor/dtor in device var init
Treat ctor/dtor in device var init as host device function so that they can be used to initialize file-scope device variables to match nvcc behavior. If they are non-trivial they will be diagnosed. We cannot add implicit host device attrs to non-trivial ctor/dtor since determining whether they are non-trivial needs to know whether they have a trivial body and all their member and base classes' ctor/dtor have trivial body, which is affected by where their bodies are defined or instantiated. Revert "[CUDA][HIP] make trivial ctor/dtor host device" This reverts commit 876f99a. Fixes: llvm#72261 Fixes: SWDEV-432412 Fixes: SWDEV-433956 Change-Id: I711db63a2166ce77dea06aad5d04cae10d96ce24
1 parent 96b5455 commit 7208e8d

11 files changed

+24
-40
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13193,10 +13193,6 @@ class Sema final {
1319313193
void maybeAddCUDAHostDeviceAttrs(FunctionDecl *FD,
1319413194
const LookupResult &Previous);
1319513195

13196-
/// May add implicit CUDAHostAttr and CUDADeviceAttr attributes to a
13197-
/// trivial cotr/dtor that does not have host and device attributes.
13198-
void maybeAddCUDAHostDeviceAttrsToTrivialCtorDtor(FunctionDecl *FD);
13199-
1320013196
/// May add implicit CUDAConstantAttr attribute to VD, depending on VD
1320113197
/// and current compilation settings.
1320213198
void MaybeAddCUDAConstantAttr(VarDecl *VD);

clang/lib/Sema/SemaCUDA.cpp

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,15 @@ Sema::CUDAFunctionPreference
225225
Sema::IdentifyCUDAPreference(const FunctionDecl *Caller,
226226
const FunctionDecl *Callee) {
227227
assert(Callee && "Callee must be valid.");
228+
229+
// Treat ctor/dtor as host device function in device var initializer to allow
230+
// trivial ctor/dtor without device attr to be used. Non-trivial ctor/dtor
231+
// will be diagnosed by checkAllowedCUDAInitializer.
232+
if (Caller == nullptr && CurCUDATargetCtx.Kind == CTCK_InitGlobalVar &&
233+
CurCUDATargetCtx.Target == CFT_Device &&
234+
(isa<CXXConstructorDecl>(Callee) || isa<CXXDestructorDecl>(Callee)))
235+
return CFP_HostDevice;
236+
228237
CUDAFunctionTarget CallerTarget = IdentifyCUDATarget(Caller);
229238
CUDAFunctionTarget CalleeTarget = IdentifyCUDATarget(Callee);
230239

@@ -730,22 +739,6 @@ void Sema::maybeAddCUDAHostDeviceAttrs(FunctionDecl *NewD,
730739
NewD->addAttr(CUDADeviceAttr::CreateImplicit(Context));
731740
}
732741

733-
// If a trivial ctor/dtor has no host/device
734-
// attributes, make it implicitly host device function.
735-
void Sema::maybeAddCUDAHostDeviceAttrsToTrivialCtorDtor(FunctionDecl *FD) {
736-
bool IsTrivialCtor = false;
737-
if (auto *CD = dyn_cast<CXXConstructorDecl>(FD))
738-
IsTrivialCtor = isEmptyCudaConstructor(SourceLocation(), CD);
739-
bool IsTrivialDtor = false;
740-
if (auto *DD = dyn_cast<CXXDestructorDecl>(FD))
741-
IsTrivialDtor = isEmptyCudaDestructor(SourceLocation(), DD);
742-
if ((IsTrivialCtor || IsTrivialDtor) && !FD->hasAttr<CUDAHostAttr>() &&
743-
!FD->hasAttr<CUDADeviceAttr>()) {
744-
FD->addAttr(CUDAHostAttr::CreateImplicit(Context));
745-
FD->addAttr(CUDADeviceAttr::CreateImplicit(Context));
746-
}
747-
}
748-
749742
// TODO: `__constant__` memory may be a limited resource for certain targets.
750743
// A safeguard may be needed at the end of compilation pipeline if
751744
// `__constant__` memory usage goes beyond limit.

clang/lib/Sema/SemaDecl.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15884,9 +15884,6 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
1588415884
if (FD && !FD->isDeleted())
1588515885
checkTypeSupport(FD->getType(), FD->getLocation(), FD);
1588615886

15887-
if (LangOpts.CUDA)
15888-
maybeAddCUDAHostDeviceAttrsToTrivialCtorDtor(FD);
15889-
1589015887
return dcl;
1589115888
}
1589215889

clang/lib/Sema/SemaOverload.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,10 +1404,8 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
14041404
// Don't allow overloading of destructors. (In theory we could, but it
14051405
// would be a giant change to clang.)
14061406
if (!isa<CXXDestructorDecl>(New)) {
1407-
CUDAFunctionTarget NewTarget = IdentifyCUDATarget(
1408-
New, isa<CXXConstructorDecl>(New)),
1409-
OldTarget = IdentifyCUDATarget(
1410-
Old, isa<CXXConstructorDecl>(New));
1407+
CUDAFunctionTarget NewTarget = IdentifyCUDATarget(New),
1408+
OldTarget = IdentifyCUDATarget(Old);
14111409
if (NewTarget != CFT_InvalidTarget) {
14121410
assert((OldTarget != CFT_InvalidTarget) &&
14131411
"Unexpected invalid target.");

clang/test/SemaCUDA/call-host-fn-from-device.cu

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ extern "C" void host_fn() {}
1212
struct Dummy {};
1313

1414
struct S {
15-
S() { static int nontrivial_ctor = 1; }
15+
S() {}
1616
// expected-note@-1 2 {{'S' declared here}}
1717
~S() { host_fn(); }
1818
// expected-note@-1 {{'~S' declared here}}

clang/test/SemaCUDA/default-ctor.cu

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ __device__ void fd() {
2525
InD ind;
2626
InH inh; // expected-error{{no matching constructor for initialization of 'InH'}}
2727
InHD inhd;
28-
Out out;
28+
Out out; // expected-error{{no matching constructor for initialization of 'Out'}}
2929
OutD outd;
3030
OutH outh; // expected-error{{no matching constructor for initialization of 'OutH'}}
3131
OutHD outhd;

clang/test/SemaCUDA/implicit-member-target-collision-cxx11.cu

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// Test 1: collision between two bases
77

88
struct A1_with_host_ctor {
9-
A1_with_host_ctor() { static int nontrivial_ctor = 1; }
9+
A1_with_host_ctor() {}
1010
};
1111

1212
struct B1_with_device_ctor {

clang/test/SemaCUDA/implicit-member-target-collision.cu

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// Test 1: collision between two bases
77

88
struct A1_with_host_ctor {
9-
A1_with_host_ctor() { static int nontrivial_ctor = 1; }
9+
A1_with_host_ctor() {}
1010
};
1111

1212
struct B1_with_device_ctor {

clang/test/SemaCUDA/implicit-member-target-inherited.cu

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// Test 1: infer inherited default ctor to be host.
77

88
struct A1_with_host_ctor {
9-
A1_with_host_ctor() { static int nontrivial_ctor = 1; }
9+
A1_with_host_ctor() {}
1010
};
1111
// expected-note@-3 {{candidate constructor (the implicit copy constructor) not viable}}
1212
// expected-note@-4 {{candidate constructor (the implicit move constructor) not viable}}
@@ -39,7 +39,6 @@ struct A2_with_device_ctor {
3939
};
4040
// expected-note@-3 {{candidate constructor (the implicit copy constructor) not viable}}
4141
// expected-note@-4 {{candidate constructor (the implicit move constructor) not viable}}
42-
// expected-note@-4 {{candidate inherited constructor not viable: call to __device__ function from __host__ function}}
4342

4443
struct B2_with_implicit_default_ctor : A2_with_device_ctor {
4544
using A2_with_device_ctor::A2_with_device_ctor;
@@ -84,7 +83,7 @@ void hostfoo3() {
8483
// Test 4: infer inherited default ctor from a field, not a base
8584

8685
struct A4_with_host_ctor {
87-
A4_with_host_ctor() { static int nontrivial_ctor = 1; }
86+
A4_with_host_ctor() {}
8887
};
8988

9089
struct B4_with_inherited_host_ctor : A4_with_host_ctor{

clang/test/SemaCUDA/implicit-member-target.cu

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// Test 1: infer default ctor to be host.
77

88
struct A1_with_host_ctor {
9-
A1_with_host_ctor() { static int nontrivial_ctor = 1; }
9+
A1_with_host_ctor() {}
1010
};
1111

1212
// The implicit default constructor is inferred to be host because it only needs
@@ -75,7 +75,7 @@ void hostfoo3() {
7575
// Test 4: infer default ctor from a field, not a base
7676

7777
struct A4_with_host_ctor {
78-
A4_with_host_ctor() { static int nontrivial_ctor = 1; }
78+
A4_with_host_ctor() {}
7979
};
8080

8181
struct B4_with_implicit_default_ctor {

0 commit comments

Comments
 (0)