[cfe-dev] Matrix Support in Clang

Florian Hahn via cfe-dev cfe-dev at lists.llvm.org
Thu Mar 26 15:21:40 PDT 2020


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:

[snip]
> Draft Specification
> 
> Matrix Type Attribute
> 
> The attribute-token matrix_type is used to declare a matrix type. It shall appear at most once in each attribute-list. The attribute shall only appertain to a typedef-name of a typedef of a non-volatile type that is a signed integer type, an unsigned integer type, or a floating-point type.
> 
> 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.”

> An attribute-argument-clause must be present and it shall have the form:
> 
> (constant-expression, constant-expression)
> 
> Both constant-expressions shall be a positive non-zero integral constant expressions. The maximum of the product of the constants is implementation defined. If that implementation defined limit is exceeded, the program is ill-formed.
> 
> An attribute of the form matrix_type(R, C) forms a matrix type with an element type of the cv-qualified type the attribute appertains to and R rows and C columns.
> 
> If a declaration of a typedef-name has a matrix_type attribute, then all declaration of that typedef-name shall have a matrix_type attribute with the same element type, number of rows, and number of columns.
> 
> 
> Matrix Type
> 
> A matrix type has an underlying element type, a constant number of rows, and a constant number of columns. Matrix types with the same element type, rows, and columns are the same type. A value of a matrix type contains rows * columns values of the element type laid out in column-major order without padding in a way compatible with an array of at least that many elements of the underlying element type.
> 
> A matrix type is a scalar type with the same alignment as its underlying element type,
> 
> 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.”)
> but objects of matrix type are not usable in constant expressions.
> 
> This is contrary to the prevailing language directions of both C and C++. It might be an acceptable temporary language restriction, but it’s not something you should specify.
> 
Sounds good, let’s drop this restriction.

> 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?

> TODO: Does it make sense to allow M::element_type, M::rows, and M::columns where M is a matrix type? We don’t support this anywhere else, but it’s convenient. The alternative is using template deduction to extract this information.
> 
> C will need a spelling for these, too.
> 
> 
I’ve added that to the TODO.
> Future Work: Initialization syntax.
> Future Work: Conversions between matrix types with const qualified and unqualified element types.
> 
> Should be defined away by handling qualifiers correctly, per above.
> 

Thanks, I’ll drop this.

> 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:"

> 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.
> 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.
> 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?

Cheers,
Florian

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20200326/bfd68b25/attachment-0001.html>


More information about the cfe-dev mailing list