-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Description
void f(decltype(nullptr) x);
void g() { f(nullptr); }Clang (and GCC) generate an instruction to zero a register when making this call. That's unnecessary -- nullptr_t contains only padding bits, so there is no need to put any particular value in the parameter.
It's a little weird that the C++ standard requires it to have the same size and alignment as a pointer, but also says that lvalue-to-rvalue conversions don't touch memory. And it's unfortunate that our ABIs require a register to be allocated to (not) passing it. But it's too late to change any of that.
We also have divergence from GCC on this:
void h() {
volatile auto p = nullptr;
p = nullptr;
p = p;
}Clang generates three volatile stores of ptr null here and zero volatile loads. GCC generates three volatile stores and one volatile load. To my reading, Clang is right and GCC is wrong: the standard is clear that there is no read from memory in this case, but each assignment does constitute a modification -- but we don't need to store null in particular, any bits would do here, so long as we perform a store. (Weirdly.)
I think instead of producing ptr null when lowering a nullptr expression, we should instead produce ptr poison, given that the representation comprises only padding bits.