Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2012-12

Registers in loops

7 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

denisgolovan

Hi all

Recently I discovered that fpc refuses to use registers in my loops even with optimization turned on (-O1,-O3 used). I tested using both Linux x86 and Windows x64 version.

The results are basically the same.
The compiler just uses stack variables.

I've also included naive asm version of the same loop just to see the comparison. All tests were done using EpikTimer.

======================================
Intel(R) Core(TM) i5-2500K CPU @ 3.30GHz
Sandy Bridge-DT XE
Microsoft Windows XP Professional x64 Edition Build 3790 Free Pascal Compiler version 2.7.1 [2012/08/25] for x86_64 Result:

asm 0.0256358138703286 sec
for downto 0.193564002384441 sec
for to 0.177300077002942 sec
repeat 0.158137833298043 sec
while 0.156996773175159 sec

Intel(R) Core(TM)2 CPU 6600 @ 2.40GHz
Linux x86
Free Pascal Compiler version 2.7.1 [2012/11/17] for i386 Result:

asm 0.049642 sec
for downto 0.322694 sec
for to 0.312163 sec
repeat 0.298781 sec
while 0.298575 sec
======================================

You can easily see that asm version is about 10 times faster. Is this something that can be fixed?

P.S. A full test source + assembler listings are attached.

Regards, Denis Golovan
patspiper
to denisgolovan: Hi all Recently I discovered that fpc refuses to use registers in my loops even with…
denisgolovan wrote
Hi all Recently I discovered that fpc refuses to use registers in my loops even with optimization turned on (-O1,-O3 used).

With the asm code commented out and without any optimization, the registers are used.

.Ll12:
# [47] for i:=1 to 100000000 do
movl $1,%ebx
decl %ebx
.balign 4,0x90
.Lj80:
incl %ebx
.Ll13:
# [48] Inc(i2);
incl %eax
.Ll14:
cmpl $100000000,%ebx
jb .Lj80
...
.Ll18:
# [53] i:=1;
movl $1,%ebx
.balign 4,0x90
.Lj111:
.Ll19:
# [55] Inc(i);
incl %ebx
.Ll20:
# [56] until i>100000000;
cmpl $100000000,%ebx
jna .Lj111
...
.Ll24:
# [61] i:=1;
movl $1,%ebx
.Ll25:
# [62] while i<100000000 do
jmp .Lj145
.balign 4,0x90
.Lj144:
.Ll26:
# [63] Inc(i);
incl %ebx
.Lj145:
.Ll27:
cmpl $100000000,%ebx
jb .Lj144

Stephano

Jonas Maebe
to patspiper
patspiper wrote 7 lines
On 13/12/12 21:51, denisgolovan wrote: > Hi all > > Recently I discovered that fpc refuses to use registers in my loops > even with optimization turned on (-O1,-O3 used). With the asm code commented out and without any optimization, the registers are used.

Indeed, adding inline assembler to a routine disables many optimizations.

Jonas

Unknown author
to Jonas Maebe
Jonas Maebe wrote 12 lines
On 14 Dec 2012, at 09:26, patspiper wrote: > On 13/12/12 21:51, denisgolovan wrote: >> Hi all >> >> Recently I discovered that fpc refuses to use registers in my loops even >> with optimization turned on (-O1,-O3 used). > With the asm code commented out and without any optimization, the registers > are used. Indeed, adding inline assembler to a routine disables many optimizations.

Doesn't adding the list of modified registers to the 'ASM' block help in this case ? I thought this was why we supported this ?

Michael.

Jonas Maebe
to Unknown author
Show quoted text 7 lines
On Fri, 14 Dec 2012, Jonas Maebe wrote: > Indeed, adding inline assembler to a routine disables many > optimizations. Doesn't adding the list of modified registers to the 'ASM' block help in this case ? I thought this was why we supported this ?

That's required to guarantee the correctness of the generated code under all circumstances. It doesn't help with register variables though:

{$asmmode intel}
procedure test;
var
   l: longint;
begin
   // compiler decides to put l into register eax
   l:=1;
   asm
     push eax
     push edx
     rdtsc
     mov  l,eax
     pop edx
     pop eax
   end; // no register changed -> no list required
   // always writes 1
   writeln(l);
end;

It would be possible to prevent registers accessed from assembler code to be put into registers, but currently the compiler does not perform any kind of analysis of assembler code, and I think it should stay that way. There are too many ways in which assembler code can be written that defeats automatic analyses. If you use assembler, you get full freedom and that freedom gets taken away from the compiler.

Jonas

denisgolovan
Indeed, adding inline assembler to a routine disables many optimizations. Jonas

Hm.
Yeap. Looks like I completely missed the point :)
Thanks for the explanation.

Regards, Denis Golovan