For non-byte-sized types like i20, we currently specify that:
When loading a value of a type like i20 with a size that is not an integral number of bytes, the result is undefined if the value was not originally written using a store of the same type.
When writing a value of a type like i20 with a size that is not an integral number of bytes, it is unspecified what happens to the extra bits that do not belong to the type, but they will typically be overwritten.
These semantics are somewhat unclear, and likely incompatible with current optimization assumptions. If "undefined" in load specification is in the sense of "undefined behavior" that means that non-byte-sized loads may not be speculatable despite the memory being dereferenceable, which is not something we're taking into account right now. The "unspecified" in the store specification is just unclear, does this mean the bits become undef, or poison, or something else?
This patch specifies that poison is stored for padding of both aggregates and non-byte-sized types. Loads of such types don't require special treatment, as the padding is not observable anyway.
I believe this covers the practical requirements for non-byte-sized types, in that a) a hardware store will likely zero out the padding bits, which is compatible with poison and b) it is possible to eliminate a store of non-byte-sized type (e.g. due to "store of loaded value"), which will leave behind the original bits (which might be poison, so making the padding anything weaker than that would render the optimization illegal).