atomics: switch to using exact types for return pairs (#41659)
This makes many more functions type-stable, by directly preserving the
element type when making the copy, and prints as `old => new`, like the
argument to atomic replace.
For replace, we use Pair{FT, FT} (like the argument). For modify, we use
NamedTuple{(:old, :success), Tuple{FT, Bool}}.