<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>Hi everyone,</p>
    <p>I'm trying to make some optimisation improvements to UComplex so
      the compiler can take advantage of SSE2 or AVX features without
      needing to write specialised code (other than using the
      "vectorcall" directive under Win64).  I am having some difficulty
      though.</p>
    <p>The record type "complex" is defined as follows:</p>
    <p>    <b>type </b>complex = <b>record</b><br>
                           re : real;<br>
                           im : real;<br>
                         <b>end</b>;</p>
    <p>(Real is equivalent to Double on x86_64)</p>
    <p>This also corresponds with how a complex number is defined for
      Extended Pascal.  Currently, when compiled under x86_64-win64, the
      fields are placed on 8-byte boundaries, but because the type as a
      whole is also on an 8-byte boundary (not 16-byte), the compiler
      cannot take advantage of the XMM registers when passing such a
      construct as a parameter or return value, and hence has to pass it
      by reference.  For high-speed scientific programming, this quickly
      adds up to a notable penalty.  For example, the compiled assembly
      language for adding together two complex numbers on x86_64-win64
      ("Z := Z + X;"):</p>
    <p>    movsd    U_$P$COMPLEX_$$_Z(%rip),%xmm0<br>
          addsd    U_$P$COMPLEX_$$_X(%rip),%xmm0<br>
          movsd    %xmm0,40(%rsp)<br>
          movsd    U_$P$COMPLEX_$$_Z+8(%rip),%xmm0<br>
          addsd    U_$P$COMPLEX_$$_X+8(%rip),%xmm0<br>
          movsd    %xmm0,48(%rsp)<br>
          movq    40(%rsp),%rax<br>
          movq    %rax,U_$P$COMPLEX_$$_Z(%rip)<br>
          movq    48(%rsp),%rax<br>
          movq    %rax,U_$P$COMPLEX_$$_Z+8(%rip)</p>
    <p>Even if the reads and writes to memory cannot be removed,
      treating the complex data type as an aligned array of doubles
      should be able to yield far more efficient code (might require
      some compiler quirks so it detects the component-wise addition in
      the inlined + operator for the complex type):</p>
    <p>    movapd   U_$P$COMPLEX_$$_Z(%rip),%xmm0<br>
          addpd    U_$P$COMPLEX_$$_X(%rip),%xmm0<br>
          movapd   %xmm0,U_$P$COMPLEX_$$_Z(%rip)
    </p>
    <p>The problem here is that there's no practical way to force the
      entire record's alignment onto a 16-byte boundary (a requirement
      for "vectorcall") without also snapping each individual field to
      such a boundary.  Strictly speaking, I don't think the 16-byte
      boundary is a requirement for the System V ABI (the Unix calling
      convention for 64-bit Intel processors), and there are unaligned
      move instructions to accommodate for this (which have
      traditionally been slightly slower than the aligned counterparts),
      but currently the Free Pascal Compiler demands the alignment,
      mainly because of shared compiler code between Windows and
      non-Windows builds.</p>
    <p>The only way to enforce a construct where the record is on a
      16-byte boundary but the two 8-byte fields are packed is to use an
      array element; e.g:</p>
    <p>  {$push}<br>
        {$codealign RECORDMIN=16}<br>
          <b>type</b> complex = <b>record</b><br>
                           part: <b>array</b>[0..1] of real;<br>
                         <b>end</b>;<br>
        {$pop}<br>
    </p>
    <p>Mapping "re" to "part[0]" and "im" to "part[1]" using a union is
      impossible because "im" will be put on the next 16-byte boundary
      and be its own separate entity.  Other constructs such as nested
      unions are possible, but this will break backward compatibility
      with code that uses the uComplex unit.</p>
    <p>A while ago I requested a means to specify an alignment on a
      per-type basis so it is easier for third-party programmers to take
      advantage of the extra efficiency brought upon by vectorcall and
      the System V ABI: <a class="moz-txt-link-freetext" href="https://bugs.freepascal.org/view.php?id=32780">https://bugs.freepascal.org/view.php?id=32780</a> -
      this effectively boils down to being able to define something akin
      to the following:</p>
    <p>    <b>type </b>complex = <b>record</b><br>
                           re : real;<br>
                           im : real;<br>
                         <b>end</b><i>{$ifdef CPUX86_64}</i> <b>align</b>
      16<i>{$endif CPUX86_64}</i>;</p>
    <p>It was assigned to Maciej last year, but hasn't seen any progress
      since.</p>
    <p>If not that alignment feature, is there any other way to cleanly
      enforce a 16-byte boundary for such a packed type without having
      to completely redesign it to the point that it breaks
      compatibility?</p>
    <p>Gareth aka. Kit</p>
    <p>P.S. I suppose what I'm getting at is that taking advantage of
      the System V ABI's vectorising capabilities is incredibly fiddly
      and, even if you know how the compiler works internally, is not a
      guarantee of getting it to work.  Vectorcall was always fiddly
      because of the alignment requirement, but any cross-platform
      solution should make it much easier to get right.<br>
    </p>
  <div id="DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2"><br />
<table style="border-top: 1px solid #D3D4DE;">
        <tr>
        <td style="width: 55px; padding-top: 13px;"><a href="https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=emailclient" target="_blank"><img src="https://ipmcdn.avast.com/images/icons/icon-envelope-tick-round-orange-animated-no-repeat-v1.gif" alt="" width="46" height="29" style="width: 46px; height: 29px;" /></a></td>
                <td style="width: 470px; padding-top: 12px; color: #41424e; font-size: 13px; font-family: Arial, Helvetica, sans-serif; line-height: 18px;">Virus-free. <a href="https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=emailclient" target="_blank" style="color: #4453ea;">www.avast.com</a>
                </td>
        </tr>
</table><a href="#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2" width="1" height="1"> </a></div></body>
</html>