[cfe-dev] Matrix Support in Clang
John McCall via cfe-dev
cfe-dev at lists.llvm.org
Thu Mar 26 16:02:42 PDT 2020
On 26 Mar 2020, at 18:21, Florian Hahn wrote:
> Thank you very much for your comments John! Responses inline and
> I’ve also updated
>
> On Mar 25, 2020, at 20:39, John McCall <rjmccall at apple.com> wrote:
>> You should require the element type to be unqualified and then apply
>> qualifiers “outside” of the matrix type. That is, you can have a
>> const float4x4, but not a const_float4x4.
>
> Agreed, thanks! I’ve added
>
> "The element type must be unqualified and qualifiers are applied to
> the matrix type directly.”
Sounds good.
>> Why do you want to guarantee the same alignment as the element type?
>> Isn’t that going to be seriously performance-limiting for most
>> matrix types?
>>
>> If your goal is to make it easy to load / store matrices from an
>> existing buffer, I would recommend adding separate operations to do
>> that instead of (I assume) expecting users to simply cast those
>> buffers to a pointer-to-matrix type and dereference. That will also
>> allow you to use non-packed representations for matrices.
>> Furthermore, you can parameterize the operation by the
>> row/column-major-ness of the buffer and then simply use a canonical
>> representation for matrix types.
>
> The main reason was allowing users to cast between element type/matrix
> pointers to load/store matrixes from buffers. But I think it would
> indeed be better to disallow such casts and not limit ourselves to the
> element type alignment. There already are the
> builtin_matrix_column_load/builtin_matrix_column_store which can be
> used instead of going through casts. In the future, similar builtins
> could be added to load data in row-major layouts.
>
> I think initially it would be best to go with implementation defined
> alignment. What do you think? (I’ve reworded the sentence to "A
> matrix type is a *scalar type* and its alignment is implementation
> defined.”)
Yeah, making the size and alignment implementation-defined is the right
spec-ese.
>> TODO: Allow reinterpret_cast from pointer to element type. Make
>> aliasing work.
>>
>> This seems like an anti-goal. Maybe you want a reinterpret_cast
>> between matrix types with the same total storage size, though? Not
>> sure if that’s a good idea.
>
> Agreed, now that we cannot cast element type pointers to matrix
> pointer I think we should disallow it here. It should simply be enough
> to drop the TODO, right?
Yeah, that would be fine.
>> Standard Conversions
>>
>> The standard conversions are extended as follows.
>>
>> For integral promotions, floating-point promotion, integral
>> conversions, floating-point conversions, and floating-integral
>> conversions: apply the rules to the underlying type of the matrix
>> type. The resulting type is a matrix type with that underlying
>> element type. The resulting value is as follows:
>>
>> * If the original value was of matrix type, each element is converted
>> element by element.
>> * If the original value was not of matrix type, each element takes
>> the value of the original value.
>>
>> This isn’t sufficient; you need to describe what happens if the
>> element counts don’t match. I assume this is ill-formed.
>
> Yes, the dimension should match.
>
> I’ve added "If the number of rows or columns differ between the
> original and resulting type, the program is ill-formed. Otherwise the
> resulting value is as follows:"
Sounds good.
>> Arithmetic Conversions
>>
>> The usual arithmetic conversions are extended as follows.
>>
>> Insert at the start:
>>
>> * If either operand is of matrix type, apply the usual arithmetic
>> conversions using its underlying element type. The resulting type is
>> a matrix type with that underlying element type.
>>
>> This seems like a mistake, mostly because of the integer promotions.
>> You really want short_matrix + short_matrix to yield an int_matrix,
>> or -short_matrix to be an int_matrix? I would recommend that you
>> specify this as working without integer promotion, so that the result
>> of an operation two integer operations just has (1) the greater rank
>> and (2) is unsigned if there’s a signedness mismatch and the signed
>> type can’t express the full range of the unsigned type.
>
> The intention of choosing the rules for the underlying type was
> consistency with the existing behavior, but maybe it would be
> beneficial to forbid them. I think with both there might be source for
> confusion, but it might be simpler to not allow promotion.
It’s an interesting question. In a totally different language, I
would say that you shouldn’t allow mis-matched binary operations or
implicit conversions, but that explicit casts should be able to do
arbitrary element-wise conversions. That’s not really consistent with
C’s normal behavior, though. It also might be really pedantic around
e.g. scalar multiplication by a literal: would you have to write
`short4x4 * (short) 2`? On the other hand, presumably you wouldn’t
want `float4x4 * 2.0` to yield a `double4x4`.
>> You also need to specify what happens if you pass a matrix as a
>> variadic argument.
>>
> Initially they would be passed similar to ext_vector values, but we
> should spell the rules out correctly here. I’ll add a TODO.
Yeah, this is definitely a long-term question.
>> Matrix Type Element Access Operator
>>
>> An expression of the form `postfix-expression
>> [expression][expression]` where the postfix-expression is of matrix
>> type is a matrix element access expression. expression shall not be a
>> comma expression, and shall be a prvalue of unscoped enumeration or
>> integral type. Given the expression E1[E2][E3], the result is an
>> lvalue of the same type as the underlying element type of the matrix
>> that refers to the value at E2 row and E3 column in the matrix. The
>> expression E1 is sequenced before E2 and E3. The expressions E2 and
>> E3 are unsequenced.
>>
>> Note: We thought about providing an expression of the form
>> `postfix-expression [expression]` to access columns of a matrix. We
>> think that such an expression would be problematic once both column
>> and row major matrixes are supported: depending on the memory layout,
>> either accessing columns or rows can be done efficiently, but not
>> both. Instead, we propose to provide builtins to extract rows and
>> columns from a matrix. This makes the operations more explicit.
>>
>> Okay, so what happens if you do write matrix[0]?
>>
>
> That is not supported. We should probably state explicitly that single
> index operators on matrix values are ill-defined or something like
> that?
Yeah, you can say that incomplete subscripts can only be used as the
base operand of another subscript. There’s a similar rule with
member-function accesses in C++, which can only be the function operand
of a call. You can enforce that rule reliably in Clang with a
placeholder type.
John.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20200326/f9b3f237/attachment.html>
More information about the cfe-dev
mailing list