[libcxx-commits] [clang] [libcxx] [clang] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)

via libcxx-commits libcxx-commits at lists.llvm.org
Sat Apr 25 03:36:44 PDT 2026


huixie90 wrote:

> Can you describe the algorithm for `compare_exchange` for `atomic_ref` that handles the case where the in-memory padding is not zero and how that algorithm uses this intrinsic?

```
bool valueRepresentationEquals(T x, T y) {
   clear_padding(&x);
   clear_padding(&y);
   return memcmp(&x, &y, sizeof(T));
}

bool atomic_ref<T>::compareExchange(T& expected, T desired) {
   T expectedCopy = expected; 
   clear_padding(&expectedCopy);
   clear_padding(&desired);

   T oldExepected = expectedCopy;

   bool r1 = CAS(&get(), &expectedCopy,  desired);
   if (r1) return true;
   
   if (!valueRepresentationEquals(oldExepected, expectedCopy)) {
      // value representation of expected changed, it is true CAS fail
      memcpy(&expected, &expectedCopy, sizeof(T));
      return false;
   }
   
   // the CAS failed due to some padding difference

   // at this point, expectedCopy should have the original's atomic_ref's padding

   T oldExepected2 = expectedCopy;
   bool r2 = CAS(&get(), &expectedCopy,  desired);
   if (r1) {
       // if the atomic_ref wasn't changed since the first CAS, it should go to this branch
        return true;
   }

   // atomic_ref has changed between the first and second CAS
   // atomic_ref's owning padding must be zeroed already because all writes to atomic_ref cleared the padding

   if (!valueRepresentationEquals(oldExepected2, expectedCopy)) {
      // value representation of expected changed, it is true CAS fail
      memcpy(&expected, &expectedCopy, sizeof(T));
      return false;
   }

   // so the second CAS failed due to padding difference (the oldExepected2 has original atomic_ref's padding but atomic_ref's padding being zeroed by other writes

  // expectedCopy has been updated again to have the updated atomic_ref, which has zeros in their paddings
  // at this point, both expectedCopy and atomic_ref must have zeroed paddings

  bool r3 = CAS(&get(), &expectedCopy,  desired);
  if (!r3) memcpy(&expected, &expectedCopy, sizeof(T));
  return r3;
}
```

The code surely can be simplied but you get the idea. @gonzalobg 

https://github.com/llvm/llvm-project/pull/75371


More information about the libcxx-commits mailing list