[llvm-bugs] [Bug 46685] New: Implement __builtin_zero_non_value_bits which was recently added to MSVC for P0528R3 and P1123R0
via llvm-bugs
llvm-bugs at lists.llvm.org
Sat Jul 11 05:46:40 PDT 2020
https://bugs.llvm.org/show_bug.cgi?id=46685
Bug ID: 46685
Summary: Implement __builtin_zero_non_value_bits which was
recently added to MSVC for P0528R3 and P1123R0
Product: clang
Version: 10.0
Hardware: PC
OS: Windows NT
Status: NEW
Severity: normal
Priority: P
Component: C++2a
Assignee: unassignedclangbugs at nondot.org
Reporter: gutenev at gmail.com
CC: blitzrakete at gmail.com, erik.pilkington at gmail.com,
llvm-bugs at lists.llvm.org, richard-llvm at metafoo.co.uk
MSVC implements __builtin_zero_non_value_bits intrinsic.
This is needed to implement C++2a features:
* P0528R3 Atomic Compare-And-Exchange With Padding Bits
* P1123R0 Atomic Compare-And-Exchange With Padding Bits For atomic_ref
__builtin_zero_non_value_bits non-atomically zeros non-value bits in types such
as
struct X
{
int a;
char b;
// 3 bytes padding for 32-bit int
};
or
struct Y
{
int a: 7;
// 25 bits of padding for 32-bit int
};
For std::atomic it can be used in constructor and in store and exchange.
So compare_exchange_* would be able to use bitwise comparison, as non-value
bits are always zeros
For std::atomic_ref non-atomically zeroing in constructor is apparently not an
option due to possible concurrent atomic_ref instances.
Still, __builtin_zero_non_value_bits can be used.
For lock-free atomics, compute the mask as follows:
target_type v;
memset(&v, 0xff, sizeof(v));
__builtin_zero_non_value_bits(&v);
integer_type value_mask;
memcpy(&value_mask, &v, sizeof(v));
Then implement compare_exchange as follows:
for(;;)
integer_type prev = _InterlockedCompareExchange(
&val, desired, expected);
if (prev == expected) {
return true; // Success
}
if ((prev ^ expected) & value_mask) {
break; // Failure due to value bits mismatch, fail
}
// Failure due to only padding bits mismatch
// Retry with new expectation for padding bits
expected = (expected & value_mask) | (prev & ~value_mask);
}
For lock-based atomic_ref just apply __builtin_zero_non_value_bits both to
target (under the lock) and comparand (possibly not under the lock)
std::atomic_ref method can also be used for std::atomic too for unification.
Note that:
* In atomic_ref method, the computation of mask should defacto result in
value_mask computed by compiler in case of optimization enabled
* In atomic method __builtin_zero_non_value_bits should also work in compile
time in constexpr constructor
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20200711/0824943b/attachment-0001.html>
More information about the llvm-bugs
mailing list