code generation for var and out parameters lazarus / 64-FPC development ---------------------------------------------------------------------- 440bx · 2018-07-11 08:24 Hello, I'm currently RTFM Programmer's Reference and getting acquainted with FPC.  On page 198, the following program appears to illustrate the use of out vs var. What is interesting is that the code that is generated to pass an out parameter is different than the code generated to pass a var parameter. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$H-} program OutParameters; Procedure DoA(var A : integer);begin  A := 2;  writeln(A);end; procedure DoB(out B : integer);begin  B := 3;  writeln(B);end; var  C, D : integer; begin  DoA(C);  DoB(D);end. In the case of the var parameter, the address of the parameter is first loaded into rax then moved into rcx as shown below (debugger assembly view) whereas in the case of the out parameter, the address is loaded directly into rcx. QuoteOutParameters.lpr:21                      DoA(C); 000000010000150A 488d05efda0000           lea    0xdaef(%rip),%rax    0000000100001511 4889c1                   mov    %rax,%rcx 0000000100001514 e847ffffff               callq  0x100001460 In the case of the out parameter, the address of the parameter is directly loaded into rcx. OutParameters.lpr:22                      DoB(D); 0000000100001519 488d0df0da0000           lea    0xdaf0(%rip),%rcx      0000000100001520 e88bffffff               callq  0x1000014b0 It seems that when using a var parameter, the address of the parameter is not passed optimally, yet the compiler knows how to generate optimal code since it does for the out parameter. Note: The above code is the result of compiling with -03 optimizations. ---------------------------------------------------------------------- Jonas Maebe · 2018-07-11 08:34 When code initially gets generated, it is full of those superfluous register move operations. The register allocator then removes most of them, but it indeed does not always succeed. There is no inherent difference between the code generation for var and out parameters. It's possible that if you reverse the order of the calls, the extra move will appear for the other one instead. ---------------------------------------------------------------------- ASerge · 2018-07-11 08:51 Quote from: Jonas Maebe on July 11, 2018, 10:34:35 amIt's possible that if you reverse the order of the calls, the extra move will appear for the other one instead. +1 For Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i begin  DoB(D);  DoA(C);  DoA(C);  DoB(D);end.generate Code: ASM  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i project1.lpr:18                           DoB(D);000000010000155E 488d059f0a0100           lea    0x10a9f(%rip),%rax        # 0x1000120040000000100001565 4889c1                   mov    %rax,%rcx0000000100001568 e883ffffff               callq  0x1000014f0 project1.lpr:19                           DoA(C);000000010000156D 488d0d8c0a0100           lea    0x10a8c(%rip),%rcx        # 0x1000120000000000100001574 e817ffffff               callq  0x100001490 project1.lpr:20                           DoA(C);0000000100001579 488d0d800a0100           lea    0x10a80(%rip),%rcx        # 0x1000120000000000100001580 e80bffffff             callq  0x100001490 project1.lpr:21                         DoB(D);0000000100001585 488d0d780a0100           lea    0x10a78(%rip),%rcx        # 0x100012004000000010000158C e85fffffff             callq  0x1000014f0 ] ---------------------------------------------------------------------- 440bx · 2018-07-11 09:01 Quote from: Jonas Maebe on July 11, 2018, 10:34:35 amThe register allocator then removes most of them, but it indeed does not always succeed. There is no inherent difference between the code generation for var and out parameters. I thought the optimizer might have been a bit lazy with -01 and thought that with -03, it would probably take care of it.  As far as there not being a difference for var and out parameters, I concur, that's why I was a bit surprised that the generated code was not the same and thought asking the compiler for deeper/greater optimization would make the superfluous load be eliminated.  Quote from: Jonas Maebe on July 11, 2018, 10:34:35 amIt's possible that if you reverse the order of the calls, the extra move will appear for the other one instead. As Serge's code above showed, the superfluous load/move only occurs for the first call.  That is very interesting. Thank you and thank Serge for your comments on this.