Sign in Join

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

Mailing lists / fpc-devel / 2008-11

Generated code of constant parameters of double type

16 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

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

Luiz Americo Pereira Camara

While discussing if is worth using const parameters for string and double types in a Lazarus bug report (
http://bugs.freepascal.org/view.php?id=12642 ), it was noticed that does not make difference using constant parameters or not for double types.

So is this the expected behavior or a bug in fpc?

Bellow is the generated code (fpc222) and the test program.

Luiz

.section .text.n_p$asmconstparameter_byvalue$double .balign 16,0x90
.globl P$ASMCONSTPARAMETER_BYVALUE$DOUBLE
P$ASMCONSTPARAMETER_BYVALUE$DOUBLE:
# Temps allocated between ebp-8 and ebp-8
# [17] begin
pushl %ebp
movl %esp,%ebp
subl $8,%esp
# Var V located at ebp+8
# Var i located at ebp-8
# [18] i := V;
movl 8(%ebp),%eax
movl %eax,-8(%ebp)
movl 12(%ebp),%eax
movl %eax,-4(%ebp)
# [19] DoIt(i);
subl $8,%esp
movl -8(%ebp),%eax
movl %eax,(%esp)
movl -4(%ebp),%eax
movl %eax,4(%esp)
call P$ASMCONSTPARAMETER_DOIT$DOUBLE
# [20] end;
leave
ret $8

.section .text.n_p$asmconstparameter_byreference$double .balign 16,0x90
.globl P$ASMCONSTPARAMETER_BYREFERENCE$DOUBLE
P$ASMCONSTPARAMETER_BYREFERENCE$DOUBLE:
# Temps allocated between ebp-8 and ebp-8
# [25] begin
pushl %ebp
movl %esp,%ebp
subl $8,%esp
# Var V located at ebp+8
# Var i located at ebp-8
# [26] i := V;
movl 8(%ebp),%eax
movl %eax,-8(%ebp)
movl 12(%ebp),%eax
movl %eax,-4(%ebp)
# [27] DoIt(i);
subl $8,%esp
movl -8(%ebp),%eax
movl %eax,(%esp)
movl -4(%ebp),%eax
movl %eax,4(%esp)
call P$ASMCONSTPARAMETER_DOIT$DOUBLE
# [28] end;
leave
ret $8

Reply by email

Luiz Americo Pereira Camara
to Florian Klaempfl
Florian Klaempfl wrote 11 lines
Luiz Americo Pereira Camara schrieb: > While discussing if is worth using const parameters for string and > double types in a Lazarus bug report ( > http://bugs.freepascal.org/view.php?id=12642 ), it was noticed that > does not make difference using constant parameters or not for double > types. > > So is this the expected behavior or a bug in fpc? It is the expected behaviour.

Thanks.

Maybe the documentation
(http://www.freepascal.org/docs-html/ref/refsu50.html#x126-13300011.4.4) can be modified to clarify this since the statement:

"A constant argument is passed by reference if its size is larger than a pointer."

leads to the conclusion that double types (8 bytes) would be passed as reference in 32bit code.

Luiz

Reply by email

Florian Klaempfl
to Luiz Americo Pereira Camara
Show quoted text 24 lines
Florian Klaempfl escreveu: > Luiz Americo Pereira Camara schrieb: >> While discussing if is worth using const parameters for string and >> double types in a Lazarus bug report ( >> http://bugs.freepascal.org/view.php?id=12642 ), it was noticed that >> does not make difference using constant parameters or not for double >> types. >> >> So is this the expected behavior or a bug in fpc? > > It is the expected behaviour. > Thanks. Maybe the documentation (http://www.freepascal.org/docs-html/ref/refsu50.html#x126-13300011.4.4) can be modified to clarify this since the statement: "A constant argument is passed by reference if its size is larger than a pointer." leads to the conclusion that double types (8 bytes) would be passed as reference in 32bit code.

Well, the bigger problem is that this is target dependent.

Reply by email

Jonas Maebe
to Florian Klaempfl
Florian Klaempfl wrote 9 lines
Luiz Americo Pereira Camara schrieb: > Maybe the documentation (http://www.freepascal.org/docs-html/ref/refsu50.html#x126-13300011.4.4 > ) can be modified to clarify this since the statement: > "A constant argument is passed by reference if its size is larger > than a pointer." > leads to the conclusion that double types (8 bytes) would be passed > as reference in 32bit code. Well, the bigger problem is that this is target dependent.

And calling convention dependent. In most cases, how exactly constant and value parameters are handled by the compiler is a private implementation detail. You cannot count on how it is exactly implemented.

Jonas

Reply by email

Luiz Americo Pereira Camara
to Jonas Maebe
Jonas Maebe wrote 17 lines
On 16 Nov 2008, at 14:52, Florian Klaempfl wrote: > Luiz Americo Pereira Camara schrieb: >> Maybe the documentation >> (http://www.freepascal.org/docs-html/ref/refsu50.html#x126-13300011.4.4) >> can be modified to clarify this since the statement: >> "A constant argument is passed by reference if its size is larger >> than a pointer." >> leads to the conclusion that double types (8 bytes) would be passed >> as reference in 32bit code. > > Well, the bigger problem is that this is target dependent. And calling convention dependent. In most cases, how exactly constant and value parameters are handled by the compiler is a private implementation detail. You cannot count on how it is exactly implemented.

Ok. I was not counting in implementation details.

My point was that this could be a missing optimization opportunity: pass by reference a 8 bytes parameter when the pointer size is 4. I also tested with TPoint (8 bytes) and it's passed by reference unlike double (also 8 bytes) that is passed by value always.

Probably i'm missing some information why double is treated differently of a record of same size. I don't have compiler knowledge. All my conclusions came from the documentation.

Luiz

Reply by email

Florian Klaempfl
to Luiz Americo Pereira Camara
Show quoted text 23 lines
Jonas Maebe escreveu: > > On 16 Nov 2008, at 14:52, Florian Klaempfl wrote: > >> Luiz Americo Pereira Camara schrieb: >>> Maybe the documentation >>> (http://www.freepascal.org/docs-html/ref/refsu50.html#x126-13300011.4.4) >>> can be modified to clarify this since the statement: >>> "A constant argument is passed by reference if its size is larger >>> than a pointer." >>> leads to the conclusion that double types (8 bytes) would be passed >>> as reference in 32bit code. >> >> Well, the bigger problem is that this is target dependent. > > And calling convention dependent. In most cases, how exactly constant > and value parameters are handled by the compiler is a private > implementation detail. You cannot count on how it is exactly implemented. Ok. I was not counting in implementation details. My point was that this could be a missing optimization opportunity: pass by reference a 8 bytes parameter when the pointer size is 4.

Don't forget that this makes an extra memory access.

Reply by email

Luiz Americo Pereira Camara
to Florian Klaempfl
Florian Klaempfl wrote 5 lines
Luiz Americo Pereira Camara schrieb: > My point was that this could be a missing optimization opportunity: > pass by reference a 8 bytes parameter when the pointer size is 4. Don't forget that this makes an extra memory access.

I will do my question in a simpler way:

Using constant parameters (add const keyword in front of an argument) is beneficial for record types with size > pointer size and for string types but not for integer and pointer types.

Currently is not beneficial for double types and there's no way to improve that. So when developing an interface that uses double types does not matter using const or not. Now and in the future. Right?

Luiz

Reply by email

Florian Klaempfl
to Luiz Americo Pereira Camara
Show quoted text 12 lines
Florian Klaempfl escreveu: > Luiz Americo Pereira Camara schrieb: >> My point was that this could be a missing optimization opportunity: >> pass by reference a 8 bytes parameter when the pointer size is 4. > > Don't forget that this makes an extra memory access. I will do my question in a simpler way: Using constant parameters (add const keyword in front of an argument) is beneficial for record types with size > pointer size and for string types but not for integer and pointer types.

No, this is not necessarily true. The extra indirect can be also slower.

Currently is not beneficial for double types and there's no way to improve that. So when developing an interface that uses double types does not matter using const or not. Now and in the future. Right?

It might matter for the optimizer in other situations.

Reply by email

Luiz Americo Pereira Camara
to Florian Klaempfl
Florian Klaempfl wrote 15 lines
Luiz Americo Pereira Camara schrieb: > Florian Klaempfl escreveu: >> Luiz Americo Pereira Camara schrieb: >>> My point was that this could be a missing optimization opportunity: >>> pass by reference a 8 bytes parameter when the pointer size is 4. >> >> Don't forget that this makes an extra memory access. > > I will do my question in a simpler way: > > Using constant parameters (add const keyword in front of an argument) > is beneficial for record types with size > pointer size and for > string types but not for integer and pointer types. No, this is not necessarily true. The extra indirect can be also slower.

For string types it will avoid incrementing and decrementing the ref count. See the test i did at
http://lazarusroad.blogspot.com/2008/11/effect-of-using-constant-parameter-for.html and the code diff at http://www.geocities.com/camara_luiz/coddiff.htm

For record (TPoint) the constant version generate less code. See the attached diff.

Show quoted text 7 lines
> > Currently is not beneficial for double types and there's no way to > improve that. So when developing an interface that uses double types > does not matter using const or not. Now and in the future. Right? It might matter for the optimizer in other situations.

I am developing an component that heavily uses double types. So for read only arguments is better to use constant parameters?

For the record: Int64 has the same behavior as double regarding this issue.

Luiz

Reply by email

Florian Klaempfl
to Luiz Americo Pereira Camara
Show quoted text 24 lines
Florian Klaempfl escreveu: > Luiz Americo Pereira Camara schrieb: >> Florian Klaempfl escreveu: >>> Luiz Americo Pereira Camara schrieb: >>>> My point was that this could be a missing optimization opportunity: >>>> pass by reference a 8 bytes parameter when the pointer size is 4. >>> >>> Don't forget that this makes an extra memory access. >> >> I will do my question in a simpler way: >> >> Using constant parameters (add const keyword in front of an argument) >> is beneficial for record types with size > pointer size and for >> string types but not for integer and pointer types. > > No, this is not necessarily true. The extra indirect can be also slower. For string types it will avoid incrementing and decrementing the ref count. See the test i did at http://lazarusroad.blogspot.com/2008/11/effect-of-using-constant-parameter-for.html and the code diff at http://www.geocities.com/camara_luiz/coddiff.htm For record (TPoint) the constant version generate less code. See the attached diff.

Please check also the code in the callee ;)

Reply by email

Luiz Americo Pereira Camara
to Florian Klaempfl
Florian Klaempfl wrote 29 lines
Luiz Americo Pereira Camara schrieb: > Florian Klaempfl escreveu: >> Luiz Americo Pereira Camara schrieb: >>> Florian Klaempfl escreveu: >>>> Luiz Americo Pereira Camara schrieb: >>>>> My point was that this could be a missing optimization >>>>> opportunity: pass by reference a 8 bytes parameter when the >>>>> pointer size is 4. >>>> >>>> Don't forget that this makes an extra memory access. >>> >>> I will do my question in a simpler way: >>> >>> Using constant parameters (add const keyword in front of an >>> argument) is beneficial for record types with size > pointer size >>> and for string types but not for integer and pointer types. >> >> No, this is not necessarily true. The extra indirect can be also >> slower. > > For string types it will avoid incrementing and decrementing the ref > count. See the test i did at > http://lazarusroad.blogspot.com/2008/11/effect-of-using-constant-parameter-for.html > and the code diff at http://www.geocities.com/camara_luiz/coddiff.htm > > For record (TPoint) the constant version generate less code. See the > attached diff. Please check also the code in the callee ;)

I already checked: is equal.

Luiz

# Temps allocated between ebp+0 and ebp+0
# [33] begin
pushl %ebp
movl %esp,%ebp
call FPC_INITIALIZEUNITS
# [34] x.x := 1;
movl $1,U_P$ASMCONSTPARAMETERREC_X
# [35] x.y := 2;
movl $2,U_P$ASMCONSTPARAMETERREC_X+4
# [36] ByValue(X);
movl $U_P$ASMCONSTPARAMETERREC_X,%eax
call P$ASMCONSTPARAMETERREC_BYVALUE$POINT
# [37] ByReference(X);
movl $U_P$ASMCONSTPARAMETERREC_X,%eax
call P$ASMCONSTPARAMETERREC_BYREFERENCE$POINT
# [38] end.
call FPC_DO_EXIT
leave
ret

Reply by email

Florian Klaempfl
to Luiz Americo Pereira Camara
Show quoted text 32 lines
Florian Klaempfl escreveu: > Luiz Americo Pereira Camara schrieb: >> Florian Klaempfl escreveu: >>> Luiz Americo Pereira Camara schrieb: >>>> Florian Klaempfl escreveu: >>>>> Luiz Americo Pereira Camara schrieb: >>>>>> My point was that this could be a missing optimization >>>>>> opportunity: pass by reference a 8 bytes parameter when the >>>>>> pointer size is 4. >>>>> >>>>> Don't forget that this makes an extra memory access. >>>> >>>> I will do my question in a simpler way: >>>> >>>> Using constant parameters (add const keyword in front of an >>>> argument) is beneficial for record types with size > pointer size >>>> and for string types but not for integer and pointer types. >>> >>> No, this is not necessarily true. The extra indirect can be also >>> slower. >> >> For string types it will avoid incrementing and decrementing the ref >> count. See the test i did at >> http://lazarusroad.blogspot.com/2008/11/effect-of-using-constant-parameter-for.html >> and the code diff at http://www.geocities.com/camara_luiz/coddiff.htm >> >> For record (TPoint) the constant version generate less code. See the >> attached diff. > > Please check also the code in the callee ;) I already checked: is equal.

No, just look at the actual assignment:
i:=v;
By const/reference it generates 5 instructions, by value only 4. The rest is entry code. If you've only one access, passing by reference might have an advantage, the more accesses you have, the better direct passing is. Just benchmark a loop ;)

Reply by email

Luiz Americo Pereira Camara
to Florian Klaempfl
Florian Klaempfl wrote 40 lines
Luiz Americo Pereira Camara schrieb: > Florian Klaempfl escreveu: >> Luiz Americo Pereira Camara schrieb: >>> Florian Klaempfl escreveu: >>>> Luiz Americo Pereira Camara schrieb: >>>>> Florian Klaempfl escreveu: >>>>>> Luiz Americo Pereira Camara schrieb: >>>>>>> My point was that this could be a missing optimization >>>>>>> opportunity: pass by reference a 8 bytes parameter when the >>>>>>> pointer size is 4. >>>>>> >>>>>> Don't forget that this makes an extra memory access. >>>>> >>>>> I will do my question in a simpler way: >>>>> >>>>> Using constant parameters (add const keyword in front of an >>>>> argument) is beneficial for record types with size > pointer size >>>>> and for string types but not for integer and pointer types. >>>> >>>> No, this is not necessarily true. The extra indirect can be also >>>> slower. >>> >>> For string types it will avoid incrementing and decrementing the >>> ref count. See the test i did at >>> http://lazarusroad.blogspot.com/2008/11/effect-of-using-constant-parameter-for.html >>> and the code diff at http://www.geocities.com/camara_luiz/coddiff.htm >>> >>> For record (TPoint) the constant version generate less code. See >>> the attached diff. >> >> Please check also the code in the callee ;) > > I already checked: is equal. No, just look at the actual assignment: i:=v; By const/reference it generates 5 instructions, by value only 4. The rest is entry code. If you've only one access, passing by reference might have an advantage, the more accesses you have, the better direct passing is. Just benchmark a loop ;)

Thanks for pointing that. Seems that the only clear advantage of const is in string types. For records it depends how is accessed/used inside the function.

Luiz

Reply by email

Alexander Klenin
to Florian Klaempfl: No, just look at the actual assignment: i:=v; By const/reference it generates 5…
Florian Klaempfl wrote 5 lines
No, just look at the actual assignment: i:=v; By const/reference it generates 5 instructions, by value only 4. The rest is entry code. If you've only one access, passing by reference might have an advantage, the more accesses you have, the better direct passing is.

This is true only if the code is compiled without optimization. At -O2 level, the access code is indeed identical from performace POV.

Just benchmark a loop ;)

I did, see attachment. On the random old PC it gives me: By val = 1.47s
By ref = 0.72s

By increasing the value of NR constant, you can diminish speed difference, but the by-ref case is always faster.

Anyway, for me the true reason for always using by-ref convention for const parameters
is semantic consistency and Delphi compatibility.

Alexander S. Klenin Insight Experts Ltd.

Reply by email

Florian Klaempfl
to Alexander Klenin
Show quoted text 12 lines
On Mon, Nov 17, 2008 at 05:39, Florian Klaempfl wrote: > No, just look at the actual assignment: > i:=v; > By const/reference it generates 5 instructions, by value only 4. The rest is > entry code. If you've only one access, passing by reference might have an > advantage, the more accesses you have, the better direct passing is. This is true only if the code is compiled without optimization. At -O2 level, the access code is indeed identical from performace POV. > Just benchmark a loop ;) I did, see attachment. On the random old PC it gives me:

Yes, the compiler can hide in the this case the additional load because the procedure is very simple. Also alignment is part of the game, but the main point is that in the ref. case the compiler can use a stack pointer based stack while in the other case it needs a frame pointer based stack.

It simply depends on the procedure code (and the architecture!) what's faster

Show quoted text 17 lines
By val = 1.47s By ref = 0.72s By increasing the value of NR constant, you can diminish speed difference, but the by-ref case is always faster. Anyway, for me the true reason for always using by-ref convention for const parameters is semantic consistency and Delphi compatibility. ------------------------------------------------------------------------ _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email