Optimizing function result when it is not used in other places
Summary
I was working on a sample and found a problem. I watched the assembly code, and it does not seem to have an alignment problem. The outputted assembly has Initialize (the assembly code preparing a clean value (It was similar to the assembly of A := Default(TTest) line)) and FPC_COPY on every loop step, and it is near 10X slower. Why adding the first Default out of the loop, affect the loop in such a manner? I noted the alignment problem because this sample is from my forum post about Default() and in the first sample, others suggested it is a alignment issue. But in this one, I think FPC thinks that because A is used outside of the loop, the result of the function should be const instead of var, which leads to making a clean variable on each loop.
System Information
Lazarus 2.3.0 (rev main-2_3-2865-g5895004fde) FPC 3.3.1 x86_64-win64-win32/win64
Example Project
program Project1;
uses
SysUtils;
type
TTest = record
V: array of QWord;
end;
procedure Assign(var A: TTest; const B: TTest); inline;
begin
if Length(A.V) <> Length(B.V) then
SetLength(A.V, Length(B.V));
if Length(B.V) <> 0 then
Move(B.V[0], A.V[0], Length(B.V) * SizeOf(QWord));
end;
procedure Assign(var A: TTest; const B: QWord); inline;
begin
if Length(A.V) <> 1 then
SetLength(A.V, 1);
A.V[0] := B;
end;
operator := (const AValue: QWord): TTest; //inline;
begin
Assign(Result, AValue);
end;
procedure Test;
var
T: QWord;
I: Int64;
A: TTest;
begin
//A := Default(TTest);
T := GetTickCount64;
for I := 1 to 1000 * 1000 * 1000 do
//Assign(A, I); //1140ms with and without Default
A := I; //1900ms with Default and 15500 without (near 10X slower)
WriteLn(GetTickCount64 - T);
end;
begin
Test;
ReadLn;
end.
Relevant 3rd party information
This post on forum: https://forum.lazarus.freepascal.org/index.php/topic,63517.msg481195.html#msg481195
And this issue: #39725