Re: [fpc-pascal] inlining functions
12.01.2019, 19:44, "Benito van der Zander" :Hi, something that appears to help is to put units in the interface uses rather than the implementation uses.When the unit mentioned in the interface uses, uses the first unit in its implementation uses, it can inline the functions from the first unit. Although I would have expected it to do the opposite. Unfortunately that does not help if the second unit needs to use types from the first unit in its interface Best,Benito Yes, I got it.The problem is that circular dependencies are too often happen in practice.The discussion is about how to make compiler inline function automatically even when circular dependencies exist. -- Regards,Denis Golovan ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] inlining functions
Hi, something that appears to help is to put units in the interface uses rather than the implementation uses. When the unit mentioned in the interface uses, uses the first unit in its implementation uses, it can inline the functions from the first unit. Although I would have expected it to do the opposite. Unfortunately that does not help if the second unit needs to use types from the first unit in its interface Best, Benito Am 12.01.19 um 13:05 schrieb denisgolovan: 12.01.2019, 14:53, "Jonas Maebe" : Not at this time (unless you use the LLVM backend). Could you give some hints on how to enable WPO/LTO under LLVM backend? http://wiki.freepascal.org/LLVM does not seem to mention anything on that. However, what you actually can do, is manually recompile all units of your program multiple times. While this won't help with inline functions called before they are parsed in those same units, it will allow inlining of function bodies in other units that were not available during the first compilation due to dependency cycles. Eh. It does not look too practical, right? Unless there is some magical receipt for that :) ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] inlining functions
12.01.2019, 16:03, "Sven Barth via fpc-pascal" :With WPO you need to compile at least twice as well as the first pass only collects information and acts on it in the second pass. Is it possible to make Lazarus do that automatically?According to Jonas it's a bit too unpractical. -- Regards,Denis Golovan ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] inlining functions
12.01.2019, 15:32, "Jonas Maebe" : > It's not yet integrated in the compiler, so you have to do it manually > right now: > a) compile everything with -al (including the RTL etc; add OPT="-a" to > the make command) > b) go in all the unit directories, and assemble the files to bitcode > using something like this: > > for file in *.ll; do > clang -emit-llvm -O -c $file > done > > c) compile your program with -a -s and do the same as in step b) for > your program > d) edit the generated link.res file, and replace all references to unit > files ending in ".o" with the same files ending in ".bc" > > If you used a custom clang rather than the one installed by default on > your system, you will also have to specify the path to the libLTO that > the linker should use. You have to do this on the ld command line in > ppas.sh. You can find the correct parameter by compiling a test > C-program with "clang -flto -### test.c", as this will print the ld > invocation to use. E.g. on macOS, it will be something like > > -lto_library > /Volumes/imac/devel/clang+llvm-7.0.0-x86_64-apple-darwin/lib/libLTO.dylib" > > On Linux, it's something like > > -plugin > /home/jmaebe/local/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/../lib/LLVMgold.so > -plugin-opt=O2 > > (or a different optimization level) Thanks, but I expected something like rebuilding compiler and adding some option to Lazarus project :) So far it looks like it's not far away from manually recompilation of each and every module. -- Regards, Denis Golovan ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] inlining functions
Am Sa., 12. Jan. 2019, 13:05 hat denisgolovan geschrieben: > > However, what you actually can do, is manually recompile all units of > your program > > multiple times. While this won't help with inline functions called > > before they are parsed in those same units, it will allow inlining of > > function bodies in other units that were not available during the first > > compilation due to dependency cycles. > > Eh. > It does not look too practical, right? > Unless there is some magical receipt for that :) > With WPO you need to compile at least twice as well as the first pass only collects information and acts on it in the second pass. Regards, Sven > ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] inlining functions
On 12/01/19 13:05, denisgolovan wrote: 12.01.2019, 14:53, "Jonas Maebe" : Not at this time (unless you use the LLVM backend). Could you give some hints on how to enable WPO/LTO under LLVM backend? http://wiki.freepascal.org/LLVM does not seem to mention anything on that. It's not yet integrated in the compiler, so you have to do it manually right now: a) compile everything with -al (including the RTL etc; add OPT="-a" to the make command) b) go in all the unit directories, and assemble the files to bitcode using something like this: for file in *.ll; do clang -emit-llvm -O -c $file done c) compile your program with -a -s and do the same as in step b) for your program d) edit the generated link.res file, and replace all references to unit files ending in ".o" with the same files ending in ".bc" If you used a custom clang rather than the one installed by default on your system, you will also have to specify the path to the libLTO that the linker should use. You have to do this on the ld command line in ppas.sh. You can find the correct parameter by compiling a test C-program with "clang -flto -### test.c", as this will print the ld invocation to use. E.g. on macOS, it will be something like -lto_library /Volumes/imac/devel/clang+llvm-7.0.0-x86_64-apple-darwin/lib/libLTO.dylib" On Linux, it's something like -plugin /home/jmaebe/local/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/../lib/LLVMgold.so -plugin-opt=O2 (or a different optimization level) However, what you actually can do, is manually recompile all units of your program multiple times. While this won't help with inline functions called before they are parsed in those same units, it will allow inlining of function bodies in other units that were not available during the first compilation due to dependency cycles. Eh. It does not look too practical, right? That's why I mentioned it's a manual process. Jonas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] inlining functions
12.01.2019, 14:53, "Jonas Maebe" : > Not at this time (unless you use the LLVM backend). Could you give some hints on how to enable WPO/LTO under LLVM backend? http://wiki.freepascal.org/LLVM does not seem to mention anything on that. > However, what you actually can do, is manually recompile all units of your > program > multiple times. While this won't help with inline functions called > before they are parsed in those same units, it will allow inlining of > function bodies in other units that were not available during the first > compilation due to dependency cycles. Eh. It does not look too practical, right? Unless there is some magical receipt for that :) -- Regards, Denis Golovan ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] inlining functions
On 12/01/19 12:47, denisgolovan wrote: 07.01.2019, 00:45, "Jonas Maebe" : Not besides breaking your dependency cycles. Sorry, but for necro-posting, but shouldn't WPO is supposed to help to inline functions as well? Not at this time (unless you use the LLVM backend). However, what you actually can do, is manually recompile all units of your program multiple times. While this won't help with inline functions called before they are parsed in those same units, it will allow inlining of function bodies in other units that were not available during the first compilation due to dependency cycles. Jonas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] inlining functions
07.01.2019, 00:45, "Jonas Maebe" : > Not besides breaking your dependency cycles. Sorry, but for necro-posting, but shouldn't WPO is supposed to help to inline functions as well? -- Regards, Denis Golovan ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] inlining functions
On 03/01/19 00:10, Benito van der Zander wrote: The one-pass thing is probably the reason it now complains about all inline functions in dependency cycles, unit A uses unit B that uses unit A. Then unit A can't inline something unit B. Any way around that? Not besides breaking your dependency cycles. Jonas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] inlining functions
Hi, procedure TStrBuilder.append(const s: RawByteString); begin append(pchar(pointer(s)), length(s)); //inlinetest.pas(24,3) Note: Call to subroutine "procedure TStrBuilder.append(const p:PChar;const l:Int64);" marked as inline is not inlined end; this seems to help procedure TStrBuilder.append(const s: RawByteString); var p: pchar; begin p := pchar(pointer(s)); append(p, length(s)); end; I would personally be in favour of removing all of the inlining hints, because they are specific to a particular compiler version and mainly cause people to waste time on premature optimisation (or on what they think is an optimisation, but in many cases slows down things due to increased instruction cache pressure). After updating from 3.1 to 3.3 I only have to look at around one thousand hints The one-pass thing is probably the reason it now complains about all inline functions in dependency cycles, unit A uses unit B that uses unit A. Then unit A can't inline something unit B. Any way around that? Best, Benito Am 02.01.19 um 00:41 schrieb Jonas Maebe: On 2019-01-02 00:19, Benito van der Zander wrote: procedure TStrBuilder.append(const s: RawByteString); begin append(pchar(pointer(s)), length(s)); //inlinetest.pas(24,3) Note: Call to subroutine "procedure TStrBuilder.append(const p:PChar;const l:Int64);" marked as inline is not inlined end; The compiler does not support inlining calls with parameters that cast a managed type to an unmanaged type at this time. Regarding the reason why something cannot be inlined: sometimes you can get more information with -vd, but not always (and even then the reason may be vague). I would personally be in favour of removing all of the inlining hints, because they are specific to a particular compiler version and mainly cause people to waste time on premature optimisation (or on what they think is an optimisation, but in many cases slows down things due to increased instruction cache pressure). Especially in this case: there is nothing potentially wrong with such a call, nor is the method in general not inlinable, so there is no way to get rid of the hint other than by removing the inline directive altogether (or by adding a version of that routine with a different name that is not declared as "inline"). This only promotes complicating code without any potential improvement of productivity or clarity of the code/programmer intent. Jonas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] inlining functions
On 2019-01-02 00:19, Benito van der Zander wrote: procedure TStrBuilder.append(const s: RawByteString); begin append(pchar(pointer(s)), length(s)); //inlinetest.pas(24,3) Note: Call to subroutine "procedure TStrBuilder.append(const p:PChar;const l:Int64);" marked as inline is not inlined end; The compiler does not support inlining calls with parameters that cast a managed type to an unmanaged type at this time. Regarding the reason why something cannot be inlined: sometimes you can get more information with -vd, but not always (and even then the reason may be vague). I would personally be in favour of removing all of the inlining hints, because they are specific to a particular compiler version and mainly cause people to waste time on premature optimisation (or on what they think is an optimisation, but in many cases slows down things due to increased instruction cache pressure). Especially in this case: there is nothing potentially wrong with such a call, nor is the method in general not inlinable, so there is no way to get rid of the hint other than by removing the inline directive altogether (or by adding a version of that routine with a different name that is not declared as "inline"). This only promotes complicating code without any potential improvement of productivity or clarity of the code/programmer intent. Jonas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] inlining functions
Hi Jonas, That is reasonable. Perhaps the hint should mention that? But why is this still not inlined:: type TStrBuilder = object procedure append(const p: pchar; const l: SizeInt); inline; procedure append(const s: RawByteString); end; implementation procedure TStrBuilder.append(const p: pchar; const l: SizeInt); inline; begin end; procedure TStrBuilder.append(const s: RawByteString); begin append(pchar(pointer(s)), length(s)); //inlinetest.pas(24,3) Note: Call to subroutine "procedure TStrBuilder.append(const p:PChar;const l:Int64);" marked as inline is not inlined end; Best, Benito Am 01.01.19 um 22:41 schrieb Jonas Maebe: On 01/01/19 22:38, Benito van der Zander wrote: and why is it not inlining the count and append call of this string builder? It is not using any implementation only function Routines can only be inlined if they are called after their implementation has been parsed. FPC compiles everything in a single pass. Jonas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] inlining functions
On 01/01/19 22:38, Benito van der Zander wrote: and why is it not inlining the count and append call of this string builder? It is not using any implementation only function Routines can only be inlined if they are called after their implementation has been parsed. FPC compiles everything in a single pass. Jonas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] inlining functions
Hi, and why is it not inlining the count and append call of this string builder? It is not using any implementation only function unit inlinetest; {$mode objfpc}{$H+} interface uses Classes, SysUtils,math; type TStrBuilder = object protected next, bufferend: pchar; //next empty pchar and first pos after the string public buffer: pstring; procedure init(abuffer:pstring); procedure final; function count: SizeInt; inline; procedure reserveadd(delta: SizeInt); procedure append(c: char); inline; procedure append(const s: RawByteString); inline; procedure append(const p: pchar; const l: SizeInt); inline; end; implementation procedure TStrBuilder.init(abuffer: pstring); begin buffer := abuffer; SetLength(buffer^, 16); //use setlength to create a new string next := pchar(buffer^); bufferend := next + length(buffer^); end; procedure TStrBuilder.final; begin if next <> bufferend then begin setlength(buffer^, count); // !!! Note: Call to subroutine "function TStrBuilder.count:Int64;" marked as inline is not inlined next := pchar(buffer^) + length(buffer^); bufferend := next; end; end; function TStrBuilder.count: SizeInt; begin result := next - pointer(buffer^); end; procedure TStrBuilder.reserveadd(delta: SizeInt); var oldlen: SizeInt; begin if next + delta > bufferend then begin oldlen := count; SetLength(buffer^, max(2*length(buffer^), oldlen + delta)); next := pchar(buffer^) + oldlen; bufferend := pchar(buffer^) + length(buffer^); end; end; procedure TStrBuilder.append(c: char); begin if next >= bufferend then reserveadd(1); next^ := c; inc(next); end; procedure TStrBuilder.append(const s: RawByteString); begin append(pchar(pointer(s)), length(s)); // !!! inlinetest.pas(71,3) Note: Call to subroutine "procedure TStrBuilder.append(const p:PChar;const l:Int64);" marked as inline is not inlined end; procedure TStrBuilder.append(const p: pchar; const l: SizeInt); inline; begin if l <= 0 then exit; if next + l > bufferend then reserveadd(l); move(p^, next^, l); inc(next, l); end; end. Bye, Benito Am 29.12.18 um 20:31 schrieb Sven Barth via fpc-pascal: Am Sa., 29. Dez. 2018, 15:23 hat Benito van der Zander mailto:ben...@benibela.de>> geschrieben: Hi, after updating from fpc 3.1 to fpc 3.3, I am getting a lot of "function was not inlined" warnings, e.g. when an inline function depends on a function not declared in the interface part like: unit inlinetest; {$mode objfpc}{$H+} interface uses Classes, SysUtils; function strContains(const str, searched: string): boolean; inline; implementation function strContainsFrom(const str, searched: string; from: SizeInt): boolean; begin result:=Pos(searched, str, from) > 0; end; function strContains(const str, searched: string): boolean; inline; begin result := strContainsFrom(str, searched, 1); end; end. Is that supposed to happen? Fpc 3.1 did not show any warning in this case (although now that I investigate it, fpc 3.1 also did not seem to inline it despite not showing the warning) Correct. FPC 3.1.1 did neither warn nor inline in this case, 3.3.1 at least warns (I think 3.2 already warns as well). Regards, Sven ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] inlining functions depending on implementation only functions
Am Sa., 29. Dez. 2018, 15:23 hat Benito van der Zander geschrieben: > Hi, > > after updating from fpc 3.1 to fpc 3.3, I am getting a lot of "function > was not inlined" warnings, e.g. when an inline function depends on a > function not declared in the interface part like: > > unit inlinetest; > > {$mode objfpc}{$H+} > > interface > > uses >Classes, SysUtils; > > > function strContains(const str, searched: string): boolean; inline; > > implementation > > function strContainsFrom(const str, searched: string; from: SizeInt): > boolean; > begin >result:=Pos(searched, str, from) > 0; > end; > > > function strContains(const str, searched: string): boolean; inline; > begin >result := strContainsFrom(str, searched, 1); > end; > > end. > > > > Is that supposed to happen? > > Fpc 3.1 did not show any warning in this case (although now that I > investigate it, fpc 3.1 also did not seem to inline it despite not > showing the warning) > Correct. FPC 3.1.1 did neither warn nor inline in this case, 3.3.1 at least warns (I think 3.2 already warns as well). Regards, Sven > ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] inlining functions depending on implementation only functions
On 12/29/18 9:16 AM, Benito van der Zander wrote: Fpc 3.1 did not show any warning in this case (although now that I investigate it, fpc 3.1 also did not seem to inline it despite not showing the warning) i think, but am not totally sure, that the addition of the warning is a recently added feature specifically to note that a function was not inlined for some reason... -- NOTE: No off-list assistance is given without prior approval. *Please keep mailing list traffic on the list unless* *a signed and pre-paid contract is in effect with us.* ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
[fpc-pascal] inlining functions depending on implementation only functions
Hi, after updating from fpc 3.1 to fpc 3.3, I am getting a lot of "function was not inlined" warnings, e.g. when an inline function depends on a function not declared in the interface part like: unit inlinetest; {$mode objfpc}{$H+} interface uses Classes, SysUtils; function strContains(const str, searched: string): boolean; inline; implementation function strContainsFrom(const str, searched: string; from: SizeInt): boolean; begin result:=Pos(searched, str, from) > 0; end; function strContains(const str, searched: string): boolean; inline; begin result := strContainsFrom(str, searched, 1); end; end. Is that supposed to happen? Fpc 3.1 did not show any warning in this case (although now that I investigate it, fpc 3.1 also did not seem to inline it despite not showing the warning) Bye, Benito ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re[2]: [fpc-pascal] inlining functions
>> > Hi, >> > when using "inline" on a procedure or function, does it completely avoid >> > the call by copying anything inside the "begin ... end" block to the >> > right place? >> Yes, that's the idea. "INLINE" is a suggestion, not obligation: sometimes they are compiled with "CALL". It looks especially not great when trying to inline assembler procedures. Calling an inline function from another inline function may (or may not) obfuscate your debug information. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] inlining functions
Am Donnerstag, den 19.10.2006, 09:05 +0200 schrieb Michael Van Canneyt: > > On Thu, 19 Oct 2006, Marc Santhoff wrote: > > > Hi, > > > > when using "inline" on a procedure or function, does it completely avoid > > the call by copying anything inside the "begin ... end" block to the > > right place? > > Yes, that's the idea. Beautiful, that saves me from losing syntax highlighting when using macros instead and is much more readable. Thanks, Marc ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] inlining functions
On Thu, 19 Oct 2006, Marc Santhoff wrote: > Hi, > > when using "inline" on a procedure or function, does it completely avoid > the call by copying anything inside the "begin ... end" block to the > right place? Yes, that's the idea. Michael. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
[fpc-pascal] inlining functions
Hi, when using "inline" on a procedure or function, does it completely avoid the call by copying anything inside the "begin ... end" block to the right place? Example: function anythingFunc(v: integer):real; inline; begin ... some calculations ... end; function TMyObject.callAnything(v: integer):real; begin result := anythingFunc(v); end This will result in two levels of calls (one for the method of TMyObject and one from inside the method to the global function) without inlining. I assume with inline on it is only *one* call, which would be a speed improvement especially when called often. Can someone confirm I understand this correctly? TIA, Marc ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal