[PATCH] D98169: [IR] Permit load/store/alloca for struct with the same scalable vectors.

Craig Topper via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 11 09:14:05 PST 2021


craig.topper added a comment.

In D98169#2619303 <https://reviews.llvm.org/D98169#2619303>, @sdesmalen wrote:

> Hi @HsiangKai, this is not a supported use-case for scalable vectors and it is explicitly called out in the LangRef:
>
>> Scalable vectors cannot be global variables or members of arrays because their size is unknown at compile time. They are allowed in structs to facilitate intrinsics returning multiple values. Structs containing scalable vectors cannot be used in loads, stores, allocas, or GEPs.
>
> There have been a few conversations about this before. I previously left a comment on D94142 <https://reviews.llvm.org/D94142> and there was also some discussion on @craig.topper's RFC to add limited support for intrinsics, which can be found here: https://lists.llvm.org/pipermail/llvm-dev/2021-January/147639.html
>
> Supporting scalable vector types as exclusive members of structs that can be used in loads/stores/allocas is a bit of a sliding scale, because the next question will be the one @frasercrmck is asking: "Why can't you mix fixed/scalable types?".
>
> It's been still relatively recent that we've settled on a definition for TypeSize which still needs to be supported in many places in the code-base. Mixing fixed/scalable adds another dimension of complexity, because then all interfaces that take an offset also need to consider the fact that it may be comprised of a fixed-width and scalable-width component. Also, at the moment there isn't really a use-case, there are no languages that allow or support structs/aggregates with scalable members.  The original advice given for "What if C/C++ allowed such a use case?" was to solve this in Clang, so as to remove the need for such support in LLVM IR.
>
> The only reason we wanted to allow the use-case for return-values/operands of intrinsics is so that we can model operations that return multiple values which can be scalable, such as first-faulting loads where it returns a data vector (the loaded data) and a predicate mask for the lanes that faulted.
>
> @HsiangKai was there a specific use-case that you had in mind for this?

We want this to support the segment load/store intrinsics defined here https://github.com/riscv/rvv-intrinsic-doc/blob/master/intrinsic_funcs/03_vector_load_store_segment_instructions_zvlsseg.md  These return 2 to 8 vectors that have been loaded into consecutive registers. I believe SVE has similar instructions. I believe SVE represents these using types wider than their normal scalable vector types and relies on the type legalizer to split them up in the backend. This works for SVE because there is only one known minimum size for all scalable vector types so the type legalizer will always split down to that minimum type.

For RISC-V vectors we already use 7 different sizes of scalable vectors to represent the ability of our instructions to operate on 2, 4, or 8 registers simultaneously. And for 1/2, 1/4, and 1/8 fractional registers.  The segment load/store instructions add an extra dimension where they can produce/consume 2, 3, or 4 pairs of registers or 2 quadruples, for examples. Following the SVE strategy would give us ambiguous types for the type legalizer.

To solve this we would like to use a struct for the segment load/stores to separate them in IR. Since clang needs an address for every variable and needs to be able to load/store them we need to support load/store/alloca.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D98169



More information about the llvm-commits mailing list