<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>