<HTML>
I feel like a beginner when I say that I've never used advanced records or enumerators before, or the "for-in" loop.  There's definite room for improvement there though, for sure.<br>
<br>
<div>I think the problem with the compiler is that it seeks to keep the record together in concurrent storage.  Storing individual fields in registers is essentially splitting it up, even if everything stays synchronised.  Given that the reference is an offset from %rbp, the compiler will know for sure that the variable is local, so there won't be any problems with multi-threading that prevents a lot of temporary register storage for safety reasons.</div><div><br>
</div><div>It could definitely be an area of research.  There are two possible approaches that I can see... look via the peephole optimiser to see if a variable on the stack can be optimised into a register, or look via the node compiler's second pass (converts nodes into assembly language) to see if a local variable of a record type can have its fields stored in registers.  The latter, while preferred, may be implausible with advanced records because of the methods.<br>
</div><br>
Gareth aka. Kit<br>
<br>
 <br>
<br>
<span style="font-weight: bold;">On Sat 23/02/19 00:17 , Benito van der Zander benito@benibela.de sent:<br>
</span><blockquote style="BORDER-LEFT: #F5F5F5 2px solid; MARGIN-LEFT: 5px; MARGIN-RIGHT:0px; PADDING-LEFT: 5px; PADDING-RIGHT: 0px"> 
  
 <defanged_meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
  
 <defanged_body smarttemplateinserted="true"> 
 <div id="smartTemplate4-template">Hi,<br>
 
 <br>
 
 <blockquote type="cite" cite="mid:CAL4d7FjqeUuHLRLni3wtMid3dzbmpbaBHCeqE=rC91jho0AvyQ@mail.gmail.com"> 
 <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;</sizeuint></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>
 
 </main+288></main+336></main+334></main+334></sizeuint></sizeuint></u_$p$project1_$$_j></u_$p$project1_$$_i></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="moz-cite-prefix">Am 22.02.19 um 16:51 schrieb Ben 
 Grasset:<br>
 
 </div> 
 <blockquote type="cite" cite="mid:CAL4d7Fjw5J4L5rM_U_ecEUoqainFDHoNfc9oxWUSs4YjUP-kFA@mail.gmail.com"> 
 <defanged_meta http-equiv="content-type" content="text/html; charset=UTF-8"> 
 <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">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</t></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;</t></div> 
 <div>    function MoveNext: Boolean; inline;</div> 
 <div>    class function TakeWhile(const A: ArrayType; 
 function F(const Val: T): Boolean): TSlice<t>; 
 static; inline;</t></div> 
 <div>    property Current: T read GetCurrent;</div> 
 <div>  end;</div> 
 <div><br>
 
 </div> 
 <div>  TTestFunc<t> = function(const Val: T): Boolean;</t></div> 
 <div><br>
 
 </div> 
 <div>  function TSlice<t>.GetCurrent: T;</t></div> 
 <div>  begin</div> 
 <div>    Result := FCurrent^;</div> 
 <div>  end;</div> 
 <div><br>
 
 </div> 
 <div>  function TSlice<t>.GetEnumerator: 
 TSlice<t>;</t></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;</t></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>;</t></t></div> 
 <div>  var</div> 
 <div>    I: SizeUInt;</div> 
 <div>    X: TTestFunc<t> absolute F;</t></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;</sizeuint></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;</sizeuint></div> 
 <div>  WriteLn(J);</div> 
 <div>end. </div> 
 </div> 
 </div> 
 </div> 
 <br>
 
 <fieldset class="mimeAttachmentHeader"></fieldset> 
 <pre class="moz-quote-pre" wrap="">_______________________________________________ 
fpc-devel maillist - <a class="moz-txt-link-abbreviated" href="mailto:fpc-devel@lists.freepascal.org">fpc-devel@lists.freepascal.org</a> 
<a class="moz-txt-link-freetext" href="http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel">http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel</a> 
</pre> 
 </defanged_meta></blockquote> 
  
 
 

_______________________________________________<br>

fpc-devel maillist  -  <a href="mailto:fpc-devel@lists.freepascal.org">fpc-devel@lists.freepascal.org</a><br>

<a target="_blank" href="<a href="http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel">http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel</a>"><span style="color: red;">http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel</span></a><br>

<br>

</defanged_body></defanged_meta></blockquote></HTML>