Sign in Join

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

Mailing lists / fpc-devel / 2013-08

Little feature teaser

31 messages · 11 people · –

Reply by email Subscribe to this list Your subscription

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

Sven Barth

Hello together!

Just a little feature teaser what I'm currently working on when I find the time. :)

=== source begin ===

program tgenfuncs;
{$modeswitch result}
generic function IsIn<T>(aElement: T; const aArray: array of T): Boolean;
var
   elem: T;
begin
   for elem in aArray do
     if elem = aElement then
       Exit(True);
   Result := False;
end;
begin
   Writeln(specialize IsIn<LongInt>(42, [21, 42, 84]));
   Writeln(specialize IsIn<LongInt>(5, [21, 42, 84]));
   Writeln(specialize IsIn<String>('Foobar', ['Foo', 'Bar', 'Blubber']));
end.

=== source end ===

=== console begin ===

PS D:\svn\fpc> .\compiler\i386\pp.exe -n -Furtl\units\i386-win32 -FEtestoutput -viwn .\fpctests\tgenfuncs.pas
Target OS: Win32 for i386
Compiling .\fpctests\tgenfuncs.pas
Linking testoutput\tgenfuncs.exe
19 lines compiled, 0.3 sec, 32224 bytes code, 1204 bytes data PS D:\svn\fpc> .\testoutput\tgenfuncs.exe
TRUE
FALSE
FALSE

=== console end ===

Regards,
Sven

Reply by email

Anthony Walter
to Sven Barth

Wow, that looks great Sven. I've been wanting generic functions for a long time. Would it be possible to add constraints like must override operators =, <, or > ... and possibly +, -, /, *, and, or, shl, shr, div, mod?

In this way you could write:

function Sum<T, Add>(const Items: TArray<T>): T;
var
  I: T;
begin
  Result := default(T);
  for I in T do
    Result := Result + T;
end;
I := Sum([1, 2]); // okay
S := Sum(['Hello', 'World']); // okay
V := Sum([Vec2(1, 2), Vec2(3, 4)]); // okay only if type TVec2 overloads
"operator TVec2.Add(const A, B: TVec2): TVec2;"
Sven Barth wrote 50 lines
Hello together! Just a little feature teaser what I'm currently working on when I find the time. :) === source begin === program tgenfuncs; {$modeswitch result} generic function IsIn<T>(aElement: T; const aArray: array of T): Boolean; var elem: T; begin for elem in aArray do if elem = aElement then Exit(True); Result := False; end; begin Writeln(specialize IsIn<LongInt>(42, [21, 42, 84])); Writeln(specialize IsIn<LongInt>(5, [21, 42, 84])); Writeln(specialize IsIn<String>('Foobar', ['Foo', 'Bar', 'Blubber'])); end. === source end === === console begin === PS D:\svn\fpc> .\compiler\i386\pp.exe -n -Furtl\units\i386-win32 -FEtestoutput -viwn .\fpctests\tgenfuncs.pas Target OS: Win32 for i386 Compiling .\fpctests\tgenfuncs.pas Linking testoutput\tgenfuncs.exe 19 lines compiled, 0.3 sec, 32224 bytes code, 1204 bytes data PS D:\svn\fpc> .\testoutput\tgenfuncs.exe TRUE FALSE FALSE === console end === Regards, Sven ______________________________**_________________ fpc-devel maillist - http://lists.freepascal.org/**mailman/listinfo/fpc-devel<http://lists.freepascal.org/mailman/listinfo/fpc-devel>

Reply by email

Mattias Gaertner
to Sven Barth: Hello together! Just a little feature teaser what I'm currently working on when I find…
Show quoted text 20 lines
[...] === source begin === program tgenfuncs; {$modeswitch result} generic function IsIn<T>(aElement: T; const aArray: array of T): Boolean; var elem: T; begin for elem in aArray do if elem = aElement then Exit(True); Result := False; end; begin Writeln(specialize IsIn<LongInt>(42, [21, 42, 84])); Writeln(specialize IsIn<LongInt>(5, [21, 42, 84]));

What is the speed?
Is it much slower compared to a line of "if
(aElement=val) or (..)... then" or a "case" statement?

What about code size?

Writeln(specialize IsIn<String>('Foobar', ['Foo', 'Bar', 'Blubber'])); end.

Mattias

Reply by email

Sven Barth
to Anthony Walter: Wow, that looks great Sven. I've been wanting generic functions for a long time. Would it…
Anthony Walter wrote
Wow, that looks great Sven. I've been wanting generic functions for a long time. Would it be possible to add constraints like must override operators =, <, or > ... and possibly +, -, /, *, and, or, shl, shr, div, mod?

I had the idea already myself to extend constraints with operator restrictions, but that is a different feature that might get implemented at a different time.

Regards,
Sven

Reply by email

Sven Barth
to Mattias Gaertner: On Fri, 02 Aug 2013 13:18:53 +0200 What is the speed? Is it much slower compared to a…
Mattias Gaertner wrote 27 lines
On Fri, 02 Aug 2013 13:18:53 +0200 Sven Barth wrote: > [...] > === source begin === > > program tgenfuncs; > > {$modeswitch result} > > generic function IsIn<T>(aElement: T; const aArray: array of T): Boolean; > var > elem: T; > begin > for elem in aArray do > if elem = aElement then > Exit(True); > Result := False; > end; > > begin > Writeln(specialize IsIn<LongInt>(42, [21, 42, 84])); > Writeln(specialize IsIn<LongInt>(5, [21, 42, 84])); What is the speed? Is it much slower compared to a line of "if (aElement=val) or (..)... then" or a "case" statement?

You can do the comparison yourself, as a "specialize IsIn<LongInt>" will generate a version of "IsIn<T>" where each "T" is replaced by "LongInt" and be completely reparsed. So it's the same as if you wrote the following from the beginning:

=== code begin ===

function IsIn(aElement: LongInt; const aArray: array of LongInt): Boolean;
var
   elem: LongInt;
begin
   for elem in aArray do
     if elem = aElement then
       Exit(True);
   Result := False;
end;

=== code end ===

AFAIK the compiler implements the for-in for arrays as a normal for-loop and thus I'd suspect that the "IsIn<T>" function is faster for a larger amount of elements (=> less jumps). Your approach with ifs is basically a loop unrolling which is better with fewer iterations. If you'd declare the "IsIn<T>" function as "inline" and the compiler would correctly handle this(*1) the compiler could in theory be able to fold the complete for-loop together in the example I gave (because only constants are used there). I don't know though whether the compiler is currently able to deduce this (I'll need to test that ^^).

(*1) The problem currently is that the implementation needs to be available when the call is parsed, but specializations are created at the end of parsing a unit. So this would need to be adjusted to allow inline generic functions to work correctly (I plan this, but not now).

What about code size?

The code size for one unit is the same as if you had (in that example) declared a variant of "IsIn" for each "LongInt" and "String". So for each "IsIn<T>" specialization with different types new code is generated if it does not yet exist in that unit. This means that if you call "IsIn<LongInt>" in different units you'll have a "IsIn<LongInt>" implementation in each unit. This is the same as for generic types btw.

Regards,
Sven

Reply by email

Sven Barth
to Sven Barth
Sven Barth wrote 5 lines
If you'd declare the "IsIn<T>" function as "inline" and the compiler would correctly handle this(*1) the compiler could in theory be able to fold the complete for-loop together in the example I gave (because only constants are used there). I don't know though whether the compiler is currently able to deduce this (I'll need to test that ^^).

Just tested and got the following results:
- the compiler uses indeed a for-loop for the for-in of arrays
- inlining does not work with open array parameters yet (2.6.x at least warned about that, 2.7.1 does not warn about that anymore :( [at least the version I have lying around] )
- using an array declared as a ranged array (array[0..2] of LongInt) the for-loop is inlined and optimized a bit (especially depending on the optimization settings), but the compiler does not yet fold the loop...

Regards,
Sven

Reply by email

Flávio Etrusco
to Sven Barth: You can do the comparison yourself, as a "specialize IsIn<LongInt>" will generate a…
Sven Barth wrote
On 02.08.2013 17:01, Mattias Gaertner wrote: > > On Fri, 02 Aug 2013 13:18:53 +0200 > Sven Barth wrote:

(...)

Show quoted text 12 lines
> What about code size? The code size for one unit is the same as if you had (in that example) declared a variant of "IsIn" for each "LongInt" and "String". So for each "IsIn<T>" specialization with different types new code is generated if it does not yet exist in that unit. This means that if you call "IsIn<LongInt>" in different units you'll have a "IsIn<LongInt>" implementation in each unit. This is the same as for generic types btw. Regards, Sven

And the same (problem) in C++. Is there some proposal to mitigate the code duplication? Or the official position is that if the project is big enough to suffer from the bloat it should avoid itself the duplicate declarations?

Regards,
Flávio

Reply by email

Sven Barth
to Sven Barth: Just tested and got the following results: - the compiler uses indeed a for-loop for the…
Sven Barth wrote 12 lines
On 02.08.2013 17:34, Sven Barth wrote: > If you'd declare the "IsIn<T>" function as "inline" and the compiler > would correctly handle this(*1) the compiler could in theory be able to > fold the complete for-loop together in the example I gave (because only > constants are used there). I don't know though whether the compiler is > currently able to deduce this (I'll need to test that ^^). Just tested and got the following results: - the compiler uses indeed a for-loop for the for-in of arrays - inlining does not work with open array parameters yet (2.6.x at least warned about that, 2.7.1 does not warn about that anymore :( [at least the version I have lying around] )

According to the source the compiler does still provide a hint. Maybe I have hints disabled for my 2.7.1 version...

- using an array declared as a ranged array (array[0..2] of LongInt) the for-loop is inlined and optimized a bit (especially depending on the optimization settings), but the compiler does not yet fold the loop...

Regards,
Sven

Reply by email

Sven Barth
to Flávio Etrusco: (...) And the same (problem) in C++. Is there some proposal to mitigate the code…
Flávio Etrusco wrote 26 lines
On Fri, Aug 2, 2013 at 12:34 PM, Sven Barth wrote: > On 02.08.2013 17:01, Mattias Gaertner wrote: >> >> On Fri, 02 Aug 2013 13:18:53 +0200 >> Sven Barth wrote: (...) >> What about code size? > > > The code size for one unit is the same as if you had (in that example) > declared a variant of "IsIn" for each "LongInt" and "String". So for each > "IsIn<T>" specialization with different types new code is generated if it > does not yet exist in that unit. This means that if you call "IsIn<LongInt>" > in different units you'll have a "IsIn<LongInt>" implementation in each > unit. This is the same as for generic types btw. > > Regards, > Sven And the same (problem) in C++. Is there some proposal to mitigate the code duplication? Or the official position is that if the project is big enough to suffer from the bloat it should avoid itself the duplicate declarations?

The problem is that it's not really possible with the unit concept FPC uses. If you want to share the code with other units the code needs to be callable from the interface section, but when you are working in the implementation section (where most specializations take place) you should not modify the interface section anymore as this needs to trigger a recompilation of all units that depend on that unit. This already leads to some hard to detect bugs in context with inlining (which does exactly that, because the node tree of the inline function is stored in the interface part of the PPU). The type of interdependencies are for example a problem in FPC itself which leads to strange compilation bugs (e.g. identifier not found, although it exists, corrupted unit loadings, etc) if you do a normal compile (Ctrl+F9 in Lazarus) after you changed something in the interface section of some heavy used unit. These bugs of course need to fixed, but they are very hard to reproduce in smaller setups...

Regards,
Sven

Reply by email

Flávio Etrusco
to Sven Barth
Sven Barth wrote 55 lines
On 02.08.2013 17:50, Flávio Etrusco wrote: > > On Fri, Aug 2, 2013 at 12:34 PM, Sven Barth > wrote: >> >> On 02.08.2013 17:01, Mattias Gaertner wrote: >>> >>> >>> On Fri, 02 Aug 2013 13:18:53 +0200 >>> Sven Barth wrote: > > > (...) > >>> What about code size? >> >> >> >> The code size for one unit is the same as if you had (in that example) >> declared a variant of "IsIn" for each "LongInt" and "String". So for each >> "IsIn<T>" specialization with different types new code is generated if it >> does not yet exist in that unit. This means that if you call >> "IsIn<LongInt>" >> in different units you'll have a "IsIn<LongInt>" implementation in each >> unit. This is the same as for generic types btw. >> >> Regards, >> Sven > > > > And the same (problem) in C++. Is there some proposal to mitigate the > code duplication? Or the official position is that if the project is > big enough to suffer from the bloat it should avoid itself the > duplicate declarations? The problem is that it's not really possible with the unit concept FPC uses. If you want to share the code with other units the code needs to be callable from the interface section, but when you are working in the implementation section (where most specializations take place) you should not modify the interface section anymore as this needs to trigger a recompilation of all units that depend on that unit. This already leads to some hard to detect bugs in context with inlining (which does exactly that, because the node tree of the inline function is stored in the interface part of the PPU). The type of interdependencies are for example a problem in FPC itself which leads to strange compilation bugs (e.g. identifier not found, although it exists, corrupted unit loadings, etc) if you do a normal compile (Ctrl+F9 in Lazarus) after you changed something in the interface section of some heavy used unit. These bugs of course need to fixed, but they are very hard to reproduce in smaller setups... Regards, Sven

Thank you very much for the detailed explanation :)

Best regards,
Flávio

Reply by email

Dennis Poon
to Flávio Etrusco: (...) And the same (problem) in C++. Is there some proposal to mitigate the code…
Show quoted text 21 lines
>> What about code size? >> > > The code size for one unit is the same as if you had (in that example) > declared a variant of "IsIn" for each "LongInt" and "String". So for each > "IsIn<T>" specialization with different types new code is generated if it > does not yet exist in that unit. This means that if you call "IsIn<LongInt>" > in different units you'll have a "IsIn<LongInt>" implementation in each > unit. This is the same as for generic types btw. > > Regards, > Sven > And the same (problem) in C++. Is there some proposal to mitigate the code duplication? Or the official position is that if the project is big enough to suffer from the bloat it should avoid itself the duplicate declarations?

If we create a third unit with a wrapper function in which it specializes the call, can we avoid the duplication code problem?

Dennis

Reply by email

Sven Barth
to Dennis Poon
"Dennis Poon" wrote 8 lines
>>> What about code size? >>> >> >> >> The code size for one unit is the same as if you had (in that example) >> declared a variant of "IsIn" for each "LongInt" and "String". So for

each

>> "IsIn<T>" specialization with different types new code is generated if

it

>> does not yet exist in that unit. This means that if you call

"IsIn<LongInt>"

Show quoted text 17 lines
>> in different units you'll have a "IsIn<LongInt>" implementation in each >> unit. This is the same as for generic types btw. >> >> Regards, >> Sven >> > > > And the same (problem) in C++. Is there some proposal to mitigate the > code duplication? Or the official position is that if the project is > big enough to suffer from the bloat it should avoid itself the > duplicate declarations? > > > If we create a third unit with a wrapper function in which it specializes

the call, can we avoid the duplication code problem?

And what would you have won with that? The idea behind generics is that you don't need to write a common piece of code multiple times for diffrent types in the source, but that the compiler is handling that for you. In your variant you'd need to call the wrapper instead of directly the generic to keep the size small and if you call the wrapper multiple times you'd trade performance (additional call) for size. Inlining might reduce this a bit again though...

Regards,
Sven

Reply by email

Sven Barth
to Florian Klämpfl: At least I fixed loop unrolling for for-in loops.
"Florian Klämpfl" wrote 8 lines
Am 02.08.2013 17:46, schrieb Sven Barth: > - using an array declared as a ranged array (array[0..2] of LongInt) the > for-loop is inlined and optimized a bit (especially depending on the > optimization settings), but the compiler does not yet fold the loop... > At least I fixed loop unrolling for for-in loops.

Cool! I'll need to test that with my test code :)

Now we "only" need need support for open arrays in inline functions... (yes, I've read the comment near the hint, that's why the "only" is in quotes ;) )

And regarding that: open arrays can only be with a "const" and none modifier, right? (and maybe "constref"?) So couldn't we just create a temp of the passed array that looks exactly like when we pass it to a function with open array argument? (at least in those cases where we pass e.g. an array range) This way we wouldn't need to adjust the array indices in the inlined function and would at least get rid of the call...

Regards,
Sven

Reply by email

Jonas Maebe
to Sven Barth
Sven Barth wrote
And regarding that: open arrays can only be with a "const" and none modifier, right?

No, they can be passed like any other parameter, including with "var" and "out".

Jonas

Reply by email

Sven Barth
to Jonas Maebe
"Jonas Maebe" wrote 8 lines
On 03 Aug 2013, at 09:36, Sven Barth wrote: > And regarding that: open arrays can only be with a "const" and none > modifier, right? No, they can be passed like any other parameter, including with "var" and

"out".

Ok, I wasn't aware of that -.-

Regards,
Sven

Reply by email

Marco van de Voort
to Sven Barth: The problem is that it's not really possible with the unit concept FPC uses. If you want…

In our previous episode, Sven Barth said:

Show quoted text 11 lines
> And the same (problem) in C++. Is there some proposal to mitigate the > code duplication? Or the official position is that if the project is > big enough to suffer from the bloat it should avoid itself the > duplicate declarations? The problem is that it's not really possible with the unit concept FPC uses. If you want to share the code with other units the code needs to be callable from the interface section, but when you are working in the implementation section (where most specializations take place) you should not modify the interface section anymore as this needs to trigger a recompilation of all units that depend on that unit.

I thought this is where constraints come in? If the specialization is completely defined by the constraint class type, you can already generate the specialization and reuse it?

At least that should avoid re-specialization of common container types for basic class types.

But admitted, Delphi doesn't support inline with generics, in that FPC is covering new ground.

Reply by email

Sven Barth
to Marco van de Voort
Marco van de Voort wrote 16 lines
In our previous episode, Sven Barth said: >> And the same (problem) in C++. Is there some proposal to mitigate the >> code duplication? Or the official position is that if the project is >> big enough to suffer from the bloat it should avoid itself the >> duplicate declarations? > > The problem is that it's not really possible with the unit concept FPC > uses. If you want to share the code with other units the code needs to > be callable from the interface section, but when you are working in the > implementation section (where most specializations take place) you > should not modify the interface section anymore as this needs to trigger > a recompilation of all units that depend on that unit. I thought this is where constraints come in? If the specialization is completely defined by the constraint class type, you can already generate the specialization and reuse it?

Yes, if constraints are used (most importantly constraints of inheritable types) then one could specialize the generic once for the given type and be done with it. But there is one problematic case. Consider the following:

=== code begin ===

type
   TTest = class
     procedure Test;
   end;
procedure TTest.Test;
begin
   Writeln('Test');
end;
type
   generic TMyGeneric<T: TTest> = class
     class procedure Test;
   end;
class procedure TMyGeneric.Test;
var
   myt: T;
begin
   myt := TTest.Create;
   myt.Test;
   myt.Free;
end;
type
   TTestSub = class
     procedure Test;
   end;
procedure TTestSub.Test;
begin
   Writeln('Foobar');
end;
type
   TMyGenericTTest = specialize TMyGeneric<TTest>;
   TMyGenericTTestSub = specialize TMyGeneric<TTestSub>;
begin
   TMyGenericTTest.Test;
   TMyGenericTTestSub.Test;
end.

=== code end ===

Now currently the output will be the following:

=== output begin ===

Test
Foobar

=== output end ===

If only the base type is specialized the output would be however:

=== output begin ===

Test
Test

=== output end ===

This would of course not only apply to normal methods, but also to non virtual constructors. This problem is not trivially to solve...

Maybe one can mark the generic as calling non virtual methods and if the class that is used for specialization overrides non-virtual methods then it needs to be really respecialized...

Another problem that could come up is overload and/or operator selection, because in the first case T will be TTest once and TTestSub the other time and in the second time it will be TTest at both times...

So here one would need to record if a called procedure has a overload or operator for other types as well and if a type is used for specialization that would trigger these overloads than an explicit specialization must be done...

I smell a decrease in performance here :P

But admitted, Delphi doesn't support inline with generics, in that FPC is covering new ground.

If I get inlining for generic functions/procedures/methods working as well, then we indeed have much new ground compared to Delphi :)

Regards,
Sven

Reply by email

Sven Barth
to Sven Barth: Cool! I'll need to test that with my test code :) Now we "only" need need support for…
Sven Barth wrote 13 lines
Am 02.08.2013 23:26 schrieb "Florian Klämpfl" < >: > > Am 02.08.2013 17:46, schrieb Sven Barth: > > - using an array declared as a ranged array (array[0..2] of LongInt) the > > for-loop is inlined and optimized a bit (especially depending on the > > optimization settings), but the compiler does not yet fold the loop... > > > > At least I fixed loop unrolling for for-in loops. Cool! I'll need to test that with my test code :)

Hmm... am I expecting too much or is it really not working?

=== code begin ===

program inlinetest;
{$modeswitch result}
type
   TLongIntArray = array[0..2] of LongInt;
function IsIn(aElement: LongInt; const aArray: TLongIntArray): Boolean;
inline;
var
   element: LongInt;
begin
   for element in aArray do
     if element = aElement then
       Exit(True);
   Result := False;
end;
procedure Test;
const
   MyArray: TLongIntArray = (42, 48, 39);
var
   b: Boolean;
begin
   b := IsIn(42, MyArray);
end;
begin
end.

=== code end ===

Tested with -O2, -O3 and -O4 and in all cases I still have the loop.

Regards,
Sven

Reply by email

Florian Klämpfl
to Sven Barth
Show quoted text 18 lines
On 03.08.2013 09:36, Sven Barth wrote: > Am 02.08.2013 23:26 schrieb "Florian Klämpfl" < > >: > > > > Am 02.08.2013 17:46, schrieb Sven Barth: > > > - using an array declared as a ranged array (array[0..2] of > LongInt) the > > > for-loop is inlined and optimized a bit (especially depending on the > > > optimization settings), but the compiler does not yet fold the loop... > > > > > > > At least I fixed loop unrolling for for-in loops. > > Cool! I'll need to test that with my test code :) Hmm... am I expecting too much or is it really not working?

First, FPC does not loop unrolling by default, you need -Ooloopunroll, second, the loop is relatively long, so let the compiler assume a long pipeline with - Cppentium4

Reply by email

Sven Barth
to Florian Klämpfl
Florian Klämpfl wrote 7 lines
> First, FPC does not loop unrolling by default, you need -Ooloopunroll, > second, the loop is relatively long, so let the compiler assume a long > pipeline with - Cppentium4 > -Oopentium4 it is.

Are you sure that you don't mean -Oppentium4? The compiler complains with —Oopentium4. And it doesn't change anything (also with -Ooloopunroll) :(

Regards,
Sven

Reply by email

Florian Klämpfl
to Sven Barth
Sven Barth wrote 12 lines
On 03.08.2013 13:12, Florian Klämpfl wrote: > >> First, FPC does not loop unrolling by default, you need -Ooloopunroll, >> second, the loop is relatively long, so let the compiler assume a long >> pipeline with - Cppentium4 >> > > -Oopentium4 it is. Are you sure that you don't mean -Oppentium4? The compiler complains with —Oopentium4. And it doesn't change anything (also with -Ooloopunroll) :(

There was indeed a mistake in optunroll.pas, -Oppentium4 -Ooloopunroll should work now.

Reply by email

Sven Barth
to Florian Klämpfl
Florian Klämpfl wrote 16 lines
Am 03.08.2013 17:19, schrieb Sven Barth: > On 03.08.2013 13:12, Florian Klämpfl wrote: >> >>> First, FPC does not loop unrolling by default, you need -Ooloopunroll, >>> second, the loop is relatively long, so let the compiler assume a long >>> pipeline with - Cppentium4 >>> >> >> -Oopentium4 it is. > > Are you sure that you don't mean -Oppentium4? The compiler complains > with —Oopentium4. And it doesn't change anything (also with > -Ooloopunroll) :( There was indeed a mistake in optunroll.pas, -Oppentium4 -Ooloopunroll should work now.

Jupp, it indeed works now. Now the compiler would "just" need to detect that the for loop is basically only using constants and evaluate that at compile time... but that's a wish for another day ;)

And the open array case of course :P - though I did just take a look at it and handling all strange cases of left sides of vecnodes which contain an open array argument somewhere might be troublesome -.-

Regards,
Sven

Reply by email

Florian Klaempfl
to Sven Barth
Sven Barth wrote 21 lines
On 03.08.2013 22:50, Florian Klämpfl wrote: > Am 03.08.2013 17:19, schrieb Sven Barth: >> On 03.08.2013 13:12, Florian Klämpfl wrote: >>> >>>> First, FPC does not loop unrolling by default, you need -Ooloopunroll, >>>> second, the loop is relatively long, so let the compiler assume a long >>>> pipeline with - Cppentium4 >>>> >>> >>> -Oopentium4 it is. >> >> Are you sure that you don't mean -Oppentium4? The compiler complains >> with —Oopentium4. And it doesn't change anything (also with >> -Ooloopunroll) :( > > There was indeed a mistake in optunroll.pas, -Oppentium4 -Ooloopunroll > should work now. Jupp, it indeed works now. Now the compiler would "just" need to detect that the for loop is basically only using constants and evaluate that at compile time... but that's a wish for another day ;)

I think item 635365 of my todo list, the autovectorizer would solve it ;)

Reply by email

Sven Barth
to Florian Klaempfl
Florian Klaempfl wrote 26 lines
Am 03.08.2013 23:31, schrieb Sven Barth: > On 03.08.2013 22:50, Florian Klämpfl wrote: >> Am 03.08.2013 17:19, schrieb Sven Barth: >>> On 03.08.2013 13:12, Florian Klämpfl wrote: >>>> >>>>> First, FPC does not loop unrolling by default, you need >>>>> -Ooloopunroll, >>>>> second, the loop is relatively long, so let the compiler assume a >>>>> long >>>>> pipeline with - Cppentium4 >>>>> >>>> >>>> -Oopentium4 it is. >>> >>> Are you sure that you don't mean -Oppentium4? The compiler complains >>> with —Oopentium4. And it doesn't change anything (also with >>> -Ooloopunroll) :( >> >> There was indeed a mistake in optunroll.pas, -Oppentium4 -Ooloopunroll >> should work now. > > Jupp, it indeed works now. Now the compiler would "just" need to detect > that the for loop is basically only using constants and evaluate that at > compile time... but that's a wish for another day ;) I think item 635365 of my todo list, the autovectorizer would solve it ;)

Then I just need to wait until you've done the 635364 other items on your list. Sounds doable :P

Regards,
Sven

Reply by email

Paul Ishenin
to Sven Barth

04.08.13, 20:20, Sven Barth пишет:

Then I just need to wait until you've done the 635364 other items on your list. Sounds doable :P

This is not doable even if Florian will do 10 items per day. The life is not as long as we wish.

Best regards,
Paul Ishenin

Reply by email

Sven Barth
to Paul Ishenin
Paul Ishenin wrote 7 lines
04.08.13, 20:20, Sven Barth пишет: > Then I just need to wait until you've done the 635364 other items on > your list. Sounds doable :P This is not doable even if Florian will do 10 items per day. The life is not as long as we wish.

You're aware that my answer was ironic (hint: there was a emoticon)? Also I don't believe that Florian's list is *that* long (though I do believe that it's quite long... - like mine :) ). Also the entries might not be ordered by priority, just by appearance or so... ;)

Regards,
Sven

Reply by email

Florian Klämpfl
to Sven Barth: Then I just need to wait until you've done the 635364 other items on your list. Sounds…
Sven Barth wrote 8 lines
>> Jupp, it indeed works now. Now the compiler would "just" need to detect >> that the for loop is basically only using constants and evaluate that at >> compile time... but that's a wish for another day ;) > > I think item 635365 of my todo list, the autovectorizer would solve it ;) Then I just need to wait until you've done the 635364 other items on your list. Sounds doable :P

It's all a matter of priority ;)

Reply by email

Dmitry Boyarintsev
to Sven Barth: Hello together! Just a little feature teaser what I'm currently working on when I find…

Does a debugger understands that?

Sven Barth wrote 50 lines
Hello together! Just a little feature teaser what I'm currently working on when I find the time. :) === source begin === program tgenfuncs; {$modeswitch result} generic function IsIn<T>(aElement: T; const aArray: array of T): Boolean; var elem: T; begin for elem in aArray do if elem = aElement then Exit(True); Result := False; end; begin Writeln(specialize IsIn<LongInt>(42, [21, 42, 84])); Writeln(specialize IsIn<LongInt>(5, [21, 42, 84])); Writeln(specialize IsIn<String>('Foobar', ['Foo', 'Bar', 'Blubber'])); end. === source end === === console begin === PS D:\svn\fpc> .\compiler\i386\pp.exe -n -Furtl\units\i386-win32 -FEtestoutput -viwn .\fpctests\tgenfuncs.pas Target OS: Win32 for i386 Compiling .\fpctests\tgenfuncs.pas Linking testoutput\tgenfuncs.exe 19 lines compiled, 0.3 sec, 32224 bytes code, 1204 bytes data PS D:\svn\fpc> .\testoutput\tgenfuncs.exe TRUE FALSE FALSE === console end === Regards, Sven ______________________________**_________________ fpc-devel maillist - http://lists.freepascal.org/**mailman/listinfo/fpc-devel<http://lists.freepascal.org/mailman/listinfo/fpc-devel>

Reply by email

Sven Barth
to Dmitry Boyarintsev

Am 06.08.2013 04:25 schrieb "Dmitry Boyarintsev" <

: Does a debugger understands that?

As long as FPC outputs the correct debug information and the source of the unit where the generic is declared is available you can safely step into it. Just test it with Lazarus and a type based generic (it should work with 2.6.x already, but I'm only really sure about 2.7.1).

Regards,
Sven

Reply by email