[libcxx] atomic header and low-level intrinsics

Hi,

I've been looking at libcxx's <atomic> and experimenting with an implementation
of the low-level intrinsics it uses, as described at

  http://libcxx.llvm.org/atomic_design_a.html

where the intrinsics include

  type __atomic_load(const type* atomic_obj, int mem_ord);

These are similar to but incompatible with the new GCC atomic intrinsics:

  __atomic Builtins (Using the GNU Compiler Collection (GCC))

which include

  type __atomic_load_n (type *ptr, int memmodel);
  void __atomic_load (type *ptr, type *ret, int memmodel);

Is there any reason not to move libcxx <atomic> to use these GCC intrinsics,
and have clang implement them?

Also, I noticed a couple of minor issues with libcxx <atomic> and its tests:

The pointer operations e.g.

    _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst)
        {return __atomic_fetch_add(&this->__a_, __op, __m);}

don't seem to match the defined intrinsics:

  void* __atomic_fetch_add(void** atomic_obj, ptrdiff_t operand, int mem_ord);

Either the low-level intrinsics need to be polymorphic, or <atomic> needs
some casts and also needs to scale the ptrdiff_t value.

Finally, various libcxx atomic tests attempt to instantiate atomic<> on a
struct A which is not trivially-copyable and hence not valid (29.5#1 in N3290).
Is libcxx intending its <atomic> to support such types on all platforms?

Al

-- IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.

Hi Al,

These are similar to but incompatible with the new GCC atomic intrinsics:

__atomic Builtins (Using the GNU Compiler Collection (GCC))

which include

type __atomic_load_n (type *ptr, int memmodel);
void __atomic_load (type *ptr, type *ret, int memmodel);

Is there any reason not to move libcxx <atomic> to use these GCC intrinsics,
and have clang implement them?

Clang already implements the intrinsics. I have a patch adding the remaining codegen parts that should be going in this week. With this applied, most of the libc++ atomics tests now pass for me.

Also, I noticed a couple of minor issues with libcxx <atomic> and its tests:

The pointer operations e.g.

   _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst)
       {return __atomic_fetch_add(&this->__a_, __op, __m);}

don't seem to match the defined intrinsics:

void* __atomic_fetch_add(void** atomic_obj, ptrdiff_t operand, int mem_ord);

Either the low-level intrinsics need to be polymorphic, or <atomic> needs
some casts and also needs to scale the ptrdiff_t value.

The intrinsics are polymorphic.

Finally, various libcxx atomic tests attempt to instantiate atomic<> on a
struct A which is not trivially-copyable and hence not valid (29.5#1 in N3290).
Is libcxx intending its <atomic> to support such types on all platforms?

This is a bug in the test. Howard said he'd fix it a couple of months ago when I raised this issue, but as I've only just got around to finishing the remainder of the bits of atomics support that libc++ needs, it probably hasn't been a high priority for him yet.

David

-- Sent from my Apple II

Hi Al,

These are similar to but incompatible with the new GCC atomic intrinsics:

__atomic Builtins (Using the GNU Compiler Collection (GCC))

which include

type __atomic_load_n (type *ptr, int memmodel);
void __atomic_load (type *ptr, type *ret, int memmodel);

Is there any reason not to move libcxx <atomic> to use these GCC intrinsics,
and have clang implement them?

Clang already implements the intrinsics. I have a patch adding the remaining codegen parts that should be going in this week. With this applied, most of the libc++ atomics tests now pass for me.

That's great news, thanks David.

Also, I noticed a couple of minor issues with libcxx <atomic> and its tests:

The pointer operations e.g.

  _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst)
      {return __atomic_fetch_add(&this->__a_, __op, __m);}

don't seem to match the defined intrinsics:

void* __atomic_fetch_add(void** atomic_obj, ptrdiff_t operand, int mem_ord);

Either the low-level intrinsics need to be polymorphic, or <atomic> needs
some casts and also needs to scale the ptrdiff_t value.

The intrinsics are polymorphic.

Finally, various libcxx atomic tests attempt to instantiate atomic<> on a
struct A which is not trivially-copyable and hence not valid (29.5#1 in N3290).
Is libcxx intending its <atomic> to support such types on all platforms?

This is a bug in the test. Howard said he'd fix it a couple of months ago when I raised this issue, but as I've only just got around to finishing the remainder of the bits of atomics support that libc++ needs, it probably hasn't been a high priority for him yet.

I accidentally dropped it, and yes, had other priorities. Thank you both for the reminder.

I'm excited about getting clang/libc++ atomics finished. Just last week I lamented about not being able to use optimal atomics in libc++abi (http://libcxxabi.llvm.org/) for the get/set handler functions. And that has certainly rekindled my interest in C++11 atomics! :slight_smile:

Howard

David Chisnall writes:

Clang already implements the intrinsics.

Does it implement the GCC intrinsics? I can't see __atomic_load_n. And only
two-argument __atomic_load is tested, not GCC's three-argument version.

The two intrinsics sets are not the same, though they are very similar.
So libcxx <atomic> only works with clang and not with GCC. If libcxx and clang
changed to use and implement the GCC intrinsics, then libcxx would work with GCC.

Al

-- IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.

Clang already implements the intrinsics.

Does it implement the GCC intrinsics? I can't see __atomic_load_n. And only
two-argument __atomic_load is tested, not GCC's three-argument version.

Sorry, I meant to say, clang implements the intrinsics that libc++ uses.

The two intrinsics sets are not the same, though they are very similar.
So libcxx <atomic> only works with clang and not with GCC. If libcxx and clang
changed to use and implement the GCC intrinsics, then libcxx would work with GCC.

And if GCC implemented the clang intrinsics, then the same is true.

The clang intrinsics are a 1:1 mapping to the C11 spec, while the GCC intrinsics are a mess, so I'm not sure that the world would be better served by adopting them.

David