Date: Fri, 23 Jan 2026 09:55:08 +0100
Hi Thiago,
thank you for your answer (in this quite long thread).
> int popcount(long double f)
> {
> std::clear_padding(f);
> return std::popcount(reinterpret_cast<uint128_t &>(f));
> }
> I'd expect this to *suppress* code by knowing
The long double has (on x86/x87) a 80-bit native (register) and a 128-bit memory representation.
So values can be moved from one representation to the next, the padding bits may exist sometimes, sometimes not.
They only get relevant, if
- one does bit_cast to a type using those bits (but bit_cast could be made to clear those bits directly) or if
- one accesses an underlying byte storage.
So the options to solve this are
A) Change the padded types to always store and copy all padding bits at all ABI boundaries.
Disadvantage: Less efficient, ABI change
B) The actual access of the padding bits is with bit_cast or with the underlying byte storage.
a) change bit_cast() to assume padding bits to be zero or add a bit_cast_clear_padding()
b) change reinterpret_cast() or add a reinterpret_cast_clear_padding()
int popcount(long double f)
{
return std::popcount(reinterpret_cast_clear_padding<uint128_t &>(f));
}
int popcount(long double f)
{
return std::popcount(std::bit_cast_clear_padding<uint128_t>(f));
}
The variant to remember, whether a std::clear_padding() happened, seems to be only feasible, if the compiler can do local reasoning or if all ABI boundaries store padding bits explicitly. In this case, one has to clearly define, when padding bits are modified and contain important bits, when they are put into an indeterminate state, when they are copied and when they are read back again. I don't think that is feasible in the end. Options A and B are, with A more or less abolishing padding or the meaning of padding. So B remains as a good option.
-----Ursprüngliche Nachricht-----
Von:Thiago Macieira via Std-Proposals <std-proposals_at_[hidden]>
Gesendet:Fr 23.01.2026 04:03
Betreff:Re: [std-proposals] Fixing std::bit_cast padding bit issues
Anlage:signature.asc
An:std-proposals_at_[hidden];
CC:Thiago Macieira <thiago_at_[hidden]>;
On Thursday, 22 January 2026 14:53:46 Pacific Standard Time Sebastian Wittmeier
via Std-Proposals wrote:
> If it is a trivially copyable variable stored on the stack,
>
> is there any guarantee that clear_padding creates code at all?
I think that's the wrong question to ask. Let's take the hypothetical example
of a popcount over a long double:
int popcount(long double f)
{
std::clear_padding(f);
return std::popcount(reinterpret_cast<uint128_t &>(f));
}
It doesn't *need* to emit code. In fact, I'd expect this to *suppress* code by
knowing that 6 of the 16 bytes are zero and thus don't contribute to the count
of bits set. The compiler should realise it only needs to popcount 8+2 bytes.
The important question is that of behaviour. So long as it behaves as if the
bits have been cleared, any as-if transformation is fine.
> Wouldn't an optimizer for each read after the clear_padding function use a
> copy with the padding bits unspecified again?
>
> And/or remove the clear_padding call?
>
> Is there any guarantee in the standard that padding bits are to be
> preserved, that they can be (re)set and are expected to stay that way until
> they are read?
That's a good question and may require text updates. In turn, that may require
some feedback from compiler vendors whether they currently have taken
liberties with this.
The important thing is that the storage for this type, whether concrete or
"as-if", must have had its bits cleared and must remain so until the next time
the variable is assigned to.
If you copy to another variable of the same type, all bets are lost. That
includes function calls where it is passed by value.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Principal Engineer - Intel Data Center - Platform & Sys. Eng.
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2026-01-23 09:11:23
