<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-1252">
  </head>
  <body>
    <p><br>
    </p>
    <div class="moz-cite-prefix">On 8/19/20 2:21 AM, Luo, Yuanke wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:SN6PR11MB3135D0A1B2CCC8110DDB453F9A5D0@SN6PR11MB3135.namprd11.prod.outlook.com">
      
      <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:DengXian;
        panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:"\@DengXian";
        panose-1:2 1 6 0 3 1 1 1 1 1;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin-top:0in;
        margin-right:0in;
        margin-bottom:8.0pt;
        margin-left:0in;
        line-height:105%;
        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:purple;
        text-decoration:underline;}
pre
        {mso-style-priority:99;
        mso-style-link:"HTML Preformatted Char";
        margin:0in;
        margin-bottom:.0001pt;
        font-size:10.0pt;
        font-family:"Courier New";}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
        {mso-style-priority:34;
        margin-top:0in;
        margin-right:0in;
        margin-bottom:8.0pt;
        margin-left:0in;
        text-indent:21.0pt;
        line-height:105%;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
p.msonormal0, li.msonormal0, div.msonormal0
        {mso-style-name:msonormal;
        mso-margin-top-alt:auto;
        margin-right:0in;
        mso-margin-bottom-alt:auto;
        margin-left:0in;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
span.HTMLPreformattedChar
        {mso-style-name:"HTML Preformatted Char";
        mso-style-priority:99;
        mso-style-link:"HTML Preformatted";
        font-family:"Courier New";}
span.EmailStyle22
        {mso-style-type:personal;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
span.EmailStyle23
        {mso-style-type:personal-reply;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        text-indent:-9.0pt;}
ol
        {margin-bottom:0in;}
ul
        {margin-bottom:0in;}</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]-->
      <div class="WordSection1">
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">Hi Hal,<o:p></o:p></p>
        <p class="MsoNormal">There is 3 aspect to be solved. <o:p></o:p></p>
        <p class="MsoListParagraph"
          style="margin-left:.5in;text-indent:-.25in;mso-list:l1 level1
          lfo3">
          <!--[if !supportLists]--><span style="mso-list:Ignore">1.<span
              style="font:7.0pt "Times New Roman"">      
            </span></span><!--[endif]-->The HW support max shape 16x16,
          so there are many register classes from 1x1 to 16x16. We need
          256 register classes.
          <o:p></o:p></p>
        <p class="MsoListParagraph"
          style="margin-left:.5in;text-indent:-.25in;mso-list:l1 level1
          lfo3">
          <!--[if !supportLists]--><span style="mso-list:Ignore">2.<span
              style="font:7.0pt "Times New Roman"">      
            </span></span><!--[endif]-->We want to support variable
          shape, so compiler don’t know what register class to fit tile
          shape as it is only known in runtime.<o:p></o:p></p>
        <p class="MsoListParagraph"
          style="margin-left:.5in;text-indent:-.25in;mso-list:l1 level1
          lfo3">
          <!--[if !supportLists]--><span style="mso-list:Ignore">3.<span
              style="font:7.0pt "Times New Roman"">      
            </span></span><!--[endif]-->The tile configure is to
          configure physical tile register, so we need to allocate
          register and then we know the shape of each physical tile
          register and configure the tile register.<o:p></o:p></p>
        <p class="MsoNormal">I think your suggestion is helpful to
          reduce the complexity if we only support fixed (constant) tile
          shape.<o:p></o:p></p>
        <p class="MsoNormal">-Yuanke</p>
      </div>
    </blockquote>
    <p><br>
    </p>
    <p>Thanks, Yuanke.</p>
    <p>It's not clear to me that having 256 register classes is, in
      itself, a problem. Is it?</p>
    <p>What does it mean to support variable-shape tiles in this
      context? Do you do something other than conservatively assume that
      they are 16x16 for register-allocation purposes?</p>
    <p> -Hal<br>
    </p>
    <p><br>
    </p>
    <blockquote type="cite"
cite="mid:SN6PR11MB3135D0A1B2CCC8110DDB453F9A5D0@SN6PR11MB3135.namprd11.prod.outlook.com">
      <div class="WordSection1">
        <p class="MsoNormal"><o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <div>
          <div style="border:none;border-top:solid #E1E1E1
            1.0pt;padding:3.0pt 0in 0in 0in">
            <p class="MsoNormal"
              style="margin-bottom:0in;margin-bottom:.0001pt;line-height:normal">
              <b>From:</b> Hal Finkel <a class="moz-txt-link-rfc2396E" href="mailto:hfinkel@anl.gov"><hfinkel@anl.gov></a> <br>
              <b>Sent:</b> Wednesday, August 19, 2020 8:20 AM<br>
              <b>To:</b> Kaylor, Andrew <a class="moz-txt-link-rfc2396E" href="mailto:andrew.kaylor@intel.com"><andrew.kaylor@intel.com></a>;
              Philip Reames <a class="moz-txt-link-rfc2396E" href="mailto:listmail@philipreames.com"><listmail@philipreames.com></a>; Luo,
              Yuanke <a class="moz-txt-link-rfc2396E" href="mailto:yuanke.luo@intel.com"><yuanke.luo@intel.com></a>;
              <a class="moz-txt-link-abbreviated" href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>; <a class="moz-txt-link-abbreviated" href="mailto:florian_hahn@apple.com">florian_hahn@apple.com</a>; Topper,
              Craig <a class="moz-txt-link-rfc2396E" href="mailto:craig.topper@intel.com"><craig.topper@intel.com></a>; Lu, Hongjiu
              <a class="moz-txt-link-rfc2396E" href="mailto:hongjiu.lu@intel.com"><hongjiu.lu@intel.com></a><br>
              <b>Subject:</b> Re: [llvm-dev] Intel AMX programming model
              discussion.<o:p></o:p></p>
          </div>
        </div>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p>Hi, Andy,<o:p></o:p></p>
        <p>I don't quite understand everything that's going on here.
          Could we model this as:<o:p></o:p></p>
        <p> 1. Define a collection of register classes, one for 2x4
          tiles, one for 4x2 tiles, etc. each populated with a set of
          tile registers. Registers can have aliasing relationships
          (instead of worrying of any kind of subregister/superregister
          relationships -- these won't be useful anyway).<o:p></o:p></p>
        <p> 2. Define the tile-configuration instructions so that they
          implicitly define all of the registers in all of the classes.<o:p></o:p></p>
        <p>Then you would still need to pre-schedule the tile operations
          as you've described, and collect the configuration information
          in order to add the ldtilecfgs, but the regular register
          allocator can handle the allocation itself in the usual way.
          What do you think?<o:p></o:p></p>
        <p> -Hal<o:p></o:p></p>
        <div>
          <p class="MsoNormal">On 8/18/20 6:58 PM, Kaylor, Andrew via
            llvm-dev wrote:<o:p></o:p></p>
        </div>
        <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
          <p class="MsoNormal"
            style="margin-bottom:0in;margin-bottom:.0001pt;line-height:normal">
            The AMX registers are complicated. The single configuration
            register (which is mostly used implicitly, similar to MXCSR
            for floating point) controls the shape of all the tile
            registers, and if you change the tile configuration every
            single tile register is cleared. In practice, if we have to
            change the the configuration while any of the tile registers
            are live, performance is going to be terrible. We need to
            handle this case for correctness, but users of this
            programming interface will need to have enough awareness of
            the performance issues and the hardware details to prevent
            this. We’ll also want a diagnostic that lets the user know
            when this has happened.<o:p></o:p></p>
          <p class="MsoNormal"
            style="margin-bottom:0in;margin-bottom:.0001pt;line-height:normal">
             <o:p></o:p></p>
          <p class="MsoNormal"
            style="margin-bottom:0in;margin-bottom:.0001pt;line-height:normal">
            When the tile configuration is set, the shape of each tile
            is locked in, so the individual tile registers aren’t
            interchangeable at that point. If a function needs 2x4
            tiles, 4x2 tiles, and 4x4 tiles, the configuration needs to
            be set with this in mind. The shape isn’t explicit in every
            instruction and intrinsic. It must be deduced. And again,
            we’ll need a way to tell the user when efficient allocation
            can’t be done. In practice, I don’t expect any function to
            be using more than three tile shapes.<o:p></o:p></p>
          <p class="MsoNormal"
            style="margin-bottom:0in;margin-bottom:.0001pt;line-height:normal">
             <o:p></o:p></p>
          <p class="MsoNormal"
            style="margin-bottom:0in;margin-bottom:.0001pt;line-height:normal">
            The implication of all this is that I don’t think the greedy
            register allocator is well suited to figure all of this out.
            We need a special pass to pre-allocate these registers. If
            the function is written in a way that makes good performance
            possible, it should be a relatively simple task to allocate
            everything with minimal spilling. If it isn’t possible to
            get good performance, we don’t need to do anything
            especially clever. We can just do something straightforward
            that is correct and let the user know that they aren’t going
            to be happy with the results.<o:p></o:p></p>
          <p class="MsoNormal"> <o:p></o:p></p>
          <p class="MsoNormal">-Andy<o:p></o:p></p>
          <p class="MsoNormal"> <o:p></o:p></p>
          <div>
            <div style="border:none;border-top:solid #E1E1E1
              1.0pt;padding:3.0pt 0in 0in 0in">
              <p class="MsoNormal"
                style="margin-bottom:0in;margin-bottom:.0001pt;line-height:normal">
                <b>From:</b> Philip Reames <a
                  href="mailto:listmail@philipreames.com"
                  moz-do-not-send="true"><listmail@philipreames.com></a>
                <br>
                <b>Sent:</b> Friday, August 14, 2020 8:29 PM<br>
                <b>To:</b> Luo, Yuanke <a
                  href="mailto:yuanke.luo@intel.com"
                  moz-do-not-send="true"><yuanke.luo@intel.com></a>;
                <a href="mailto:llvm-dev@lists.llvm.org"
                  moz-do-not-send="true">llvm-dev@lists.llvm.org</a>; <a
                  href="mailto:florian_hahn@apple.com"
                  moz-do-not-send="true">
                  florian_hahn@apple.com</a>; Kaylor, Andrew <a
                  href="mailto:andrew.kaylor@intel.com"
                  moz-do-not-send="true">
                  <andrew.kaylor@intel.com></a>; Topper, Craig <a
                  href="mailto:craig.topper@intel.com"
                  moz-do-not-send="true">
                  <craig.topper@intel.com></a>; Lu, Hongjiu <a
                  href="mailto:hongjiu.lu@intel.com"
                  moz-do-not-send="true"><hongjiu.lu@intel.com></a><br>
                <b>Subject:</b> Re: [llvm-dev] Intel AMX programming
                model discussion.<o:p></o:p></p>
            </div>
          </div>
          <p class="MsoNormal"> <o:p></o:p></p>
          <p>I find your answer unconvincing.  I'm not going to debate
            it as I don't wish to take the time to build the appropriate
            context, but my initial response is skepticism.<o:p></o:p></p>
          <p>Philip<o:p></o:p></p>
          <div>
            <p class="MsoNormal">On 8/14/20 4:49 PM, Luo, Yuanke wrote:<o:p></o:p></p>
          </div>
          <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
            <p class="MsoNormal">[Yuanke] AMX register is special. It
              needs to be configured before use and the config
              instruction is expensive. To avoid unnecessary tile
              configure, we collect the tile shape information as much
              as possible and combine them into one ldtilecfg
              instruction. The ldtilecfg instruction should dominate any
              AMX instruction that access tile register. On the other
              side, the ldtilecfg should post-dominated the instruction
              that define the tile shape. For tile register spill, it
              should avoid re-config due to the different tile shape,
              the spilled register should be reloaded to the register
              that share the same tile shape. Since tile register
              allocation is special and it may allocate general virtual
              register to configure tile register, we can add a sperate
              pass to do it before general register allocation pass.
              After register allocation, the tile shape information is
              not needed anymore, so we can transform the pseudo AMX
              instruction to real AMX instruction by removing the row
              and column operands.<o:p></o:p></p>
            <p>[Philip]<o:p></o:p></p>
            <p>This seems complicated.<o:p></o:p></p>
            <p>Reading through the documentation, there appears to be a
              single global tile config for all tile registers at any
              time.<o:p></o:p></p>
            <p>Why not simply model this tile config as a designated
              special register and the tile instructions as having an
              implicit use of this register?  That would seem to ensure
              that the register allocator has all the constraints
              needed.  You'd need to teach it how to spill the special
              registers with the appropriate instructions, but that
              seems a lot more straight forward?<o:p></o:p></p>
            <p class="MsoNormal"><span
                style="font-size:10.5pt;line-height:105%">[Yuanke] In
                that case user need to configure the tile register by
                themselves. Spilling configure register is very
                expensive, because it clears all the tile data register
                to zero. In our proposal, compiler is responsible to
                deduce the shape for virtual of tile data register,
                allocate physical registers for them and then configure
                those physical register. We may build the dependency as
                you proposed and it can be used for machine IR check to
                ensure tile data register is configured before use. </span><o:p></o:p></p>
            <p class="MsoNormal"><span
                style="font-size:10.5pt;line-height:105%"> </span><o:p></o:p></p>
            <div>
              <div style="border:none;border-top:solid #E1E1E1
                1.0pt;padding:3.0pt 0in 0in 0in">
                <p class="MsoNormal"
                  style="margin-bottom:0in;margin-bottom:.0001pt;line-height:normal">
                  <b>From:</b> Philip Reames <a
                    href="mailto:listmail@philipreames.com"
                    moz-do-not-send="true"><listmail@philipreames.com></a>
                  <br>
                  <b>Sent:</b> Saturday, August 15, 2020 1:17 AM<br>
                  <b>To:</b> Luo, Yuanke <a
                    href="mailto:yuanke.luo@intel.com"
                    moz-do-not-send="true"><yuanke.luo@intel.com></a>;
                  <a href="mailto:llvm-dev@lists.llvm.org"
                    moz-do-not-send="true">llvm-dev@lists.llvm.org</a>;
                  <a href="mailto:florian_hahn@apple.com"
                    moz-do-not-send="true">
                    florian_hahn@apple.com</a>; Kaylor, Andrew <a
                    href="mailto:andrew.kaylor@intel.com"
                    moz-do-not-send="true">
                    <andrew.kaylor@intel.com></a>; Topper, Craig <a
                    href="mailto:craig.topper@intel.com"
                    moz-do-not-send="true">
                    <craig.topper@intel.com></a>; Lu, Hongjiu <a
                    href="mailto:hongjiu.lu@intel.com"
                    moz-do-not-send="true"><hongjiu.lu@intel.com></a><br>
                  <b>Subject:</b> Re: [llvm-dev] Intel AMX programming
                  model discussion.<o:p></o:p></p>
              </div>
            </div>
            <p class="MsoNormal"> <o:p></o:p></p>
            <p> <o:p></o:p></p>
            <div>
              <p class="MsoNormal">On 8/14/20 6:27 AM, Luo, Yuanke via
                llvm-dev wrote:<o:p></o:p></p>
            </div>
            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
              <p class="MsoNormal">Hi,<o:p></o:p></p>
              <p class="MsoNormal">Intel Advanced Matrix Extensions
                (Intel AMX) is a new programming paradigm consisting of
                two components: a set of 2-dimensional registers (tiles)
                representing sub-arrays from a larger 2-dimensional
                memory image, and accelerators able to operate on tiles.
                Capability of Intel AMX implementation is enumerated by
                palettes. Two palettes are supported: palette 0
                represents the initialized state and palette 1 consists
                of 8 tile registers of up to 1 KB size, which is
                controlled by a tile control register.<o:p></o:p></p>
              <p class="MsoNormal">The instruction manual is posted at <a
href="https://software.intel.com/content/www/us/en/develop/download/intel-architecture-instruction-set-extensions-programming-reference.html"
                  moz-do-not-send="true">
https://software.intel.com/content/www/us/en/develop/download/intel-architecture-instruction-set-extensions-programming-reference.html</a>.<o:p></o:p></p>
              <p class="MsoNormal">The AMX abi proposal is posted at <a
href="https://groups.google.com/g/x86-64-abi/c/NRejFm7pwb4"
                  moz-do-not-send="true">
                  https://groups.google.com/g/x86-64-abi/c/NRejFm7pwb4</a>.<o:p></o:p></p>
              <p class="MsoNormal">This email is to discuss the
                programming model for AMX. Florian has introduced the
                matrix type and intrinsics in LLVM community. We’d like
                to adopt some ideas from it.<o:p></o:p></p>
              <p class="MsoNormal">Here is what we propose for the AMX
                programming model.<o:p></o:p></p>
              <p class="MsoListParagraph"
                style="margin-left:.5in;text-indent:-.25in;mso-list:l0
                level1 lfo2">
                <!--[if !supportLists]--><span style="mso-list:Ignore">1.<span
                    style="font:7.0pt "Times New Roman"">      
                  </span></span><!--[endif]--> Data type. <o:p></o:p></p>
              <p class="MsoNormal">We’d like to have fixed vector type
                for AMX. Since the shape to AMX register can be
                configurable, the vector size is the maximum size of AMX
                register. That means the vector size is 1024 bytes.<o:p></o:p></p>
              <p class="MsoNormal">The C code may look like this.<o:p></o:p></p>
              <p class="MsoNormal">typedef int _tile_data
                __attribute__((__vector_size__(1024), __aligned__(64)));<o:p></o:p></p>
              <p class="MsoNormal">_tile_data tile;<o:p></o:p></p>
              <p class="MsoNormal">And the LLVM IR may look like this.<o:p></o:p></p>
              <p class="MsoNormal">@tile = dso_local local_unnamed_addr
                global <256 x i32> zeroinitializer, align 64<o:p></o:p></p>
              <p class="MsoNormal">For llvm IR, it is nice to have a new
                type x86_amxtile that can be mapped to AMX registers.<o:p></o:p></p>
              <p class="MsoListParagraph"
                style="margin-left:.5in;text-indent:-.25in;mso-list:l0
                level1 lfo2">
                <!--[if !supportLists]--><span style="mso-list:Ignore">2.<span
                    style="font:7.0pt "Times New Roman"">      
                  </span></span><!--[endif]-->AMX Intrinsics. <o:p></o:p></p>
              <p class="MsoNormal">The internal intrinsics are 1:1
                mapped to AMX instructions. The parameter m, n, k
                identifies the shape of the tile. The shape can be
                variable, but it cannot exceed the size that AMX HW can
                support. Compiler can deduce shape of the tile from the
                AMX intrinsics.<o:p></o:p></p>
              <p class="MsoNormal" style="text-indent:5.5pt">_tile_data
                _tile_loadd_internal(char m, short n, const void *base,
                int stride);<o:p></o:p></p>
              <p class="MsoNormal">_tile_data _tile_dpbssd_internal(char
                m, short n, short k, _tile_data dst, _tile_data src1,
                _tile_data src2);<o:p></o:p></p>
              <p class="MsoNormal">_tile_data
                _tile_dpbf16ps_internal(char m, short n, short k,
                _tile_data dst, _tile_data src1, _tile_data src2);<o:p></o:p></p>
              <p class="MsoNormal">void _tile_stored_internal(char m,
                short n, void *base, int stride, _tile_data tile);<o:p></o:p></p>
              <p class="MsoListParagraph"
                style="margin-left:.5in;text-indent:-.25in;mso-list:l0
                level1 lfo2">
                <!--[if !supportLists]--><span style="mso-list:Ignore">3.<span
                    style="font:7.0pt "Times New Roman"">      
                  </span></span><!--[endif]-->User interfaces.<o:p></o:p></p>
              <p class="MsoNormal">The tile shape and tile data are
                combined into a struct in C language. The shape of the
                tile is only allowed to be initialized once. The user
                interface looks as this.<o:p></o:p></p>
              <p class="MsoNormal">   3  #define __DEFAULT_FN_AMX    \<o:p></o:p></p>
              <p class="MsoNormal">   4 
                __attribute__((__always_inline__, __nodebug__,
                __target__("amx-int8")))<o:p></o:p></p>
              <p class="MsoNormal">   9 typedef struct __tile_str {<o:p></o:p></p>
              <p class="MsoNormal">10   const char row;<o:p></o:p></p>
              <p class="MsoNormal">11   const short col;<o:p></o:p></p>
              <p class="MsoNormal">12   _tile_data tile;<o:p></o:p></p>
              <p class="MsoNormal">13 }__tile;<o:p></o:p></p>
              <p class="MsoNormal">14<o:p></o:p></p>
              <p class="MsoNormal">15 __DEFAULT_FN_AMX<o:p></o:p></p>
              <p class="MsoNormal">16 void __tile_loadd(__tile *dst,
                const void *base, long stride) {<o:p></o:p></p>
              <p class="MsoNormal">17   dst->tile =
                _tile_loadd_internal(dst->row, dst->col, base,
                stride);<o:p></o:p></p>
              <p class="MsoNormal">18 }<o:p></o:p></p>
              <p class="MsoNormal">19<o:p></o:p></p>
              <p class="MsoNormal">20 __DEFAULT_FN_AMX<o:p></o:p></p>
              <p class="MsoNormal">21 void __tile_dpbsud(__tile *dst,
                __tile src1, __tile src2) {<o:p></o:p></p>
              <p class="MsoNormal">22   dst->tile =
                _tile_dpbssd_internal(src1.row, src2.col, src1.col,
                dst->tile, src1.tile, src2.tile);<o:p></o:p></p>
              <p class="MsoNormal">23 }<o:p></o:p></p>
              <p class="MsoNormal">24<o:p></o:p></p>
              <p class="MsoNormal">25 __DEFAULT_FN_AMX<o:p></o:p></p>
              <p class="MsoNormal">26 void __tile_stored(void *base,
                long stride, __tile src) {<o:p></o:p></p>
              <p class="MsoNormal">27   _tile_stored_internal(src.row,
                src.col, base, stride, src.tile);<o:p></o:p></p>
              <p class="MsoNormal">28 }<o:p></o:p></p>
              <p class="MsoNormal"> <o:p></o:p></p>
              <p class="MsoListParagraph"
                style="margin-left:.5in;text-indent:-.25in;mso-list:l0
                level1 lfo2">
                <!--[if !supportLists]--><span style="mso-list:Ignore">4.<span
                    style="font:7.0pt "Times New Roman"">      
                  </span></span><!--[endif]-->Example code<o:p></o:p></p>
              <p class="MsoNormal">The example shows how to use the user
                interface in a function.
                <o:p></o:p></p>
              <p class="MsoNormal"> 51 void api(int cond, short row,
                short col) {<o:p></o:p></p>
              <p class="MsoNormal">52   __tile a = {row, col};<o:p></o:p></p>
              <p class="MsoNormal">53   __tile b = {row, col};<o:p></o:p></p>
              <p class="MsoNormal">54   __tile c = {row, col};<o:p></o:p></p>
              <p class="MsoNormal">55<o:p></o:p></p>
              <p class="MsoNormal">56   if(cond) {<o:p></o:p></p>
              <p class="MsoNormal">57     __tile_loadd(&a, buf,
                STRIDE);<o:p></o:p></p>
              <p class="MsoNormal">58     __tile_loadd(&b, buf,
                STRIDE);<o:p></o:p></p>
              <p class="MsoNormal">59     __tile_loadd(&c, buf,
                STRIDE);<o:p></o:p></p>
              <p class="MsoNormal">60   } else {<o:p></o:p></p>
              <p class="MsoNormal">61     __tile_loadd(&a, buf2,
                STRIDE);<o:p></o:p></p>
              <p class="MsoNormal">62     __tile_loadd(&b, buf2,
                STRIDE);<o:p></o:p></p>
              <p class="MsoNormal">63     __tile_loadd(&c, buf2,
                STRIDE);<o:p></o:p></p>
              <p class="MsoNormal">64   }<o:p></o:p></p>
              <p class="MsoNormal"><span lang="IT">65  
                  __tile_dpbsud(&c, a, b);</span><o:p></o:p></p>
              <p class="MsoNormal">66   __tile_stored(buf, STRIDE, c);<o:p></o:p></p>
              <p class="MsoNormal">67 }<o:p></o:p></p>
              <p class="MsoListParagraph"
                style="margin-left:.5in;text-indent:-.25in;mso-list:l0
                level1 lfo2">
                <!--[if !supportLists]--><span style="mso-list:Ignore">5.<span
                    style="font:7.0pt "Times New Roman"">      
                  </span></span><!--[endif]-->LLVM IR<o:p></o:p></p>
              <p class="MsoNormal">The LLVM intrinsics IR take the row
                and column information as the input parameter, so that
                compiler can deduce the shape of tile data. The
                remaining parameters are what AMX instructions require.
                This is the LLVM IR corresponding to the example code.<o:p></o:p></p>
              <p class="MsoNormal">12 define dso_local void @api(i32
                %cond, i16 signext %row, i16 signext %col)
                local_unnamed_addr #2 {<o:p></o:p></p>
              <p class="MsoNormal">13 entry:<o:p></o:p></p>
              <p class="MsoNormal">14   %tobool = icmp eq i32 %cond, 0<o:p></o:p></p>
              <p class="MsoNormal">15   %sext = shl i16 %col, 8<o:p></o:p></p>
              <p class="MsoNormal">16   %conv.i31 = ashr exact i16
                %sext, 8<o:p></o:p></p>
              <p class="MsoNormal">17   br i1 %tobool, label %if.else,
                label %if.then<o:p></o:p></p>
              <p class="MsoNormal">18<o:p></o:p></p>
              <p class="MsoNormal">19
                if.then:                                          ;
                preds = %entry<o:p></o:p></p>
              <p class="MsoNormal">20   %0 = tail call <256 x i32>
                @llvm.x86.tileloadd64(i16 %row, i16 %conv.i31, i8*
                getelementptr inbounds ([1024 x i8], [1024 x i8]* @buf,
                i64 0, i64 0), i64 32) #3<o:p></o:p></p>
              <p class="MsoNormal">21   %1 = tail call <256 x i32>
                @llvm.x86.tileloadd64(i16 %row, i16 %conv.i31, i8*
                getelementptr inbounds ([1024 x i8], [1024 x i8]* @buf,
                i64 0, i64 0), i64 32) #3<o:p></o:p></p>
              <p class="MsoNormal">22   %2 = tail call <256 x i32>
                @llvm.x86.tileloadd64(i16 %row, i16 %conv.i31, i8*
                getelementptr inbounds ([1024 x i8], [1024 x i8]* @buf,
                i64 0, i64 0), i64 32) #3<o:p></o:p></p>
              <p class="MsoNormal">23   br label %if.end<o:p></o:p></p>
              <p class="MsoNormal">24<o:p></o:p></p>
              <p class="MsoNormal">25 if.else:                     
                                    ; preds = %entry<o:p></o:p></p>
              <p class="MsoNormal">26   %3 = tail call <256 x i32>
                @llvm.x86.tileloadd64(i16 %row, i16 %conv.i31, i8*
                getelementptr inbounds ([1024 x i8], [1024 x i8]* @buf2,
                i64 0, i64 0), i64 32) #3<o:p></o:p></p>
              <p class="MsoNormal">27   %4 = tail call <256 x i32>
                @llvm.x86.tileloadd64(i16 %row, i16 %conv.i31, i8*
                getelementptr inbounds ([1024 x i8], [1024 x i8]* @buf2,
                i64 0, i64 0), i64 32) #3<o:p></o:p></p>
              <p class="MsoNormal">28   %5 = tail call <256 x i32>
                @llvm.x86.tileloadd64(i16 %row, i16 %conv.i31, i8*
                getelementptr inbounds ([1024 x i8], [1024 x i8]* @buf2,
                i64 0, i64 0), i64 32) #3<o:p></o:p></p>
              <p class="MsoNormal">29   br label %if.end<o:p></o:p></p>
              <p class="MsoNormal">30<o:p></o:p></p>
              <p class="MsoNormal">31
                if.end:                                           ;
                preds = %if.else, %if.then<o:p></o:p></p>
              <p class="MsoNormal">32   %a.sroa.1186.0 = phi <256 x
                i32> [ %3, %if.else ], [ %0, %if.then ]<o:p></o:p></p>
              <p class="MsoNormal">33   %b.sroa.1068.0 = phi <256 x
                i32> [ %4, %if.else ], [ %1, %if.then ]<o:p></o:p></p>
              <p class="MsoNormal">34   %c.sroa.1149.0 = phi <256 x
                i32> [ %5, %if.else ], [ %2, %if.then ]<o:p></o:p></p>
              <p class="MsoNormal">35   %6 = tail call <256 x i32>
                @llvm.x86.tdpbssd(i16 %row, i16 %conv.i31, i16
                %conv.i31, <256 x i32> %c.sroa.1149.0, <256 x
                i32> %a.sroa.1186.0, <256 x i32>
                %b.sroa.1068.0) #3<o:p></o:p></p>
              <p class="MsoNormal">36   tail call void
                @llvm.x86.tilestored64(i16 %row, i16 %conv.i31, i8*
                getelementptr inbounds ([1024 x i8], [1024 x i8]* @buf,
                i64 0, i64 0), i64 32, <256 x i32> %6) #3<o:p></o:p></p>
              <p class="MsoNormal">37   ret void<o:p></o:p></p>
              <p class="MsoNormal">38 }<o:p></o:p></p>
              <p class="MsoListParagraph"
                style="margin-left:.5in;text-indent:-.25in;mso-list:l0
                level1 lfo2">
                <!--[if !supportLists]--><span style="mso-list:Ignore">6.<span
                    style="font:7.0pt "Times New Roman"">      
                  </span></span><!--[endif]-->Shape propagation<o:p></o:p></p>
              <p class="MsoNormal">When in -O0 build, some general
                load/store for tile vector is generated by front-end. We
                need to root from AMX intrinsics to propagate the shape
                information to the virtual tile register. If the an AMX
                intrinsic use the result of load instruction, the shape
                is propagated to the load and the load is transformed to
                tile load intrinsic. If the store instruction uses any
                result of AMX intrinsic, the shape is propagated to
                store instruction and the store is transformed to tile
                store intrinsic<o:p></o:p></p>
              <p class="MsoListParagraph"
                style="margin-left:.5in;text-indent:-.25in;mso-list:l0
                level1 lfo2">
                <!--[if !supportLists]--><span style="mso-list:Ignore">7.<span
                    style="font:7.0pt "Times New Roman"">      
                  </span></span><!--[endif]-->Machine IR<o:p></o:p></p>
              <p class="MsoNormal">Since the AMX intrinsics take the row
                and column as the input parameters, we can create a
                pseudo instruction corresponding to it. The AMX
                intrinsics are lowered to the pseudo AMX instruction
                which has extra row and column operands corresponding to
                AMX intrinsic. The real AMX instructions don’t need the
                row and column operands. The row and column information
                should be configured by ldtilecfg before executing any
                AMX instruction.<o:p></o:p></p>
              <p class="MsoListParagraph"
                style="margin-left:.5in;text-indent:-.25in;mso-list:l0
                level1 lfo2">
                <!--[if !supportLists]--><span style="mso-list:Ignore">8.<span
                    style="font:7.0pt "Times New Roman"">      
                  </span></span><!--[endif]-->Register allocation<o:p></o:p></p>
              <p class="MsoNormal">AMX register is special. It needs to
                be configured before use and the config instruction is
                expensive. To avoid unnecessary tile configure, we
                collect the tile shape information as much as possible
                and combine them into one ldtilecfg instruction. The
                ldtilecfg instruction should dominate any AMX
                instruction that access tile register. On the other
                side, the ldtilecfg should post-dominated the
                instruction that define the tile shape. For tile
                register spill, it should avoid re-config due to the
                different tile shape, the spilled register should be
                reloaded to the register that share the same tile shape.
                Since tile register allocation is special and it may
                allocate general virtual register to configure tile
                register, we can add a sperate pass to do it before
                general register allocation pass. After register
                allocation, the tile shape information is not needed
                anymore, so we can transform the pseudo AMX instruction
                to real AMX instruction by removing the row and column
                operands.<o:p></o:p></p>
            </blockquote>
            <p>This seems complicated.<o:p></o:p></p>
            <p>Reading through the documentation, there appears to be a
              single global tile config for all tile registers at any
              time.<o:p></o:p></p>
            <p>Why not simply model this tile config as a designated
              special register and the tile instructions as having an
              implicit use of this register?  That would seem to ensure
              that the register allocator has all the constraints
              needed.  You'd need to teach it how to spill the special
              registers with the appropriate instructions, but that
              seems a lot more straight forward?<o:p></o:p></p>
            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
              <p class="MsoListParagraph"
                style="margin-left:.5in;text-indent:-.25in;mso-list:l0
                level1 lfo2">
                <!--[if !supportLists]--><span style="mso-list:Ignore">9.<span
                    style="font:7.0pt "Times New Roman"">      
                  </span></span><!--[endif]-->Use recommendation <o:p></o:p></p>
              <p class="MsoNormal">Due to the shape configure issue, we
                recommend user to define the tile shape at the entry of
                the function entry and inline function as much as
                possible. The AMX instructions focus on computation
                instead of storage, so global variable for tile data is
                not recommended.<o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:10.5pt;line-height:105%"> </span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:10.5pt;line-height:105%">Thanks</span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:10.5pt;line-height:105%">Yuanke</span><o:p></o:p></p>
              <p class="MsoNormal"
                style="margin-bottom:0in;margin-bottom:.0001pt;line-height:normal">
                <br>
                <br>
                <br>
                <br>
                <o:p></o:p></p>
              <pre>_______________________________________________<o:p></o:p></pre>
              <pre>LLVM Developers mailing list<o:p></o:p></pre>
              <pre><a href="mailto:llvm-dev@lists.llvm.org" moz-do-not-send="true">llvm-dev@lists.llvm.org</a><o:p></o:p></pre>
              <pre><a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" moz-do-not-send="true">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><o:p></o:p></pre>
            </blockquote>
          </blockquote>
          <p class="MsoNormal"
            style="margin-bottom:0in;margin-bottom:.0001pt;line-height:normal">
            <br>
            <br>
            <o:p></o:p></p>
          <pre>_______________________________________________<o:p></o:p></pre>
          <pre>LLVM Developers mailing list<o:p></o:p></pre>
          <pre><a href="mailto:llvm-dev@lists.llvm.org" moz-do-not-send="true">llvm-dev@lists.llvm.org</a><o:p></o:p></pre>
          <pre><a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" moz-do-not-send="true">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><o:p></o:p></pre>
        </blockquote>
        <pre>-- <o:p></o:p></pre>
        <pre>Hal Finkel<o:p></o:p></pre>
        <pre>Lead, Compiler Technology and Programming Languages<o:p></o:p></pre>
        <pre>Leadership Computing Facility<o:p></o:p></pre>
        <pre>Argonne National Laboratory<o:p></o:p></pre>
      </div>
    </blockquote>
    <pre class="moz-signature" cols="72">-- 
Hal Finkel
Lead, Compiler Technology and Programming Languages
Leadership Computing Facility
Argonne National Laboratory</pre>
  </body>
</html>