<div dir="ltr"><div dir="ltr">There's not really any way to do what that does with a normal for loop without copying the array though, which is whole point basically.<div><br></div><div>Here's the actual assembly I get from FPC for "main":</div><div><br></div><div><div>.section .text.n_main,"x"</div><div><span style="white-space:pre">    </span>.balign 16,0x90</div><div>.globl<span style="white-space:pre"> </span>PASCALMAIN</div><div>PASCALMAIN:</div><div>.globl<span style="white-space:pre">    </span>main</div><div>main:</div><div>.Lc12:</div><div>.seh_proc main</div><div><span style="white-space:pre">    </span>pushq<span style="white-space:pre">        </span>%rbp</div><div>.seh_pushreg %rbp</div><div>.Lc14:</div><div>.Lc15:</div><div><span style="white-space:pre">        </span>movq<span style="white-space:pre"> </span>%rsp,%rbp</div><div>.Lc16:</div><div><span style="white-space:pre">        </span>leaq<span style="white-space:pre"> </span>-176(%rsp),%rsp</div><div>.seh_stackalloc 176</div><div><span style="white-space:pre">     </span>movq<span style="white-space:pre"> </span>%rbx,-136(%rbp)</div><div><span style="white-space:pre">       </span>movq<span style="white-space:pre"> </span>%rdi,-128(%rbp)</div><div><span style="white-space:pre">       </span>movq<span style="white-space:pre"> </span>%rsi,-120(%rbp)</div><div><span style="white-space:pre">       </span>movq<span style="white-space:pre"> </span>%r12,-112(%rbp)</div><div>.seh_savereg %rbx, 40</div><div>.seh_savereg %rdi, 48</div><div>.seh_savereg %rsi, 56</div><div>.seh_savereg %r12, 64</div><div>.seh_endprologue</div><div><span style="white-space:pre">        </span>call<span style="white-space:pre"> </span>fpc_initializeunits</div><div><span style="white-space:pre">   </span>movq<span style="white-space:pre"> </span>$100000000,-8(%rbp)</div><div><span style="white-space:pre">   </span>leaq<span style="white-space:pre"> </span>RTTI_$P$TAKEWHILEEXAMPLE_$$_def00000014(%rip),%rdx</div><div><span style="white-space:pre">    </span>leaq<span style="white-space:pre"> </span>-8(%rbp),%r9</div><div><span style="white-space:pre">  </span>leaq<span style="white-space:pre"> </span>U_$P$TAKEWHILEEXAMPLE_$$_ARR(%rip),%rcx</div><div><span style="white-space:pre">       </span>movl<span style="white-space:pre"> </span>$1,%r8d</div><div><span style="white-space:pre">       </span>call<span style="white-space:pre"> </span>fpc_dynarray_setlength</div><div><span style="white-space:pre">        </span>movq<span style="white-space:pre"> </span>$-1,%rdx</div><div><span style="white-space:pre">      </span>.p2align 4,,10</div><div><span style="white-space:pre">        </span>.p2align 3</div><div>.Lj35:</div><div><span style="white-space:pre">       </span>addq<span style="white-space:pre"> </span>$1,%rdx</div><div><span style="white-space:pre">       </span>movq<span style="white-space:pre"> </span>U_$P$TAKEWHILEEXAMPLE_$$_ARR(%rip),%rax</div><div><span style="white-space:pre">       </span>movq<span style="white-space:pre"> </span>%rdx,(%rax,%rdx,8)</div><div><span style="white-space:pre">    </span>cmpq<span style="white-space:pre"> </span>$99999999,%rdx</div><div><span style="white-space:pre">        </span>jnae<span style="white-space:pre"> </span>.Lj35</div><div><span style="white-space:pre"> </span>xorl<span style="white-space:pre"> </span>%esi,%esi</div><div><span style="white-space:pre">     </span>xorl<span style="white-space:pre"> </span>%ebx,%ebx</div><div><span style="white-space:pre">     </span>leaq<span style="white-space:pre"> </span>P$TAKEWHILEEXAMPLE_$$_TEST$QWORD$$BOOLEAN(%rip),%rax</div><div><span style="white-space:pre">  </span>movq<span style="white-space:pre"> </span>%rax,-88(%rbp)</div><div><span style="white-space:pre">        </span>movq<span style="white-space:pre"> </span>$0,-80(%rbp)</div><div><span style="white-space:pre">  </span>movq<span style="white-space:pre"> </span>U_$P$TAKEWHILEEXAMPLE_$$_ARR(%rip),%rax</div><div><span style="white-space:pre">       </span>movq<span style="white-space:pre"> </span>%rax,-56(%rbp)</div><div><span style="white-space:pre">        </span>movq<span style="white-space:pre"> </span>U_$P$TAKEWHILEEXAMPLE_$$_ARR(%rip),%rax</div><div><span style="white-space:pre">       </span>movq<span style="white-space:pre"> </span>%rax,-48(%rbp)</div><div><span style="white-space:pre">        </span>movq<span style="white-space:pre"> </span>U_$P$TAKEWHILEEXAMPLE_$$_ARR(%rip),%rcx</div><div><span style="white-space:pre">       </span>call<span style="white-space:pre"> </span>fpc_dynarray_high</div><div><span style="white-space:pre">     </span>movq<span style="white-space:pre"> </span>%rax,%rdi</div><div><span style="white-space:pre">     </span>movq<span style="white-space:pre"> </span>$-1,%r12</div><div><span style="white-space:pre">      </span>.p2align 4,,10</div><div><span style="white-space:pre">        </span>.p2align 3</div><div>.Lj39:</div><div><span style="white-space:pre">       </span>addq<span style="white-space:pre"> </span>$1,%r12</div><div><span style="white-space:pre">       </span>movq<span style="white-space:pre"> </span>U_$P$TAKEWHILEEXAMPLE_$$_ARR(%rip),%rax</div><div><span style="white-space:pre">       </span>movq<span style="white-space:pre"> </span>(%rax,%r12,8),%rcx</div><div><span style="white-space:pre">    </span>call<span style="white-space:pre"> </span>*-88(%rbp)</div><div><span style="white-space:pre">    </span>testb<span style="white-space:pre">        </span>%al,%al</div><div><span style="white-space:pre">       </span>je<span style="white-space:pre">   </span>.Lj38</div><div><span style="white-space:pre"> </span>addq<span style="white-space:pre"> </span>$8,-48(%rbp)</div><div><span style="white-space:pre">  </span>.p2align 4,,10</div><div><span style="white-space:pre">        </span>.p2align 3</div><div><span style="white-space:pre">    </span>cmpq<span style="white-space:pre"> </span>%r12,%rdi</div><div><span style="white-space:pre">     </span>jnbe<span style="white-space:pre"> </span>.Lj39</div><div>.Lj38:</div><div><span style="white-space:pre">    </span>leaq<span style="white-space:pre"> </span>-56(%rbp),%rax</div><div><span style="white-space:pre">        </span>vmovups<span style="white-space:pre">      </span>(%rax),%xmm1</div><div><span style="white-space:pre">  </span>vmovsd<span style="white-space:pre">       </span>16(%rax),%xmm0</div><div><span style="white-space:pre">        </span>vmovups<span style="white-space:pre">      </span>%xmm1,-32(%rbp)</div><div><span style="white-space:pre">       </span>vmovsd<span style="white-space:pre">       </span>%xmm0,-16(%rbp)</div><div><span style="white-space:pre">       </span>movq<span style="white-space:pre"> </span>-32(%rbp),%rax</div><div><span style="white-space:pre">        </span>subq<span style="white-space:pre"> </span>$8,%rax</div><div><span style="white-space:pre">       </span>movq<span style="white-space:pre"> </span>%rax,-16(%rbp)</div><div><span style="white-space:pre">        </span>jmp<span style="white-space:pre">  </span>.Lj47</div><div><span style="white-space:pre"> </span>.p2align 4,,10</div><div><span style="white-space:pre">        </span>.p2align 3</div><div>.Lj46:</div><div><span style="white-space:pre">       </span>movq<span style="white-space:pre"> </span>-16(%rbp),%rax</div><div><span style="white-space:pre">        </span>movq<span style="white-space:pre"> </span>(%rax),%rsi</div><div><span style="white-space:pre">   </span>movq<span style="white-space:pre"> </span>%rsi,%rbx</div><div>.Lj47:</div><div><span style="white-space:pre">        </span>addq<span style="white-space:pre"> </span>$8,-16(%rbp)</div><div><span style="white-space:pre">  </span>movq<span style="white-space:pre"> </span>-24(%rbp),%rax</div><div><span style="white-space:pre">        </span>cmpq<span style="white-space:pre"> </span>-16(%rbp),%rax</div><div><span style="white-space:pre">        </span>jnae<span style="white-space:pre"> </span>.Lj52</div><div><span style="white-space:pre"> </span>cmpq<span style="white-space:pre"> </span>-32(%rbp),%rax</div><div><span style="white-space:pre">        </span>je<span style="white-space:pre">   </span>.Lj52</div><div><span style="white-space:pre"> </span>movb<span style="white-space:pre"> </span>$1,%al</div><div><span style="white-space:pre">        </span>jmp<span style="white-space:pre">  </span>.Lj50</div><div>.Lj52:</div><div><span style="white-space:pre">    </span>xorb<span style="white-space:pre"> </span>%al,%al</div><div>.Lj50:</div><div><span style="white-space:pre">  </span>testb<span style="white-space:pre">        </span>%al,%al</div><div><span style="white-space:pre">       </span>jne<span style="white-space:pre">  </span>.Lj46</div><div><span style="white-space:pre"> </span>call<span style="white-space:pre"> </span>fpc_get_output</div><div><span style="white-space:pre">        </span>movq<span style="white-space:pre"> </span>%rax,%rsi</div><div><span style="white-space:pre">     </span>movq<span style="white-space:pre"> </span>%rbx,%r8</div><div><span style="white-space:pre">      </span>movq<span style="white-space:pre"> </span>%rsi,%rdx</div><div><span style="white-space:pre">     </span>xorl<span style="white-space:pre"> </span>%ecx,%ecx</div><div><span style="white-space:pre">     </span>call<span style="white-space:pre"> </span>fpc_write_text_uint</div><div><span style="white-space:pre">   </span>movq<span style="white-space:pre"> </span>%rsi,%rcx</div><div><span style="white-space:pre">     </span>call<span style="white-space:pre"> </span>fpc_writeln_end</div><div><span style="white-space:pre">       </span>call<span style="white-space:pre"> </span>fpc_do_exit</div><div><span style="white-space:pre">   </span>movq<span style="white-space:pre"> </span>-136(%rbp),%rbx</div><div><span style="white-space:pre">       </span>movq<span style="white-space:pre"> </span>-128(%rbp),%rdi</div><div><span style="white-space:pre">       </span>movq<span style="white-space:pre"> </span>-120(%rbp),%rsi</div><div><span style="white-space:pre">       </span>movq<span style="white-space:pre"> </span>-112(%rbp),%r12</div><div><span style="white-space:pre">       </span>leaq<span style="white-space:pre"> </span>(%rbp),%rsp</div><div><span style="white-space:pre">   </span>popq<span style="white-space:pre"> </span>%rbp</div><div><span style="white-space:pre">  </span>ret</div><div>.seh_endproc</div><div>.Lc13:</div></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Feb 22, 2019 at 7:17 PM Benito van der Zander <<a href="mailto:benito@benibela.de">benito@benibela.de</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
  
    
  
  <div>
    <div id="gmail-m_-6459721920992548386smartTemplate4-template">Hi,<br>
      <br>
      <blockquote type="cite">
        <div>The trick with enumerators is to never make them classes,
          and use advanced records instead, I've found. This way you
          avoid the heap allocation and the implicit try/finally. Also
          make sure you inline the MoveNext and GetCurrent! </div>
      </blockquote>
    </div>
    <div><br>
    </div>
    <div>that's what I do.</div>
    <div><br>
    </div>
    <div><br>
    </div>
    <div>But the generated assembly is still worse than an old for loop,
      because it keeps all the fields of the record in memory.</div>
    <div><br>
    </div>
    <div>for example<br>
    </div>
    <div><br>
    </div>
    <div>>   for I in TSlice<SizeUInt>.TakeWhile(Arr, Test) do
      J := I;</div>
    <div><br>
    </div>
    <div>generates something like this<br>
    </div>
    <div><br>
    </div>
    <div>0000000000401290 488b45f0                 mov   
      -0x10(%rbp),%rax<br>
      0000000000401294 488b00                   mov    (%rax),%rax<br>
      0000000000401297 488905b22a0300           mov   
      %rax,0x32ab2(%rip)        # 0x433d50 <U_$P$PROJECT1_$$_I><br>
      project1.lpr:75                           J := I;<br>
      000000000040129E 488905bb2a0300           mov   
      %rax,0x32abb(%rip)        # 0x433d60 <U_$P$PROJECT1_$$_J><br>
      project1.lpr:74                           for I in
      TSlice<SizeUInt>.TakeWhile(Arr, Test) do<br>
      00000000004012A5 488345f008               addq   $0x8,-0x10(%rbp)<br>
      project1.lpr:69                           begin<br>
      00000000004012AA 488b45e8                 mov    -0x18(%rbp),%rax<br>
      project1.lpr:74                           for I in
      TSlice<SizeUInt>.TakeWhile(Arr, Test) do<br>
      00000000004012AE 483b45f0                 cmp    -0x10(%rbp),%rax<br>
      00000000004012B2 720a                     jb     0x4012be
      <main+334><br>
      00000000004012B4 483b45e0                 cmp    -0x20(%rbp),%rax<br>
      00000000004012B8 7404                     je     0x4012be
      <main+334><br>
      00000000004012BA b001                     mov    $0x1,%al<br>
      00000000004012BC eb02                     jmp    0x4012c0
      <main+336><br>
      00000000004012BE 30c0                     xor    %al,%al<br>
      00000000004012C0 84c0                     test   %al,%al<br>
      00000000004012C2 75cc                     jne    0x401290
      <main+288><br>
    </div>
    <div><br>
    </div>
    <div>Nearly every line is accessing some memory, when it could keep
      everything in a few registers. amd64 has 16 registers, but fpc
      seems to only know three when records are involved<br>
    </div>
    <div><br>
    </div>
    <br>
    <div><br>
      Cheers,<br>
      Benito </div>
    <br>
    <div class="gmail-m_-6459721920992548386moz-cite-prefix">Am 22.02.19 um 16:51 schrieb Ben
      Grasset:<br>
    </div>
    <blockquote type="cite">
      
      <div dir="ltr">
        <div dir="ltr">
          <div dir="ltr">On Fri, Feb 22, 2019 at 1:07 AM Paul van Helden
            <<a href="mailto:paul@planetgis.co.za" target="_blank">paul@planetgis.co.za</a>> wrote:<br>
          </div>
          <div class="gmail_quote">
            <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
              <div dir="ltr">
                <div class="gmail_quote">
                  <div> How do you make a (for in) enumerator with a
                    record? I don't use them for exactly this reason,
                    and they did seem to be another useful language
                    feature that turned out to be poorly implemented by
                    Embarcadero. (Haven't checked with FPC).</div>
                </div>
              </div>
            </blockquote>
            <div><br>
            </div>
            <div>Here's an example (for FPC) that demonstrates it by
              implementing the "take-while" pattern:</div>
            <div><br>
            </div>
            <div>program TakeWhileExample;</div>
            <div><br>
            </div>
            <div>{$mode Delphi}{$H+}{$J-}</div>
            <div>{$modeswitch NestedProcVars}</div>
            <div>{$ImplicitExceptions Off}</div>
            <div>{$PointerMath On}</div>
            <div><br>
            </div>
            <div>type</div>
            <div>  TSlice<T> = record</div>
            <div>  public type</div>
            <div>    PT = ^T;</div>
            <div>    ArrayType = array of T;</div>
            <div>  private</div>
            <div>    FFirst, FLast, FCurrent: PT;</div>
            <div>    function GetCurrent: T; inline;</div>
            <div>  public</div>
            <div>    function GetEnumerator: TSlice<T>; inline;</div>
            <div>    function MoveNext: Boolean; inline;</div>
            <div>    class function TakeWhile(const A: ArrayType;
              function F(const Val: T): Boolean): TSlice<T>;
              static; inline;</div>
            <div>    property Current: T read GetCurrent;</div>
            <div>  end;</div>
            <div><br>
            </div>
            <div>  TTestFunc<T> = function(const Val: T): Boolean;</div>
            <div><br>
            </div>
            <div>  function TSlice<T>.GetCurrent: T;</div>
            <div>  begin</div>
            <div>    Result := FCurrent^;</div>
            <div>  end;</div>
            <div><br>
            </div>
            <div>  function TSlice<T>.GetEnumerator:
              TSlice<T>;</div>
            <div>  begin</div>
            <div>    Result := Self;</div>
            <div>    with Result do FCurrent := FFirst - 1;</div>
            <div>  end;</div>
            <div><br>
            </div>
            <div>  function TSlice<T>.MoveNext: Boolean;</div>
            <div>  begin</div>
            <div>    Inc(FCurrent);</div>
            <div>    Exit((FCurrent <= FLast) and (FFirst <>
              FLast));</div>
            <div>  end;</div>
            <div><br>
            </div>
            <div>  function Test(const Val: SizeUInt): Boolean; inline;</div>
            <div>  begin</div>
            <div>    Exit((Val < 50000000));</div>
            <div>  end;</div>
            <div><br>
            </div>
            <div>  class function TSlice<T>.TakeWhile(const A:
              ArrayType; function F(const Val: T): Boolean):
              TSlice<T>;</div>
            <div>  var</div>
            <div>    I: SizeUInt;</div>
            <div>    X: TTestFunc<T> absolute F;</div>
            <div>    //FPC generates slightly better code for the
              "absolute" way, not sure why...</div>
            <div>  begin</div>
            <div>    with Result do begin</div>
            <div>      FFirst := @A[0];</div>
            <div>      FLast := @A[0];</div>
            <div>      for I := 0 to High(A) do</div>
            <div>        case X(A[I]) of</div>
            <div>          True: Inc(FLast);</div>
            <div>          False: Exit();</div>
            <div>        end;</div>
            <div>    end;</div>
            <div>  end;</div>
            <div><br>
            </div>
            <div>var</div>
            <div>  I, J: SizeUInt;</div>
            <div>  Arr: TSlice<SizeUInt>.ArrayType;</div>
            <div><br>
            </div>
            <div>begin</div>
            <div>  SetLength(Arr, 100000000);</div>
            <div>  for I := 0 to 99999999 do Arr[I] := I;</div>
            <div>  I := 0;</div>
            <div>  J := 0;</div>
            <div>  for I in TSlice<SizeUInt>.TakeWhile(Arr, Test)
              do J := I;</div>
            <div>  WriteLn(J);</div>
            <div>end. </div>
          </div>
        </div>
      </div>
      <br>
      <fieldset class="gmail-m_-6459721920992548386mimeAttachmentHeader"></fieldset>
      <pre class="gmail-m_-6459721920992548386moz-quote-pre">_______________________________________________
fpc-devel maillist  -  <a class="gmail-m_-6459721920992548386moz-txt-link-abbreviated" href="mailto:fpc-devel@lists.freepascal.org" target="_blank">fpc-devel@lists.freepascal.org</a>
<a class="gmail-m_-6459721920992548386moz-txt-link-freetext" href="http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel" target="_blank">http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel</a>
</pre>
    </blockquote>
  </div>

_______________________________________________<br>
fpc-devel maillist  -  <a href="mailto:fpc-devel@lists.freepascal.org" target="_blank">fpc-devel@lists.freepascal.org</a><br>
<a href="http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel" rel="noreferrer" target="_blank">http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel</a><br>
</blockquote></div>