<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:#0563C1;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:#954F72;
        text-decoration:underline;}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
        {mso-style-priority:34;
        margin-top:0cm;
        margin-right:0cm;
        margin-bottom:0cm;
        margin-left:36.0pt;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri",sans-serif;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:72.0pt 90.0pt 72.0pt 90.0pt;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="#0563C1" vlink="#954F72">
<div class="WordSection1">
<p class="MsoNormal">Adding Support For Vectorcall Calling Convention<o:p></o:p></p>
<p class="MsoNormal">=====================================================<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Vectorcall Calling Convention for x64<o:p></o:p></p>
<p class="MsoNormal">----------------------------------------------------<o:p></o:p></p>
<p class="MsoNormal">The __vectorcall calling convention specifies that arguments to<o:p></o:p></p>
<p class="MsoNormal">functions are to be passed in registers, when possible. __vectorcall<o:p></o:p></p>
<p class="MsoNormal">uses more registers for arguments than __fastcall or the default x64<o:p></o:p></p>
<p class="MsoNormal">calling convention use. The __vectorcall calling convention is only<o:p></o:p></p>
<p class="MsoNormal">supported in native code on x86 and x64 processors that include<o:p></o:p></p>
<p class="MsoNormal">Streaming SIMD Extensions 2 (SSE2) and above.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">The Definition of HVA Types<o:p></o:p></p>
<p class="MsoNormal">--------------------------------------<span style="color:red"><o:p></o:p></span></p>
<p class="MsoNormal">A Homogeneous Vector Aggregate (HVA) type is a composite type of up<o:p></o:p></p>
<p class="MsoNormal">to four data members that have identical vector types. An HVA type has<o:p></o:p></p>
<p class="MsoNormal">the same alignment requirement as the vector type of its members.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">For example:<o:p></o:p></p>
<p class="MsoNormal">    typedef struct {<o:p></o:p></p>
<p class="MsoNormal">    __m256 x;<o:p></o:p></p>
<p class="MsoNormal">    __m256 y;<o:p></o:p></p>
<p class="MsoNormal">    __m256 z;<o:p></o:p></p>
<p class="MsoNormal">    } hva3; // HVA type with 3 __m256 elements<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Vectorcall Extension<o:p></o:p></p>
<p class="MsoNormal">----------------------------<o:p></o:p></p>
<p class="MsoNormal">Vectorcall extends the standard x64 calling convention while adding<o:p></o:p></p>
<p class="MsoNormal">support for HVA and vector types.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">There are four main differences:<o:p></o:p></p>
<p class="MsoNormal">-  Floating-point types are considered vector types just like __m128,<o:p></o:p></p>
<p class="MsoNormal">       __m256 and __m512. The first 6 vector typed arguments are<o:p></o:p></p>
<p class="MsoNormal">       saved in physical registers XMM0/YMM0/ZMM0 until XMM5/YMM5/ZMM5.<o:p></o:p></p>
<p class="MsoNormal">-  After vector types and integer types are allocated, HVA types are<o:p></o:p></p>
<p class="MsoNormal">       allocated, in ascending order, to unused vector registers<o:p></o:p></p>
<p class="MsoNormal">       XMM0/YMM0/ZMM0 to XMM5/YMM5/ZMM5.<o:p></o:p></p>
<p class="MsoNormal">-  Just like in the default x65 CC, Shadow space is allocated for<o:p></o:p></p>
<p class="MsoNormal">       vector/HVA types. The size is fixed to 8 bytes per argument.<o:p></o:p></p>
<p class="MsoNormal">-  HVA types are returned in XMM0/YMM0/ZMM0 to XMM3/YMM3/ZMM3 while<o:p></o:p></p>
<p class="MsoNormal">       vector types are returned in XMM0/YMM0/ZMM0 and integers in RAX<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">For more information or examples please see also:<o:p></o:p></p>
<p class="MsoNormal">https://msdn.microsoft.com/en-us/library/dn375768.aspx<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Observations<o:p></o:p></p>
<p class="MsoNormal">------------------<o:p></o:p></p>
<p class="MsoNormal">-  LLVM IR must preserve the original position of the arguments.<o:p></o:p></p>
<p class="MsoNormal">-  Since HVA structures are allocated in lower priority than vector<o:p></o:p></p>
<p class="MsoNormal">       types, the vector types should be allocated first. Hence, one<o:p></o:p></p>
<p class="MsoNormal">       pass on the argument list is not sufficient anymore, because HVA<o:p></o:p></p>
<p class="MsoNormal">       structures are allocated on a second pass.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Issues in Clang<o:p></o:p></p>
<p class="MsoNormal">--------------------<o:p></o:p></p>
<p class="MsoNormal">Structure Expansion<o:p></o:p></p>
<p class="MsoNormal">~~~~~~~~~~~~~~~~~~~<o:p></o:p></p>
<p class="MsoNormal">The current clang implementation expends HVA structures into multiple<o:p></o:p></p>
<p class="MsoNormal">vector types.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">For example:<o:p></o:p></p>
<p class="MsoNormal">C code: int __vectorcall foo(hva3 a);<o:p></o:p></p>
<p class="MsoNormal">LLVM IR Output: define x86_vectorcallcc i32 @foo(__m256 %a.0, __m256 %a.1, __m256 %a.2);
<o:p></o:p></p>
<p class="MsoNormal">*The example omits the decoration that is added to the function name<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Thus the backend can't differentiate between expended HVA structures and<o:p></o:p></p>
<p class="MsoNormal">simple vector types, and doesn't know the original position of each<o:p></o:p></p>
<p class="MsoNormal">parameter in the argument list.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">We cannot rely on debug information or updated argument names to<o:p></o:p></p>
<p class="MsoNormal">identify HVA structures.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">HVA Classification<o:p></o:p></p>
<p class="MsoNormal">~~~~~~~~~~~~~~~~~~<o:p></o:p></p>
<p class="MsoNormal">Clang should understand if each HVA should be expended. In other words,<o:p></o:p></p>
<p class="MsoNormal">the FE should know if an HVA structure should be passed by value (by<o:p></o:p></p>
<p class="MsoNormal">codegen) or passed indirect.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">The current implementation doesn’t follow the two argument list rounds<o:p></o:p></p>
<p class="MsoNormal">concept of vectorcall, in which Clang first goes over integer and vector<o:p></o:p></p>
<p class="MsoNormal">types and only after that over the HVA types. As a result the HVA<o:p></o:p></p>
<p class="MsoNormal">structures are passed incorrectly.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Proposed Solution<o:p></o:p></p>
<p class="MsoNormal">--------------------------<o:p></o:p></p>
<p class="MsoNormal">The ABI in LLVM IR must provide argument position. The information is<o:p></o:p></p>
<p class="MsoNormal">important in order to allocate the correct physical register.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">The information can be achieved by passing HVA structures by value. It<o:p></o:p></p>
<p class="MsoNormal">will replace the existing expansion of the HVA structure arguments.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">For Example:<o:p></o:p></p>
<p class="MsoNormal">Instead of: define x86_vectorcallcc i32 @foo(__m256 %a.0, __m256 %a.1, __m256 %a.2);<o:p></o:p></p>
<p class="MsoNormal">Pass the following: define x86_vectorcallcc i32 @foo(%struct.hva3 %a);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">CodeGen needs to know if the structure is an HVA.<o:p></o:p></p>
<p class="MsoNormal">There are four possible ways to solve that:<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">1. CodeGen will analyze the structures just like currently done in clang<o:p></o:p></p>
<p class="MsoNormal">   in order to identify HVA structures<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">2. CodeGen can assume that structure arguments passed by value (not<o:p></o:p></p>
<p class="MsoNormal">   expended) are HVA structures<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">3. Clang will use an existing attribute that will mark that this HVA<o:p></o:p></p>
<p class="MsoNormal">   should be passed in registers.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">4. Clang will pass a new attribute that will indicate if this is an HVA<o:p></o:p></p>
<p class="MsoNormal">   structure that should be expended and passed in register<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">I propose to use the third option.<o:p></o:p></p>
<p class="MsoNormal">The existing attribute "InReg" has similar meaning (argument should be<o:p></o:p></p>
<p class="MsoNormal">saved in register) and is defined to be target specific.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Other reasons why I prefer this option are:<o:p></o:p></p>
<p class="MsoNormal">- Avoiding code duplication between clang and codegen<o:p></o:p></p>
<p class="MsoNormal">- Avoiding making assumptions that are not necessarily true (for example<o:p></o:p></p>
<p class="MsoNormal">"long double _Complex" type that is passed by structure as well) or<o:p></o:p></p>
<p class="MsoNormal">might be violated in the future<o:p></o:p></p>
<p class="MsoNormal">- Avoiding adding new keywords that are not necessary.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">In case we encounter a structure passed by value with an InReg flag set,<o:p></o:p></p>
<p class="MsoNormal">we can surely assume that this is an HVA.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">I will be happy to get your comments or inputs on vectorcall calling convention and
<o:p></o:p></p>
<p class="MsoNormal">the suggested solution.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Thanks,<o:p></o:p></p>
<p class="MsoNormal">Oren<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<p>---------------------------------------------------------------------<br>
Intel Israel (74) Limited</p>

<p>This e-mail and any attachments may contain confidential material for<br>
the sole use of the intended recipient(s). Any review or distribution<br>
by others is strictly prohibited. If you are not the intended<br>
recipient, please contact the sender and delete all copies.</p></body>
</html>