<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Ping.<div class=""><br class=""></div><div class="">I’ve also put up 2 patches on Phabricator, to illustrate how the implementation could look like:</div><div class=""><br class=""></div><div class="">1. <span style="color: rgba(0, 0, 0, 0.85098); font-family: "Helvetica Neue";" class="">[Matrix] Add matrix type to Clang (WIP). </span><a href="https://reviews.llvm.org/D72281" class="">https://reviews.llvm.org/D72281</a></div><div class="">2. <span style="color: rgba(0, 0, 0, 0.85098); font-family: "Helvetica Neue";" class="">[Matrix] Add __builtin_matrix_insert to Clang (WIP). </span><a href="https://reviews.llvm.org/D72283" class="">https://reviews.llvm.org/D72283</a></div><div class=""><br class=""><div><br class=""></div><div>Cheers,</div><div>Florian</div><div><br class=""><blockquote type="cite" class=""><div class="">On Dec 20, 2019, at 18:31, Florian Hahn via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" class="">cfe-dev@lists.llvm.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><span class=""><span class="" style="caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Hello,</span></span></div><span class=""><span class="" style="caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><div class=""><span class=""><span class="" style="caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class=""></span></span></div>This is a Clang-focused follow up to the original proposal on llvm-dev (</span><a href="http://lists.llvm.org/pipermail/llvm-dev/2019-October/136240.html" class="" style="background-color: rgb(255, 255, 255);">http://lists.llvm.org/pipermail/llvm-dev/2019-October/136240.html</a><span class="" style="caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">). On the LLVM side, we recently landed the first commit adding matrix intrinsics as proposed.</span><br class="" style="caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">On the Clang side, we would like to propose adding support for matrix math operations to Clang. This includes adding a new matrix type (similar to ext_vector_type) and a set of builtins to operate on values of the matrix type.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span textcolor="#172b4d" class="" style="background-color: rgb(255, 255, 255);">Our main motivation for the matrix support in Clang is to give users a way to</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"></span><div class="" data-section-style="5" style="margin: 12px 0px; caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><ul id="GXO9CAfukUr" class="" style="line-height: 20px; padding: 0px 0px 0px 40px;"><li id="GXO9CAroPnP" class="" value="1" style="margin-bottom: 0.4em;"><span class=""><span textcolor="#172b4d" class="">Guarantee generation of high-quality code for matrix operations. For isolated operations, we can guarantee vector code generation suitable for the target. For trees of operations, the proposed value type helps with eliminating temporary loads & stores.</span> <br class=""></span></li><li id="GXO9CALHQyJ" class="" style="margin-bottom: 0.4em;"><span class=""><span textcolor="#172b4d" class="">Make use of specialized matrix ISA extensions, like the new matrix instructions in ARM v8.6 or various proprietary matrix accelerators, in their C/C++ code.</span> <br class=""></span></li><li id="GXO9CAsv87p" class="" style="margin-bottom: 0.4em;"><span class=""><span textcolor="#172b4d" class="">Move optimizations from matrix wrapper libraries into the compiler. </span><span textcolor="#172b4d" class="">We use it internally to simplify an Eigen-style matrix library, by relying on LLVM for generating tiled & fused loops for matrix operations.</span> <br class=""></span></li></ul></div><span class=""><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">The rest of this RFC is structured as follows: First we propose a draft specification for the matrix type and accompanying builtins. Next we show an example of how matrix operations will be lowered by Clang, followed by a discussion of the contributing criteria for new extensions.  We wrap up the RFC by discussing possible extensions to the matrix type.</span></span><br class="" style="caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); font-size: 16px; background-color: rgb(255, 255, 255);"><h2 id="GXO9CAMHcpM" class="" style="margin: 1.25em 0px 0.75em; line-height: 22px; caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><font size="3" class="">Draft Specification</font></h2><h3 id="GXO9CAQnvex" class="" style="margin: 1.25em 0px 0.75em; line-height: 16px; caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><font size="3" class="">Matrix TYPE Attribute</font></h3><span class=""><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">The </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">attribute-token</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">matrix_type</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> is used to declare a matrix type. It shall appear at most once in each </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">attribute-list</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">. The attribute shall only appertain to a </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">typedef-name</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> of a typedef of a non-volatile type that is a </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">signed integer type</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">, an </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">unsigned integer type</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">, or a </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">floating-point type</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">. An </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">attribute-argument-clause</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> must be present and it shall have the form:</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">(<i class="">constant-expression</i>, <i class="">constant-expression</i>)</code><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Both </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">constant-expression</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">s 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.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">An </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">attribute</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> of the form </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">matrix_type(</code><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">R</code></i><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">, </code><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">C</code></i><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">)</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> forms a matrix type with an element type of the cv-qualified type the attribute appertains to and </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">R</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> rows and </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">C</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> columns.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">If a declaration of a </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">typedef-name</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> has a </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">matrix_type</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> attribute, then all declaration of that </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">typedef-name</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> shall have a </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">matrix_type</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> attribute with the same element type, number of rows, and number of columns.</span></span><div class=""><span class="" style="font-size: 14px;"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"></span><h3 id="GXO9CArLQor" class="" style="margin: 1.25em 0px 0.75em; line-height: 16px; caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><font size="3" class="">Matrix Type</font></h3><span class=""><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">A matrix type has an underlying </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">element type</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">, 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 </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">rows * columns</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> values of the </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">element type</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> laid out in column-major order without padding in a way compatible with an array of at least that many elements of the underlying </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">element type</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">A matrix type is a </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">scalar type </i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">with the same alignment as its underlying element type, but objects of matrix type are not usable in constant expressions.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">TODO: Allow reinterpret_cast from pointer to element type. Make aliasing work.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Future Work: Initialization syntax.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Future Work: Access syntax. </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">m[col][row]</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Future Work: Conversions between matrix types with const qualified and unqualified element types.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Future Work: Conversions between matrix types with different element types.</span></span></div><div class=""><span class="" style="font-size: 14px;"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"></span><h3 id="GXO9CABJGdF" class="" style="margin: 1.25em 0px 0.75em; line-height: 16px; caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><font size="3" class="">Matrix Type builtin Operations</font></h3><span class=""><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Each matrix type supports a collection of builtin expressions that look like function calls but do not form an overload set. Here they are described as function declarations with rules for how to construct the argument list types and return type and the library description elements from [library.description.structure.specifications]/3 in the C++ standard. </span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Definitions:</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"></span><div class="" data-section-style="5" style="margin: 12px 0px; caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><ul id="GXO9CA079ga" class="" style="line-height: 20px; padding: 0px 0px 0px 40px;"><li id="GXO9CAXp3Qu" class="" value="1" style="margin-bottom: 0.4em;"><span class=""><i class="">M, M1, M2, M3</i> - Matrix types <br class=""></span></li><li id="GXO9CANvXAk" class="" style="margin-bottom: 0.4em;"><span class=""><i class="">T</i> - Element type <br class=""></span></li><li id="GXO9CApPDi5" class="" style="margin-bottom: 0.4em;"><span class="">row, col - Row and column arguments respectively. </span></li></ul></div><span class=""><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">All operations on matrix types match the behavior of the underlying element type with respect to signed overflows.</span></span><div class=""><span class="" style="font-size: 14px;"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"></span><br class="" style="caret-color: rgb(51, 51, 51); font-size: 16px; background-color: rgb(255, 255, 255);"><font size="3" class=""><b class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Element Operations</b><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"></font><br class="" style="caret-color: rgb(51, 51, 51); font-size: 16px; background-color: rgb(255, 255, 255);"><span class=""><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="font-size: 14px;">P</span>reconditions: </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">row</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> and </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">col</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> are in the ranges [0, rows in </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">M</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">) and [0, columns in </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">M</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">) respectively.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);"><i class="">M</i> __builtin_matrix_insert(<i class="">M</i> matrix, int row, int col, <i class="">T</i> elt)</code><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Remarks: The return type and the type </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">T</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> are inferred from the cv-unqualified type of the </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">matrix</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> argument and its cv-unqualified </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">element type</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> respectively.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Returns: a copy of </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">matrix</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> with the element at the specified row and column set to </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">elt</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);"><i class="">T</i> __builtin_matrix_extract(<i class="">M</i> matrix, int row, int col)</code><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">The return type is inferred from the cv-unqualified type of the </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">matrix</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> argument’s </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">element type</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Returns: a copy of the element at the specified row and column.</span></span><div class=""><span class=""><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"></span><br class="" style="caret-color: rgb(51, 51, 51); font-size: 16px; background-color: rgb(255, 255, 255);"><font size="3" class=""><b class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Simple Binary Operations</b><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"></font><br class="" style="caret-color: rgb(51, 51, 51); font-size: 16px; background-color: rgb(255, 255, 255);"><span class=""><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">For the following binary operations </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">matrix1</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> and </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">matrix2</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> shall be matrix values of the same cv-unqualified type, and the return type is the cv-unqualified version of that type. </span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);"><i class="">M</i> __builtin_matrix_add(<i class="">M</i> matrix1, <i class="">M</i> matrix2)</code><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Returns: A matrix </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">Res</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> equivalent to the code below, where </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">col</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> refers to the number of columns of M, </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">row</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> to the number of rows of M and </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">EltTy</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> to the element type of M.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"></span><pre id="GXO9CAZZ7rw" class="" style="background-color: rgb(242, 242, 242); line-height: 20px; text-shadow: white 0px 1px; padding: 5px 5px 5px 30px; white-space: nowrap; position: relative; margin-top: 1em; margin-bottom: 1em; caret-color: rgb(51, 51, 51);"><font face="Helvetica" class=""><i class="">M</i> Res;<br class="">for (int C = 0; C < col; ++C) {<br class="">  for (int R = 0; R < row; ++R) {<br class="">    EltTy Elt = __builtin_matrix_extract(matrix1, R, C) + <br class="">                     __builtin_matrix_extract(matrix2, R, C)<br class="">    Res = __builtin_matrix_insert(Res, R, C, Elt);<br class="">  }<br class="">}</font></pre><span class=""><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);"><i class="">M</i> __builtin_matrix_sub(<i class="">M</i> matrix1, <i class="">M</i> matrix2)</code><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Returns: A matrix </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">Res</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> equivalent to the code below, where </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">col</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> refers to the number of columns of M, </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">row</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> to the number of rows of M and </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">EltTy</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> to the element type of M.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"></span><pre id="GXO9CApF8IV" class="" style="background-color: rgb(242, 242, 242); line-height: 20px; text-shadow: white 0px 1px; padding: 5px 5px 5px 30px; white-space: nowrap; position: relative; margin-top: 1em; margin-bottom: 1em; caret-color: rgb(51, 51, 51);"><font face="Helvetica" class=""><i class="">M</i> Res;<br class="">for (int C = 0; C < col; ++C) {<br class="">  for (int R = 0; R < row; ++R) {<br class="">    EltTy Elt = __builtin_matrix_extract(matrix1, R, C) - <br class="">                     __builtin_matrix_extract(matrix2, R, C)<br class="">    Res = __builtin_matrix_insert(Res, R, C, Elt);<br class="">  }<br class="">}</font></pre><div class=""><br class=""></div><div class=""><br class=""></div><b class="" style="caret-color: rgb(51, 51, 51); font-size: 16px; background-color: rgb(255, 255, 255);">Other Operations</b><br class="" style="caret-color: rgb(51, 51, 51); font-size: 16px; background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); font-size: 16px; background-color: rgb(255, 255, 255);"><span class=""><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);"><i class="">M3</i> __builtin_matrix_multiply(<i class="">M1</i> matrix1, <i class="">M2</i> matrix2)</code><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Mandates: </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">M1</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> and </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">M2</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> shall be matrix types with the same cv-unqualified element type and </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">M1</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">’s number of columns matching </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">M2</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">’s number of row.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Remarks: The return type is a cv-unqualified matrix type with the same element type as </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">M1</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> and </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">M2</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> if both </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">M1</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> and </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">M2</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">’s element type is const, or the cv-unqualified element type otherwise, and with the same number of rows as </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">M1</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> and the same number of columns as </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">M2</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Returns: A matrix </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">Res</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> equivalent to the code below, where </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">col</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> refers to the number of columns of M, </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">row</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> to the number of rows of M, </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">EltTy</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> to the element type of M and </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">inner</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> refers to the number of columns of M1.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"></span><pre id="GXO9CAL8VSH" class="" style="background-color: rgb(242, 242, 242); line-height: 20px; text-shadow: white 0px 1px; padding: 5px 5px 5px 30px; white-space: nowrap; position: relative; margin-top: 1em; margin-bottom: 1em; caret-color: rgb(51, 51, 51);"><font face="Helvetica" class=""><i class="">M</i> Res;<br class="">for (int C = 0; C < col; ++C) {<br class="">  for (int R = 0; R < row; ++R) {<br class="">    EltTy Elt = 0;<br class="">    for (int K = 0; K < inner; ++K) {<br class="">      Elt += __builtin_matrix_extract(matrix1, R, K) * <br class="">                 __builtin_matrix_extract(matrix2, K, C)<br class="">  }<br class="">  Res = __builtin_matrix_insert(Res, R, C, Elt);<br class="">}</font></pre><span class=""><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Remark: With respect to rounding errors, the operation preserves the behavior of the separate multiply and add operations by default. We propose to provide a Clang option to override this behavior and allow contraction of those operations (e.g. -ffp-contract=matrix).</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);"><i class="">M2</i> __builtin_matrix_transpose(<i class="">M1</i> matrix)</code><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Remarks: The return type is a cv-unqualified matrix type that has the same element type as </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">M1</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> and has the the same number of rows as </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">M1</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> has columns and the same number of columns as </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">M1</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> has rows.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Returns: A matrix </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">Res</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> equivalent to the code below, where </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">col</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> refers to the number of columns of M, and </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">row</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> to the number of rows of M.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"></span><pre id="GXO9CAkn8rZ" class="" style="background-color: rgb(242, 242, 242); line-height: 20px; text-shadow: white 0px 1px; padding: 5px 5px 5px 30px; white-space: nowrap; position: relative; margin-top: 1em; margin-bottom: 1em; caret-color: rgb(51, 51, 51);"><font face="Helvetica" class=""><i class="">M</i> Res;<br class="">for (int C = 0; C < col; ++C) {<br class="">  for (int R = 0; R < row; ++R) {<br class="">    EltTy Elt = __builtin_matrix_extract(matrix, R, C);<br class="">    Res = __builtin_matrix_insert(Res, C, R, Elt);<br class="">  }<br class="">}</font></pre><span class=""><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">M</code></i><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);"> __builtin_matrix_column_load(</code><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">T</code></i><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);"> *ptr, int row, int col, int stride)</code><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Mandates: </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">row</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> and </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">col</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> shall be integral constants greater than 0. </span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Preconditions: </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">stride >= </code><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">row</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Remarks: The return type is a cv-unqualified matrix type with an element type of the cv-unqualified version of </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">T</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> and a number of rows and columns equal to </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">row</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> and </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">col</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> respectively.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Returns: A matrix </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">Res</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> equivalent to:</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"></span><pre id="GXO9CAYgF6K" class="" style="background-color: rgb(242, 242, 242); line-height: 20px; text-shadow: white 0px 1px; padding: 5px 5px 5px 30px; white-space: nowrap; position: relative; margin-top: 1em; margin-bottom: 1em; caret-color: rgb(51, 51, 51);"><font face="Helvetica" class=""><i class="">M</i> Res;<br class="">for (int C = 0; C < col; ++C) {<br class="">  for (int R = 0; R < row; ++K)<br class="">    Res = __builtin_matrix_insert(Res, R, C, ptr[R]);<br class="">  ptr += stride<br class="">}</font></pre><span class=""><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><font face="Helvetica" class=""><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">void __builtin_matrix_column_store(<i class="">M</i> matrix, <i class="">T</i> *ptr, int stride)</code><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"></font><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Preconditions: </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">stride</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> is greater than or equal to the number of rows in </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">M</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Effects: Equivalent to:</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"></span><pre id="GXO9CA0f2i5" class="" style="background-color: rgb(242, 242, 242); line-height: 20px; text-shadow: white 0px 1px; padding: 5px 5px 5px 30px; white-space: nowrap; position: relative; margin-top: 1em; margin-bottom: 1em; caret-color: rgb(51, 51, 51);"><font face="Helvetica" class="">for (int C = 0; C < <i class="">columns </i><i class="">in</i><i class=""> M</i>; ++C) {<br class="">  for (int R = 0; R < <i class="">rows </i><i class="">in M</i>; ++K)<br class="">    ptr[R] = __builtin_matrix_extract(matrix, R, C);<br class="">  ptr += stride<br class="">}</font></pre><span class=""><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Remarks: The type </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">T</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> is the const-unqualified version of the </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">matrix</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> argument’s </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">element type</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);"><i class="">M</i> __builtin_matrix_scalar_multiply(<i class="">M</i> matrix, <i class="">T</i> scalar)</code><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Returns: A matrix </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">Res</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> equivalent to the code below, where </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">col</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> refers to the number of columns of M, and </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">row</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> to the number of rows of M.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"></span><pre id="GXO9CArYmVv" class="" style="background-color: rgb(242, 242, 242); line-height: 20px; text-shadow: white 0px 1px; padding: 5px 5px 5px 30px; white-space: nowrap; position: relative; margin-top: 1em; margin-bottom: 1em; caret-color: rgb(51, 51, 51);"><font face="Helvetica" class=""><i class="">M</i> Res;<br class="">for (int C = 0; C < col; ++C) {<br class="">  for (int R = 0; R < row; ++R) {<br class="">    EltTy Elt = __builtin_matrix_extract(matrix, R, C) * scalar;<br class="">    Res = __builtin_matrix_insert(Res, R, C, Elt);<br class="">  }<br class="">}</font></pre><span class=""><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Remarks: The return type and the type </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">T</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> are the cv-unqualified type of the </span><code class="" style="background-color: rgb(242, 242, 242); padding: 1px; margin: 0px -1px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; caret-color: rgb(51, 51, 51);">matrix</code><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> argument and its cv-unqualified </span><i class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">element type</i><span class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"> respectively.</span></span><br class="" style="caret-color: rgb(51, 51, 51); font-size: 16px; background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); font-size: 16px; background-color: rgb(255, 255, 255);"><h2 id="GXO9CAuR9KH" class="" style="margin: 1.25em 0px 0.75em; line-height: 22px; caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><font size="3" class="">Example </font></h2><span class=""><span textcolor="#172b4d" class="" style="background-color: rgb(255, 255, 255);">This code performs a matrix-multiply of two 4x4 matrices followed by an matrix addition:</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"></span><pre id="GXO9CAX0xX9" class="" style="background-color: rgb(242, 242, 242); line-height: 20px; text-shadow: white 0px 1px; padding: 5px 5px 5px 30px; white-space: nowrap; position: relative; margin-top: 1em; margin-bottom: 1em; caret-color: rgb(51, 51, 51);"><font face="Helvetica" class="">typedef float m4x4_t __attribute__((matrix_type(4, 4)));<br class="">void f(m4x4_t *a, m4x4_t *b, m4x4_t *c, m4x4_t *r) {<br class="">  *r = __builtin_matrix_add(__builtin_matrix_multiply(*a, *b), *c);<br class="">}</font></pre><span class=""><span textcolor="#172b4d" class="" style="background-color: rgb(255, 255, 255);">This will get lowered by Clang to the LLVM IR below. In our current implementation, we use LLVM’s array type as storage type for the matrix data. Before accessing the data, we cast the array to a vector type. This allows us to use the element width as alignment, without running into issues with LLVM’s large default alignment for vector types, which is problematic in structs.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"></span><pre id="GXO9CAhuj3Y" class="" style="background-color: rgb(242, 242, 242); line-height: 20px; text-shadow: white 0px 1px; padding: 5px 5px 5px 30px; white-space: nowrap; position: relative; margin-top: 1em; margin-bottom: 1em; caret-color: rgb(51, 51, 51);"><font face="Helvetica" class="">define void @f([16 x float]* %a, [16 x float]* %b, [16 x float]* %c, [16 x float]* %r) #0 {<br class="">entry:<br class="">  %a.addr = alloca [16 x float]*, align 8<br class="">  %b.addr = alloca [16 x float]*, align 8<br class="">  %c.addr = alloca [16 x float]*, align 8<br class="">  %r.addr = alloca [16 x float]*, align 8<br class="">  store [16 x float]* %a, [16 x float]** %a.addr, align 8<br class="">  store [16 x float]* %b, [16 x float]** %b.addr, align 8<br class="">  store [16 x float]* %c, [16 x float]** %c.addr, align 8<br class="">  store [16 x float]* %r, [16 x float]** %r.addr, align 8<br class="">  %0 = load [16 x float]*, [16 x float]** %a.addr, align 8<br class="">  %1 = bitcast [16 x float]* %0 to <16 x float>*<br class="">  %2 = load <16 x float>, <16 x float>* %1, align 4<br class="">  %3 = load [16 x float]*, [16 x float]** %b.addr, align 8<br class="">  %4 = bitcast [16 x float]* %3 to <16 x float>*<br class="">  %5 = load <16 x float>, <16 x float>* %4, align 4<br class="">  %6 = call <16 x float> @llvm.matrix.multiply.v16f32.v16f32.v16f32(<16 x float> %2, <16 x float> %5, i32 4, i32 4, i32 4)<br class="">  %7 = load [16 x float]*, [16 x float]** %c.addr, align 8<br class="">  %8 = bitcast [16 x float]* %7 to <16 x float>*<br class="">  %9 = load <16 x float>, <16 x float>* %8, align 4<br class="">  %10 = fadd <16 x float> %6, %9<br class="">  %11 = load [16 x float]*, [16 x float]** %r.addr, align 8<br class="">  %12 = bitcast [16 x float]* %11 to <16 x float>*<br class="">  store <16 x float> %10, <16 x float>* %12, align 4<br class="">  ret void<br class="">}<br class="">declare <16 x float> @llvm.matrix.multiply.v16f32.v16f32.v16f32(<16 x float>, <16 x float>, i32 immarg, i32 immarg, i32 immarg)</font></pre><br class="" style="caret-color: rgb(51, 51, 51); font-size: 16px; background-color: rgb(255, 255, 255);"><h2 id="GXO9CAahOFU" class="" style="margin: 1.25em 0px 0.75em; line-height: 22px; caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><font size="3" class="">Contributing Criteria</font></h2><div class=""><font class=""><i class="">Evidence of a significant user community: This is based on a number of factors, including an existing user community, the perceived likelihood that users would adopt such a feature if it were available, and any secondary effects that come from, e.g., a library adopting the feature and providing benefits to its users.<br class=""></i>Currently this is part of one of our compiler toolchains and used on a few large internal codebases. The matrix type can be used by matrix libraries like Eigen, to offload some of the optimization responsibility from the library to the compiler. It would also be suitable target for implementing a standard matrix library. It also provides functionality similar to various libraries for matrix math on small matrixes, like <a href="https://developer.apple.com/documentation/accelerate/working_with_matrices" class="">https://developer.apple.com/documentation/accelerate/working_with_matrices</a>, with more flexibility (supports any combination of input dimensions).<br class=""><br class=""><i class="">A specific need to reside within the Clang tree: There are some extensions that would be better expressed as a separate tool, and should remain as separate tools even if they end up being hosted as part of the LLVM umbrella project.<br class=""></i>We want to expose this feature at the C/C++ level. For that, it needs to be part of Clang.<br class=""><br class=""><i class="">A specification: The specification must be sufficient to understand the design of the feature as well as interpret the meaning of specific examples. The specification should be detailed enough that another compiler vendor could implement the feature.</i><br class="">We currently have the design above and will work on a more comprehensive spec.<br class=""><br class=""><i class="">Representation within the appropriate governing organization: For extensions to a language governed by a standards committee (C, C++, OpenCL), the extension itself must have an active proposal and proponent within that committee and have a reasonable chance of acceptance. Clang should drive the standard, not diverge from it. This criterion does not apply to all extensions, since some extensions fall outside of the realm of the standards bodies.<br class=""></i>We think this extension would fall outside of the realm of the standards bodies. It is an implementation detail used to implement matrix math libraries and such, much like the vector extensions are an implementation detail for SIMD libraries.<br class=""><br class=""><i class="">A long-term support plan: increasingly large or complex extensions to Clang need matching commitments to supporting them over time, including improving their implementation and specification as Clang evolves. The capacity of the contributor to make that commitment is as important as the commitment itself.<br class=""></i>We are using this internally and adding this feature to Clang upstream means we intend to support it as part of our ongoing Clang work.<br class=""><br class=""><i class="">A high-quality implementation: The implementation must fit well into Clang's architecture, follow LLVM's coding conventions, and meet Clang's quality standards, including diagnostics and complete AST representations. This is particularly important for language extensions, because users will learn how those extensions work through the behavior of the compiler.<br class=""></i>Will we provide a series of patches to implement the extension soon and look forward to any feedback to make sure the patches meet the quality requirement.<br class=""><br class=""><i class="">A test suite: Extensive testing is crucial to ensure that the language extension is not broken by ongoing maintenance in Clang. The test suite should be complete enough that another compiler vendor could conceivably validate their implementation of the feature against it</i><br class="">We will provide this as part of Clang’s unit tests and test-suite.<br class=""></font></div><div class="" data-section-style="6" style="margin: 12px 0px; counter-reset: indent0 0 indent1 0 indent2 0 indent3 0 indent4 0 indent5 0 indent6 0 indent7 0 indent8 0; caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); font-size: 16px; background-color: rgb(255, 255, 255);"><ul id="GXO9CA9gVip" class="" style="line-height: 20px; padding: 0px 0px 0px 40px; list-style-type: none !important;"></ul></div><h2 id="GXO9CAsn5Fz" class="" style="margin: 1.25em 0px 0.75em; line-height: 22px; caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><font size="3" class="">Extensions</font></h2><span class=""><span textcolor="#172b4d" class="" style="background-color: rgb(255, 255, 255);">Initially we want to focus on 2D matrixes without padding in column-major layout as a concrete use case. This is similar to the defaults for the Matrix type in Eigen, for example. But our proposed type can be extended naturally to</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"></span><div class="" data-section-style="5" style="margin: 12px 0px; caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><ul id="GXO9CAqgpTh" class="" style="line-height: 20px; padding: 0px 0px 0px 40px;"><li id="GXO9CASh87e" class="" value="1" style="margin-bottom: 0.4em;"><span class=""><span textcolor="#172b4d" class="">Support N (known constant) dimensions by turning matrix_type attribute into a variadic attribute.</span> <br class=""></span></li><li id="GXO9CAEVc38" class="" style="margin-bottom: 0.4em;"><span class=""><span textcolor="#172b4d" class="">Support column/row-wise padding, by adding a column_padding clause to the attribute.<br class="">Dealing with the padding could be exclusively handled on the frontend side, by emitting additional shufflevector instructions to extract the data. If there is a desire to exploit the padding more on the LLVM side, we can add a set of intrinsics for that.</span> <br class=""></span></li><li id="GXO9CA8mj8h" class="" style="margin-bottom: 0.4em;"><span class=""><span textcolor="#172b4d" class="">Support row & column major layouts, by adding a layout clause to the attribute.<br class="">Again, this naively could be handled while lowering to LLVM IR in Clang using shufflevector to produce flattened vectors with the required layout. For better optimisations, the LLVM intrinsics relying on shape/layout information can be extended to take the layout as additional argument. Through propagating the layout information similar to the dimensions, we should be able to optimise the points where we need to transform the layout of the underlying matrixes.</span> <br class=""></span></li></ul></div><span class=""><span textcolor="#172b4d" class="" style="background-color: rgb(255, 255, 255);">In all cases, we require known integer constants as dimensions and we do not plan to support dynamic dimensions for now, as the main optimization potential comes from the fact that we know the dimensions. Supporting dynamic dimensions should be fairly straight forward, but means we lose the ability to type check matrix expressions at compile time and we also have to rely on dynamic dimension during code generation.</span><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);"><br class="" style="caret-color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">Cheers,</span></div><div class=""><span class=""> Florian</span></div></div></div></div>_______________________________________________<br class="">cfe-dev mailing list<br class=""><a href="mailto:cfe-dev@lists.llvm.org" class="">cfe-dev@lists.llvm.org</a><br class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev<br class=""></div></blockquote></div><br class=""></div></body></html>