This is an archive of the discontinued LLVM Phabricator instance.

[CUDA] Implement nv_weak attribute for functions
AbandonedPublic

Authored by Hahnfeld on May 22 2018, 8:53 AM.

Details

Reviewers
tra
aaron.ballman
Summary

This is needed for relocatable device code with CUDA 9 and later.
Before this patch, linking two or more object files resulted in
"Multiple definition" errors for a group of functions from
cuda_device_runtime_api.h which are annoted with "nv_weak".

CUDA headers already used this attribute in earlier releases, but
until CUDA 8.0 the only definitions in cuda_device_runtime_api.h
were conditional under defined(__CUDABE__) which is explicitly
undefined in Clang's wrapper. However since CUDA 9.0 this has
changed to !defined(__CUDACC_RTC__). Trying to add that define
resulted in errors that nvrtc_device_runtime.h could not be found.

Reported by Andrea Bocci!

Diff Detail

Event Timeline

Hahnfeld created this revision.May 22 2018, 8:53 AM
tra added a comment.Jun 1 2018, 10:25 AM

IIUIC, nv_weak is a synonym for weak (<rant>why, oh why did they need it?</rant>)
You may need to hunt down and change few other places that deal with the weak attribute.
E.g.: https://github.com/llvm-project/llvm-project-20170507/blob/master/clang/lib/AST/Decl.cpp#L4267
https://github.com/llvm-project/llvm-project-20170507/blob/master/clang/lib/CodeGen/ItaniumCXXABI.cpp#L3045

In D47201#1119249, @tra wrote:

IIUIC, nv_weak is a synonym for weak (<rant>why, oh why did they need it?</rant>)
You may need to hunt down and change few other places that deal with the weak attribute.
E.g.: https://github.com/llvm-project/llvm-project-20170507/blob/master/clang/lib/AST/Decl.cpp#L4267
https://github.com/llvm-project/llvm-project-20170507/blob/master/clang/lib/CodeGen/ItaniumCXXABI.cpp#L3045

If it is truly a synonym for weak, then a better implementation would be to make no semantic distinction between the two attributes -- just add new spellings to weak. If you need to make minor distinctions between the spellings, you can do it using accessors on the attribute.

include/clang/Basic/Attr.td
1515

No new, undocumented attributes, please.

In D47201#1119249, @tra wrote:

IIUIC, nv_weak is a synonym for weak (<rant>why, oh why did they need it?</rant>)
You may need to hunt down and change few other places that deal with the weak attribute.
E.g.: https://github.com/llvm-project/llvm-project-20170507/blob/master/clang/lib/AST/Decl.cpp#L4267
https://github.com/llvm-project/llvm-project-20170507/blob/master/clang/lib/CodeGen/ItaniumCXXABI.cpp#L3045

If it is truly a synonym for weak, then a better implementation would be to make no semantic distinction between the two attributes -- just add new spellings to weak. If you need to make minor distinctions between the spellings, you can do it using accessors on the attribute.

I first went with this approach but then thought it would be better to restrict the new attribute as much as possible. That's why I added a completely new one which is only applicable to functions, but not to variables and CXXRecords. Let me know if you'd prefer nv_weak to be a full alias of weak and I'll revert to what @aaron.ballman suggested.

In D47201#1119249, @tra wrote:

IIUIC, nv_weak is a synonym for weak (<rant>why, oh why did they need it?</rant>)
You may need to hunt down and change few other places that deal with the weak attribute.
E.g.: https://github.com/llvm-project/llvm-project-20170507/blob/master/clang/lib/AST/Decl.cpp#L4267
https://github.com/llvm-project/llvm-project-20170507/blob/master/clang/lib/CodeGen/ItaniumCXXABI.cpp#L3045

If it is truly a synonym for weak, then a better implementation would be to make no semantic distinction between the two attributes -- just add new spellings to weak. If you need to make minor distinctions between the spellings, you can do it using accessors on the attribute.

I first went with this approach but then thought it would be better to restrict the new attribute as much as possible. That's why I added a completely new one which is only applicable to functions, but not to variables and CXXRecords. Let me know if you'd prefer nv_weak to be a full alias of weak and I'll revert to what @aaron.ballman suggested.

I don't know enough about nv_weak's semantics to definitively say one way or the other -- I can find no documentation on this attribute (official or otherwise). However, based purely on the changes made here, I'd likely add the accessors and only go with a single semantic attribute. You can check for the proper subjects by looking at the parsed attribute kind in SemaDeclAttr.cpp and restricting the subjects there (it's a bit less declarative this way, but we don't have a way to map subject lists to spellings like we do for accessors because it's not a common need).

tra added a comment.Jun 5 2018, 4:15 PM

I've experimented a bit and I think that we may not need this patch at all.
As far as I can tell, nv_weak is only applicable to device functions. It's ignored for global kernels and is apparently forbidden for data.
For device functions nvcc produces .weak attribute in PTX.

Using plain old attribute((weak)) does exactly the same. Considering that nv_weak is only used inside CUDA SDK headers, substituting weak in place of nv_weak will result in correct PTX, which is all we really need. I don't see much benefit turning it into full blown attribute just to mimic an internal CUDA implementation detail we don't care all that much about.

Now, replacing it in CUDA headers for all CUDA versions we support may be tricky. Let me give it a try. I'll send a patch, if I manage to make it work.