[PATCH] D94964: [LangRef] Describe memory layout for vectors types

Bjorn Pettersson via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 17 13:53:07 PDT 2021


bjope added a comment.

In D94964#2632569 <https://reviews.llvm.org/D94964#2632569>, @nlopes wrote:

> Overall LGTM. Thanks for documenting this! It was painful to reverse-engineer this when implementing it in Alive2..
>
> My only concern is about leaving vector sizes not multiple of a byte as unspecified. Doing so is the same as saying those are illegal; can't be used in practice. Can we define those as being padded, where the padding is poison, like in structs? That allows using vectors where padding isn't easy, like <8 x i3>. How do you store that to memory if the direct store is left unspecified? And with people using weird integer sizes for ML & FPGAs, I think it's a good idea to define this case.
> Alive2 is being conservative here and defining the padding as zero, but it should be poison IMHO.

The idea I used for describing the layout of the vectors was to base it on the fact that bitcast is allowed between first class (non-agg) types of the same size. And bitcast is defined as doing store/load. IMO the reasoning for padding should be the same for vectors and scalars that has a store size that is larger than the type size (for example, <3 x i3> should be handled just like i9).

A type such as i9 has a type store size of 16 bits according to DataLayout. So when doing a store i9 it could be seen as if 16 bits are written. The content of the seven padding bits is not defined after the store, so saying that they contain "poison" is probably ok. As long as you load/store the same size things should be ok. If you for example do store i9, followed by load i9, then you should get the same i9 value back. Similarly if you store i9, load <3 x i3> and bitcast to i9, then you should also get the same result back.  But I also believe that you could store i9, load i16, store i16, load i9 and get the same result back (so that would copy the padding). I figure the latter is similar to what happens when doing memcpy on a struct (if the padding in the struct is defined as poison).

However, what I referred to when writing "unspecified" was that the position of the padding bits isn't described (and defined) by the language reference. Afaict different targets are allowed to put the padding at different positions, not only depending on endianness, when the type size is smaller than the type store size. If the position of the padding needs to be defined, then it will be interesting to find out how different targets are doing it. There could even be some target out there that for example is padding differently for i4 and i12. Maybe it has to be defined by the DataLayout somehow, if it is needed.

Btw, the target I'm working with is one of those weird targets with support for vectors with none byte-sized elements. It had probably been a lot simpler for us if each vector element was padded to the size of a byte when storing the vector to memory (similar to how it works for arrays), but that is not how it works in LLVM IR (although the load/store in the DSP is padding between each element when dealing with such vectors).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D94964/new/

https://reviews.llvm.org/D94964



More information about the llvm-commits mailing list