llvm atomics on 64-bit values

I need an atomic pointer exchange, so I took a look at Support/Atomic.h, and the only supported types are 32-bit values. I can’t figure out an obvious reason for this other than perhaps nobody ever had need of this yet, but given that this is kind of a low level thing, I thought I should ask first. Is there any reason I should not add 64-bit versions of the atomic functions?

Additionally, the function I need looks like __sync_test_and_set() on GNU, for which the documentation has this to say:

Many targets have only minimal support for such locks, and do not support a full exchange operation. In this case, a target may support reduced functionality here by which the only valid value to store is the immediate constant 1. The exact value actually stored in * is implementation defined.

Does anyone happen to know the details here? Is this true on any platform we support?

We’re already using std::atomic<> in Clang:

$ ack ‘std::atomic’ | cat
lib/Basic/VirtualFileSystem.cpp:843: static std::atomic UID;
lib/Frontend/ASTUnit.cpp:214:static std::atomic ActiveASTUnitObjects;
lib/Frontend/CompilerInvocation.cpp:1956: static std::atomic GraveYardSize;
tools/libclang/CIndexCodeCompletion.cpp:319:static std::atomic CodeCompletionResultObjects;

I’d use it for pointer-sized values. I probably wouldn’t use it on uint64_t, since that’ll probably give some 32-bit toolchain somewhere heartburn.

It should work for uint64_t, for anything that supports C++11, but don't necessarily expect it to be fast. PowerPC32 doesn't have 64-bit atomics, so will get a call out to a helper function that will acquire a lock, do the operation, and then release the lock. This is quite a bit more expensive than a 32-bit atomic, which will be three instructions.

On x86-32, you may still get the call to the runtime function, but if your system targets i586+ then the implementation will be a simple atomic operation.