Index: docs/ScalableVectorType.rst =================================================================== --- docs/ScalableVectorType.rst +++ docs/ScalableVectorType.rst @@ -31,12 +31,38 @@ relationship between different scalable vector types without knowing their exact length. -The runtime multiple is not expected to change during program execution for SVE, -but it is possible. The model of scalable vectors presented in this RFC assumes -that the multiple will be constant within a function but not necessarily across -functions. As suggested in the recent RISC-V rfc, a new function attribute to -inherit the multiple across function calls will allow for function calls with -vector arguments/return values and inlining/outlining optimizations. +The runtime multiple is not expected to change during program execution for SVE +or the SX Aurora architecture. For the RISC-V V extension, it may change on a +per-function basis, which precludes interprocedural optimizations. To deal +with this, a new function attribute is proposed to indicate that a function +does not inherit the runtime multiple from its callers and should not be +considered for any optimizations of that type. I leave working out the details +to those working on RVV. + +Restrictions +------------ + +Global variables cannot be scalable vector types, because they need to be a +fixed size in the appropriate section of a resulting binary. + +Scalable vector types cannot be members of StructType or ArrayType aggregates +because they are defined to be fixed size; while they could be extended as +well, that isn't required to support scalable vectors and would need more +code changes. + +Supporting scalable vectors in C structs (as in Arm's proposed ACLE for SVE) +will still be possible by having clang lower the struct to a plain pointer +with vscale-based offset calculations. + +Legalization +------------ + +To legalize a scalable vector IR type to SelectionDAG types, the same procedure +is used as for fixed-length vectors, one minor difference: + + - If the target does not support scalable vectors, the runtime multiple is + assumed to be a constant '1' and the scalable flag is dropped. Legalization + proceeds as normal after this. IR Textual Form --------------- @@ -66,16 +92,14 @@ --------------- To serialize scalable vectors to bitcode, a new boolean field is added to the -type record. If the field is not present the type will default to a fixed-length -vector type, preserving backwards compatibility. +type record if the vector is scalable, and is omitted if fixed-length. This +preserves backwards compatibility with existing bitcode. Size Queries ------------ This is a proposal for how to deal with querying the size of scalable types for -analysis of IR. While it has not been implemented in full, the general approach -works well for calculating offsets into structures with scalable types in a -modified version of ComputeValueVTs in our downstream compiler. +analysis of IR. For current IR types that have a known size, all query functions return a single integer constant. For scalable types a second integer is needed to indicate the @@ -83,50 +107,23 @@ the actual length. For primitive types, `getPrimitiveSizeInBits()` will function as it does today, -except that it will no longer return a size for vector types (it will return 0, -as it does for other derived types). The majority of calls to this function are -already for scalar rather than vector types. - -For derived types, a function `getScalableSizePairInBits()` will be added, which -returns a pair of integers (one to indicate unscaled bits, the other for bits -that need to be scaled by the runtime multiple). For backends that do not need -to deal with scalable types the existing methods will suffice, but a debug-only -assert will be added to them to ensure they aren't used on scalable types. - -Similar functionality will be added to DataLayout. - -Comparisons between sizes will use the following methods, assuming that X and -Y are non-zero integers and the form is of { unscaled, scaled }. - -{ X, 0 } { Y, 0 }: Normal unscaled comparison. - -{ 0, X } { 0, Y }: Normal comparison within a function, or across - functions that inherit vector length. Cannot be - compared across non-inheriting functions. - -{ X, 0 } > { 0, Y }: Cannot return true. - -{ X, 0 } = { 0, Y }: Cannot return true. - -{ X, 0 } < { 0, Y }: Can return true. - -{ Xu, Xs } { Yu, Ys }: Gets complicated, need to subtract common - terms and try the above comparisons; it - may not be possible to get a good answer. - -It's worth noting that we don't expect the last case (mixed scaled and -unscaled sizes) to occur. Richard Sandiford's proposed C extensions -(http://lists.llvm.org/pipermail/cfe-dev/2018-May/057830.html) explicitly -prohibits mixing fixed-size types into sizeless struct. - -I don't know if we need a 'maybe' or 'unknown' result for cases comparing scaled -vs. unscaled; I believe the gcc implementation of SVE allows for such -results, but that supports a generic polynomial length representation. - -My current intention is to rely on functions that clone or copy values to -check whether they are being used to copy scalable vectors across function -boundaries without the inherit vlen attribute and raise an error there instead -of requiring passing the Function a type size is from for each comparison. If -there's a strong preference for moving the check to the size comparison function -let me know; I will be starting work on patches for this later in the year if -there's no major problems with the idea. +except that if the type is a VectorType marked as Scalable, it will assert. + +A new function `getScalableSizeInBits()` will be added, which returns a struct +containing an integer to represent the minimum size and a boolean flag to +indicate that the minimum size is scaled by the runtime multiple. For backends +that do not need to deal with scalable types the existing methods will suffice, +but an assert will be added to them to ensure they aren't used on scalable types. +This will reduce the number of code changes required. + +Similar functionality will be added to DataLayout, and the struct definition +will be shared between them. + +Comparisons between unscaled-only or scaled-only sizes will work as expected, +and convenience operators will be provided. For now, if unscaled sizes are +compared against scaled sizes, the comparison operator will assert. This +restriction may be relaxed in future if a valid use case is found. + +Comparisons between scaled sizes with different runtime multiples is invalid, +and this proposal relies on interprocedural optimizations being disallowed +in such cases (RVV).