-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[clang] constexpr atomic builtins (__c11_atomic_OP and __atomic_OP) #98756
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
hanickadot
wants to merge
8
commits into
llvm:main
Choose a base branch
from
hanickadot:P3309-constexpr-atomic-clang
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
7d65b13
[clang] implement P3309 atomic builtins in constant evaluator
hanickadot 1994a55
[clang] refactor EvaluateAtomic* builtin support functions. Comments …
hanickadot 8aee298
[clang] add __atomic_fetch_(add|sub) and __atomic_(add|sub)_fetch tes…
hanickadot 9de180f
[clang] revert making atomic builtins constexpr, it's not needed, as …
hanickadot 537178b
[clang] allow constexpr atomics only in C++ mode, check for valid Mem…
hanickadot b87075c
Revert "[clang] revert making atomic builtins constexpr, it's not nee…
hanickadot 5318bcc
[clang] more tests for constexpr atomics
hanickadot 34b174d
[clang] constexpr atomic tests for `__int128` + release notes
hanickadot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1744,97 +1744,97 @@ def SyncSwapN : Builtin, SyncBuiltinsTemplate { | |
| // C11 _Atomic operations for <stdatomic.h>. | ||
| def C11AtomicInit : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_init"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicLoad : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_load"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicStore : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_store"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicExchange : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_exchange"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicCompareExchangeStrong : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_compare_exchange_strong"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicCompareExchangeWeak : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_compare_exchange_weak"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicFetchAdd : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_fetch_add"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicFetchSub : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_fetch_sub"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicFetchAnd : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_fetch_and"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicFetchOr : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_fetch_or"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicFetchXor : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_fetch_xor"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicFetchNand : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_fetch_nand"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicFetchMax : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_fetch_max"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicFetchMin : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_fetch_min"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicThreadFence : Builtin { | ||
| let Spellings = ["__c11_atomic_thread_fence"]; | ||
| let Attributes = [NoThrow]; | ||
| let Attributes = [NoThrow, Constexpr]; | ||
| let Prototype = "void(int)"; | ||
| } | ||
|
|
||
| def C11AtomicSignalFence : Builtin { | ||
| let Spellings = ["__c11_atomic_signal_fence"]; | ||
| let Attributes = [NoThrow]; | ||
| let Attributes = [NoThrow, Constexpr]; | ||
| let Prototype = "void(int)"; | ||
| } | ||
|
|
||
|
|
@@ -1847,133 +1847,133 @@ def C11AtomicIsLockFree : Builtin { | |
| // GNU atomic builtins. | ||
| def AtomicLoad : AtomicBuiltin { | ||
| let Spellings = ["__atomic_load"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When removing the constexpr-ness from these functions in C, please also make sure |
||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicLoadN : AtomicBuiltin { | ||
| let Spellings = ["__atomic_load_n"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicStore : AtomicBuiltin { | ||
| let Spellings = ["__atomic_store"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicStoreN : AtomicBuiltin { | ||
| let Spellings = ["__atomic_store_n"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicExchange : AtomicBuiltin { | ||
| let Spellings = ["__atomic_exchange"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicExchangeN : AtomicBuiltin { | ||
| let Spellings = ["__atomic_exchange_n"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicCompareExchange : AtomicBuiltin { | ||
| let Spellings = ["__atomic_compare_exchange"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicCompareExchangeN : AtomicBuiltin { | ||
| let Spellings = ["__atomic_compare_exchange_n"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicFetchAdd : AtomicBuiltin { | ||
| let Spellings = ["__atomic_fetch_add"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicFetchSub : AtomicBuiltin { | ||
| let Spellings = ["__atomic_fetch_sub"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicFetchAnd : AtomicBuiltin { | ||
| let Spellings = ["__atomic_fetch_and"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicFetchOr : AtomicBuiltin { | ||
| let Spellings = ["__atomic_fetch_or"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicFetchXor : AtomicBuiltin { | ||
| let Spellings = ["__atomic_fetch_xor"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicFetchNand : AtomicBuiltin { | ||
| let Spellings = ["__atomic_fetch_nand"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicAddFetch : AtomicBuiltin { | ||
| let Spellings = ["__atomic_add_fetch"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicSubFetch : AtomicBuiltin { | ||
| let Spellings = ["__atomic_sub_fetch"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicAndFetch : AtomicBuiltin { | ||
| let Spellings = ["__atomic_and_fetch"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicOrFetch : AtomicBuiltin { | ||
| let Spellings = ["__atomic_or_fetch"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicXorFetch : AtomicBuiltin { | ||
| let Spellings = ["__atomic_xor_fetch"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicMaxFetch : AtomicBuiltin { | ||
| let Spellings = ["__atomic_max_fetch"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicMinFetch : AtomicBuiltin { | ||
| let Spellings = ["__atomic_min_fetch"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicNandFetch : AtomicBuiltin { | ||
| let Spellings = ["__atomic_nand_fetch"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
|
|
@@ -1991,7 +1991,7 @@ def AtomicClear : Builtin { | |
|
|
||
| def AtomicThreadFence : Builtin { | ||
| let Spellings = ["__atomic_thread_fence"]; | ||
| let Attributes = [NoThrow]; | ||
| let Attributes = [NoThrow, Constexpr]; | ||
| let Prototype = "void(int)"; | ||
| } | ||
|
|
||
|
|
@@ -2003,7 +2003,7 @@ def ScopedAtomicThreadFence : Builtin { | |
|
|
||
| def AtomicSignalFence : Builtin { | ||
| let Spellings = ["__atomic_signal_fence"]; | ||
| let Attributes = [NoThrow]; | ||
| let Attributes = [NoThrow, Constexpr]; | ||
| let Prototype = "void(int)"; | ||
| } | ||
|
|
||
|
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm worried about changing the C11 atomic builtins for a C++26 feature; I think there are more changes needed as a result. For example, changing this to be constexpr means we now run the risk of accepting this code in C: https://godbolt.org/z/hc3oqYx6b
We likely are missing test coverage for this kind of thing in C, so I would recommend 1) add test coverage to this PR and if it breaks as a result of these changes, then 2) I would probably add some
getLangOpts().CPlusPluschecks in the constant expression evaluator. We could invent new tablegen to say "this is constexpr only in C++", but it's not clear to me whether there will be enough builtins that need such functionality or not, but that's another (cleaner, but a heavier lift for a new contributor) option.Hmm, but I just remembered that
__has_constexpr_builtin(https://clang.llvm.org/docs/LanguageExtensions.html#has-constexpr-builtin) is a thing, so we may need that tablegen solution after all because otherwise we change the behavior here in confusing ways: https://godbolt.org/z/qGY575MGr FWIW, here's an example of some recent changes to tablegen that you could model your changes after: https://github.com/llvm/llvm-project/pull/91894/files