So, to use your example with 80-bit long double on x86, where
sizeof(long double) is 16, the behavior of memcpy must be equivalent to
copying 16 bytes from the source to target, not 10. And this can be
observed by a program such as this:

  bool test(const long double& d1)
  {
    unsigned char buf1[sizeof(long double)];
    memcpy(buf1, &d1, sizeof(long double));
    long double d2;
    memcpy(&d2, buf1, sizeof(long double));
    unsigned char buf2[sizeof(long double)];
    memcpy(buf2, &d2, sizeof(long double));

    return memcmp(buf1, buf2, sizeof(long double)) == 0;
  }


This function must always return true, under the specification of memcpy
and memcmp (which is also defined in C as operating on n characters).
Whether the compiler generates code that does the actual copies and
comparison of 16 bytes, or 10 bytes (for *both* copying and comparison)
or none at all and just generates an equivalent of `return true` is QoI.

I think you're right regarding padding bits being observable, albeit only at run-time. We have some wording that specifies values of padding bits (e.g. zero-initialization says padding bits are zero), and so there are some cases where padding bits are not indeterminate. I was operating under the assumption that padding bits are indeterminate in all cases, but they're not.

However, there is nothing that guarantees you that your test function is well-defined. If d1 has dynamic storage duration or is marked [[indeterminate]], padding bytes have indeterminate value, so you're just reading uninitialized memory, and the function has undefined behavior. In most other cases (e.g. local variables), d1 has padding bits with erroneous value. This is a huge footgun, and encouraging users to modify and access padding is exactly the wrong design direction.

Even in the few cases where padding bits have specified value, that value is very easily lost through lvalue-to-rvalue conversion or any kind of arithmetic operation.
 
The proposed clear_padding utility would be defined as "sets all bits in
the object representation that do not participate in value
representation to zero" or something along these lines. This is a
perfectly reasonable definition that is in line with the existing object
model.

I have yet to hear any attempt at an argument for why we would want a clear_padding utility rather than a bit_cast_zero_padding utility. As I've said, padding bits are very easily lost. It also requires expert-level knowledge to understand when padding bits have some specified value and when they revert back to indeterminate or erroneous value. A clear_padding utility also would not work for constant evaluation.
 
That being said, I'm not strongly opposed to making bit_cast preserve the values of padding bits at run-time. However, that doesn't really solve the problem that I set out to fix here. Those padding bits are almost certainly going to be erroneous or indeterminate if the user doesn't use clear_padding, and clear_padding doesn't really work during constant evaluation without substantial changes to implementations.

The clear_padding + bit_cast idiom encourages the user to write the wrong kind of code. If you forget clear_padding, you may get undefined behavior, and what is currently a degenerate form of bit_cast that we could reject at compile time (because it always produces UB) becomes undiagnosable; the user could have run bit_cast expecting the padding bits to be copied, and the compiler has no way of knowing whether that's the intent. Very sharp edge!