<html>
<head>
<base href="https://bugs.llvm.org/">
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - Implement __builtin_zero_non_value_bits which was recently added to MSVC for P0528R3 and P1123R0"
href="https://bugs.llvm.org/show_bug.cgi?id=46685">46685</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>Implement __builtin_zero_non_value_bits which was recently added to MSVC for P0528R3 and P1123R0
</td>
</tr>
<tr>
<th>Product</th>
<td>clang
</td>
</tr>
<tr>
<th>Version</th>
<td>10.0
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>Windows NT
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>C++2a
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedclangbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>gutenev@gmail.com
</td>
</tr>
<tr>
<th>CC</th>
<td>blitzrakete@gmail.com, erik.pilkington@gmail.com, llvm-bugs@lists.llvm.org, richard-llvm@metafoo.co.uk
</td>
</tr></table>
<p>
<div>
<pre>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</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>