Skip to content

Implement __builtin_zero_non_value_bits which was recently added to MSVC for P0528R3 and P1123R0 #46030

@AlexGuteniev

Description

@AlexGuteniev
Bugzilla Link 46685
Version 10.0
OS Windows NT
CC @zygoloid

Extended Description

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugzillaIssues migrated from bugzillac++20clang:codegenIR generation bugs: mangling, exceptions, etc.clang:frontendLanguage frontend issues, e.g. anything involving "Sema"diverges-from:msvcDoes the clang frontend diverge from msvc on this issue

    Type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions