Re: [fpc-devel] Registers allocation technique

2014-10-01 Thread Sergei Gorelkin

30.09.2014 23:34, Sven Barth пишет:

On 30.09.2014 18:37, Lag Programming wrote:

1) Unless a function calls another function, the function result
register will always be in rax. Calling for inlined functions doesn't
change this behaviour as it's not a real function call.


RAX will only then be used for the function result when it is really needed 
(e.g. the last
assignment in a function).


To somewhat clarify: the reqirement is to place result into RAX at the function exit point. This is 
unrelated to assignments to the 'result' variable in code.


 Before that the compiler might reuse RAX as it pleases.
Likewise, the value of 'result' may be placed into any register or even to 
memory.

Regards,
Sergei

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Registers allocation technique

2014-09-30 Thread Sven Barth

On 30.09.2014 18:37, Lag Programming wrote:

1) Unless a function calls another function, the function result
register will always be in rax. Calling for inlined functions doesn't
change this behaviour as it's not a real function call.


RAX will only then be used for the function result when it is really 
needed (e.g. the last assignment in a function). Before that the 
compiler might reuse RAX as it pleases.


Please note that a function result might also be returned by memory 
(managed types and large records), by SSE register (floating point 
values) or in RAX AND RDX (records of which the size is less or equal to 
16 Byte).


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Registers allocation technique

2014-09-30 Thread Lag Programming
   Thank you Sven. 
   Unfortunately I can't find a way to compress the information in few lines 
without losing important information. I've already done that mistake in the 
first mail, now I'll try to fully explain why I'm interested in the way these 
registers are allocated. Even if the mail is long I've tried to write it as 
readable as possible. I'll try to explain, step by step, with the help of 3 
versions of a common function. I've chosen the pos function.
 

HERE IS THE ORIGINAL VERSION. YOU CAN SKIP THE PASCAL CODE.
{Elapsed time for this function in tests:6830ms.
# Var $result located in register r14
# Var i located in register rbx
# Var MaxLen located in register r13
# Var pc located in register r12
Temps allocated between rsp+16 and rsp+48}
Function PosORIGINAL(Const Substr : AnsiString; Const Source : AnsiString) : 
SizeInt;
var
  i,MaxLen : SizeInt;
  pc : pchar;
begin
  RESULT:=0;
  if Length(SubStr)0 then
   begin
 MaxLen:=Length(source)-Length(SubStr);
 i:=0;
 pc:=@source[1];
 while (i=MaxLen) do
  begin
inc(i);
if (SubStr[1]=pc^) and
   (CompareByte(Substr[1],pc^,Length(SubStr))=0) then
 begin
   RESULT:=i;
   exit;
 end;
inc(pc);
  end;
   end;
end;


HERE COMES THE FIRST MODIFIED VERSION OF THE ORIGINAL FUNCTION. YOU CAN SKIP 
THE PASCAL CODE.
{Compared with PosORIGINAL, variable MaxLen has been removed, the while 
loop has been replaced with a for loop and if Length(SubStr)0 then is 
replaced by if Length(SubStr)0 then.
Elapsed time for this function in tests:6000ms. That's ~800ms faster than 
original function.
# Var $result located in register r12
# Var pc located in register r14
# Var I located in register rbx
Temps allocated between rsp+16 and rsp+48}
{Function PosFASTER(Const Substr:AnsiString; Const Source:AnsiString):SizeInt;
var pc:pchar;
I:SIZEINT;
begin
if Length(SubStr)0 then
   begin
   pc:=@source[1];
   for I:=1 to (Length(source)-Length(SubStr)+1) do
   if (SubStr[1]=pc^)and(CompareByte(Substr[1],pc^,Length(SubStr))=0) then 
exit(I) else inc(pc);
   end;
RESULT:=0;
end;}


HERE COMES THE VERSION I'D LIKE TO RUN FASTEST. YOU CAN SKIP THE PASCAL CODE.
{Compared with function PosFASTER, variable I:SIZEINT has been removed and 
replaced with result.
Elapsed time for this function in tests:6600ms. WHICH IS NOT WHAT I WANTED!!!
# Temps allocated between rsp+16 and rsp+40
# Var $result located in register r13
# Var pc located in register rbx}
Function PosWISHTORUNFASTEST(Const Substr:AnsiString; Const 
Source:AnsiString):SizeInt;
var pc:pchar;
begin
if Length(SubStr)0 then
   begin
   pc:=@source[1];
   for RESULT:=1 to (Length(source)-Length(SubStr)+1) do
   if (SubStr[1]=pc^)and(CompareByte(Substr[1],pc^,Length(SubStr))=0) then 
exit else inc(pc);
   end;
RESULT:=0;
end;


   CONCLUSION
   The second version(PosFASTER) runs noticeable faster(6000ms.) compared to 
the original version(6800ms). I wish the third version(PosWISHTORUNFASTEST) to 
run even faster(less than 6000ms in my tests). Why? Because by removing the 
variable I:SIZEINT; I consider I make the job easier to the compiler. Instead 
of running faster, the third version(PosWISHTORUNFASTEST) runs significantly 
slower(6600ms) than the second version(PosFASTER)(6000ms). There are two 
possible reasons for this slowdown:
   1)I hit the if...then...else anomaly again, but I strongly doubt this is 
the reason of the slowdown.
   2)Using r13(result) is slower than rbx(I). If this is the case then I'd 
like a solution for these situations. In my mind I have three approaches:
   a) When function result is used in a for loop, try to assign a better 
register.
   b) If the first approach is not good, then give the programmer the chance to 
act as a child: I would like one of these registers for a variable, or I don't 
want a register in the r12-r15 range for the function result. I think C has a 
directive register for variables, I don't know much about it.
   c) If none of the above is ok, then please explain how can I identify the 
functions that can use the result in for loops without penalties regarding 
speed. For example I've noticed that if a function doesn't contain a call to 
another function or procedure than, a int64 result is returned in rax, not r12, 
which should be ok for me, see Function Pos(c : Char; Const s : AnsiString) : 
SizeInt;.

   I'm not much interested in while loops as I'm interested in for ones. I 
hope I've explained better this time.
   Thank you for patience.


 
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel